├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── ReleaseNotes.md ├── build.cake ├── build.ps1 ├── docfx ├── .gitignore ├── api │ ├── .gitignore │ ├── .manifest │ └── index.md ├── assets │ └── appLogo.png ├── doc │ ├── appdetailspage.md │ ├── builtins.md │ ├── cakeintro.md │ ├── handlers.md │ ├── hosts.md │ ├── intro.md │ ├── logging.md │ ├── manifests.md │ ├── scriptcsintro.md │ ├── templating.md │ ├── toc.yml │ └── updatemgr.md ├── docfx.json ├── index.md ├── samples │ └── AutoPublish.ps1 └── toc.yml ├── extensions.cake ├── src ├── Cake.ClickTwice.Tests │ ├── App.config │ ├── Cake.ClickTwice.Tests.csproj │ ├── ClickTwiceFixture.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── UnitTest1.cs │ ├── UnitTestLogger.cs │ └── packages.config ├── Cake.ClickTwice │ ├── App.config │ ├── Cake.ClickTwice.csproj │ ├── Cake.ClickTwice.nuspec │ ├── CakeLogger.cs │ ├── CakePublishExtensions.cs │ ├── CakePublishManager.cs │ ├── CakeTemplatePublisher.cs │ ├── ClickTwiceAliases.cs │ ├── ClickTwiceManager.cs │ ├── ClickTwiceManagerExtensions.cs │ ├── ClickTwiceRunner.cs │ ├── ManifestPublisher.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── PublishException.cs │ ├── Samples.cs │ ├── TemplatePackageSettingsExtensions.cs │ └── packages.config ├── ClickTwice.Handlers.AppDetailsPage │ ├── AppDetailsPageHandler.cs │ ├── ClickTwice.Handlers.AppDetailsPage.csproj │ ├── PackageEngine.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Templating │ │ ├── PackageTemplateService.cs │ │ └── TemplateEngine.cs │ └── packages.config ├── ClickTwice.Handlers.sln ├── ClickTwice.Publisher.Core │ ├── App.config │ ├── AppInfoManager.cs │ ├── BasePublishManager.cs │ ├── ClickTwice.Publisher.Core.csproj │ ├── ClickTwice.Publisher.Core.csproj.DotSettings │ ├── ClickTwice.Publisher.Core.nuspec │ ├── CoreExtensions.cs │ ├── Exceptions │ │ ├── BuildFailedException.cs │ │ ├── HandlerProcessingException.cs │ │ └── OperationInProgressException.cs │ ├── Handlers │ │ ├── AppInfoHandler.cs │ │ ├── BuildConfigurator.cs │ │ ├── HandlerResponse.cs │ │ ├── InstallPageHandler.cs │ │ ├── Interfaces.cs │ │ ├── MockInputHandler.cs │ │ └── PublishPageHandler.cs │ ├── IPublishManager.cs │ ├── Loggers │ │ ├── ConsoleLogger.cs │ │ ├── FileLogger.cs │ │ └── IPublishLogger.cs │ ├── Manager.cs │ ├── ManifestManager.cs │ ├── Manifests │ │ ├── AppManifest.cs │ │ └── ExtendedAppInfo.cs │ ├── Properties │ │ ├── AssemblyInfo.cs │ │ ├── Resources.Designer.cs │ │ └── Resources.resx │ ├── Resources │ │ ├── EncodedImages.cs │ │ ├── LaunchPage.cs │ │ ├── LaunchPage.tt │ │ ├── LaunchPageCode.cs │ │ ├── LaunchPageModel.cs │ │ ├── PublishPage.cs │ │ ├── PublishPage.tt │ │ └── PublishPageCode.cs │ └── packages.config ├── ClickTwice.Publisher.MSBuild │ ├── ArgBuilder.cs │ ├── BuildDomain.cs │ ├── ClickTwice.Publisher.MSBuild.csproj │ ├── DirectPublisher.cs │ ├── Loggers │ │ └── BuildMessageLogger.cs │ ├── MSBuildResolver.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ └── PublishManager.cs ├── ClickTwice.Templates.Packager │ ├── ClickTwice.Templates.Packager.pssproj │ └── Script.ps1 ├── ClickTwice.Templates.SolidState │ ├── ClickTwice.Templates.SolidState.csproj │ ├── ClickTwice.Templates.SolidState.csproj.user │ ├── ClickTwice.Templates.SolidState.nuspec │ ├── Index.cshtml │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Web.Debug.config │ ├── Web.Release.config │ ├── Web.config │ ├── js │ │ ├── app.js │ │ └── site.js │ ├── packages.config │ └── site.css ├── ClickTwice.Templating │ ├── ClickTwice.Templating.csproj │ ├── IPackager.cs │ ├── ITemplatePublisher.cs │ ├── MinimalPackager.cs │ ├── PackagingMode.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── TemplatePackageSettings.cs │ ├── TemplatePackager.cs │ ├── VisualStudioPackager.cs │ └── packages.config ├── ClickTwice.UpdateManager │ ├── ClickTwice.UpdateManager.csproj │ ├── ClickTwice.UpdateManager.nuspec │ ├── Extensions.cs │ ├── Properties │ │ ├── Annotations.cs │ │ └── AssemblyInfo.cs │ ├── UpdateEventArgs.cs │ ├── UpdateInfo.cs │ ├── UpdateManagerCommands.cs │ ├── UpdateManagerEvents.cs │ ├── UpdateManagerProperties.cs │ ├── UpdateManagerViewModel.cs │ └── packages.config ├── ClickTwice.sln ├── ClickTwice.sln.DotSettings ├── NuGet.config ├── ScriptCs.ClickTwice │ ├── ClickTwicePack.cs │ ├── ClickTwicePackSettings.cs │ ├── ConsoleScriptHost.cs │ ├── IScriptHost.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Publisher.cs │ ├── Samples.cs │ ├── ScriptCs.ClickTwice.csproj │ ├── ScriptCs.ClickTwice.nuspec │ ├── ScriptPack.cs │ ├── ScriptTemplatePublisher.cs │ ├── SessionExtensions.cs │ └── packages.config └── TestApp │ ├── App.config │ ├── Program.cs │ ├── Properties │ └── AssemblyInfo.cs │ └── TestApp.csproj ├── tools ├── Modules │ └── packages.config └── packages.config ├── usage.cake └── usage.csx /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | build/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | 28 | # MSTest test Results 29 | [Tt]est[Rr]esult*/ 30 | [Bb]uild[Ll]og.* 31 | 32 | # NUNIT 33 | *.VisualState.xml 34 | TestResult.xml 35 | 36 | # Build Results of an ATL Project 37 | [Dd]ebugPS/ 38 | [Rr]eleasePS/ 39 | dlldata.c 40 | 41 | # DNX 42 | project.lock.json 43 | artifacts/ 44 | 45 | *_i.c 46 | *_p.c 47 | *_i.h 48 | *.ilk 49 | *.meta 50 | *.obj 51 | *.pch 52 | *.pdb 53 | *.pgc 54 | *.pgd 55 | *.rsp 56 | *.sbr 57 | *.tlb 58 | *.tli 59 | *.tlh 60 | *.tmp 61 | *.tmp_proj 62 | *.log 63 | *.vspscc 64 | *.vssscc 65 | .builds 66 | *.pidb 67 | *.svclog 68 | *.scc 69 | 70 | # Chutzpah Test files 71 | _Chutzpah* 72 | 73 | # Visual C++ cache files 74 | ipch/ 75 | *.aps 76 | *.ncb 77 | *.opensdf 78 | *.sdf 79 | *.cachefile 80 | 81 | # Visual Studio profiler 82 | *.psess 83 | *.vsp 84 | *.vspx 85 | 86 | # TFS 2012 Local Workspace 87 | $tf/ 88 | 89 | # Guidance Automation Toolkit 90 | *.gpState 91 | 92 | # ReSharper is a .NET coding add-in 93 | _ReSharper*/ 94 | *.[Rr]e[Ss]harper 95 | *.DotSettings.user 96 | 97 | # JustCode is a .NET coding add-in 98 | .JustCode 99 | 100 | # TeamCity is a build add-in 101 | _TeamCity* 102 | 103 | # DotCover is a Code Coverage Tool 104 | *.dotCover 105 | 106 | # NCrunch 107 | _NCrunch_* 108 | .*crunch*.local.xml 109 | 110 | # MightyMoose 111 | *.mm.* 112 | AutoTest.Net/ 113 | 114 | # Web workbench (sass) 115 | .sass-cache/ 116 | 117 | # Installshield output folder 118 | [Ee]xpress/ 119 | 120 | # DocProject is a documentation generator add-in 121 | DocProject/buildhelp/ 122 | DocProject/Help/*.HxT 123 | DocProject/Help/*.HxC 124 | DocProject/Help/*.hhc 125 | DocProject/Help/*.hhk 126 | DocProject/Help/*.hhp 127 | DocProject/Help/Html2 128 | DocProject/Help/html 129 | 130 | # Click-Once directory 131 | publish/ 132 | 133 | # Publish Web Output 134 | *.[Pp]ublish.xml 135 | *.azurePubxml 136 | ## TODO: Comment the next line if you want to checkin your 137 | ## web deploy settings but do note that will include unencrypted 138 | ## passwords 139 | #*.pubxml 140 | 141 | *.publishproj 142 | 143 | # NuGet Packages 144 | *.nupkg 145 | # The packages folder can be ignored because of Package Restore 146 | **/packages/* 147 | # except build/, which is used as an MSBuild target. 148 | !**/packages/build/ 149 | # Uncomment if necessary however generally it will be regenerated when needed 150 | #!**/packages/repositories.config 151 | 152 | # Windows Azure Build Output 153 | csx/ 154 | *.build.csdef 155 | 156 | # Windows Store app package directory 157 | AppPackages/ 158 | 159 | # Visual Studio cache files 160 | # files ending in .cache can be ignored 161 | *.[Cc]ache 162 | # but keep track of directories ending in .cache 163 | !*.[Cc]ache/ 164 | 165 | # Others 166 | ClientBin/ 167 | [Ss]tyle[Cc]op.* 168 | ~$* 169 | *~ 170 | *.dbmdl 171 | *.dbproj.schemaview 172 | *.pfx 173 | *.publishsettings 174 | node_modules/ 175 | orleans.codegen.cs 176 | 177 | # RIA/Silverlight projects 178 | Generated_Code/ 179 | 180 | # Backup & report files from converting an old project file 181 | # to a newer Visual Studio version. Backup files are not needed, 182 | # because we have git ;-) 183 | _UpgradeReport_Files/ 184 | Backup*/ 185 | UpgradeLog*.XML 186 | UpgradeLog*.htm 187 | 188 | # SQL Server files 189 | *.mdf 190 | *.ldf 191 | 192 | # Business Intelligence projects 193 | *.rdl.data 194 | *.bim.layout 195 | *.bim_*.settings 196 | 197 | # Microsoft Fakes 198 | FakesAssemblies/ 199 | 200 | # Node.js Tools for Visual Studio 201 | .ntvs_analysis.dat 202 | 203 | # Visual Studio 6 build log 204 | *.plg 205 | 206 | # Visual Studio 6 workspace options file 207 | *.opt 208 | 209 | # LightSwitch generated files 210 | GeneratedArtifacts/ 211 | _Pvt_Extensions/ 212 | ModelManifest.xml 213 | /src/ClickTwice.Templates.SolidState/TemplatePackage.nuspec 214 | 215 | #Cake (generated) 216 | [Tt]ools/** 217 | ![Tt]ools/packages.config 218 | 219 | artifacts/** 220 | 221 | src/**/*ClickTwice*xml -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Alistair Chapman and Contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ClickTwice 2 | # The ultimate WPF build toolchain 3 | 4 | ## Introduction 5 | 6 | As the name implies, ClickTwice is the missing step from the ClickOnce deployment technology. ClickTwice allows you to decouple your build and deploy steps from Visual Studio, instead integrating them with your preferred build environment. Currently, three environments are supported: 7 | 8 | - Cake build scripts 9 | - ScriptCs scripts 10 | - Self-hosting (custom tool) 11 | 12 | ClickTwice doesn't just build and publish your app: it also provides a powerful framework for pre- and post-processing your application at publish-time, allowing for a wide range of new abilities as pluggable handlers. 13 | 14 | ## Getting Started 15 | 16 | ClickTwice is usually run by a *"host"*, a context to help control and configure ClickTwice itself. Out-of-the-box, the easiest way to get started is by using the Cake or ScriptCs host. Alternatively, you can self-host the toolchain to get more fine-tuned control over the build. Plus, since it's all just .NET, you can integrate the toolchain directly into your own applications. -------------------------------------------------------------------------------- /ReleaseNotes.md: -------------------------------------------------------------------------------- 1 | # 0.1.0 2 | - Initial release of Cake support 3 | - Initial release of ScriptCs support 4 | - Major refactoring of core projects 5 | 6 | # 0.1.1 7 | - Fixes small bugs in NuGet packaging 8 | - Adds fluent API to `AppInfoManager`/`AppInfoHandler` 9 | - Updates to documentation -------------------------------------------------------------------------------- /docfx/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | ############### 3 | # folder # 4 | ############### 5 | /**/DROP/ 6 | /**/TEMP/ 7 | /**/packages/ 8 | /**/bin/ 9 | /**/obj/ 10 | _site 11 | -------------------------------------------------------------------------------- /docfx/api/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | ############### 3 | # temp file # 4 | ############### 5 | *.yml 6 | -------------------------------------------------------------------------------- /docfx/api/index.md: -------------------------------------------------------------------------------- 1 | # ClickTwice 2 | 3 | The ultimate WPF build toolchain. 4 | 5 | Browse through the API using the menu on the left. 6 | -------------------------------------------------------------------------------- /docfx/assets/appLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agc93/ClickTwice/44a54537730991343aac69ed7f07e387f18c9b6b/docfx/assets/appLogo.png -------------------------------------------------------------------------------- /docfx/doc/appdetailspage.md: -------------------------------------------------------------------------------- 1 | # ClickTwice App Page Generator 2 | 3 | ## Introduction 4 | 5 | This powerful handler comes shipped with most ClickTwice packages and provides for dead simple page generation abilities with user-built templates and full support for Razor syntax in templates. 6 | 7 | Whereas the `InstallPageHandler` simply produces a basic one-file template to launch your ClickTwice-published app, using this handler you can generate much more complex sites, built from one or multiple pages. 8 | 9 | ## Usage 10 | 11 | To use, just add a new instance of `AppDetailsPageHandler` to your handlers using the appropriate method for your host: 12 | 13 | ```csharp 14 | //for Cake 15 | PublishApp(projectPath) 16 | .WithHandler(new AppDetailsPageHandler("TemplatePackage")) // your package ID here 17 | .PublishTo("./artifacts/publish/"); 18 | ``` 19 | 20 | ```csharp 21 | // for scriptcs 22 | pack.Configure(s => s.WithHandler(new AppDetailsPageHandler("TemplatePackage"))); 23 | pack.PublishApp(projectPath).To("./artifacts/publish"); 24 | ``` 25 | 26 | Where `"TemplatePackage"` is the NuGet package ID of your chosen template. You can optionally provide a source as well, for use with private NuGet repositories. In addition to specifying a template name as above, you can also provide a `FileInfo` object to use a local `nupkg` file for your template. 27 | 28 | > [!WARNING] 29 | > The `AppDetailsPageHandler` requires both a standard manifest (`.cltw`) **and** an `app.info` file. The handler will not run without both. 30 | 31 | ## Template packages 32 | 33 | As outlined in the [Templating documentation](/doc/templating.html), ClickTwice templates are simply a NuGet package full of static files and any number of `*.cshtml` Razor view files. 34 | 35 | When the handler is run, it will copy all static content into the publish directory (see below), and will then run any `.cshtml` files through the Razor compiler, generating `.html` files in the same relative location. 36 | 37 | > [!NOTE] 38 | > If you don't have your own template, the `ClickTwice.Templates.SolidState` package is a good start! 39 | 40 | > [!NOTE] 41 | > ClickTwice template packages do not require any special metadata, but are often prefixed with `ClickTwice.Templates`. 42 | 43 | ### Web files 44 | 45 | In order to keep deployment directories clean and simple, ClickTwice does not leave generated views in the deployment root: it puts them in a separate content directory (available as `ContentDirectory` in the `Model`), with the exception of the special view named `index.cshtml` which will be generated in-place. 46 | 47 | ### File Name Mappings 48 | 49 | Using third-party templates is obviously dead simple, but can lead to a problem: incorrect file naming and file naming conflicts. The answer to this in the `AppDetailsPageHandler` is in it's optional `Dictionary FileNameMap` property. This dictionary is a simple source-to-target mapping of file names found in the provided template and what file they should be generated as in the destination folder: 50 | 51 | ```csharp 52 | //for Cake 53 | PublishApp(projectPath) 54 | .WithHandler(new AppDetailsPageHandler("ClickTwice.Templates.SolidState") { 55 | FileNameMap = new Dictionary { 56 | {"index.html", "details.html"} 57 | } 58 | }) 59 | .PublishTo("./artifacts/publish/"); 60 | ``` 61 | 62 | This will generate `index.cshtml` (note the `html` extension) from the *"ClickTwice.Templates.SolidState"* NuGet package in the target folder as `details.html`. -------------------------------------------------------------------------------- /docfx/doc/builtins.md: -------------------------------------------------------------------------------- 1 | # Built-in (aka out-of-the-box) objects 2 | 3 | The ClickTwice libraries are shipped with a few must-have and basic handlers and other types to cover common scenarios without duplication. They are: 4 | 5 | - `PublishPageHandler` (`IOutputHandler`) - This handler is a drop-in replacement for the old "Install" page generated by Visual Studio. It also serves as a reference implementation of an output handler. 6 | - `InstallPageHandler` (`IOutputHandler`) - This handler is intended as a more capable and up-to-date launch and install page, built as a single-file template with full HTML5/JS/CSS3 support. 7 | - `AppInfoHandler` (`IInputHandler` and `IOutputHandler`) - Handler for parsing, updating and publishing application information in an `app.info` file. 8 | - `AppDetailsPageHandler` (`IOutputHandler`) - Included with the ScriptCs and Cake hosts, this handler can generate pages or whole sites from Razor templates using a model derived from the ClickTwice manifest and an `app.info` file. Not included with the Core package. 9 | - `BuildConfigurator` (`IBuildConfigurator`) - Base type for custom build configurators to implement. -------------------------------------------------------------------------------- /docfx/doc/cakeintro.md: -------------------------------------------------------------------------------- 1 | # Cake publisher 2 | 3 | > Publish ClickOnce apps from your Cake scripts the easy way. 4 | 5 | The ClickTwice host for Cake is a standard Cake addin, exposing multiple ways of publishing your app. 6 | 7 | ## Installation 8 | 9 | First, install/include the addin by adding the `#addin` declaration as below. 10 | 11 | ``` 12 | #addin nuget:?package=Cake.ClickTwice 13 | 14 | //or to use the latest development release 15 | #addin nuget:?package=Cake.ClickTwice&prerelease 16 | ``` 17 | 18 | The NuGet prerelease packages are automatically built and deployed from the `develop` branch so they can be considered bleeding-edge while the non-prerelease packages will be much more stable. 19 | 20 | Versioning is predominantly SemVer-compliant so you can set your version constraints if you're worried about changes. 21 | 22 | > [!NOTE] 23 | > These packages include their dependent libraries (including RazorEngine and friends) at this time, as Cake is currently unable to correctly reference NuGet dependencies. 24 | 25 | ## Usage 26 | 27 | To publish your app, just use the `PublishApp` alias, as per below: 28 | 29 | ```csharp 30 | Task("Publish") 31 | .Does(() => 32 | { 33 | PublishApp(yourProjectPathHere).To("./artifacts/publish/"); 34 | }); 35 | ``` 36 | That's it! Now that is just a plain MSBuild build and publish, with no additional features. If you want to add handlers, just use `WithHandler` or use `LogTo` to add loggers: 37 | 38 | ```csharp 39 | Task("Publish") 40 | .Does(() => 41 | { 42 | PublishApp(yourProjectPathHere) 43 | .WithHandler(new InstallPageHandler()) 44 | .LogTo(new FileLogger()) 45 | .To("./artifacts/publish/"); 46 | }); 47 | ``` 48 | 49 | And there's even more options available from the [`ClickTwiceManager`](/api/Cake.ClickTwice.ClickTwiceManagerExtensions.html) to explore. For example, the following works: 50 | 51 | ```csharp 52 | Task("Publish") 53 | .Does(() => 54 | { 55 | PublishApp(yourProjectPathHere) 56 | .WithHandler(new InstallPageHandler()) 57 | .LogTo(new FileLogger()) 58 | .SetConfiguration("Debug") 59 | .ForceRebuild() 60 | .SetBuildPlatform(MSBuildPlatform.x64) 61 | .ThrowOnHandlerFailure() 62 | .WithVersion("0.9.2.1") 63 | .To("./artifacts/publish/"); 64 | }); 65 | ``` 66 | 67 | ## Split form usage 68 | 69 | If you already have customised `MSBuild` alias actions you use, no need to replace them! You can also use the `ClickTwice` property alias to build complex actions: 70 | 71 | ```csharp 72 | Task("Publish") 73 | .Does(() => 74 | var appInfo = new AppInfoHandler(); 75 | ClickTwice.RunInputHandlers(projectPath, appInfo); 76 | MSBuild(projectPath, settings => 77 | settings.SetPlatformTarget(PlatformTarget.MSIL) 78 | .WithTarget("Publish") //important! 79 | .SetConfiguration("Debug")); 80 | //build here 81 | ClickTwice.GenerateManifest(projectPath).Publish("./path/to/published/files"); 82 | ClickTwice.RunOutputHandlers("./path/to/published/files", appInfo, new InstallPageHandler()); 83 | }); 84 | ``` 85 | 86 | Note that this is not the recommended method and can be easy to get wrong. Further, reliably determining the "./path/to/published/files" in the above example may not always be trivial. It is usually a folder called "app.publish" in the build output directory. It is strongly recommended to use the `PublishApp` alias instead. -------------------------------------------------------------------------------- /docfx/doc/handlers.md: -------------------------------------------------------------------------------- 1 | # Handlers 2 | 3 | Handlers are one of the most powerful parts of the ClickTwice toolchain. Handlers are generic processing modules: when included in a publish, they are automatically invoked at the correct stage in the build to perform any sort of operation on your application. 4 | 5 | Handlers can be *input handlers*, *output handlers* or sometimes both. Input handlers are run on the project source, before building. An input handler can transform your source, add missing or generated files, update metadata or anything you need to do before publishing. Output handlers, on the other hand, are run on the published output, before copying to the target location. This means they have access to the final published app files, including any generated manifests, and can do any post-build or pre-deploy steps as required. 6 | 7 | ## Using handlers 8 | 9 | The exact syntax for using handlers depends on your choice of host, but essentially comes down to adding `IInputHandler` and `IOutputHandler` objects to the `InputHandlers` and `OutputHandlers` collections on your `PublishManager`. Since that is a scary way of putting it, the built-in hosts both include a simple `WithHandler` method, so you can do the following: 10 | 11 | ```csharp 12 | //PublishApp(...) //for Cake 13 | //Configure(...) //for scriptcs 14 | publish.WithHandler(new InstallPageHandler); 15 | ``` 16 | 17 | Remember, this syntax may vary slightly between hosts, so check the documentation for more detail. 18 | 19 | ## Building handlers 20 | 21 | Building your own build handlers is dead simple: just create a `public` class, that inherits from `IInputHandler` or `IOutputHandler`. Give your handler a `Name` property, and implement the required `Process(string)` method and you're good to go! 22 | 23 | ```csharp 24 | using ClickTwice.Publisher.Core.Handlers; 25 | 26 | public class SimpleHandler : IInputHandler 27 | { 28 | public string Name => "Simple Handler"; 29 | 30 | HandlerResponse Process(string inputPath) { 31 | return new HandlerResponse(this, true); 32 | } 33 | } 34 | ``` 35 | 36 | That's it! You can do anything you like in your handler. The `HandlerResponse` object you return just needs to return a `bool` to indicate if it was successful or not, and an optional message for the user. The `inputPath` parameter will be the path to the project directory (i.e. the source). 37 | 38 | ### Configurators 39 | 40 | There is also a special kind of quasi-handler called a *build configurator*. Configurators run during the build phase, right before invoking MSBuild, and can be used to perform low-level tweaks of the build configuration before building, without any post-processing. Note that since these have the option of modifying your builds in unpredictable and potentially dangerous ways, make sure to only ever use configurators you fully trust! Some hosts will even print a warning before invoking configurators for clarity. 41 | 42 | > Configurators are an early preview feature and may change in future releases 43 | 44 | #### Custom configurator 45 | 46 | Configurators inherit from `BuildConfigurator`, and can override the `ProcessConfiguration` and `ProcessTargets` methods to read or manipulate the dictionary of build properties or list of build targets. These configurators are perfect for fine-tuned control of build properties and parameters such as suppressing errors or adding new custom targets to your publish. -------------------------------------------------------------------------------- /docfx/doc/hosts.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agc93/ClickTwice/44a54537730991343aac69ed7f07e387f18c9b6b/docfx/doc/hosts.md -------------------------------------------------------------------------------- /docfx/doc/intro.md: -------------------------------------------------------------------------------- 1 | 2 | # ClickTwice 3 | # The ultimate WPF build toolchain 4 | 5 | ## Introduction 6 | 7 | As the name implies, ClickTwice is the missing step from the ClickOnce deployment technology. ClickTwice allows you to decouple your build and deploy steps from Visual Studio, instead integrating them with your preferred build environment. Currently, three environments are supported: 8 | 9 | - Cake build scripts 10 | - ScriptCs scripts 11 | - Self-hosting (custom tool) 12 | 13 | ClickTwice doesn't just build and publish your app: it also provides a powerful framework for pre- and post-processing your application at publish-time, allowing for a wide range of new abilities as pluggable handlers. 14 | 15 | ## How it works 16 | 17 | The ClickTwice toolchain, at a high-level, performs the following operations when you publish your app: 18 | 19 | 1. Runs input handlers on the project source 20 | 1. Runs build configurators (if present) 21 | 1. Builds your app (using MSBuild) to a temporary folder 22 | 1. Generates a ClickTwice manifest in the output location 23 | 1. Runs output handlers on the published app 24 | 1. Copies the publish files to the target destination 25 | 26 | Much of the power of ClickTwice is in it's flexible design. Publishing can invoke every step of this process or only a few, and each step is pluggable and extensible so you can tailor your build code to match your workflow. 27 | 28 | ## How to use 29 | 30 | ClickTwice is usually run by a *"host"*, a context to help control and configure ClickTwice itself. Out-of-the-box, the easiest way to get started is by using the Cake or ScriptCs host. Alternatively, you can self-host the toolchain to get more fine-tuned control over the build. Plus, since it's all just .NET, you can integrate the toolchain directly into your own applications. -------------------------------------------------------------------------------- /docfx/doc/logging.md: -------------------------------------------------------------------------------- 1 | # Logging 2 | 3 | ClickTwice includes its own built-in logging subsystem, based on the `IPublishLogger` interface. This simplified interface allows for logging just two types of messages: normal logging, and build messages. Due to the verbosity that build logs often include, build messages are generally disabled by default. 4 | 5 | Logging is implemented in the host, and is used to log the output of all handlers, the build itself and all the parts of a publish operation. Individual hosts may therefore ship their own loggers. 6 | 7 | There are only two loggers shipped in the main library at this time: 8 | 9 | - `ConsoleLogger` - Basic logger to write non-build messages to the system console 10 | - `FileLogger` - Writes log messages to file, and publishes the file in the publish directory (under "Logs") 11 | 12 | ## Building a logger 13 | 14 | Building a custom logger is very simple. Just create a new class and implement the `IPublishLogger` interface, which is just: 15 | 16 | ```csharp 17 | void Log(string content); 18 | bool IncludeBuildMessages { get; } 19 | string Close(string outputPath); 20 | ``` 21 | 22 | `IncludeBuildMessages` controls whether the logger should be given full build logs or not, while the `Close` method is called at the end of the publish operation for any cleanup operations (writing to file etc). You can return null or throw a new `NotImplementedException` if your logger has no clean up to do. -------------------------------------------------------------------------------- /docfx/doc/manifests.md: -------------------------------------------------------------------------------- 1 | # Manifests 2 | 3 | Application manifests describe important metadata about your published application. 4 | 5 | In ClickTwice, there are two kinds of manifests generated as part of a "standard" publish: the ClickOnce manifest and the ClickTwice manifest. 6 | 7 | ClickOnce manifests are special `.application` files that Windows (and Internet Explorer) know how to handle in order to launch a deployed application. These XML doucments are full of data, including your app's metadata, information on digital signatures and keys in the application, deployment and framework information. 8 | 9 | The ClickTwice manifest is a simplified JSON document (`*.cltw`) with only the relevant application metadata used in building, publishing and distributing your application. You can find the full (C#) schema for this format [here](/api/ClickTwice.Publisher.Core.Manifests.AppManifest.html). This file is used internally by ClickTwice and some of the built-in handlers for more detailed app metadata. Note that this file is wholly independent of the ClickOnce `.application` manifest, which is still present in the output. 10 | 11 | #### `app.info` 12 | 13 | > Please note that the `app.info` file will be merged into the ClickTwice manifest (as `AppInfo`) in a future update. 14 | 15 | The `app.info` file is a separate metadata file that contains generic user-friendly messages, such as a summary of the app's functionality, contact and support information and author details. This information is mostly of use to post-deployment tools, such as page generators, forms and scripts. This file is wholly optional and is currently provided by the `AppInfoHandler`. -------------------------------------------------------------------------------- /docfx/doc/scriptcsintro.md: -------------------------------------------------------------------------------- 1 | # ScriptCs publish host 2 | 3 | > Publish ClickOnce apps from C# scripts the easy way. 4 | 5 | The ClickTwice host for ScriptCs is distributed as a script pack, exposing a dead-simple API for publishing your app. 6 | 7 | ## Installation 8 | 9 | First, install the script pack using the command below 10 | 11 | ```powershell 12 | scriptcs -Install ScriptCs.ClickTwice 13 | 14 | # or to use the latest development release 15 | scriptcs -Pre -Install ScriptCs.ClickTwice 16 | ``` 17 | 18 | The NuGet prerelease packages are automatically built and deployed from the `develop` branch so they can be considered bleeding-edge while the non-prerelease packages will be much more stable. 19 | 20 | > [!NOTE] 21 | > The `ScriptCs.ClickTwice` uses NuGet dependencies to bring in some third-party libraries. Check the package details if you are worried about this. 22 | 23 | ## Usage 24 | 25 | First, you'll need to import the script pack using the `Require` method, then to publish your app, just use the `PublishApp` method, as per below: 26 | 27 | ```csharp 28 | var pack = Require(); 29 | pack.PublishApp(yourProjectPathHere).To("./artifacts/publish/"); 30 | ``` 31 | 32 | That's it! Now that is just a plain MSBuild build and publish, with no additional features. If you want to add handlers, you will need to configure your settings object. You can do this by preparing an `Action` and pass it directly into your `PublishApp` method, or use the `Configure` method 33 | 34 | ```csharp 35 | pack.Configure(s => s.WithHandler(new AppInfoHandler()).WithLogger(new FileLogger())); 36 | pack.PublishApp(yourProjectPathHere).To("./artifacts/publish"); 37 | ``` 38 | 39 | And there's even more options available from the [`ClickTwicePackSettings`](/api/ScriptCs.ClickTwice.ClickTwicePackSettings.html) to explore. For example, the following also works: 40 | 41 | ```csharp 42 | pack.Configure(s => 43 | s.SetConfiguration("Debug") 44 | .UseIntegratedMsBuild() 45 | .SetPlatform("AnyCPU") 46 | .EnableBuildMessages() 47 | .WithHandler(new AppInfoHandler()) 48 | .WithLogger(new FileLogger()) 49 | ); 50 | pack.PublishApp(yourProjectPathHere).To("./artifacts/publish/"); 51 | ``` 52 | 53 | Plus, since ScriptCs scripts can run any C# code, you can now supercharge your build script with anything you can do with C#! 54 | 55 | ## C# 6 support 56 | 57 | Note that due to an incompatibility between the internal builder that ships with ClickTwice and the way that ScriptCs loads assemblies, we can only build WPF applications using C# 6 features, by using a system-local copy of MSBuild (i.e. 'shelling out'). 58 | 59 | If you don't have MSBuild installed in your build environment, and don't need C# 6 features, you can build using a special bundled-in MSBuild instance by adding `UseIntegratedMsBuild()` to your configuration. 60 | 61 | ```csharp 62 | pack.Configure(s => s.UseIntegratedMsBuild()); 63 | pack.PublishApp(yourProjectPathHere).To("./artifacts/publish/"); 64 | ``` 65 | 66 | ```csharp 67 | // alternate short form 68 | pack.PublishApp(yourProjectPathHere, s => s.UseIntegratedMsBuild()).To("./artifacts/publish/"); 69 | ``` 70 | 71 | Using this, you don't even need MSBuild installed to build your app! -------------------------------------------------------------------------------- /docfx/doc/templating.md: -------------------------------------------------------------------------------- 1 | # ClickTwice page templates 2 | 3 | ## The model object 4 | 5 | The ClickTwice Core library includes a simple model class called the `LaunchPageModel`, with a basic structure as below 6 | 7 | ```csharp 8 | public class LaunchPageModel { 9 | // trimmed 10 | public AppManifest Manifest { get; set; } 11 | public ExtendedAppInfo AppInfo { get; set; } 12 | public string ContentDirectory { get; set; } 13 | public string Launcher { get; set; } 14 | public string Installer { get; set; } 15 | } 16 | ``` 17 | 18 | Now this model is never directly used by the core but can instead be consumed by handlers for generating practically anything. Out of the box, the powerful `AppDetailsPageHandler` uses this model to generate fast and simple app pages (perfect for intranets or GitHub Pages!), but you can use the same basic model for almost anything. 19 | 20 | ## Creating app details templates 21 | 22 | The `AppDetailsPageHandler` included with most ClickTwice packages is powered by Razor and NuGet, the same tools you use to build pages every day! That means that you can point it any NuGet package containing `.cshtml` files to quickly generate whole websites at a time. You can find more details on the `AppDetailsPageHandler` in it's [own documentation](/doc/appdetailspage.html). 23 | 24 | A ClickTwice template package is dead simple to create. All you need is a Razor view file (`.cshtml` extension) that can take a `LaunchPageModel` object as it's model and you're ready to go. To make it easier, ClickTwice ships with template packaging and publishing built-in, so you don't even need to switch tools! 25 | 26 | For Cake: 27 | ```csharp 28 | Task("Template-Publishing") 29 | .Does(() => { 30 | ClickTwice.PublishTemplate("./path/to/template/dir/", s => 31 | s.AddAuthor("Alistair Chapman") 32 | .UsePackageId("TemplatePackage") 33 | .UseVersion("0.0.1") 34 | .UseDescription("Optional description")) 35 | .ToPackageFile("artifacts/publish.nupkg") 36 | .ToGallery(galleryUri: "http://nuget.org/api/v2"); 37 | }); 38 | ``` 39 | 40 | or for ScriptCs: 41 | 42 | ```csharp 43 | PublishTemplate("C:/path/to/template/directory") 44 | .SetMetadata("Package.Id", "0.0.1", "Author Name") 45 | .ToPackageFile("artifacts/publish.nupkg") 46 | .ToGallery(galleryUri: "http://nuget.org/api/v2"); 47 | ``` 48 | 49 | Then you can consume your new template in the `AppDetailsPageHandler`: 50 | 51 | ```csharp 52 | //for Cake 53 | PublishApp(projectPath) 54 | .WithHandler(new AppDetailsPageHandler("TemplatePackage")) // your package ID here 55 | .PublishTo("./artifacts/publish/"); 56 | ``` 57 | 58 | ```csharp 59 | // for scriptcs 60 | pack.Configure(s => s.WithHandler(new AppDetailsPageHandler("TemplatePackage"))); 61 | pack.PublishApp(projectPath).To("./artifacts/publish"); 62 | ``` 63 | -------------------------------------------------------------------------------- /docfx/doc/toc.yml: -------------------------------------------------------------------------------- 1 | - name: Introduction 2 | href: intro.md 3 | - name: Fundamentals 4 | items: 5 | - name: Handlers 6 | href: handlers.md 7 | - name: Manifests 8 | href: manifests.md 9 | - name: Logging 10 | href: logging.md 11 | - name: Built-In Types 12 | href: builtins.md 13 | - name: Hosts 14 | items: 15 | - name: Cake 16 | href: cakeintro.md 17 | - name: ScriptCs 18 | href: scriptcsintro.md 19 | - name: App Details Page 20 | items: 21 | - name: Details Page handler 22 | href: appdetailspage.md 23 | - name: Templating 24 | href: templating.md 25 | - name: Update Manager 26 | href: updatemgr.md -------------------------------------------------------------------------------- /docfx/doc/updatemgr.md: -------------------------------------------------------------------------------- 1 | # ClickTwice Update Manager 2 | 3 | ## Introduction 4 | 5 | The ClickTwice Update Manager is a standalone library for use in WPF applications to more easily integrate with your ClickOnce deployment environment. It's fully compatible with any ClickOnce network deployment, even if you're not using the rest of the ClickTwice toolchain. 6 | 7 | You can install the update manager using the following command: 8 | 9 | > `Install-Package ClickTwice.UpdateManager` 10 | 11 | This will install the library into your application. The Update Manager is wholly self-contained in a special `UpdateManagerViewModel` class, that you can either use as a `DataContext` directly, inherit from, or use as a property in your existing view models. A short summary of the functions available from the view model is below. 12 | 13 | ## Message Properties 14 | 15 | These are simple `string` properties, perfect for binding to a `TextBlock`, providing key pieces of information: 16 | 17 | - `ApplicationInfoMessage` - returns a simple summary of current application version and build date 18 | - `DeploymentInfoMessage` - returns a summary of the current deployment version and source 19 | - `UpdateCheckStatusMessage` - returns a message for the current update status 20 | - `UpdateProgressMessage` - returns a message on the progress of any ongoing update operations 21 | - `UpdateProgress` - (`int`) returns the progress of any current update operations 22 | 23 | ## Toggle Properties 24 | 25 | These are simple `boolean` properties, handy for toggling visibility of messages and buttons 26 | 27 | - `IsDeployed` - `true` if the current application is ClickOnce-deployed 28 | - `IsUpdateAvailable` - `true` if there is an update available 29 | - `IsUpdateInProgress` - `true` if there is an update operation currently in progress 30 | 31 | 32 | ## Events and commands 33 | 34 | You can also use these events and commands to control updates from within your application 35 | 36 | - `OnUpdateStarting` - `event` fires when an update operation is started 37 | - `OnUpdateComplete` - `event` fires to indicate a completed update operation 38 | - `UpdateApplicationCommand` - `ICommand` for invoking a update operation on-demand 39 | - `CheckUpdatesCommand` - `ICommand` to check for available updates from the deployment source 40 | 41 | ## Full API Reference 42 | 43 | Click API reference above to check the [full API](/api/ClickTwice.UpdateManager.UpdateManagerViewModel.html) for `UpdateManagerViewModel` and take back control of your ClickOnce updates the easy way! -------------------------------------------------------------------------------- /docfx/docfx.json: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": [ 3 | { 4 | "src": [ 5 | { 6 | "files": [ 7 | "src/**.csproj" 8 | ], 9 | "exclude": [ 10 | "**/obj/**", 11 | "**/bin/**", 12 | "docfx/**", 13 | "**/ClickTwice.Templates.*/**", 14 | "**/*.Tests/**" 15 | ], 16 | "cwd": "../" 17 | } 18 | ], 19 | "dest": "api" 20 | } 21 | ], 22 | "build": { 23 | "content": [ 24 | { 25 | "files": [ 26 | "api/**.yml", 27 | "api/index.md" 28 | ] 29 | }, 30 | { 31 | "files": [ 32 | "doc/**.md", 33 | "doc/**/toc.yml" 34 | ], 35 | "exclude": [ 36 | "obj/**", 37 | "_site/**" 38 | ] 39 | }, 40 | { 41 | "files": [ 42 | "toc.yml", 43 | "*.md" 44 | ], 45 | "exclude": [ 46 | "obj/**", 47 | "_site/**" 48 | ] 49 | } 50 | ], 51 | "resource": [ 52 | { 53 | "files": [ 54 | "assets/**" 55 | ], 56 | "exclude": [ 57 | "obj/**", 58 | "_site/**" 59 | ] 60 | } 61 | ], 62 | "overwrite": [ 63 | { 64 | "files": [ 65 | "apidoc/**.md" 66 | ], 67 | "exclude": [ 68 | "obj/**", 69 | "_site/**" 70 | ] 71 | } 72 | ], 73 | "dest": "_site", 74 | "template": [ 75 | "statictoc" 76 | ], 77 | "globalMetadata": { 78 | "_appTitle": "ClickTwice", 79 | "_appFooter": "Copyright © 2017 Alistair Chapman", 80 | "_appLogoPath": "assets/appLogo.png" 81 | }, 82 | "noLangKeyword": false 83 | } 84 | } -------------------------------------------------------------------------------- /docfx/index.md: -------------------------------------------------------------------------------- 1 | # ClickTwice 2 | # The ultimate WPF build toolchain 3 | 4 | ## Introduction 5 | 6 | As the name implies, ClickTwice is the missing step from the ClickOnce deployment technology. ClickTwice allows you to decouple your build and deploy steps from Visual Studio, instead integrating them with your preferred build environment. Currently, three environments are supported: 7 | 8 | - Cake build scripts 9 | - ScriptCs scripts 10 | - Self-hosting (custom tool) 11 | 12 | ClickTwice doesn't just build and publish your app: it also provides a powerful framework for pre- and post-processing your application at publish-time, allowing for a wide range of new abilities as pluggable handlers. 13 | 14 | ## Getting Started 15 | 16 | ClickTwice is usually run by a *"host"*, a context to help control and configure ClickTwice itself. Out-of-the-box, the easiest way to get started is by using the Cake or ScriptCs host. Alternatively, you can self-host the toolchain to get more fine-tuned control over the build. Plus, since it's all just .NET, you can integrate the toolchain directly into your own applications. -------------------------------------------------------------------------------- /docfx/samples/AutoPublish.ps1: -------------------------------------------------------------------------------- 1 | # 2 | # AutoPublish.ps1 3 | # 4 | Param ( 5 | [string]$ProjectFilePath, 6 | [string]$Configuration, 7 | [string]$DeployPath 8 | ) 9 | Write-Host "ClickTwice Publisher - Script Publish Tool" 10 | 11 | $outputPrefix = " " 12 | 13 | function GetProgramFilesPath() { 14 | $os_type = (Get-WmiObject -Class Win32_ComputerSystem).SystemType -match '(x64)' 15 | If (-not ${env:ProgramFiles(x86)}) { 16 | $programFilesPath = $env:ProgramFiles 17 | } Else { 18 | $programFilesPath = ${env:ProgramFiles(x86)} 19 | } 20 | return $programFilesPath 21 | } 22 | 23 | function CheckMSBuildPath () 24 | { 25 | $path = GetProgramFilesPath 26 | If (-not $env:msbuild) { 27 | if (Test-Path "$path\MSBuild\14.0") { 28 | $msbuild = "$path\MSBuild\14.0\Bin\MSBuild.exe" 29 | } else { 30 | if (Test-Path "$path\MSBuild\12.0") { 31 | $msbuild = "$path\MSBuild\12.0\Bin\MSBuild.exe" 32 | } else { 33 | $msbuild = "C:\Windows\Microsoft.NET\Framework\v4.0.30319\msbuild.EXE" 34 | } 35 | } 36 | } Else { 37 | $msbuild = $env:msbuild 38 | } 39 | return $msbuild 40 | } 41 | 42 | function GetProjectDirectory ($projectFile) 43 | { 44 | return Get-ChildItem $ProjectFilePath | % {$_.DirectoryName} 45 | } 46 | 47 | function GetApplicationName() { 48 | [string]$projectName = Get-ChildItem $ProjectFilePath | % {$_.BaseName} 49 | return $projectName 50 | } 51 | $msbuild = CheckMSBuildPath 52 | Write-Host "Using MSBuild from $msbuild" 53 | Write-Host $outputPrefix"Cleaning the build directory..." 54 | Invoke-Expression "& '$msbuild' $ProjectFilePath /p:Configuration=$Configuration /p:Platform=AnyCPU /t:clean /v:quiet /nologo" 55 | 56 | Write-Host $outputPrefix"Building Executable application..." 57 | Invoke-Expression "& '$msbuild' $ProjectFilePath /p:Configuration=$Configuration /p:Platform=AnyCPU /t:build /v:quiet /nologo" 58 | $projectDir = GetProjectDirectory($ProjectFilePath) 59 | $appName = GetApplicationName 60 | $newExeVersion = Get-ChildItem $projectDir\bin\$Configuration\$appName.exe | Select-Object -ExpandProperty VersionInfo | % { $_.FileVersion } 61 | 62 | Write-Host $outputPrefix"Building ClickOnce installer..." 63 | # 64 | # Because the ClickOnce target doesn't automatically update or sync the application version 65 | # with the assembly version of the EXE, we need to grab the version off of the built assembly 66 | # and update the Executable.csproj file with the new application version. 67 | # 68 | $ProjectXml = [xml](Get-Content $ProjectFilePath) 69 | $ns = new-object Xml.XmlNamespaceManager $ProjectXml.NameTable 70 | $ns.AddNamespace('msb', 'http://schemas.microsoft.com/developer/msbuild/2003') 71 | $AppVersion = $ProjectXml.SelectSingleNode("//msb:Project/msb:PropertyGroup/msb:ApplicationVersion", $ns) 72 | $AppVersion.InnerText = $newExeVersion 73 | $TargetPath = Resolve-Path $ProjectFilePath 74 | $ProjectXml.Save($TargetPath) 75 | 76 | Invoke-Expression "& '$msbuild' $ProjectFilePath /p:Configuration=$Configuration /p:Platform=AnyCPU /t:publish /v:quiet /nologo" 77 | 78 | Write-Host $outputPrefix"Deploying application files to target..." 79 | $LocalInstallerPath = (Resolve-Path "$projectDir\bin\$Configuration\app.publish").ToString() + "\*" 80 | Copy-Item $LocalInstallerPath $DeployPath -Recurse -Force 81 | -------------------------------------------------------------------------------- /docfx/toc.yml: -------------------------------------------------------------------------------- 1 | 2 | - name: Documentation 3 | href: doc/ 4 | homepage: doc/intro.md 5 | - name: API Reference 6 | href: api/ 7 | homepage: api/index.md 8 | -------------------------------------------------------------------------------- /extensions.cake: -------------------------------------------------------------------------------- 1 | public void AddIfNotExists(List list, FilePath file) { 2 | if (list.Any(f => f.FullPath.EndsWith(file.GetFilename().ToString()))) return; 3 | list.Add(file); 4 | } 5 | 6 | public void AddIfNotExists(List list, IEnumerable files) { 7 | foreach (var file in files) { 8 | AddIfNotExists(list, file); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Cake.ClickTwice.Tests/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/Cake.ClickTwice.Tests/ClickTwiceFixture.cs: -------------------------------------------------------------------------------- 1 | using Cake.Core; 2 | using Cake.Core.Diagnostics; 3 | using Cake.Core.IO; 4 | using Cake.Core.Tooling; 5 | using Cake.Testing; 6 | using ClickTwice.Publisher.Core.Loggers; 7 | using Xunit.Abstractions; 8 | 9 | namespace Cake.ClickTwice.Tests 10 | { 11 | public class ClickTwiceFixture 12 | { 13 | public ClickTwiceFixture(ITestOutputHelper output) 14 | { 15 | var environment = FakeEnvironment.CreateWindowsEnvironment(); 16 | Environment = environment; 17 | var fileSystem = new FakeFileSystem(environment); 18 | fileSystem.CreateDirectory("./artifacts"); 19 | //fileSystem.CreateFile(PackageFilePath.FullPath).SetContent(SamplePackageJson); 20 | FileSystem = fileSystem; 21 | Logger = new UnitTestLogger(output); 22 | } 23 | 24 | public IFileSystem FileSystem { get; set; } 25 | 26 | public ICakeEnvironment Environment { get; set; } 27 | private ICakeLog Log { get; set; } = new FakeLog(); 28 | private IPublishLogger Logger { get; } 29 | 30 | public ClickTwiceManager Run(FilePath projectFile) 31 | { 32 | var manager = new ClickTwiceManager(projectFile.FullPath, Log, Environment, FileSystem, 33 | new ProcessRunner(Environment, Log), new ToolLocator(Environment, new ToolRepository(Environment), new ToolResolutionStrategy(FileSystem, Environment, new Globber(FileSystem, Environment), new FakeConfiguration()))); 34 | manager.LogTo(Logger); 35 | return manager; 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/Cake.ClickTwice.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("Cake.ClickTwice.Tests")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("Cake.ClickTwice.Tests")] 12 | [assembly: AssemblyCopyright("Copyright © 2016")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("ea73b387-5f21-417b-9c73-b7aa51ea82e6")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /src/Cake.ClickTwice.Tests/UnitTest1.cs: -------------------------------------------------------------------------------- 1 | using ClickTwice.Publisher.Core; 2 | using ClickTwice.Publisher.Core.Handlers; 3 | using Xunit; 4 | using Xunit.Abstractions; 5 | 6 | namespace Cake.ClickTwice.Tests 7 | { 8 | public class AliasTests 9 | { 10 | public AliasTests(ITestOutputHelper helper) 11 | { 12 | Output = helper; 13 | } 14 | 15 | private ITestOutputHelper Output { get; set; } 16 | 17 | [Fact] 18 | public void CakeAliasTest() 19 | { 20 | var fixture = new ClickTwiceFixture(Output); 21 | var mgr = 22 | fixture.Run( 23 | @"C:\Users\alist\Source\ACN\myTaxFramework\FormDocuments\DocumentConversion\DocumentConversion.csproj"); 24 | mgr.BuildAction = manager => 25 | { 26 | foreach (var logger in manager.Loggers) 27 | { 28 | logger.Log("Building project..."); 29 | } 30 | }; 31 | mgr.SetConfiguration("Debug") 32 | .ThrowOnHandlerFailure() 33 | .ForceRebuild() 34 | .WithHandler(new AppInfoHandler(new AppInfoManager())) 35 | .PublishTo(fixture.FileSystem.GetDirectory("./artifacts").Path); 36 | 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Cake.ClickTwice.Tests/UnitTestLogger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using ClickTwice.Publisher.Core.Loggers; 3 | using Xunit.Abstractions; 4 | 5 | namespace Cake.ClickTwice.Tests 6 | { 7 | public class UnitTestLogger : IPublishLogger 8 | { 9 | public UnitTestLogger(ITestOutputHelper helper) 10 | { 11 | Logger = helper; 12 | IncludeBuildMessages = true; 13 | } 14 | 15 | private ITestOutputHelper Logger { get; set; } 16 | 17 | public void Log(string content) 18 | { 19 | Logger.WriteLine(content); 20 | } 21 | 22 | public bool IncludeBuildMessages { get; set; } 23 | public string Close(string outputPath) 24 | { 25 | throw new NotImplementedException(); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/Cake.ClickTwice.Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/Cake.ClickTwice/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/Cake.ClickTwice/Cake.ClickTwice.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Cake.ClickTwice 5 | ClickTwice Publisher for Cake 6 | Alistair Chapman 7 | achapman 8 | https://opensource.org/licenses/MIT 9 | https://github.com/agc93/clicktwice 10 | https://maxcdn.icons8.com/Color/PNG/96/Industry/engineering-96.png 11 | false 12 | Cake host for ClickTwice publishing, including the addin and all required libraries 13 | Copyright 2016 14 | clicktwice publish clickonce wpf msbuild cake build 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/Cake.ClickTwice/CakeLogger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Cake.Core.Diagnostics; 3 | using ClickTwice.Publisher.Core.Loggers; 4 | 5 | namespace Cake.ClickTwice 6 | { 7 | /// 8 | /// ClickTwice logger for writing messages to the Cake log 9 | /// 10 | public class CakeLogger : IPublishLogger 11 | { 12 | public CakeLogger(ICakeLog log) 13 | { 14 | CakeLog = log; 15 | } 16 | 17 | private ICakeLog CakeLog { get; set; } 18 | 19 | public void Log(string content) 20 | { 21 | CakeLog.Information(content); 22 | } 23 | 24 | public bool IncludeBuildMessages => false; 25 | 26 | public string Close(string outputPath) 27 | { 28 | throw new NotImplementedException(); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /src/Cake.ClickTwice/CakePublishExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Cake.Common.Tools.MSBuild; 5 | using ClickTwice.Publisher.Core; 6 | 7 | namespace Cake.ClickTwice 8 | { 9 | internal static class CakePublishExtensions 10 | { 11 | internal static void AddTargets(this MSBuildSettings settings, PublishBehaviour behaviour) 12 | { 13 | foreach (var target in GetTargets(behaviour)) 14 | { 15 | settings.WithTarget(target); 16 | } 17 | } 18 | 19 | private static List GetTargets(PublishBehaviour behaviour) 20 | { 21 | var targets = new List {"PrepareForBuild"}; 22 | switch (behaviour) 23 | { 24 | case PublishBehaviour.None: 25 | targets.Add("Build", "Publish"); 26 | break; 27 | case PublishBehaviour.CleanFirst: 28 | targets.Add("Clean", "Build", "Publish"); 29 | break; 30 | case PublishBehaviour.DoNotBuild: 31 | targets.Add("Publish"); 32 | break; 33 | default: 34 | throw new ArgumentOutOfRangeException(nameof(behaviour), behaviour, null); 35 | } 36 | return targets; 37 | } 38 | 39 | internal static void AddProperties(this MSBuildSettings settings, params Dictionary[] dicts) 40 | { 41 | var props = dicts.First(); 42 | foreach (var dict in dicts.Skip(1)) 43 | { 44 | props = props.Concat(dict.Where(p => !props.ContainsKey(p.Key))) 45 | .ToDictionary(k => k.Key, v => v.Value); 46 | } 47 | foreach (var prop in props) 48 | { 49 | settings.WithProperty(prop.Key, prop.Value); 50 | } 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /src/Cake.ClickTwice/CakeTemplatePublisher.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using ClickTwice.Templating; 7 | 8 | namespace Cake.ClickTwice 9 | { 10 | public class CakeTemplatePublisher : ITemplatePublisher 11 | { 12 | public CakeTemplatePublisher(string templateDirectory, TemplatePackageSettings settings) 13 | { 14 | Metadata = settings; 15 | Packager = new TemplatePackager(settings); 16 | TemplateDirectory = templateDirectory; 17 | } 18 | 19 | private string TemplateDirectory { get; set; } 20 | 21 | private TemplatePackager Packager { get; set; } 22 | 23 | public TemplatePackageSettings Metadata { get; } 24 | public PackagingMode PackagingMode { get; } = PackagingMode.Minimal; 25 | public ITemplatePublisher ToPackageFile(string outputPath) 26 | { 27 | var mgr = new TemplatePackager(Metadata); 28 | var fi = mgr.Package(TemplateDirectory, PackagingMode); 29 | fi.CopyTo(outputPath); 30 | return this; 31 | } 32 | 33 | public ITemplatePublisher ToGallery(string apiKey = null, string galleryUri = null) 34 | { 35 | var mgr = new TemplatePackager(Metadata) 36 | { 37 | PublishDestination = new Uri(galleryUri ?? "https://nuget.org/api/v2") 38 | }; 39 | if (apiKey == null) 40 | { 41 | mgr.PublishPackage(mgr.Package(TemplateDirectory, PackagingMode).FullName); 42 | } 43 | else 44 | { 45 | mgr.PublishPackage(mgr.Package(TemplateDirectory, PackagingMode).FullName, apiKey); 46 | } 47 | return this; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Cake.ClickTwice/ClickTwiceManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Cake.Core; 5 | using Cake.Core.Diagnostics; 6 | using Cake.Core.IO; 7 | using Cake.Core.Tooling; 8 | using ClickTwice.Publisher.Core; 9 | using ClickTwice.Publisher.Core.Handlers; 10 | using ClickTwice.Publisher.Core.Loggers; 11 | 12 | namespace Cake.ClickTwice 13 | { 14 | /// 15 | /// Manager for publishing ClickOnce applications from Cake scripts 16 | /// 17 | public class ClickTwiceManager 18 | { 19 | internal ClickTwiceManager(FilePath projectFile, ICakeLog log, ICakeEnvironment environment, IFileSystem fs, 20 | IProcessRunner runner, IToolLocator toolLocator) 21 | { 22 | Log = log; 23 | Environment = environment; 24 | FileSystem = fs; 25 | ProcessRunner = runner; 26 | ToolLocator = toolLocator; 27 | ProjectFilePath = projectFile.MakeAbsolute(Environment).FullPath; 28 | } 29 | 30 | internal ICakeEnvironment Environment { get; set; } 31 | 32 | private ICakeLog Log { get; set; } 33 | internal IFileSystem FileSystem { get; set; } 34 | internal IProcessRunner ProcessRunner { get; set; } 35 | 36 | internal string ProjectFilePath { get; set; } 37 | 38 | internal string Platform { get; set; } = "AnyCPU"; 39 | internal string Configuration { get; set; } = "Release"; 40 | 41 | internal List InputHandlers { get; set; } = new List(); 42 | internal List OutputHandlers { get; set; } = new List(); 43 | internal List Loggers { get; set; } = new List(); 44 | internal bool CleanOutput { get; set; } 45 | internal bool ForceBuild { get; set; } = true; 46 | 47 | internal string PublishVersion { get; set; } 48 | 49 | internal Action BuildAction { get; set; } 50 | 51 | private bool AppInfoSupported 52 | => 53 | InputHandlers.Any( 54 | h => h.GetType() == typeof(AppInfoHandler)); 55 | 56 | internal IToolLocator ToolLocator { get; set; } 57 | 58 | /// 59 | /// Publishes the app to the given directory using the current settings 60 | /// 61 | /// Output path for the final published artifacts 62 | public void PublishTo(DirectoryPath outputDirectory) 63 | { 64 | OutputHandlers.Add(new PublishPageHandler()); 65 | Loggers.Add(new CakeLogger(Log)); 66 | var mgr = new CakePublishManager(this); 67 | var responses = mgr.PublishApp(outputDirectory.MakeAbsolute(Environment).FullPath, 68 | ForceBuild ? PublishBehaviour.CleanFirst : PublishBehaviour.DoNotBuild); 69 | foreach (var r in responses) 70 | { 71 | Log.Information($"Handler finished: {r.Result} - {r.ResultMessage}"); 72 | } 73 | } 74 | 75 | /// 76 | /// Publishes the app to the given directory using the current settings 77 | /// 78 | /// Output path for the final published artifacts 79 | /// Convenience method. Equivalent to 80 | public void To(DirectoryPath outputDirectory) 81 | { 82 | PublishTo(outputDirectory); 83 | } 84 | 85 | internal Action> ErrorAction { get; set; } 86 | 87 | /// 88 | /// Generates an app manifest without publishing the whole application 89 | /// 90 | /// Directory to publish to 91 | /// Metadata source to use in generating the manifest 92 | public void GenerateManifest(DirectoryPath publishDirectoryPath, 93 | InformationSource source = InformationSource.Both) 94 | { 95 | var mgr = new ManifestManager(new FilePath(ProjectFilePath).MakeAbsolute(Environment).FullPath, 96 | publishDirectoryPath.MakeAbsolute(Environment).FullPath, 97 | source); 98 | mgr.DeployManifest(mgr.CreateAppManifest()); 99 | } 100 | } 101 | } -------------------------------------------------------------------------------- /src/Cake.ClickTwice/ManifestPublisher.cs: -------------------------------------------------------------------------------- 1 | using Cake.Core.IO; 2 | using ClickTwice.Publisher.Core; 3 | 4 | namespace Cake.ClickTwice 5 | { 6 | /// 7 | /// Convenience class for generating app manifests 8 | /// 9 | public class ManifestPublisher 10 | { 11 | internal ManifestPublisher(ClickTwiceRunner runner, string projectFilePath) 12 | { 13 | Runner = runner; 14 | ProjectFilePath = new FilePath(projectFilePath).MakeAbsolute(Runner.Environment); 15 | } 16 | 17 | private FilePath ProjectFilePath { get; set; } 18 | 19 | private ClickTwiceRunner Runner { get; set; } 20 | 21 | /// 22 | /// Publish the generated manifest at the given path 23 | /// 24 | /// Path to the output file 25 | /// Used to control the sourcing of app metadata 26 | public void Publish(string outputPath, InformationSource source = InformationSource.Both) 27 | { 28 | var mgr = new ManifestManager(ProjectFilePath.FullPath, outputPath, source); 29 | mgr.DeployManifest(mgr.CreateAppManifest()); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/Cake.ClickTwice/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | 9 | [assembly: AssemblyTitle("Cake.ClickTwice")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("")] 13 | [assembly: AssemblyProduct("Cake.ClickTwice")] 14 | [assembly: AssemblyCopyright("Copyright © 2016")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | 18 | // Setting ComVisible to false makes the types in this assembly not visible 19 | // to COM components. If you need to access a type in this assembly from 20 | // COM, set the ComVisible attribute to true on that type. 21 | 22 | [assembly: ComVisible(false)] 23 | [assembly: InternalsVisibleTo("Cake.ClickTwice.Tests")] 24 | 25 | // The following GUID is for the ID of the typelib if this project is exposed to COM 26 | 27 | [assembly: Guid("56941755-0ce6-46e3-ba6f-4450f9c0ae68")] 28 | 29 | // Version information for an assembly consists of the following four values: 30 | // 31 | // Major Version 32 | // Minor Version 33 | // Build Number 34 | // Revision 35 | // 36 | // You can specify all the values or you can default the Build and Revision Numbers 37 | // by using the '*' as shown below: 38 | // [assembly: AssemblyVersion("1.0.*")] 39 | 40 | [assembly: AssemblyVersion("1.0.0.0")] 41 | [assembly: AssemblyFileVersion("1.0.0.0")] 42 | [assembly: InternalsVisibleTo("Cake.ClickTwice.Tests")] -------------------------------------------------------------------------------- /src/Cake.ClickTwice/PublishException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.Serialization; 5 | using ClickTwice.Publisher.Core.Handlers; 6 | 7 | namespace Cake.ClickTwice 8 | { 9 | /// 10 | /// Thrown when an error occurs during publishing 11 | /// 12 | public class PublishException : Exception 13 | { 14 | /// 15 | /// Create a new exception with the given text 16 | /// 17 | /// The message to return to the user 18 | public PublishException(string message) : base(message) 19 | { 20 | } 21 | 22 | /// 23 | /// Create a new exception with the given text and inner exception 24 | /// 25 | /// The message to return to the user 26 | /// The inner exception 27 | public PublishException(string message, Exception innerException) : base(message, innerException) 28 | { 29 | } 30 | 31 | /// 32 | /// Create a new exception with the given text and handler responses 33 | /// 34 | /// The responses from the handlers collection that threw the exception 35 | /// The message to return to the user 36 | public PublishException(IEnumerable responses, string message) : this(message) 37 | { 38 | Errors = responses; 39 | } 40 | 41 | /// 42 | /// Create a new exception with the given handler responses 43 | /// 44 | /// The responses from the handlers collection that threw the exception 45 | public PublishException(IEnumerable responses) 46 | : this(responses, string.Join(Environment.NewLine, responses.Select(r => r.ResultMessage))) 47 | { 48 | } 49 | 50 | /// 51 | /// 52 | /// 53 | /// 54 | /// 55 | protected PublishException(SerializationInfo info, StreamingContext context) : base(info, context) 56 | { 57 | } 58 | 59 | /// 60 | /// Collection of responses from the handlers that threw the exception 61 | /// 62 | public IEnumerable Errors { get; set; } = new List(); 63 | } 64 | } -------------------------------------------------------------------------------- /src/Cake.ClickTwice/Samples.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using ClickTwice.Templating; 7 | 8 | namespace Cake.ClickTwice 9 | { 10 | class Samples 11 | { 12 | public void Sample() 13 | { 14 | var a = new Action(s => 15 | s.AddAuthor("Alistair Chapman") 16 | .UsePackageId("TemplatePackage") 17 | .UseVersion("0.0.1") 18 | .UseDescription("Optional description")); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Cake.ClickTwice/TemplatePackageSettingsExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using ClickTwice.Templating; 7 | 8 | namespace Cake.ClickTwice 9 | { 10 | public static class TemplatePackageSettingsExtensions 11 | { 12 | public static TemplatePackageSettings AddAuthor(this TemplatePackageSettings settings, params string[] authors) 13 | { 14 | settings.Authors.AddRange(authors); 15 | return settings; 16 | } 17 | 18 | public static TemplatePackageSettings UseDescription(this TemplatePackageSettings settings, string description) 19 | { 20 | settings.Description = description; 21 | return settings; 22 | } 23 | 24 | public static TemplatePackageSettings UsePackageId(this TemplatePackageSettings settings, string id) 25 | { 26 | settings.Id = id; 27 | return settings; 28 | } 29 | 30 | public static TemplatePackageSettings UseVersion(this TemplatePackageSettings settings, string version) 31 | { 32 | settings.Version = version; 33 | return settings; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Cake.ClickTwice/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/ClickTwice.Handlers.AppDetailsPage/AppDetailsPageHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using System.Linq; 4 | using ClickTwice.Handlers.AppDetailsPage.Templating; 5 | using ClickTwice.Publisher.Core; 6 | using ClickTwice.Publisher.Core.Handlers; 7 | using ClickTwice.Publisher.Core.Manifests; 8 | 9 | namespace ClickTwice.Handlers.AppDetailsPage 10 | { 11 | public class AppDetailsPageHandler : IOutputHandler 12 | { 13 | 14 | public AppDetailsPageHandler(string templateName, string source = "http://nuget.org/api/v2") : this(new PackageEngine(templateName, source)) 15 | { 16 | } 17 | 18 | public AppDetailsPageHandler(FileInfo localPackage) : this(new PackageEngine(localPackage)) 19 | { 20 | } 21 | 22 | private AppDetailsPageHandler(PackageEngine engine) { 23 | var extractPackage = engine.ExtractPackage(); 24 | TemplateDirectory = extractPackage; 25 | Engine = new TemplateEngine(TemplateDirectory); 26 | } 27 | 28 | private TemplateEngine Engine { get; set; } 29 | 30 | private DirectoryInfo TemplateDirectory { get; set; } 31 | 32 | public string Name => "App Details Page generator"; 33 | public HandlerResponse Process(string outputPath) 34 | { 35 | var di = new DirectoryInfo(outputPath); 36 | if (!di.Exists) throw new DirectoryNotFoundException("Invalid output path!"); 37 | var files = di.GetFiles(); 38 | var manifestPresent = files.Any(f => f.Extension == ".cltw"); 39 | var infoPresent = files.Any(f => f.Name == "app.info"); 40 | if (!(manifestPresent && infoPresent)) 41 | { 42 | return new HandlerResponse(this, false, "This handler requires both a deployment manifest (cltw file) and an info file (app.info)! Try adding AppInfoHandler to your OutputHandlers and ensure you have set an InformationSource to generate a manifest."); 43 | } 44 | Manifest = ManifestManager.ReadFromFile(GetManifest(outputPath).FullName); 45 | AppInfo = AppInfoManager.ReadFromFile(GetInfoFile(outputPath).FullName); 46 | Engine.Manifest = Manifest; 47 | Engine.AppInfo = AppInfo; 48 | var contentDirectory = Engine.CreateContentDirectory(new DirectoryInfo(outputPath)); 49 | contentDirectory.Copy(outputPath, copySubDirs: true); 50 | if (FileNameMap.Any()) 51 | { 52 | var outFiles = new DirectoryInfo(outputPath).GetFiles(); 53 | foreach (var file in FileNameMap) 54 | { 55 | var target = outFiles.FirstOrDefault(f => f.Name == file.Key); 56 | target?.Rename(file.Value); 57 | } 58 | } 59 | Engine.Dispose(); 60 | return new HandlerResponse(this, true); 61 | } 62 | 63 | private ExtendedAppInfo AppInfo { get; set; } 64 | 65 | private AppManifest CreateManifest(string deployDir) 66 | { 67 | var mgr = new ManifestManager(string.Empty, deployDir, InformationSource.AppManifest); 68 | var appManifest = mgr.CreateAppManifest(); 69 | return appManifest; 70 | } 71 | 72 | private FileInfo GetManifest(string outputPath) 73 | { 74 | return new DirectoryInfo(outputPath).GetFiles("*.cltw").FirstOrDefault(); 75 | } 76 | 77 | private FileInfo GetInfoFile(string outputPath) 78 | { 79 | return new DirectoryInfo(outputPath).GetFiles("app.info").FirstOrDefault(); 80 | } 81 | 82 | internal AppManifest Manifest { get; set; } 83 | 84 | public Dictionary FileNameMap { get; set; } = new Dictionary(); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/ClickTwice.Handlers.AppDetailsPage/ClickTwice.Handlers.AppDetailsPage.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {0D7CFAB8-AB4B-4DD7-8B74-96BBCB81F48F} 8 | Library 9 | Properties 10 | ClickTwice.Handlers.AppDetailsPage 11 | ClickTwice.Handlers.AppDetailsPage 12 | v4.5.2 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | ..\packages\Microsoft.Web.Xdt.2.1.1\lib\net40\Microsoft.Web.XmlTransform.dll 35 | True 36 | 37 | 38 | ..\packages\NuGet.Core.2.14.0\lib\net40-Client\NuGet.Core.dll 39 | 40 | 41 | ..\packages\RazorEngine.3.9.3\lib\net45\RazorEngine.dll 42 | 43 | 44 | 45 | 46 | 47 | ..\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll 48 | True 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | {af189adc-d4a9-4a30-aa12-d5cfd96523be} 61 | ClickTwice.Publisher.Core 62 | 63 | 64 | 65 | 66 | 67 | 68 | 75 | -------------------------------------------------------------------------------- /src/ClickTwice.Handlers.AppDetailsPage/PackageEngine.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using NuGet; 3 | 4 | namespace ClickTwice.Handlers.AppDetailsPage 5 | { 6 | class PackageEngine 7 | { 8 | private DefaultPackagePathResolver Resolver { get; set; } 9 | 10 | private PackageEngine() 11 | { 12 | Resolver = new DefaultPackagePathResolver(Path.Combine(Path.GetTempPath(), "TemplatePackages")); 13 | FileSystem = new PhysicalFileSystem(Path.Combine(Path.GetTempPath(), "Templates")); 14 | } 15 | internal PackageEngine(string packageId, string repoSource) : this() 16 | { 17 | Repository = PackageRepositoryFactory.Default.CreateRepository(repoSource); 18 | Manager = new PackageManager(Repository, Resolver, FileSystem); 19 | Package = Repository.FindPackage(packageId, new VersionSpec() {MinVersion = new SemanticVersion(0, 0, 0, 0)}, 20 | true, true); 21 | } 22 | 23 | internal PackageEngine(FileInfo localPackage) : this() 24 | { 25 | var dir = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), "LocalTemplates")); 26 | localPackage.CopyTo(Path.Combine(dir.FullName, localPackage.Name), true); 27 | Repository = new LocalPackageRepository(dir.FullName, true); 28 | Manager = new PackageManager(Repository, Resolver, FileSystem); 29 | Package = Repository.FindPackage(localPackage.Name.Replace(localPackage.Extension, string.Empty), new VersionSpec() {MinVersion = new SemanticVersion(0, 0, 0, 0)}, 30 | true, true); 31 | } 32 | 33 | internal DirectoryInfo ExtractPackage() 34 | { 35 | var dirPath = Path.Combine(Path.GetTempPath(), "Templates", Package.Id); 36 | var packageFiles = Package.GetContentFiles(); 37 | Package.ExtractContents(FileSystem, dirPath); 38 | return new DirectoryInfo(Path.Combine(dirPath, "content")); 39 | } 40 | 41 | private IPackage Package { get; set; } 42 | 43 | private PackageManager Manager { get; set; } 44 | 45 | private PhysicalFileSystem FileSystem { get; set; } 46 | 47 | private IPackageRepository Repository { get; set; } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/ClickTwice.Handlers.AppDetailsPage/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("ClickTwice.Handlers.AppDetailsPage")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("ClickTwice.Handlers.AppDetailsPage")] 12 | [assembly: AssemblyCopyright("Copyright © 2016")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("0d7cfab8-ab4b-4dd7-8b74-96bbcb81f48f")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /src/ClickTwice.Handlers.AppDetailsPage/Templating/PackageTemplateService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using RazorEngine.Templating; 5 | 6 | namespace ClickTwice.Handlers.AppDetailsPage.Templating 7 | { 8 | class PackageTemplateManager : ITemplateManager 9 | { 10 | public PackageTemplateManager(DirectoryInfo templateDirectory) 11 | { 12 | PackageDirectory = templateDirectory; 13 | } 14 | 15 | private DirectoryInfo PackageDirectory { get; set; } 16 | 17 | public ITemplateSource Resolve(ITemplateKey key) 18 | { 19 | return new PackageTemplateSource(new FileInfo(key.GetUniqueKeyString())); 20 | } 21 | 22 | public ITemplateKey GetKey(string name, ResolveType resolveType, ITemplateKey context) 23 | { 24 | var files = PackageDirectory.EnumerateFiles("*.cshtml", SearchOption.AllDirectories); 25 | var template = files.FirstOrDefault(f => f.Name == name); 26 | if (template == null) throw new FileNotFoundException("Could not find requested template", name); 27 | return new PackageKey(template.FullName, resolveType, context); 28 | } 29 | 30 | public void AddDynamic(ITemplateKey key, ITemplateSource source) 31 | { 32 | throw new NotImplementedException(); 33 | } 34 | } 35 | 36 | internal class PackageTemplateSource : ITemplateSource 37 | { 38 | public PackageTemplateSource(FileInfo file) 39 | { 40 | File = file; 41 | } 42 | 43 | private FileInfo File { get; set; } 44 | 45 | public TextReader GetTemplateReader() 46 | { 47 | return File.OpenText(); 48 | } 49 | 50 | public string TemplateFile => File.FullName; 51 | public string Template => System.IO.File.ReadAllText(File.FullName); 52 | } 53 | 54 | internal class PackageKey : BaseTemplateKey 55 | { 56 | private DirectoryInfo Directory { get; set; } 57 | private FileInfo File { get; set; } 58 | private string Id { get; set; } 59 | 60 | public PackageKey(string name, ResolveType resolveType, ITemplateKey context) : base(name, resolveType, context) 61 | { 62 | File = new FileInfo(name); 63 | Directory = File.Directory; 64 | } 65 | 66 | public override string GetUniqueKeyString() 67 | { 68 | return File.FullName; 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/ClickTwice.Handlers.AppDetailsPage/Templating/TemplateEngine.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using ClickTwice.Publisher.Core.Manifests; 5 | using ClickTwice.Publisher.Core.Resources; 6 | using RazorEngine.Templating; 7 | 8 | namespace ClickTwice.Handlers.AppDetailsPage.Templating 9 | { 10 | class TemplateEngine : IDisposable 11 | { 12 | private IRazorEngineService Engine { get; } 13 | 14 | public TemplateEngine(DirectoryInfo directory) 15 | { 16 | var config = new RazorEngine.Configuration.TemplateServiceConfiguration 17 | { 18 | TemplateManager = new PackageTemplateManager(directory), 19 | CachingProvider = new DefaultCachingProvider(t => { }) 20 | }; 21 | Engine = RazorEngineService.Create(config); 22 | SourceDirectory = directory; 23 | WorkingDirectory = 24 | Directory.CreateDirectory(Path.Combine(directory.Parent.Parent.FullName, $"{directory.Parent.Name}.Content")); 25 | } 26 | 27 | private DirectoryInfo SourceDirectory { get; set; } 28 | 29 | private DirectoryInfo WorkingDirectory { get; set; } 30 | 31 | internal AppManifest Manifest { get; set; } = new AppManifest(); 32 | internal ExtendedAppInfo AppInfo { get; set; } = new ExtendedAppInfo(); 33 | 34 | internal DirectoryInfo CreateContentDirectory(DirectoryInfo outputPath) 35 | { 36 | var model = new LaunchPageModel(Manifest, AppInfo) 37 | { 38 | ContentDirectory = "./Web Files", 39 | Launcher = outputPath.GetFiles("*.application").First().Name, 40 | Installer = outputPath.GetFiles("setup.exe").FirstOrDefault()?.Name ?? "#" 41 | }; 42 | if (model.AppInfo.Links == null) model.AppInfo.Links = new LinkList(); 43 | var webFilesDir = Directory.CreateDirectory(Path.Combine(WorkingDirectory.FullName, "Web Files")); 44 | var otherFiles = SourceDirectory.EnumerateFiles("*", SearchOption.AllDirectories).Where(f => !f.Extension.Contains("cshtml")); 45 | foreach (var otherFile in otherFiles) 46 | { 47 | var targetRelativePath = otherFile.FullName.Replace(SourceDirectory.FullName, string.Empty).Substring(1); 48 | var fullPath = Path.Combine(webFilesDir.FullName, targetRelativePath); 49 | Directory.CreateDirectory(new FileInfo(fullPath).Directory.FullName); 50 | otherFile.CopyTo( 51 | fullPath, true); 52 | } 53 | 54 | var templateFiles = SourceDirectory.EnumerateFiles("*.cshtml", SearchOption.AllDirectories).Where(f => f.Name.ToLower() != "index.cshtml"); 55 | foreach (var templateFile in templateFiles) 56 | { 57 | var targetRelativePath = templateFile.FullName.Replace(SourceDirectory.FullName, string.Empty).Substring(1); 58 | var fullPath = Path.Combine(webFilesDir.FullName, targetRelativePath); 59 | Directory.CreateDirectory(new FileInfo(fullPath).Directory.FullName); 60 | var compile = Engine.RunCompile(templateFile.Name, typeof (LaunchPageModel), model); 61 | File.WriteAllText(compile, fullPath); 62 | } 63 | var indexFile = SourceDirectory.GetFiles("index.cshtml").FirstOrDefault(); 64 | if (indexFile != null) 65 | { 66 | var indexDestPath = Path.Combine(WorkingDirectory.FullName, 67 | indexFile.FullName.Replace(indexFile.Extension, ".html") 68 | .Replace(SourceDirectory.FullName, string.Empty) 69 | .Substring(1)); 70 | 71 | var indexOutput = Engine.RunCompile(indexFile.Name, typeof(LaunchPageModel), model); 72 | File.WriteAllText(indexDestPath, indexOutput); 73 | } 74 | foreach (var file in WorkingDirectory.EnumerateFiles("*.cshtml", SearchOption.AllDirectories)) 75 | { 76 | file.Delete(); 77 | } 78 | return WorkingDirectory; 79 | } 80 | 81 | public void Dispose() 82 | { 83 | Engine.Dispose(); 84 | WorkingDirectory.Delete(recursive: true); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/ClickTwice.Handlers.AppDetailsPage/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/ClickTwice.Handlers.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.23107.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClickTwice.Handlers.Core", "ClickTwice.Handlers.Core\ClickTwice.Handlers.Core.csproj", "{0D3B980C-97CC-4677-BDA3-ADEF398F4B3C}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClickTwice.Templates.SolidState", "ClickTwice.Templates.SolidState\ClickTwice.Templates.SolidState.csproj", "{D79DA00F-846A-4B74-BC00-88E035B21477}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClickTwice.Templates.SolidState.Package", "ClickTwice.Templates.SolidState.Package\ClickTwice.Templates.SolidState.Package.csproj", "{0451BAEF-DF2E-4B98-8644-94EE9415E389}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {0D3B980C-97CC-4677-BDA3-ADEF398F4B3C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {0D3B980C-97CC-4677-BDA3-ADEF398F4B3C}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {0D3B980C-97CC-4677-BDA3-ADEF398F4B3C}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {0D3B980C-97CC-4677-BDA3-ADEF398F4B3C}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {D79DA00F-846A-4B74-BC00-88E035B21477}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {D79DA00F-846A-4B74-BC00-88E035B21477}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {D79DA00F-846A-4B74-BC00-88E035B21477}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {D79DA00F-846A-4B74-BC00-88E035B21477}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {0451BAEF-DF2E-4B98-8644-94EE9415E389}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {0451BAEF-DF2E-4B98-8644-94EE9415E389}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {0451BAEF-DF2E-4B98-8644-94EE9415E389}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {0451BAEF-DF2E-4B98-8644-94EE9415E389}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | EndGlobal 35 | -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.Core/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.Core/AppInfoManager.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Linq; 3 | using ClickTwice.Publisher.Core.Manifests; 4 | using Newtonsoft.Json; 5 | 6 | namespace ClickTwice.Publisher.Core 7 | { 8 | public class AppInfoManager : Manager 9 | { 10 | private ExtendedAppInfo AppInfo { get; } = new ExtendedAppInfo(); 11 | public AppInfoManager(string projectFilePath) : base(projectFilePath) 12 | { 13 | 14 | } 15 | 16 | public AppInfoManager() : base(string.Empty) 17 | { 18 | 19 | } 20 | 21 | public AppInfoManager(ExtendedAppInfo appInfo) : base(string.Empty) 22 | { 23 | this.AppInfo = appInfo; 24 | } 25 | 26 | public AppInfoManager AddAuthor(string authorName) 27 | { 28 | AppInfo.Author.Names.AddIfNotExists(authorName); 29 | return this; 30 | } 31 | 32 | public AppInfoManager AddContactDetails(ContactDetails details) 33 | { 34 | AppInfo.Author = details; 35 | return this; 36 | } 37 | 38 | public AppInfoManager AddInstallationInformation(string information) 39 | { 40 | AppInfo.InstallationInformation = information; 41 | return this; 42 | } 43 | 44 | public AppInfoManager AddPrerequisites(params string[] prerequisites) 45 | { 46 | foreach (var prerequisite in prerequisites) 47 | { 48 | AppInfo.PrerequisiteInformation.Add(prerequisite); 49 | } 50 | return this; 51 | } 52 | 53 | public AppInfoManager AddSupportInformation(string supportInfo) 54 | { 55 | AppInfo.SupportInformation = supportInfo; 56 | return this; 57 | } 58 | 59 | public AppInfoManager AddDeveloperNotice(string devInfo) 60 | { 61 | AppInfo.DeveloperInformation = devInfo; 62 | return this; 63 | } 64 | 65 | public AppInfoManager AddAppInformation(string appInfo) 66 | { 67 | AppInfo.AppInformation = appInfo; 68 | return this; 69 | } 70 | 71 | public void DeployAppInformation(string pathToDeploymentDir) 72 | { 73 | var j = JsonConvert.SerializeObject(AppInfo, Formatting.Indented); 74 | var fi = GetInfoFile(pathToDeploymentDir); 75 | File.WriteAllText(fi.FullName, j); 76 | } 77 | 78 | private static FileInfo GetInfoFile(string pathToDeploymentDir) 79 | { 80 | var di = new DirectoryInfo(pathToDeploymentDir); 81 | if (!di.Exists) throw new DirectoryNotFoundException($"Could not find deployment directory at {pathToDeploymentDir}"); 82 | if (di.GetFiles("*.application").Any()) 83 | { 84 | return new FileInfo(Path.Combine(di.FullName, "app.info")); 85 | } 86 | throw new FileNotFoundException($"Could not locate application manifest in {di.Name} directory", di.FullName); 87 | } 88 | 89 | public static ExtendedAppInfo ReadFromFile(string fullPathToInfoFile) 90 | { 91 | return JsonConvert.DeserializeObject(File.ReadAllText(fullPathToInfoFile)); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.Core/ClickTwice.Publisher.Core.csproj.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | CSharp60 -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.Core/ClickTwice.Publisher.Core.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ClickTwice.Publisher.Core 5 | ClickTwice Publisher Core 6 | Alistair Chapman 7 | achapman 8 | https://opensource.org/licenses/MIT 9 | https://github.com/agc93/clicktwice 10 | https://maxcdn.icons8.com/Color/PNG/96/Industry/engineering-96.png 11 | false 12 | Core library for all ClickTwice publish tools, including the host libraries 13 | Copyright 2016 14 | clicktwice publish clickonce wpf msbuild 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.Core/Exceptions/BuildFailedException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.Serialization; 4 | 5 | namespace ClickTwice.Publisher.Core.Exceptions 6 | { 7 | [Serializable] 8 | public class BuildFailedException : Exception 9 | { 10 | public IEnumerable TargetExceptions { get; } 11 | public Exception Exception { get; } 12 | 13 | public BuildFailedException() 14 | { 15 | } 16 | 17 | public BuildFailedException(string message) : base(message) 18 | { 19 | } 20 | 21 | public BuildFailedException(string message, Exception innerException) : base(message, innerException) 22 | { 23 | } 24 | 25 | public BuildFailedException(Exception exception, IEnumerable innerExceptions) 26 | { 27 | this.Exception = exception; 28 | this.TargetExceptions = innerExceptions; 29 | } 30 | 31 | protected BuildFailedException(SerializationInfo info, StreamingContext context) : base(info, context) 32 | { 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.Core/Exceptions/HandlerProcessingException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.Serialization; 4 | using ClickTwice.Publisher.Core.Handlers; 5 | 6 | namespace ClickTwice.Publisher.Core.Exceptions 7 | { 8 | [Serializable] 9 | public class HandlerProcessingException : Exception 10 | { 11 | private List inputHandlers; 12 | private List outputHandlers; 13 | 14 | public HandlerProcessingException() 15 | { 16 | } 17 | 18 | public HandlerProcessingException(string message) : base(message) 19 | { 20 | } 21 | 22 | private HandlerProcessingException(List inputHandlers) 23 | { 24 | this.inputHandlers = inputHandlers; 25 | } 26 | 27 | public HandlerProcessingException(List outputHandlers) 28 | { 29 | this.outputHandlers = outputHandlers; 30 | } 31 | 32 | public HandlerProcessingException(string message, Exception innerException) : base(message, innerException) 33 | { 34 | } 35 | 36 | protected HandlerProcessingException(SerializationInfo info, StreamingContext context) : base(info, context) 37 | { 38 | } 39 | 40 | public HandlerProcessingException(List handlers, List results) : this(handlers) 41 | { 42 | this.HandlerResponses = results; 43 | } 44 | 45 | public List HandlerResponses { get; set; } 46 | 47 | public HandlerProcessingException(List handlers, List results) : this(handlers) 48 | { 49 | this.HandlerResponses = results; 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.Core/Exceptions/OperationInProgressException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ClickTwice.Publisher.Core.Exceptions 4 | { 5 | public class OperationInProgressException : Exception 6 | { 7 | public OperationInProgressException(OperationType operationType) : base(BuildMessage(operationType)) 8 | { 9 | this.Operation = operationType; 10 | } 11 | 12 | public OperationInProgressException(OperationType operationType, InvalidOperationException innerException) : base(BuildMessage(operationType), innerException) 13 | { 14 | 15 | } 16 | 17 | private static string BuildMessage(OperationType operationType) 18 | { 19 | return $"{operationType} operation already in progress"; 20 | } 21 | 22 | public OperationType Operation { get; set; } 23 | } 24 | } -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.Core/Handlers/AppInfoHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using ClickTwice.Publisher.Core.Manifests; 5 | 6 | namespace ClickTwice.Publisher.Core.Handlers 7 | { 8 | public class AppInfoHandler : IInputHandler, IOutputHandler 9 | { 10 | public AppInfoHandler(AppInfoManager manager = null) 11 | { 12 | Manager = manager; 13 | } 14 | 15 | public AppInfoHandler(Action configure) 16 | { 17 | Configuration = configure; 18 | } 19 | 20 | private Action Configuration { get; set; } 21 | 22 | private AppInfoManager Manager { get; set; } 23 | 24 | public string Name => "app.info file handler"; 25 | HandlerResponse IOutputHandler.Process(string outputPath) 26 | { 27 | var di = new DirectoryInfo(outputPath); 28 | if (AppInfo != null) 29 | { 30 | //we found a manifest at input time 31 | 32 | //there wasn't a manifest when we started 33 | // so we clearly just created this 34 | } 35 | //This will either create one using the passed in Manager or the discovered app.info 36 | Manager?.DeployAppInformation(outputPath); 37 | return new HandlerResponse(this, di.GetFiles("app.info").Any(), $"Deployed app.info in '{di.Name}' directory"); 38 | } 39 | 40 | HandlerResponse IInputHandler.Process(string inputPath) 41 | { 42 | var files = new DirectoryInfo(inputPath).EnumerateFiles("app.info", SearchOption.AllDirectories).ToList(); 43 | var projects = new DirectoryInfo(inputPath).EnumerateFiles("*.csproj", SearchOption.TopDirectoryOnly); 44 | if (files.Any()) 45 | { 46 | AppInfo = AppInfoManager.ReadFromFile(files.First().FullName); 47 | Manager = new AppInfoManager(AppInfo); 48 | } 49 | else 50 | { 51 | Manager = new AppInfoManager(projects.FirstOrDefault()?.FullName); 52 | } 53 | if (Configuration != null && Manager != null) 54 | { 55 | Configuration.Invoke(Manager); 56 | } 57 | return new HandlerResponse(this, true); 58 | } 59 | 60 | private ExtendedAppInfo AppInfo { get; set; } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.Core/Handlers/BuildConfigurator.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace ClickTwice.Publisher.Core.Handlers 4 | { 5 | public abstract class BuildConfigurator : IBuildConfigurator 6 | { 7 | public abstract string Name { get; } 8 | public virtual Dictionary ProcessConfiguration(Dictionary configuration) 9 | { 10 | return null; 11 | } 12 | 13 | public virtual List ProcessTargets(List targets) 14 | { 15 | return new List(); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.Core/Handlers/HandlerResponse.cs: -------------------------------------------------------------------------------- 1 | namespace ClickTwice.Publisher.Core.Handlers 2 | { 3 | public class HandlerResponse 4 | { 5 | public HandlerResult Result { get; set; } 6 | public IHandler Handler { get; set; } 7 | public string ResultMessage { get; private set; } = string.Empty; 8 | 9 | private HandlerResponse(IHandler handler) 10 | { 11 | Handler = handler; 12 | } 13 | public HandlerResponse(IHandler handler, bool succeeded) : this(handler) 14 | { 15 | Result = succeeded ? HandlerResult.OK : HandlerResult.Error; 16 | } 17 | 18 | public HandlerResponse(IHandler handler, bool succeeded, string message) : this(handler, succeeded) 19 | { 20 | ResultMessage = message; 21 | } 22 | 23 | public HandlerResponse(IHandler handler, HandlerResult result, string message) : this(handler) 24 | { 25 | Result = result; 26 | ResultMessage = message; 27 | } 28 | } 29 | 30 | public enum HandlerResult 31 | { 32 | NotRun, 33 | OK, 34 | Error 35 | } 36 | } -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.Core/Handlers/InstallPageHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using System.Linq; 4 | using ClickTwice.Publisher.Core.Resources; 5 | 6 | namespace ClickTwice.Publisher.Core.Handlers 7 | { 8 | public class InstallPageHandler : IOutputHandler 9 | { 10 | public InstallPageHandler(string fileName = "index.htm", string linkText = null, string linkTarget = null) 11 | { 12 | this.OutputFileName = fileName; 13 | AdditionalLink = new KeyValuePair(linkText, linkTarget); 14 | UseLink = !string.IsNullOrWhiteSpace(linkTarget) && !string.IsNullOrWhiteSpace(linkText); 15 | } 16 | 17 | private bool UseLink { get; set; } 18 | 19 | private KeyValuePair AdditionalLink { get; set; } 20 | 21 | public string OutputFileName { get; set; } 22 | 23 | public string Name => "Improved application launch page generator"; 24 | public HandlerResponse Process(string outputPath) 25 | { 26 | try 27 | { 28 | var page = new LaunchPage(outputPath, OutputFileName); 29 | if (UseLink) page.AdditionalLink = AdditionalLink; 30 | page.CreatePage(); 31 | if (new DirectoryInfo(outputPath).GetFiles(OutputFileName).Any()) 32 | { 33 | return new HandlerResponse(this, true, $"{OutputFileName} successfully generated in " + outputPath); 34 | } 35 | return new HandlerResponse(this, false, 36 | $"Launch page was not generated. Check to ensure a ClickTwice manifest has been deployed in the target directory"); 37 | } 38 | catch (System.Exception ex) 39 | { 40 | return new HandlerResponse(this, false, $"{ex.GetType()} error encountered while generating launch page in {outputPath}. Check your deployment files and try again. {System.Environment.NewLine} {ex.Message}"); 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.Core/Handlers/Interfaces.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace ClickTwice.Publisher.Core.Handlers 4 | { 5 | public interface IInputHandler : IHandler 6 | { 7 | HandlerResponse Process(string inputPath); 8 | } 9 | 10 | public interface IHandler 11 | { 12 | string Name { get; } 13 | } 14 | 15 | public interface IBuildConfigurator : IHandler 16 | { 17 | Dictionary ProcessConfiguration(Dictionary configuration); 18 | List ProcessTargets(List targets); 19 | } 20 | 21 | public interface IOutputHandler : IHandler 22 | { 23 | HandlerResponse Process(string publishPath); 24 | } 25 | } -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.Core/Handlers/MockInputHandler.cs: -------------------------------------------------------------------------------- 1 | namespace ClickTwice.Publisher.Core.Handlers 2 | { 3 | internal class MockInputHandler : IInputHandler 4 | { 5 | public HandlerResponse Process(string inputPath) 6 | { 7 | return new HandlerResponse(this, true, "Processed input"); 8 | } 9 | 10 | public string Name => "Mock Input"; 11 | } 12 | } -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.Core/Handlers/PublishPageHandler.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Linq; 3 | using ClickTwice.Publisher.Core.Resources; 4 | 5 | namespace ClickTwice.Publisher.Core.Handlers 6 | { 7 | public class PublishPageHandler : IOutputHandler 8 | { 9 | public string Name => "publish.htm Generator"; 10 | public HandlerResponse Process(string outputPath) 11 | { 12 | try 13 | { 14 | var page = new PublishPage(outputPath); 15 | page.CreatePage(); 16 | if (new DirectoryInfo(outputPath).GetFiles("publish.htm").Any()) 17 | { 18 | return new HandlerResponse(this, true, "publish.htm successfully generated in " + outputPath); 19 | } 20 | return new HandlerResponse(this, false, 21 | $"publish.htm was not generated. Check to ensure a ClickTwice manifest has been deployed in the target directory"); 22 | } 23 | catch 24 | { 25 | return new HandlerResponse(this, false, $"Error encountered while generating publish.htm page in {outputPath}. Check your deployment files and try again."); 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.Core/IPublishManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Security; 4 | using ClickTwice.Publisher.Core.Exceptions; 5 | using ClickTwice.Publisher.Core.Handlers; 6 | using ClickTwice.Publisher.Core.Loggers; 7 | 8 | namespace ClickTwice.Publisher.Core 9 | { 10 | public interface IPublishManager : IDisposable 11 | { 12 | string Configuration { set; } 13 | string Platform { set; } 14 | List InputHandlers { set; } 15 | List OutputHandlers { set; } 16 | List BuildConfigurators { set; } 17 | List Loggers { get; } 18 | string ProjectFilePath { get; } 19 | bool CleanOutputOnCompletion { set; } 20 | 21 | /// Thrown when input or output handlers encounter an exception. 22 | /// Thrown when a build or publish operation is already in progress. 23 | /// Invalid behaviour type provided. 24 | /// The caller does not have the required permission. 25 | /// Thrown when the build fails. 26 | List PublishApp(string targetPath, 27 | PublishBehaviour behaviour = PublishBehaviour.CleanFirst); 28 | } 29 | 30 | public enum OperationType 31 | { 32 | Clean, 33 | Build, 34 | Publish, 35 | Deploy 36 | } 37 | 38 | public enum PublishBehaviour 39 | { 40 | None, 41 | CleanFirst, 42 | DoNotBuild 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.Core/Loggers/ConsoleLogger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ClickTwice.Publisher.Core.Loggers 4 | { 5 | public class ConsoleLogger : IPublishLogger 6 | { 7 | public ConsoleLogger(bool includeBuildMessages = false) 8 | { 9 | IncludeBuildMessages = includeBuildMessages; 10 | } 11 | public void Log(string content) 12 | { 13 | Console.WriteLine(content); 14 | } 15 | 16 | public bool IncludeBuildMessages { get; set; } 17 | public string Close(string outputPath) 18 | { 19 | throw new NotImplementedException(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.Core/Loggers/FileLogger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | 5 | namespace ClickTwice.Publisher.Core.Loggers 6 | { 7 | public class FileLogger : IPublishLogger 8 | { 9 | private List Messages { get; set; } = new List(); 10 | public FileLogger(bool includeBuildMessages = true) 11 | { 12 | IncludeBuildMessages = includeBuildMessages; 13 | } 14 | public void Log(string content) 15 | { 16 | Messages.Add(content); 17 | } 18 | 19 | public bool IncludeBuildMessages { get; set; } 20 | public string Close(string outputPath) 21 | { 22 | var path = Path.Combine(outputPath, $"BuildLog_{DateTime.Now.ToString("YYMMdd-HHmmss")}.txt"); 23 | File.WriteAllLines(path, Messages); 24 | return $"Log file written to {path}"; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.Core/Loggers/IPublishLogger.cs: -------------------------------------------------------------------------------- 1 | namespace ClickTwice.Publisher.Core.Loggers 2 | { 3 | public interface IPublishLogger 4 | { 5 | void Log(string content); 6 | bool IncludeBuildMessages { get; } 7 | string Close(string outputPath); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.Core/Manager.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Linq; 3 | 4 | namespace ClickTwice.Publisher.Core 5 | { 6 | public abstract class Manager 7 | { 8 | protected Manager(string projectFilePath) 9 | { 10 | this.ProjectFilePath = projectFilePath; 11 | } 12 | 13 | public string ProjectFilePath { get; protected set; } 14 | 15 | public bool CleanOutputOnCompletion { protected get; set; } = true; 16 | 17 | protected string ReadVersionFromAssemblyInfo() 18 | { 19 | var projectFolder = new FileInfo(ProjectFilePath).Directory; 20 | var infoFilePath = Path.Combine(projectFolder.FullName, "Properties", "AssemblyInfo.cs"); 21 | var props = File.ReadAllLines(infoFilePath).Where(l => l.StartsWith("[assembly: ")).ToList(); 22 | var v = props.Property("Version"); 23 | return v; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.Core/Manifests/AppManifest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace ClickTwice.Publisher.Core.Manifests 5 | { 6 | public class AppManifest 7 | { 8 | public string ApplicationName { get; set; } = string.Empty; 9 | public string ShortName { get; set; } = string.Empty; 10 | public string AuthorName { get; set; } = string.Empty; 11 | public string PublisherName { get; set; } = string.Empty; 12 | public string SuiteName { get; set; } = string.Empty; 13 | [Obsolete("Use an ExtendedAppInfo object (or the AppInfoManager) to store application information")] 14 | public string Summary { get; set; } = string.Empty; 15 | public string Description { get; set; } = string.Empty; 16 | public string Copyright { get; set; } = string.Empty; 17 | public Version FrameworkVersion { get; set; } = new Version(0,0); 18 | public Version AppVersion { get; set; } = new Version(0,0); 19 | public IEnumerable Prerequisites { get; set; } = new List(); 20 | public ExtendedAppInfo AppInfo { get; set; } = new ExtendedAppInfo(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.Core/Manifests/ExtendedAppInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace ClickTwice.Publisher.Core.Manifests 5 | { 6 | public class ExtendedAppInfo 7 | { 8 | public ExtendedAppInfo() 9 | { 10 | Links = new LinkList(); 11 | } 12 | public string AppInformation { get; set; } = string.Empty; 13 | public string InstallationInformation { get; set; } = string.Empty; 14 | public IList PrerequisiteInformation { get; set; } = new List(); 15 | public ContactDetails Author { get; set; } = new ContactDetails(); 16 | public string SupportInformation { get; set; } = string.Empty; 17 | public string DeveloperInformation { get; set; } = string.Empty; 18 | public LinkList Links { get; set; } 19 | } 20 | 21 | public class LinkList 22 | { 23 | public Uri SupportUrl { get; set; } = new Uri("about:blank"); 24 | public Uri DocumentationUri { get; set; } = new Uri("about:blank"); 25 | public Uri DeveloperDocumentation { get; set; } = new Uri("about:blank"); 26 | } 27 | 28 | public class ContactDetails 29 | { 30 | public IEnumerable Names { get; set; } = new List(); 31 | public string Phone { get; set; } = string.Empty; 32 | public string Email { get; set; } = string.Empty; 33 | public string Location { get; set; } = string.Empty; 34 | //public string Times { get; set; } = string.Empty; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.Core/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("ClickTwice.Publisher.Core")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("ClickTwice.Publisher.Core")] 12 | [assembly: AssemblyCopyright("Copyright © 2015")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("af189adc-d4a9-4a30-aa12-d5cfd96523be")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.Core/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace ClickTwice.Publisher.Core.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ClickTwice.Publisher.Core.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized string similar to data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAUEBAQEBAUEBAUHBQQFBwkHBQUHCQoICAkICAoNCgsLCwsKDQwMDA0MDAwPDxERDw8XFhYWFxkZGRkZGRkZGRn/2wBDAQYGBgoJChQNDRQWEQ4RFhkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRn/wAARCAOEB4ADAREAAhEBAxEB/8QAGwABAQEBAQEBAQAAAAAAAAAAAgEAAwUEBgf/xAA0EAACAgEDAwIFBQACAwEBAAMBEQAhMQJBURJhcYGRIqGxwfAyQtHh8VJiAxNygpKiI7L/xAAaAQEBAQEBAQEAAAAAAAAAAAAAAQIDBAUG/8QAFxEBAQEBAAAAAAAAAAAAAAAAABEBIf/aAAwDAQACEQMRAD8A/mQD1fEPhz+Ofo34hQQH0rpKR+zgTVuBRJH5zCqbJe5GfzmBQfYGy [rest of string was truncated]";. 65 | /// 66 | internal static string BackgroundOne { 67 | get { 68 | return ResourceManager.GetString("BackgroundOne", resourceCulture); 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.Core/Resources/LaunchPageCode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using ClickTwice.Publisher.Core.Manifests; 6 | 7 | namespace ClickTwice.Publisher.Core.Resources 8 | { 9 | partial class LaunchPage 10 | { 11 | public LaunchPageModel Model { get; set; } 12 | public LaunchPage(string deploymentPath, string outputFileName) 13 | { 14 | var fi = new DirectoryInfo(deploymentPath).GetFiles("*.cltw").FirstOrDefault(); 15 | if (fi == null) 16 | { 17 | var mgr = new ManifestManager(string.Empty, deploymentPath, InformationSource.AppManifest); 18 | var manifest = mgr.CreateAppManifest(); 19 | this.Manifest = manifest; 20 | } 21 | else 22 | { 23 | Manifest = ManifestManager.ReadFromFile(fi.FullName); 24 | } 25 | this.DeploymentDir = new DirectoryInfo(deploymentPath); 26 | 27 | AppLauncher = DeploymentDir.GetFiles("*.application").First(); 28 | if (Manifest.FrameworkVersion == null) 29 | { 30 | Manifest.FrameworkVersion = new Version(4, 5); 31 | } 32 | this.Model = new LaunchPageModel(Manifest); 33 | this.OutputFileName = outputFileName; 34 | } 35 | 36 | private string OutputFileName { get; set; } 37 | 38 | internal void CreatePage() 39 | { 40 | var page = this.TransformText(); 41 | File.WriteAllText(Path.Combine(DeploymentDir.FullName, OutputFileName), page); 42 | } 43 | 44 | private FileInfo AppLauncher { get; set; } 45 | 46 | private AppManifest Manifest { get; set; } 47 | 48 | private DirectoryInfo DeploymentDir { get; set; } 49 | 50 | private IEnumerable Images => EncodedImages.Backgrounds; 51 | 52 | internal KeyValuePair AdditionalLink { get; set; } = new KeyValuePair(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.Core/Resources/LaunchPageModel.cs: -------------------------------------------------------------------------------- 1 | using ClickTwice.Publisher.Core.Manifests; 2 | 3 | namespace ClickTwice.Publisher.Core.Resources 4 | { 5 | public class LaunchPageModel 6 | { 7 | public LaunchPageModel(AppManifest manifest) 8 | { 9 | if (manifest == null) manifest = new AppManifest(); 10 | Manifest = manifest; 11 | } 12 | 13 | public LaunchPageModel(AppManifest manifest, ExtendedAppInfo appinfo) : this(manifest) 14 | { 15 | if (appinfo == null) appinfo = new ExtendedAppInfo(); 16 | AppInfo = appinfo; 17 | } 18 | 19 | public AppManifest Manifest { get; set; } 20 | 21 | public ExtendedAppInfo AppInfo { get; set; } 22 | 23 | public string ContentDirectory { get; set; } = string.Empty; 24 | public string Launcher { get; set; } = string.Empty; 25 | public string Installer { get; set; } = string.Empty; 26 | } 27 | } -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.Core/Resources/PublishPageCode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using ClickTwice.Publisher.Core.Manifests; 5 | 6 | namespace ClickTwice.Publisher.Core.Resources 7 | { 8 | partial class PublishPage 9 | { 10 | 11 | internal AppManifest Manifest { get; } 12 | internal FileInfo AppLauncher { get; set; } 13 | 14 | internal PublishPage(string deploymentPath) 15 | { 16 | this.DeploymentDir = new DirectoryInfo(deploymentPath); 17 | var infos = this.DeploymentDir.GetFiles("*.cltw"); 18 | var mgr = new ManifestManager(string.Empty, deploymentPath, InformationSource.AppManifest); 19 | var manifest = mgr.CreateAppManifest(); 20 | this.Manifest = manifest; 21 | AppLauncher = DeploymentDir.GetFiles("*.application").First(); 22 | if (Manifest.FrameworkVersion == null) 23 | { 24 | Manifest.FrameworkVersion = new Version(4,5); 25 | } 26 | } 27 | 28 | internal DirectoryInfo DeploymentDir { get; } 29 | 30 | internal string Generate() 31 | { 32 | return this.TransformText(); 33 | } 34 | 35 | internal void CreatePage() 36 | { 37 | var page = Generate(); 38 | File.WriteAllText(Path.Combine(DeploymentDir.FullName, "publish.htm"), page); 39 | } 40 | 41 | internal ExtendedAppInfo AppInfo { get; private set; } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.Core/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.MSBuild/ArgBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace ClickTwice.Publisher.MSBuild 8 | { 9 | class ArgBuilder 10 | { 11 | private StringBuilder _sb; 12 | 13 | public ArgBuilder(string argBase = "") 14 | { 15 | _sb = new StringBuilder(argBase); 16 | } 17 | 18 | public ArgBuilder Append(string arg) 19 | { 20 | _sb.Append($" {arg}"); 21 | return this; 22 | } 23 | 24 | public ArgBuilder AppendQuoted(string arg) 25 | { 26 | _sb.Append($@" ""{arg}"""); 27 | return this; 28 | } 29 | 30 | public override string ToString() 31 | { 32 | return _sb.ToString(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.MSBuild/BuildDomain.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using ClickTwice.Publisher.Core; 8 | using ClickTwice.Publisher.Core.Exceptions; 9 | using ClickTwice.Publisher.Core.Loggers; 10 | using ClickTwice.Publisher.MSBuild.Loggers; 11 | using Microsoft.Build.Evaluation; 12 | using Microsoft.Build.Execution; 13 | using Microsoft.Build.Framework; 14 | 15 | namespace ClickTwice.Publisher.MSBuild 16 | { 17 | /// This class is not currently in use and is preserved only for experimental use in future releases 18 | [Serializable] 19 | class BuildDomain : MarshalByRefObject 20 | { 21 | 22 | private static BuildManager Manager => BuildManager.DefaultBuildManager; 23 | 24 | internal static Action Log { get; set; } 25 | 26 | internal static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) 27 | { 28 | var assemblyName = args.Name.Split(',').FirstOrDefault(); 29 | Log($"Resolving {assemblyName}"); 30 | return assemblyName == null ? Assembly.Load(args.Name) : Assembly.Load(assemblyName); 31 | } 32 | 33 | internal static void Dom_AssemblyLoad(object sender, AssemblyLoadEventArgs args) 34 | { 35 | Log($" Loading {args.LoadedAssembly.FullName}"); 36 | } 37 | 38 | internal static bool Build(string projectFilePath, Dictionary props, List targets, IEnumerable publishLoggers) 39 | { 40 | var pc = new ProjectCollection(); 41 | Log("Configuring loggers"); 42 | var loggers = new List { new BuildMessageLogger(publishLoggers.Where(l => l.IncludeBuildMessages).ToList()) }; 43 | Log($"Added {loggers.Count} loggers"); 44 | var buildParams = new BuildParameters(pc) 45 | { 46 | DetailedSummary = true, 47 | Loggers = loggers, 48 | DefaultToolsVersion = "14.0" 49 | }; 50 | var reqData = new BuildRequestData(projectFilePath, props, "14.0", targets.ToArray(), null); 51 | Log("Preparing for build"); 52 | try 53 | { 54 | Manager.BeginBuild(buildParams); 55 | } 56 | catch (InvalidOperationException ex) when (ex.Message.Contains("in progress")) 57 | { 58 | throw new OperationInProgressException(OperationType.Build, ex); 59 | } 60 | Log("Starting MSBuild build"); 61 | var buildResult = Manager.BuildRequest(reqData); 62 | Log($"MSBuild build complete: {buildResult.OverallResult}"); 63 | if (buildResult.OverallResult == BuildResultCode.Success) 64 | { 65 | return true; 66 | } 67 | if (buildResult.Exception?.Message != null) 68 | { 69 | Log($"MSBuild build failed with {buildResult.Exception.GetType().Name}: {buildResult.Exception.Message}"); 70 | } 71 | return false; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.MSBuild/ClickTwice.Publisher.MSBuild.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {A0A4508D-C0B8-4F18-A61F-7D5B98E0AEF6} 8 | Library 9 | Properties 10 | ClickTwice.Publisher.MSBuild 11 | ClickTwice.Publisher.MSBuild 12 | v4.5.2 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | {af189adc-d4a9-4a30-aa12-d5cfd96523be} 56 | ClickTwice.Publisher.Core 57 | 58 | 59 | 60 | 67 | -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.MSBuild/DirectPublisher.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using ClickTwice.Publisher.Core; 10 | using ClickTwice.Publisher.Core.Exceptions; 11 | using ClickTwice.Publisher.Core.Handlers; 12 | using ClickTwice.Publisher.MSBuild.Loggers; 13 | using Microsoft.Build.Framework; 14 | 15 | namespace ClickTwice.Publisher.MSBuild 16 | { 17 | public class DirectPublisher : BasePublishManager 18 | { 19 | private readonly string _msBuildPath; 20 | 21 | public DirectPublisher(string projectFilePath, InformationSource source = InformationSource.Both) : base(projectFilePath) 22 | { 23 | _msBuildPath = MSBuildResolver.GetMSBuildPath(); 24 | } 25 | 26 | private ConcurrentQueue OutputQueue { get; set; } = new ConcurrentQueue(); 27 | 28 | protected override bool BuildProject(Dictionary props, List targets) 29 | { 30 | Log("Preparing MSBuild"); 31 | var args = new ArgBuilder(); 32 | args.Append(string.Join(Environment.NewLine, props.Select(p => $"/p:{p.Key}={p.Value}"))) 33 | .Append($"/t:{string.Join(",", targets)}") 34 | .Append(ProjectFilePath); 35 | bool success; 36 | var proc = new Process 37 | { 38 | StartInfo = new ProcessStartInfo(_msBuildPath, args.ToString()) 39 | { 40 | RedirectStandardOutput = true, 41 | RedirectStandardError = true, 42 | CreateNoWindow = true, 43 | UseShellExecute = false, 44 | WorkingDirectory = Environment.CurrentDirectory 45 | } 46 | }; 47 | proc.OutputDataReceived += Proc_OutputDataReceived; 48 | proc.OutputDataReceived += TryWriteOutput; 49 | proc.ErrorDataReceived += Proc_OutputDataReceived; 50 | try 51 | { 52 | Log("Invoking MSBuild process"); 53 | proc.Start(); 54 | proc.BeginOutputReadLine(); 55 | proc.WaitForExit(); 56 | Log($"Process completed - {proc.ExitCode}"); 57 | WriteAllOutput(); 58 | success = proc.ExitCode == 0; 59 | } 60 | catch (Exception ex) 61 | { 62 | Log($"{ex.GetType()} - {ex.Message}"); 63 | Log($"Failed to invoke MSBuild from {_msBuildPath}"); 64 | Log(proc.StandardError.ReadToEnd()); 65 | success = false; 66 | } 67 | return success; 68 | } 69 | 70 | private void WriteAllOutput() 71 | { 72 | while (!OutputQueue.IsEmpty) 73 | { 74 | string item; 75 | if (OutputQueue.TryDequeue(out item)) Log(item, true); 76 | } 77 | } 78 | 79 | private void TryWriteOutput(object sender, DataReceivedEventArgs dataReceivedEventArgs) 80 | { 81 | if (OutputQueue.IsEmpty) return; 82 | string item; 83 | if (OutputQueue.TryDequeue(out item)) Log(item, true); 84 | } 85 | 86 | protected override void PostBuild(FileSystemInfo targetPath) 87 | { 88 | base.PostBuild(targetPath); 89 | var m = PrepareManifestManager(targetPath.FullName); 90 | m?.DeployManifest(m.CreateAppManifest()); 91 | } 92 | 93 | private ManifestManager PrepareManifestManager(string targetPath) 94 | { 95 | return !string.IsNullOrWhiteSpace(targetPath) ? new ManifestManager(ProjectFilePath, targetPath) : null; 96 | } 97 | 98 | private void Proc_OutputDataReceived(object sender, DataReceivedEventArgs e) 99 | { 100 | if (e.Data != null) OutputQueue.Enqueue(e.Data); 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.MSBuild/Loggers/BuildMessageLogger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using ClickTwice.Publisher.Core.Loggers; 4 | using Microsoft.Build.Framework; 5 | 6 | namespace ClickTwice.Publisher.MSBuild.Loggers 7 | { 8 | public class BuildMessageLogger : ILogger 9 | { 10 | public BuildMessageLogger(IList loggers) 11 | { 12 | this.Loggers = loggers; 13 | Verbosity = LoggerVerbosity.Normal; 14 | } 15 | 16 | private IList Loggers { get; set; } 17 | 18 | public void Initialize(IEventSource eventSource) 19 | { 20 | eventSource.AnyEventRaised += EventSource_AnyEventRaised; 21 | } 22 | 23 | private void EventSource_AnyEventRaised(object sender, BuildEventArgs e) 24 | { 25 | foreach (var logger in Loggers) 26 | { 27 | logger.Log($"{DateTime.Now.ToString("T")} - {e.Message}"); 28 | } 29 | } 30 | 31 | public void Shutdown() 32 | { 33 | return; 34 | } 35 | 36 | public LoggerVerbosity Verbosity { get; set; } 37 | public string Parameters { get; set; } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/ClickTwice.Publisher.MSBuild/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("ClickTwice.Publisher.MSBuild")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("ClickTwice.Publisher.MSBuild")] 12 | [assembly: AssemblyCopyright("Copyright © 2016")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("a0a4508d-c0b8-4f18-a61f-7d5b98e0aef6")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /src/ClickTwice.Templates.Packager/ClickTwice.Templates.Packager.pssproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | 2.0 6 | 6CAFC0C6-A428-4d30-A9F9-700E829FEA51 7 | Exe 8 | MyApplication 9 | MyApplication 10 | ClickTwice.Templates.Packager 11 | 12 | 13 | true 14 | full 15 | false 16 | bin\Debug\ 17 | DEBUG;TRACE 18 | prompt 19 | 4 20 | 21 | 22 | pdbonly 23 | true 24 | bin\Release\ 25 | TRACE 26 | prompt 27 | 4 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/ClickTwice.Templates.Packager/Script.ps1: -------------------------------------------------------------------------------- 1 | # 2 | # Script.ps1 3 | # 4 | #Param ( 5 | # [string]$ProjectDir 6 | #) 7 | 8 | #$ProjectFile = Get-ChildItem -File "*.csproj" | Select-Object -Property FullName 9 | $ProjectFile = "C:\Users\ucrm4\Source\Repos\ClickTwice\src\ClickTwice.Templates.SolidState\ClickTwice.Templates.SolidState.csproj" 10 | $ProjectXml = [xml](Get-Content $ProjectFile) 11 | $ns = new-object Xml.XmlNamespaceManager $ProjectXml.NameTable 12 | $ns.AddNamespace('msb', 'http://schemas.microsoft.com/developer/msbuild/2003') 13 | $ContentFiles = $ProjectXml.SelectNodes("//msb:Project/msb:ItemGroup/msb:Content", $ns) 14 | $ContentFiles | Select-Object -Property Include | select {$_.Attributes.ItemOf["Include"] -ne ""} 15 | $AppVersion = $ProjectXml.SelectSingleNode("//msb:Project/msb:PropertyGroup/msb:ApplicationVersion", $ns) 16 | $AppVersion.InnerText = $newExeVersion -------------------------------------------------------------------------------- /src/ClickTwice.Templates.SolidState/ClickTwice.Templates.SolidState.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | CurrentPage 10 | True 11 | False 12 | False 13 | False 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | True 23 | True 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/ClickTwice.Templates.SolidState/ClickTwice.Templates.SolidState.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ClickTwice.Templates.SolidState 5 | 0.0.1 6 | ClickTwice App Template - Solid State 7 | Alistair Chapman 8 | Alistair Chapman 9 | false 10 | Solid State template for use with the ClickTwice AppDetails handler 11 | Initial experimental package 12 | Copyright 2016 13 | ClickTwice 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/ClickTwice.Templates.SolidState/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ClickTwice.Templates.SolidState")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ClickTwice.Templates.SolidState")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("d79da00f-846a-4b74-bc00-88e035b21477")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /src/ClickTwice.Templates.SolidState/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /src/ClickTwice.Templates.SolidState/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | -------------------------------------------------------------------------------- /src/ClickTwice.Templates.SolidState/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/ClickTwice.Templates.SolidState/js/app.js: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /src/ClickTwice.Templates.SolidState/js/site.js: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /src/ClickTwice.Templates.SolidState/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/ClickTwice.Templates.SolidState/site.css: -------------------------------------------------------------------------------- 1 | body { 2 | } 3 | -------------------------------------------------------------------------------- /src/ClickTwice.Templating/ClickTwice.Templating.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {F34D7CE7-5BE7-4393-9F0C-8F23B8DBC05D} 8 | Library 9 | Properties 10 | ClickTwice.Templating 11 | ClickTwice.Templating 12 | v4.5.2 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | ..\packages\Microsoft.Web.Xdt.2.1.1\lib\net40\Microsoft.Web.XmlTransform.dll 35 | True 36 | 37 | 38 | ..\packages\NuGet.Core.2.14.0\lib\net40-Client\NuGet.Core.dll 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | {af189adc-d4a9-4a30-aa12-d5cfd96523be} 63 | ClickTwice.Publisher.Core 64 | 65 | 66 | 67 | 68 | 69 | 70 | 77 | -------------------------------------------------------------------------------- /src/ClickTwice.Templating/IPackager.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace ClickTwice.Templating 4 | { 5 | internal interface IPackager 6 | { 7 | List GetContentFiles(string rootDirectory); 8 | } 9 | } -------------------------------------------------------------------------------- /src/ClickTwice.Templating/ITemplatePublisher.cs: -------------------------------------------------------------------------------- 1 | namespace ClickTwice.Templating 2 | { 3 | public interface ITemplatePublisher 4 | { 5 | TemplatePackageSettings Metadata { get; } 6 | PackagingMode PackagingMode { get; } 7 | ITemplatePublisher ToPackageFile(string outputPath); 8 | ITemplatePublisher ToGallery(string apiKey = null, string galleryUri = null); 9 | } 10 | } -------------------------------------------------------------------------------- /src/ClickTwice.Templating/MinimalPackager.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using System.Linq; 4 | using ClickTwice.Publisher.Core; 5 | 6 | namespace ClickTwice.Templating 7 | { 8 | internal class MinimalPackager : IPackager 9 | { 10 | public List GetContentFiles(string rootDirectory) 11 | { 12 | var files = new DirectoryInfo(rootDirectory).EnumerateFilesForExtensions(false, ".nupkg", ".nuspec", ".config"); 13 | return 14 | files.Select(f => f.FullName) 15 | .Select(n => n.Replace(rootDirectory, string.Empty).Trim().TrimStart('\\')) 16 | .ToList(); 17 | //return 18 | // new DirectoryInfo(rootDirectory).GetFilesExceptExtensions(".nupkg", ".nuspec", ".dll", ".config") 19 | // .Select(f => f.FullName.Replace(rootDirectory, string.Empty)) 20 | // .ToList(); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/ClickTwice.Templating/PackagingMode.cs: -------------------------------------------------------------------------------- 1 | namespace ClickTwice.Templating 2 | { 3 | public enum PackagingMode 4 | { 5 | VisualStudio, 6 | Minimal 7 | } 8 | } -------------------------------------------------------------------------------- /src/ClickTwice.Templating/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ClickTwice.Templating")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ClickTwice.Templating")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("f34d7ce7-5be7-4393-9f0c-8f23b8dbc05d")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/ClickTwice.Templating/TemplatePackageSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace ClickTwice.Templating 8 | { 9 | public class TemplatePackageSettings 10 | { 11 | public List Authors { get; set; } = new List(); 12 | public string Description { get; set; } 13 | public string Id { get; set; } 14 | public string Version { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/ClickTwice.Templating/TemplatePackager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using NuGet; 6 | 7 | namespace ClickTwice.Templating 8 | { 9 | public class TemplatePackager 10 | { 11 | public Uri PublishDestination { get; set; } = new Uri("http://nudev.azurewebsites.net"); 12 | private Manifest NuSpec { get; set; } 13 | public TemplatePackager(string id, string version, string authors, string description) 14 | { 15 | var manifest = new Manifest 16 | { 17 | Metadata = 18 | { 19 | Id = id, 20 | Version = version, 21 | Authors = authors, 22 | Description = description 23 | } 24 | }; 25 | NuSpec = manifest; 26 | } 27 | 28 | public TemplatePackager(TemplatePackageSettings settings) : this(settings.Id, settings.Version, string.Join(", ", settings.Authors), settings.Description) 29 | { 30 | } 31 | 32 | private void SetContentFiles(List contentFiles) 33 | { 34 | NuSpec.Files = new List(); 35 | contentFiles = contentFiles.Select(f => f.Contains("\\") ? f.Replace("\\", "/") : f).ToList(); 36 | NuSpec.Files.AddRange(contentFiles.Select(f => new ManifestFile() {Source = f, Target = $"content/{f}"})); 37 | } 38 | private IPackager Packager { get; set; } 39 | public FileInfo Package(string templateProjectDirectory, PackagingMode mode) 40 | { 41 | switch (mode) 42 | { 43 | case PackagingMode.VisualStudio: 44 | Packager = new VisualStudioPackager(); 45 | break; 46 | case PackagingMode.Minimal: 47 | Packager = new MinimalPackager(); 48 | break; 49 | default: 50 | throw new ArgumentOutOfRangeException(nameof(mode), mode, null); 51 | } 52 | var files = Packager.GetContentFiles(templateProjectDirectory); 53 | SetContentFiles(files); 54 | using (var stream = new FileStream(Path.Combine(templateProjectDirectory, "TemplatePackage.nuspec"), FileMode.Create)) 55 | { 56 | //NuSpec.Save(stream, validate: true); 57 | } 58 | //NuSpec.Save(new FileStream(Path.Combine(templateProjectDirectory, "TemplatePackage.nuspec"), FileMode.Create), validate: true); 59 | var package = BuildPackage(templateProjectDirectory); 60 | return package; 61 | } 62 | 63 | private FileInfo BuildPackage(string outputDirectory) 64 | { 65 | var builder = new PackageBuilder(); 66 | builder.Populate(NuSpec.Metadata); 67 | builder.PopulateFiles(outputDirectory, NuSpec.Files); 68 | var path = Path.Combine(outputDirectory, $"{NuSpec.Metadata.Id}.nupkg"); 69 | using ( 70 | FileStream stream = new FileStream(path, FileMode.Create)) 71 | { 72 | builder.Save(stream); 73 | } 74 | return new FileInfo(path); 75 | } 76 | 77 | public void PublishPackage(string pathToNupkg) 78 | { 79 | PublishPackage(pathToNupkg, System.Environment.GetEnvironmentVariable("ApiKey")); 80 | } 81 | 82 | public void PublishPackage(string pathToNupkg, string apiKey) 83 | { 84 | var fi = new FileInfo(pathToNupkg); 85 | var localRepo = PackageRepositoryFactory.Default.CreateRepository(fi.Directory.FullName); 86 | var package = localRepo.FindPackagesById(fi.Name.Replace(fi.Extension, string.Empty)).First(); 87 | var size = fi.Length; 88 | var ps = new PackageServer(PublishDestination.ToString(), "userAgent"); 89 | ps.PushPackage(apiKey, package, size, 1800, false); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/ClickTwice.Templating/VisualStudioPackager.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using System.Linq; 4 | using System.Xml; 5 | 6 | namespace ClickTwice.Templating 7 | { 8 | internal class VisualStudioPackager : IPackager 9 | { 10 | public List GetContentFiles(string rootDirectory) 11 | { 12 | var xml = new XmlDocument(); 13 | xml.Load(new DirectoryInfo(rootDirectory).GetFiles("*.csproj").First().FullName); 14 | XmlNamespaceManager mgr = new XmlNamespaceManager(xml.NameTable); 15 | mgr.AddNamespace("msb", "http://schemas.microsoft.com/developer/msbuild/2003"); 16 | var nodeList = xml.SelectNodes("//msb:Project/msb:ItemGroup/msb:Content", mgr); 17 | if (nodeList != null) 18 | { 19 | var contentFiles = 20 | nodeList.Cast() 21 | .Where(x => !string.IsNullOrWhiteSpace(x.Attributes?["Include"].Value)) 22 | .Select(x => x.Attributes["Include"].Value); 23 | return contentFiles.Where(f => !f.EndsWith("config")).ToList(); 24 | } 25 | return new List(); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/ClickTwice.Templating/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/ClickTwice.UpdateManager/ClickTwice.UpdateManager.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {27FECEED-7288-46CD-B2F2-A40936EFA312} 8 | Library 9 | Properties 10 | ClickTwice.UpdateManager 11 | ClickTwice.UpdateManager 12 | v4.5.2 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | ..\packages\Wpf.MvvmTools.1.0.3\lib\net45\MvvmTools.dll 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 69 | -------------------------------------------------------------------------------- /src/ClickTwice.UpdateManager/ClickTwice.UpdateManager.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ClickTwice.UpdateManager 5 | 1 6 | ClickTwice Update Manager (WPF) 7 | Alistair Chapman 8 | Alistair Chapman 9 | https://opensource.org/licenses/MIT 10 | https://github.com/agc93/clicktwice 11 | https://maxcdn.icons8.com/Color/PNG/96/Industry/engineering-96.png 12 | false 13 | A helper library for managing updates to ClickOnce-deployed applications. Provides a fully-fledged ViewModel for use in WPF apps allowing for granular control and visibility into application updates. This library is built around the standard System.Deployment update mechanisms. 14 | Copyright 2015. Icon by Icons8 15 | wpf mvvm clickonce deployment update upgrade 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/ClickTwice.UpdateManager/Extensions.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | 3 | namespace ClickTwice.UpdateManager 4 | { 5 | static class Extensions 6 | { 7 | public static string SplitCamelCase(this string str) 8 | { 9 | return Regex.Replace( 10 | Regex.Replace( 11 | str, 12 | @"(\P{Ll})(\P{Ll}\p{Ll})", 13 | "$1 $2" 14 | ), 15 | @"(\p{Ll})(\P{Ll})", 16 | "$1 $2" 17 | ); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/ClickTwice.UpdateManager/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("ClickTwice.UpdateManager")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("ClickTwice.UpdateManager")] 12 | [assembly: AssemblyCopyright("Copyright © 2015")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("27feceed-7288-46cd-b2f2-a40936efa312")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /src/ClickTwice.UpdateManager/UpdateEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ClickTwice.UpdateManager 4 | { 5 | public class UpdateEventArgs : EventArgs 6 | { 7 | public Version PreviousVersion { get; set; } 8 | public Version NewVersion { get; set; } 9 | public UpdateInfo UpdateInfo { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/ClickTwice.UpdateManager/UpdateInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ClickTwice.UpdateManager 4 | { 5 | public class UpdateInfo 6 | { 7 | public Version NewVersion { get; internal set; } 8 | public bool Mandatory { get; internal set; } 9 | public Version MinimumVersion { get; internal set; } 10 | public DownloadSize DownloadSize { get; internal set; } 11 | 12 | public Uri UpdateSource { get; internal set; } 13 | 14 | public string InfoMessage 15 | => 16 | $"New update available! New {(Mandatory ? "required update to" : string.Empty)} version {NewVersion.ToString(4)} ({DownloadSize} download)" 17 | ; 18 | } 19 | 20 | public class DownloadSize 21 | { 22 | private long ByteCount { get; set; } 23 | public DownloadSize(int bytes) 24 | { 25 | ByteCount = bytes; 26 | } 27 | 28 | public DownloadSize(long bytes) 29 | { 30 | ByteCount = bytes; 31 | } 32 | 33 | public long Bytes => ByteCount; 34 | 35 | public long Kilobytes => (ByteCount/1024); 36 | public long Megabytes => ((ByteCount/1024)/1024); 37 | public long Gigabytes => (((ByteCount/1024)/1024)/1024); 38 | public override string ToString() 39 | { 40 | return GetBytesReadable(ByteCount); 41 | } 42 | 43 | public string ToString(int places) 44 | { 45 | string suffix = "0."; 46 | for (int i = 0; i < places; i++) 47 | { 48 | suffix = suffix + "#"; 49 | } 50 | var format = suffix + " "; 51 | return GetBytesReadable(ByteCount, format); 52 | } 53 | 54 | // Returns the human-readable file size for an arbitrary, 64-bit file size 55 | // The default format is "0.### XB", e.g. "4.2 KB" or "1.434 GB" 56 | private string GetBytesReadable(long i, string format = "0.## ") 57 | { 58 | // Get absolute value 59 | long absolute_i = (i < 0 ? -i : i); 60 | // Determine the suffix and readable value 61 | string suffix; 62 | double readable; 63 | if (absolute_i >= 0x1000000000000000) // Exabyte 64 | { 65 | suffix = "EB"; 66 | readable = (i >> 50); 67 | } 68 | else if (absolute_i >= 0x4000000000000) // Petabyte 69 | { 70 | suffix = "PB"; 71 | readable = (i >> 40); 72 | } 73 | else if (absolute_i >= 0x10000000000) // Terabyte 74 | { 75 | suffix = "TB"; 76 | readable = (i >> 30); 77 | } 78 | else if (absolute_i >= 0x40000000) // Gigabyte 79 | { 80 | suffix = "GB"; 81 | readable = (i >> 20); 82 | } 83 | else if (absolute_i >= 0x100000) // Megabyte 84 | { 85 | suffix = "MB"; 86 | readable = (i >> 10); 87 | } 88 | else if (absolute_i >= 0x400) // Kilobyte 89 | { 90 | suffix = "KB"; 91 | readable = i; 92 | } 93 | else 94 | { 95 | return i.ToString("0 B"); // Byte 96 | } 97 | // Divide by 1024 to get fractional value 98 | readable = (readable / 1024); 99 | // Return formatted number with suffix 100 | return readable.ToString(format) + suffix; 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/ClickTwice.UpdateManager/UpdateManagerCommands.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Input; 2 | using MvvmTools; 3 | 4 | namespace ClickTwice.UpdateManager 5 | { 6 | public partial class UpdateManagerViewModel 7 | { 8 | public ICommand UpdateApplicationCommand => new RelayCommand(UpdateApp, o => IsUpdateAvailable); 9 | public ICommand CheckUpdatesCommand => new RelayCommand(CheckForUpdates, o => IsDeployed); 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/ClickTwice.UpdateManager/UpdateManagerEvents.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | 3 | namespace ClickTwice.UpdateManager 4 | { 5 | public partial class UpdateManagerViewModel 6 | { 7 | 8 | public event UpdateHandler UpdateCompleted; 9 | public event UpdateHandler UpdateStarting; 10 | private UpdateEventArgs e = null; 11 | 12 | public delegate void UpdateHandler(UpdateManagerViewModel m, UpdateEventArgs e); 13 | 14 | protected virtual void OnUpdateComplete() 15 | { 16 | e = new UpdateEventArgs 17 | { 18 | PreviousVersion = Assembly.GetExecutingAssembly().GetName().Version, 19 | NewVersion = UpdateInfo.NewVersion, 20 | UpdateInfo = UpdateInfo 21 | }; 22 | UpdateCompleted?.Invoke(this, e); 23 | } 24 | 25 | protected virtual void OnUpdateStarting() 26 | { 27 | e = new UpdateEventArgs 28 | { 29 | PreviousVersion = Assembly.GetExecutingAssembly().GetName().Version, 30 | NewVersion = UpdateInfo.NewVersion, 31 | UpdateInfo = UpdateInfo 32 | }; 33 | UpdateStarting?.Invoke(this, e); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/ClickTwice.UpdateManager/UpdateManagerProperties.cs: -------------------------------------------------------------------------------- 1 | using System.Deployment.Application; 2 | 3 | namespace ClickTwice.UpdateManager 4 | { 5 | public partial class UpdateManagerViewModel 6 | { 7 | private bool _isUpdateAvailable; 8 | private bool _isUpdateInProgress; 9 | private int _updateProgress; 10 | private string _updateProgressMessage; 11 | 12 | public bool IsDeployed => ApplicationDeployment.IsNetworkDeployed; 13 | 14 | public bool IsUpdateAvailable 15 | { 16 | get { return _isUpdateAvailable; } 17 | set 18 | { 19 | if (value == _isUpdateAvailable) return; 20 | _isUpdateAvailable = value; 21 | OnPropertyChanged(); 22 | } 23 | } 24 | 25 | public bool IsUpdateInProgress 26 | { 27 | get { return _isUpdateInProgress; } 28 | set 29 | { 30 | if (value == _isUpdateInProgress) return; 31 | _isUpdateInProgress = value; 32 | OnPropertyChanged(); 33 | } 34 | } 35 | 36 | #region Progress 37 | public int UpdateProgress 38 | { 39 | get { return _updateProgress; } 40 | set 41 | { 42 | if (value == _updateProgress) return; 43 | _updateProgress = value; 44 | OnPropertyChanged(); 45 | } 46 | } 47 | 48 | public string UpdateProgressMessage 49 | { 50 | get { return _updateProgressMessage; } 51 | set 52 | { 53 | if (value == _updateProgressMessage) return; 54 | _updateProgressMessage = value; 55 | OnPropertyChanged(); 56 | } 57 | } 58 | #endregion 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/ClickTwice.UpdateManager/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /src/ClickTwice.sln.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | True 3 | MS -------------------------------------------------------------------------------- /src/NuGet.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/ScriptCs.ClickTwice/ClickTwicePack.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Reflection; 4 | using ClickTwice.Publisher.Core; 5 | using ClickTwice.Publisher.Core.Loggers; 6 | using ClickTwice.Publisher.MSBuild; 7 | using Microsoft.VisualBasic.Logging; 8 | using ScriptCs.Contracts; 9 | 10 | namespace ScriptCs.ClickTwice 11 | { 12 | public class ClickTwicePack : IScriptPackContext 13 | { 14 | public Publisher PublishApp(string projectFilePath, Action configure = null) 15 | { 16 | configure?.Invoke(Settings); 17 | var host = new ConsoleScriptHost(); 18 | BasePublishManager mgr; 19 | if (Settings.UseDirectPublish) 20 | { 21 | mgr = new DirectPublisher(projectFilePath, ToSource(Settings)); 22 | } 23 | else 24 | { 25 | mgr = new PublishManager(projectFilePath, ToSource(Settings)); 26 | } 27 | mgr.Configuration = Settings.Configuration; 28 | mgr.Platform = Settings.Platform; 29 | mgr.CleanOutputOnCompletion = Settings.OutputClean; 30 | mgr.InputHandlers = Settings.InputHandlers; 31 | mgr.OutputHandlers = Settings.OutputHandlers; 32 | mgr.Loggers = Settings.Loggers; 33 | mgr.Loggers.RemoveAll(l => l.GetType() == typeof(ConsoleLogger)); 34 | mgr.Loggers.Add(new ConsoleLogger(Settings.LogBuildMessages)); 35 | if (!string.IsNullOrWhiteSpace(Settings.PublishVersion)) 36 | { 37 | mgr.AdditionalProperties.Add("ApplicationVersion", Settings.PublishVersion); 38 | } 39 | return new Publisher(mgr) {Host = host}; 40 | } 41 | 42 | public void Configure(Action configure) 43 | { 44 | configure.Invoke(Settings); 45 | } 46 | 47 | public ScriptTemplatePublisher PublishTemplate(string templateDirectory) 48 | { 49 | return new ScriptTemplatePublisher(templateDirectory); 50 | } 51 | 52 | private ClickTwicePackSettings Settings { get; set; } = new ClickTwicePackSettings(); 53 | 54 | [System.Diagnostics.CodeAnalysis.SuppressMessage("ReSharper", "ConvertIfStatementToReturnStatement")] 55 | private static InformationSource ToSource(ClickTwicePackSettings settings) 56 | { 57 | if (settings.UseAppManifest && settings.UseAssemblyInfo) return InformationSource.Both; 58 | if (settings.UseAppManifest) return InformationSource.AppManifest; 59 | if (settings.UseAssemblyInfo) return InformationSource.AssemblyInfo; 60 | return InformationSource.None; 61 | } 62 | 63 | private System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) 64 | { 65 | var assemblyName = args.Name.Split(',').FirstOrDefault(); 66 | Console.WriteLine($"Resolving {assemblyName}"); 67 | return assemblyName == null ? Assembly.Load(args.Name) : Assembly.Load(assemblyName); 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /src/ScriptCs.ClickTwice/ClickTwicePackSettings.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using ClickTwice.Publisher.Core.Handlers; 3 | using ClickTwice.Publisher.Core.Loggers; 4 | 5 | namespace ScriptCs.ClickTwice 6 | { 7 | public class ClickTwicePackSettings 8 | { 9 | public ClickTwicePackSettings WithHandler(IHandler handler) 10 | { 11 | var input = handler as IInputHandler; 12 | var output = handler as IOutputHandler; 13 | if (input != null) 14 | { 15 | InputHandlers.Add(input); 16 | } 17 | if (output != null) 18 | { 19 | OutputHandlers.Add(output); 20 | } 21 | return this; 22 | } 23 | 24 | public ClickTwicePackSettings WithLogger(IPublishLogger logger) 25 | { 26 | Loggers.Add(logger); 27 | return this; 28 | } 29 | 30 | public ClickTwicePackSettings LogTo(IPublishLogger logger) 31 | { 32 | WithLogger(logger); 33 | return this; 34 | } 35 | 36 | public ClickTwicePackSettings SetConfiguration(string configuration) 37 | { 38 | this.Configuration = configuration; 39 | return this; 40 | } 41 | 42 | public ClickTwicePackSettings SetPlatform(string platform) 43 | { 44 | Platform = platform; 45 | return this; 46 | } 47 | 48 | public ClickTwicePackSettings PreserveBuildOutput() 49 | { 50 | OutputClean = false; 51 | return this; 52 | } 53 | 54 | public ClickTwicePackSettings EnableBuildMessages() 55 | { 56 | LogBuildMessages = true; 57 | return this; 58 | } 59 | 60 | public ClickTwicePackSettings UseIntegratedMsBuild() 61 | { 62 | UseDirectPublish = false; 63 | return this; 64 | } 65 | 66 | public ClickTwicePackSettings UseAssemblyInfoMetadata(bool useAssemblyInfo = true) 67 | { 68 | UseAssemblyInfo = useAssemblyInfo; 69 | return this; 70 | } 71 | 72 | public ClickTwicePackSettings UseAppManifestMetadata(bool useMetadata = true) 73 | { 74 | UseAppManifest = useMetadata; 75 | return this; 76 | } 77 | 78 | public ClickTwicePackSettings WithVersion(string version) 79 | { 80 | PublishVersion = version; 81 | return this; 82 | } 83 | 84 | internal bool LogBuildMessages { get; set; } 85 | 86 | internal bool OutputClean { get; set; } = true; 87 | 88 | internal string Platform { get; set; } = "AnyCPU"; 89 | 90 | internal string Configuration { get; set; } = "Release"; 91 | 92 | internal bool UseDirectPublish { get; set; }= true; 93 | 94 | internal bool UseAssemblyInfo { get; set; } 95 | 96 | internal bool UseAppManifest { get; set; } = true; 97 | 98 | internal string PublishVersion { get; set; } = string.Empty; 99 | 100 | internal List Loggers { get; set; } = new List(); 101 | 102 | internal List OutputHandlers { get; set; } = new List(); 103 | 104 | internal List InputHandlers { get; set; } = new List(); 105 | } 106 | } -------------------------------------------------------------------------------- /src/ScriptCs.ClickTwice/ConsoleScriptHost.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using static System.Console; 7 | 8 | namespace ScriptCs.ClickTwice 9 | { 10 | class ConsoleScriptHost : IScriptHost 11 | { 12 | public void Log(string message) 13 | { 14 | Console.WriteLine(message); 15 | } 16 | 17 | public void Error(string message) 18 | { 19 | var oldColor = ForegroundColor; 20 | ForegroundColor = ConsoleColor.Red; 21 | WriteLine(message); 22 | ForegroundColor = oldColor; 23 | } 24 | 25 | public string GetCurrentPath() 26 | { 27 | return Environment.CurrentDirectory; 28 | } 29 | 30 | public void ExitWithException(Exception ex, int exitCode = 1) 31 | { 32 | Error("====================="); 33 | Error(ex.Message); 34 | Error("====================="); 35 | Environment.Exit(exitCode); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/ScriptCs.ClickTwice/IScriptHost.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace ScriptCs.ClickTwice 8 | { 9 | public interface IScriptHost 10 | { 11 | void Log(string message); 12 | void Error(string message); 13 | string GetCurrentPath(); 14 | void ExitWithException(Exception ex, int exitCode = 1); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/ScriptCs.ClickTwice/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ScriptCs.ClickTwice")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ScriptCs.ClickTwice")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("bb0e350d-e8f5-4deb-baa9-14eda2c8d6df")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/ScriptCs.ClickTwice/Publisher.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using ClickTwice.Publisher.Core; 4 | using ClickTwice.Publisher.Core.Exceptions; 5 | using ClickTwice.Publisher.Core.Handlers; 6 | 7 | namespace ScriptCs.ClickTwice 8 | { 9 | public class Publisher 10 | { 11 | 12 | internal Publisher(IPublishManager mgr) 13 | { 14 | Manager = mgr; 15 | } 16 | 17 | internal IScriptHost Host { private get; set; } 18 | 19 | public void To(string outputPath) 20 | { 21 | try 22 | { 23 | Host?.Log($"Publishing to {outputPath}"); 24 | Manager.PublishApp(outputPath); 25 | Host?.Log("Publish operation completed!"); 26 | } 27 | catch (HandlerProcessingException ex) 28 | { 29 | Host?.Error(string.Join(Environment.NewLine, ex.HandlerResponses.Where(r => r.Result == HandlerResult.Error).Select(r => $"{r.Handler.Name} - {r.ResultMessage}"))); 30 | } 31 | } 32 | 33 | private IPublishManager Manager { get; set; } 34 | } 35 | } -------------------------------------------------------------------------------- /src/ScriptCs.ClickTwice/Samples.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using ClickTwice.Publisher.Core.Loggers; 7 | 8 | namespace ScriptCs.ClickTwice 9 | { 10 | class Samples 11 | { 12 | private void Sample() 13 | { 14 | ClickTwicePack pack = null; 15 | pack.Configure(s => s.WithLogger(new ConsoleLogger())); 16 | pack.PublishApp("./path/to/project.proj").To("./artifacts/publish"); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/ScriptCs.ClickTwice/ScriptCs.ClickTwice.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {BB0E350D-E8F5-4DEB-BAA9-14EDA2C8D6DF} 8 | Library 9 | Properties 10 | ScriptCs.ClickTwice 11 | ScriptCs.ClickTwice 12 | v4.6 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | 36 | ..\packages\ScriptCs.Contracts.0.17.1\lib\net45\ScriptCs.Contracts.dll 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | {af189adc-d4a9-4a30-aa12-d5cfd96523be} 62 | ClickTwice.Publisher.Core 63 | 64 | 65 | {a0a4508d-c0b8-4f18-a61f-7d5b98e0aef6} 66 | ClickTwice.Publisher.MSBuild 67 | 68 | 69 | {f34d7ce7-5be7-4393-9f0c-8f23b8dbc05d} 70 | ClickTwice.Templating 71 | 72 | 73 | 74 | 75 | 76 | 77 | 84 | -------------------------------------------------------------------------------- /src/ScriptCs.ClickTwice/ScriptCs.ClickTwice.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ScriptCs.ClickTwice 5 | ClickTwice Publisher for ScriptCs 6 | Alistair Chapman 7 | achapman 8 | https://opensource.org/licenses/MIT 9 | https://github.com/agc93/clicktwice 10 | https://maxcdn.icons8.com/Color/PNG/96/Industry/engineering-96.png 11 | false 12 | ScriptCs host for ClickTwice publishing, including the script pack 13 | Copyright 2016 14 | clicktwice publish clickonce wpf msbuild scriptcs build 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 29 | 30 | -------------------------------------------------------------------------------- /src/ScriptCs.ClickTwice/ScriptPack.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using ScriptCs.Contracts; 4 | 5 | namespace ScriptCs.ClickTwice 6 | { 7 | public class ScriptPack : ScriptPack 8 | { 9 | public override void Initialize(IScriptPackSession session) 10 | { 11 | session.ImportNamespace("ScriptCs.ClickTwice"); 12 | 13 | //session.AddMSBuildReferences(); 14 | session.AddClickTwiceReferences(); 15 | base.Initialize(session); 16 | AppDomain.CurrentDomain.AssemblyLoad += CurrentDomain_AssemblyLoad; 17 | AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; 18 | } 19 | 20 | private System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) 21 | { 22 | if (args.Name.StartsWith("Microsoft.Build")) 23 | { 24 | Console.WriteLine($"== {args.Name}"); 25 | } 26 | return null; 27 | } 28 | 29 | private void CurrentDomain_AssemblyLoad(object sender, AssemblyLoadEventArgs args) 30 | { 31 | if (args.LoadedAssembly.FullName.StartsWith("Microsoft.Build")) 32 | { 33 | Console.WriteLine($"++ {args.LoadedAssembly.FullName}"); 34 | } 35 | } 36 | 37 | public override IScriptPackContext GetContext() 38 | { 39 | return new ClickTwicePack(); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/ScriptCs.ClickTwice/ScriptTemplatePublisher.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using ClickTwice.Templating; 4 | 5 | namespace ScriptCs.ClickTwice 6 | { 7 | public class ScriptTemplatePublisher : ITemplatePublisher 8 | { 9 | public ScriptTemplatePublisher(string templateDirectory) 10 | { 11 | TemplateDirectory = templateDirectory; 12 | } 13 | 14 | private string TemplateDirectory { get; } 15 | 16 | public ScriptTemplatePublisher SetMetadata(string id, string version, string author, string description = null) 17 | { 18 | Metadata = new TemplatePackageSettings() 19 | { 20 | Id = id, 21 | Version = version, 22 | Description = description, 23 | Authors = author.Split(',', ';').ToList() 24 | }; 25 | return this; 26 | } 27 | 28 | public TemplatePackageSettings Metadata { get; private set; } 29 | 30 | public ScriptTemplatePublisher SetMetadata(TemplatePackageSettings settings) 31 | { 32 | Metadata = settings; 33 | return this; 34 | } 35 | 36 | public ScriptTemplatePublisher EnableVisualStudioMode() 37 | { 38 | PackagingMode = PackagingMode.VisualStudio; 39 | return this; 40 | } 41 | 42 | public PackagingMode PackagingMode { get; set; } = PackagingMode.Minimal; 43 | 44 | public ITemplatePublisher ToPackageFile(string outputPath) 45 | { 46 | var mgr = new TemplatePackager(Metadata); 47 | var fi = mgr.Package(TemplateDirectory, PackagingMode); 48 | fi.CopyTo(outputPath); 49 | return this; 50 | } 51 | 52 | public ITemplatePublisher ToGallery(string apiKey = null, string galleryUri = null) 53 | { 54 | var mgr = new TemplatePackager(Metadata) 55 | { 56 | PublishDestination = new Uri(galleryUri ?? "https://nuget.org/api/v2") 57 | }; 58 | if (apiKey == null) 59 | { 60 | mgr.PublishPackage(mgr.Package(TemplateDirectory, PackagingMode).FullName); 61 | } 62 | else 63 | { 64 | mgr.PublishPackage(mgr.Package(TemplateDirectory, PackagingMode).FullName, apiKey); 65 | } 66 | return this; 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /src/ScriptCs.ClickTwice/SessionExtensions.cs: -------------------------------------------------------------------------------- 1 | using ClickTwice.Publisher.MSBuild; 2 | using ScriptCs.Contracts; 3 | 4 | namespace ScriptCs.ClickTwice 5 | { 6 | internal static class SessionExtensions 7 | { 8 | internal static void AddMSBuildReferences(this IScriptPackSession session) 9 | { 10 | session.AddReference(MSBuildResolver.GetBuildAssemblyPath("Microsoft.Build")); 11 | session.AddReference(MSBuildResolver.GetBuildAssemblyPath("Microsoft.Build.Framework")); 12 | session.AddReference(MSBuildResolver.GetBuildAssemblyPath("Microsoft.Build.Tasks") ?? 13 | MSBuildResolver.GetBuildAssemblyPath("Microsoft.Build.Tasks.Core") ?? 14 | MSBuildResolver.GetBuildAssemblyPath("Microsoft.Build.Tasks.v4.0")); 15 | session.AddReference(MSBuildResolver.GetBuildAssemblyPath("Microsoft.Build.Utilities.Core") ?? 16 | MSBuildResolver.GetBuildAssemblyPath("Microsoft.Build.Utilities") ?? 17 | MSBuildResolver.GetBuildAssemblyPath("Microsoft.Build.Utilities.v4.0")); 18 | 19 | session.ImportNamespace("Microsoft.Build"); 20 | session.ImportNamespace("Microsoft.Build.Framework"); 21 | session.ImportNamespace("Microsoft.Build.Evaluation"); 22 | session.ImportNamespace("Microsoft.Build.Execution"); 23 | } 24 | 25 | internal static void AddClickTwiceReferences(this IScriptPackSession session) 26 | { 27 | session.AddReference("ClickTwice.Publisher.Core"); 28 | //session.AddReference("ClickTwice.Handlers.AppDetailsPage"); 29 | session.AddReference("ClickTwice.Templating"); 30 | 31 | session.ImportNamespace("ClickTwice.Publisher.Core"); 32 | session.ImportNamespace("ClickTwice.Publisher.Core.Resources"); 33 | session.ImportNamespace("ClickTwice.Publisher.Core.Handlers"); 34 | session.ImportNamespace("ClickTwice.Publisher.Core.Loggers"); 35 | session.ImportNamespace("ClickTwice.Templating"); 36 | //session.ImportNamespace("ClickTwice.Handlers.AppDetailsPage"); 37 | //TODO reenable 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /src/ScriptCs.ClickTwice/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /src/TestApp/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/TestApp/Program.cs: -------------------------------------------------------------------------------- 1 | using ClickTwice.Publisher.Core; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | using System.IO; 6 | using System.Linq; 7 | using ClickTwice.Handlers.AppDetailsPage; 8 | using ClickTwice.Publisher.Core.Handlers; 9 | using ClickTwice.Publisher.Core.Loggers; 10 | using ClickTwice.Publisher.MSBuild; 11 | using ClickTwice.Templating; 12 | 13 | namespace TestApp 14 | { 15 | internal class Program 16 | { 17 | private static string DefaultProjectPath { get; set; } = 18 | //@"C:\Users\UCRM4\Source\ACN\TFSShowcase\src\ScreenshotReportCreator\ScreenshotReportCreator.csproj"; // ATO 19 | //@"C:\Users\alist_000\Source\ACN\TFSShowcase\src\ScreenshotReportCreator\ScreenshotReportCreator.csproj"; //others 20 | //@"C:\Users\alist\Source\ACN\TFSShowcase\src\ScreenshotReportCreator\ScreenshotReportCreator.csproj"; // Zenbook 21 | //@"C:\Users\alist_000\Source\ACN\myTaxFramework\FormDocuments\DocumentConversion\DocumentConversion.csproj"; 22 | @"C:\Users\alist\Source\ACN\myTaxFramework\FormDocuments\DocumentConversion\DocumentConversion.csproj"; 23 | //@"C:\Users\UCRM4\Source\ACN\myTaxFramework\FormDocuments\DocumentConversion\DocumentConversion.csproj"; 24 | 25 | private static void Main(string[] args) 26 | { 27 | var packager = new TemplatePackager("ClickTwice.Templates.SolidState", "0.0.1", "Alistair Chapman", 28 | "ClickTwice Template using the HTML5UP Solid State design"); 29 | //var package = packager.Package(@"C:\Users\alist\Source\ClickTwice\src\ClickTwice.Templates.SolidState", PackagingMode.VisualStudio); 30 | var package = packager.Package(@"C:\Users\alist\Source\TEMP\solid-state", PackagingMode.Minimal); 31 | var handler = new AppDetailsPageHandler(package); 32 | if (args.Any()) 33 | { 34 | DefaultProjectPath = args.First(); 35 | } 36 | var log = new ConsoleLogger(); 37 | var file = new FileLogger(); 38 | var info = new AppInfoManager(); 39 | var infoHandler = new AppInfoHandler(); 40 | BuildInfo(info); 41 | var mgr = new PublishManager(DefaultProjectPath, InformationSource.Both) 42 | { 43 | Platform = "AnyCPU", 44 | Configuration = "Debug", 45 | InputHandlers = new List {infoHandler}, 46 | OutputHandlers = new List {infoHandler, new PublishPageHandler(), new InstallPageHandler("install.htm"), handler }, 47 | Loggers = new List { log, file } 48 | }; 49 | // ReSharper disable once RedundantArgumentDefaultValue 50 | var path = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"))); 51 | var result = mgr.PublishApp(path.FullName, behaviour: PublishBehaviour.CleanFirst); 52 | //var manager = new ManifestManager(DefaultProjectPath, path.FullName, InformationSource.Both); 53 | //var manifest = manager.CreateAppManifest(); 54 | //var cltw = manager.DeployManifest(manifest); 55 | Process.Start(path.FullName); 56 | Console.WriteLine(result.Select(r => $"{r.Handler.Name} - {r.Result} - {r.ResultMessage}" + Environment.NewLine)); 57 | } 58 | 59 | private static void BuildInfo(AppInfoManager info) 60 | { 61 | info.AddAuthor("Alistair Chapman"); 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /src/TestApp/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("TestApp")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("TestApp")] 12 | [assembly: AssemblyCopyright("Copyright © 2016")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("8a9ef8f0-60ec-4ddf-a89f-271b382e910c")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /tools/Modules/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /tools/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /usage.cake: -------------------------------------------------------------------------------- 1 | //#r "src/packages/Newtonsoft.Json.8.0.2/lib/net45/Newtonsoft.Json.dll" 2 | #r "artifacts/build/Cake.ClickTwice/Cake.ClickTwice.dll" 3 | //#r "artifacts/ClickTwice.dll" 4 | #r "artifacts/lib/ClickTwice.Publisher.Core/ClickTwice.Publisher.Core.dll" 5 | 6 | #r "artifacts/lib/ClickTwice.Handlers.AppDetailsPage/ClickTwice.Handlers.AppDetailsPage.dll" 7 | 8 | var target = Argument("target", "Publish"); 9 | //using ClickTwice.Handlers.AppDetailsPage; 10 | //using ClickTwice.Publisher.Core.Handlers; 11 | //using ClickTwice.Publisher.Core; 12 | 13 | var projectPath = File(@"./path/to/the/project.proj"); 14 | 15 | Setup(ctx => 16 | { 17 | // Executed BEFORE the first task. 18 | Information("Running tasks..."); 19 | CleanDirectory("./artifacts/publish"); 20 | CreateDirectory("./artifacts/publish"); 21 | }); 22 | 23 | Task("Publish") 24 | .Does(() => 25 | { 26 | PublishApp(projectPath) 27 | .SetConfiguration("Debug") 28 | .ThrowOnHandlerFailure() 29 | .WithHandler(new AppInfoHandler(new AppInfoManager())) 30 | .WithHandler(new AppDetailsPageHandler("ClickTwice.Templates.SolidState") { 31 | FileNameMap = new Dictionary { 32 | {"index.html", "details.html"} 33 | } 34 | }) 35 | .WithHandler(new InstallPageHandler(fileName: "index.html", linkText: "Details", linkTarget: "details.html")) 36 | .PublishTo("./artifacts/publish/"); 37 | }); 38 | 39 | Task("Long-Form") 40 | .Does(() => { 41 | var handler = new AppInfoHandler(new AppInfoManager()); 42 | ClickTwice.RunInputHandlers(projectPath, handler); 43 | MSBuild(projectPath, settings => 44 | settings.SetPlatformTarget(PlatformTarget.MSIL) 45 | .WithProperty("PublishDir", Directory("./artifacts/publish").Path.MakeAbsolute(Context.Environment).ToString() + "\\") 46 | .SetVerbosity(Verbosity.Quiet) 47 | .WithTarget("Build") 48 | .WithTarget("Publish") 49 | .SetConfiguration("Debug")); 50 | //build here 51 | ClickTwice.GenerateManifest(projectPath).Publish("./artifacts/publish"); 52 | ClickTwice.RunOutputHandlers("./artifacts/publish", handler, new InstallPageHandler()); 53 | }); 54 | 55 | Task("Template-Publishing") 56 | .Does(() => { 57 | ClickTwice.PublishTemplate("./artifacts/template/", s => 58 | s.AddAuthor("Alistair Chapman") 59 | .UsePackageId("TemplatePackage") 60 | .UseVersion("0.0.1") 61 | .UseDescription("Optional description")) 62 | .ToPackageFile("artifacts/publish.nupkg") 63 | .ToGallery(galleryUri: "http://nuget.org/api/v2"); 64 | }); 65 | 66 | RunTarget(target); -------------------------------------------------------------------------------- /usage.csx: -------------------------------------------------------------------------------- 1 | var pack = Require(); 2 | 3 | pack.Configure(s => 4 | s 5 | .SetConfiguration("Debug") 6 | .WithHandler(new AppInfoHandler(new AppInfoManager())) 7 | .WithHandler(new InstallPageHandler(fileName: "index.html", linkText: "Details", linkTarget: "details.html")) 8 | ); 9 | pack.PublishApp(@"C:\Users\alist\Source\ACN\myTaxFramework\FormDocuments\DocumentConversion\DocumentConversion.csproj").To("./artifacts/publish"); 10 | 11 | PublishTemplate("C:/path/to/template/directory") 12 | .SetMetadata("Package.Id", "0.0.1", "Author Name") 13 | .ToPackageFile("artifacts/publish.nupkg") 14 | .ToGallery(galleryUri: "http://nuget.org/api/v2"); --------------------------------------------------------------------------------