diff --git a/.gitignore b/.gitignore
index 2176ca2..88d444c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+OutputRoot/
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
diff --git a/PecanWaffleSamplesVs/Properties/pecan-waffle-settings.props b/PecanWaffleSamplesVs/Properties/pecan-waffle-settings.props
index bcb1002..0f9a508 100644
--- a/PecanWaffleSamplesVs/Properties/pecan-waffle-settings.props
+++ b/PecanWaffleSamplesVs/Properties/pecan-waffle-settings.props
@@ -7,7 +7,7 @@
Output\ProjectTemplates\CSharp\Pecan Waffle\Multi Project Samples\
false
..\packages\
- $(MSBuildProjectDirectory)\templates\
+ $(MSBuildProjectDirectory)\..\templates\
\ No newline at end of file
diff --git a/appveyor.ps1 b/appveyor.ps1
new file mode 100644
index 0000000..12c46f3
--- /dev/null
+++ b/appveyor.ps1
@@ -0,0 +1,20 @@
+$env:ExitOnPesterFail = $true
+$env:IsDeveloperMachine=$true
+$env:PSBUlidEnableMaskingSecretsInPSCmdlets=$false
+
+(new-object Net.WebClient).DownloadString("https://raw.github.com/madskristensen/ExtensionScripts/master/AppVeyor/vsix.ps1") | iex
+if($env:APPVEYOR_REPO_BRANCH -eq "release"){
+ # install vsixgallery script
+ Vsix-IncrementVsixVersion | Vsix-UpdateBuildVersion
+
+ .\build.ps1
+
+ if ($env:APPVEYOR_REPO_NAME -eq "VSSolutionTemplates/VSSolutionTemplates") {
+ Vsix-PublishToGallery
+ }
+}
+else {
+ .\build.ps1
+}
+
+Vsix-PushArtifacts
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 0000000..68db4a5
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,9 @@
+os: Visual Studio 2015
+
+configuration: Release
+
+build_script:
+ - ps: .\appveyor.ps1
+
+artifacts:
+ - path: 'OutputRoot\\**\*.vsix'
\ No newline at end of file
diff --git a/build.ps1 b/build.ps1
new file mode 100644
index 0000000..97e7680
--- /dev/null
+++ b/build.ps1
@@ -0,0 +1,140 @@
+[cmdletbinding(DefaultParameterSetName='build')]
+param(
+ [Parameter(ParameterSetName='build',Position=1)]
+ [string]$configuration = 'Release',
+
+ [Parameter(ParameterSetName='build',Position=2)]
+ [System.IO.DirectoryInfo]$outputPath,
+
+ [Parameter(ParameterSetName='build',Position=3)]
+ [switch]$cleanBeforeBuild,
+
+ [Parameter(ParameterSetName='build',Position=3)]
+ [switch]$buildAllProjects,
+
+ # clean parameters
+ [Parameter(ParameterSetName='clean',Position=0)]
+ [switch]$clean
+)
+
+Set-StrictMode -Version Latest
+
+function Get-ScriptDirectory{
+ split-path (((Get-Variable MyInvocation -Scope 1).Value).MyCommand.Path)
+}
+$scriptDir = ((Get-ScriptDirectory) + "\")
+
+if([string]::IsNullOrWhiteSpace($outputPath)){
+ $outputPath = (Join-Path $scriptDir 'OutputRoot')
+}
+
+$env:GeoffreyBinPath = $outputPath
+[string]$slnFile = (get-item(Join-Path $scriptDir 'PecanWaffle.sln')).FullName
+[string]$sln2File = (get-item(join-path $scriptDir 'templates\MultiprojTemplates01\MultiprojTemplates01.sln')).FullName
+
+function EnsurePsbuildInstlled{
+ [cmdletbinding()]
+ param(
+ [string]$psbuildInstallUri = 'https://raw.githubusercontent.com/ligershark/psbuild/master/src/GetPSBuild.ps1'
+ )
+ process{
+ if(-not (Get-Command "Invoke-MsBuild" -errorAction SilentlyContinue)){
+ 'Installing psbuild from [{0}]' -f $psbuildInstallUri | Write-Verbose
+ (new-object Net.WebClient).DownloadString($psbuildInstallUri) | iex
+ }
+
+ # make sure it's loaded and throw if not
+ if(-not (Get-Command "Invoke-MsBuild" -errorAction SilentlyContinue)){
+ throw ('Unable to install/load psbuild from [{0}]' -f $psbuildInstallUri)
+ }
+ }
+}
+
+[hashtable]$buildProperties = @{
+ 'Configuration'=$configuration
+ 'DeployExtension'='false'
+ 'OutputPath'=$outputPath.FullName
+ 'VisualStudioVersion'='14.0'
+}
+
+function Build-Projects{
+ [cmdletbinding()]
+ param()
+ process {
+ $env:IsDeveloperMachine=$true
+ if($outputPath -eq $null){throw 'outputpath is null'}
+
+ [string[]]$projectToBuild = $slnFile
+ if( $buildAllProjects -eq $true){
+ $projectToBuild += $slnFile
+ }
+
+ foreach($file in $projectToBuild){
+ if(-not (Test-Path $file)){
+ throw ('Could not find the project to build at [{0}]' -f $file)
+ }
+ }
+
+ if(-not (Test-Path $OutputPath)){
+ 'Creating output folder [{0}]' -f $outputPath | Write-Output
+ New-Item -Path $outputPath -ItemType Directory
+ }
+
+ Invoke-MSBuild $projectToBuild -properties $buildProperties
+ }
+}
+
+function Clean{
+ [cmdletbinding()]
+ param()
+ process {
+ [System.IO.FileInfo]$projectToBuild = $slnFile
+
+ if(-not (Test-Path $projectToBuild)){
+ throw ('Could not find the project to build at [{0}]' -f $projectToBuild)
+ }
+
+ Invoke-MSBuild $projectToBuild -targets Clean -properties $buildProperties
+
+ [System.IO.DirectoryInfo[]]$foldersToDelete = (Get-ChildItem $scriptDir -Include bin,obj -Recurse -Directory)
+ $foldersToDelete += $outputPath
+
+ foreach($folder in $foldersToDelete){
+ if(Test-Path $folder){
+ Remove-Item $folder -Recurse -Force
+ }
+ }
+ }
+}
+
+function RestoreNuGetPackages(){
+ [cmdletbinding()]
+ param()
+ process{
+ Push-Location
+ try{
+ 'restoring nuget packages' | Write-Output
+ Set-Location (get-item ($slnfile)).Directory.FullName
+ Invoke-CommandString -command (get-nuget) -commandArgs restore
+
+ Set-Location (get-item ($sln2File)).Directory.FullName
+ Invoke-CommandString -command (get-nuget) -commandArgs restore
+ }
+ finally{
+ Pop-Location
+ }
+ }
+}
+
+
+# being script
+try{
+ EnsurePsbuildInstlled
+ Import-NuGetPowershell
+ RestoreNuGetPackages
+ Build-Projects
+}
+catch{
+ "Build failed with an exception:`n`n{0}`n`n{1}`n`n{2}" -f ($_.Exception),(Get-PSCallStack|Out-String),($Error|Out-String) | Write-Error
+ exit 1
+}
diff --git a/readme.md b/readme.md
new file mode 100644
index 0000000..ab72459
--- /dev/null
+++ b/readme.md
@@ -0,0 +1 @@
+[](https://ci.appveyor.com/project/sayedihashimi/pecan-waffle-samples)
\ No newline at end of file
diff --git a/templates/MultiprojTemplates01/_project.vstemplate b/templates/MultiprojTemplates01/_project.vstemplate
new file mode 100644
index 0000000..87ce952
--- /dev/null
+++ b/templates/MultiprojTemplates01/_project.vstemplate
@@ -0,0 +1,32 @@
+
+
+
+ Contoso Zebra
+ Multi project template demo
+ Zebra
+ CSharp
+
+ 1000
+ true
+ true
+ Enabled
+ true
+ sw-file-icon.png
+ 13f73839-d148-4d9d-97df-1281d67a14ea
+
+ 1
+
+
+ PecanWaffleSamplesVs, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
+ PecanWaffleSamplesVs.SolutionWizard
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/templates/MultiprojTemplates01/pw-templateinfo.ps1 b/templates/MultiprojTemplates01/pw-templateinfo.ps1
new file mode 100644
index 0000000..3371028
--- /dev/null
+++ b/templates/MultiprojTemplates01/pw-templateinfo.ps1
@@ -0,0 +1,62 @@
+[cmdletbinding()]
+param()
+
+$templateInfo = New-Object -TypeName psobject -Property @{
+ Name = 'ContosoZebra'
+ Type = 'ProjectTemplate'
+ DefaultProjectName = 'Zebra'
+ CreateNewFolder = $false
+ AfterInstall = {
+ Update-PWPackagesPathInProjectFiles -slnRoot ($SolutionRoot)
+ }
+}
+
+$templateInfo | replace (
+ ('Contoso', {"$ProjectName"}, {"$DefaultProjectName"}),
+
+ ('2ADA6741-AB4A-4283-BA8B-DE88E003B934', {"$ProjectId"}, {[System.Guid]::NewGuid()},@("*.*proj")),
+ ('278808B0-B3F3-4883-9A84-2B6429925011', {"$ProjectId"}, {[System.Guid]::NewGuid()},@("*.*proj")),
+ ('16481A0B-2B4B-484F-97BC-7AA09422AF8C', {"$ProjectId"}, {[System.Guid]::NewGuid()},@("*.*proj")),
+ ('74CA4CD8-C186-47D5-91A5-D59836037C0D', {"$ProjectId"}, {[System.Guid]::NewGuid()},@("*.*proj")),
+ ('751ACB67-5C02-4232-B562-8E2D90A1D5CE', {"$ProjectId"}, {[System.Guid]::NewGuid()},@("*.*proj")),
+ ('6154DCBD-66FD-4FDA-98F5-AB85D0C13A99', {"$ProjectId"}, {[System.Guid]::NewGuid()},@("*.*proj")),
+ ('FC2E39BF-7F1F-471E-895A-C9A7CAC2E54A', {"$ProjectId"}, {[System.Guid]::NewGuid()},@("*.*proj")),
+ ('66095F59-BE7A-48D8-8643-FFF894E66B4F', {"$ProjectId"}, {[System.Guid]::NewGuid()},@("*.*proj"))
+)
+
+# when the template is run any filename with the given string will be updated
+$templateInfo | update-filename (
+ ,('Contoso', {"$ProjectName"}<#,$null,@('.csproj','.bak','.projitems','.shproj','.cs')#>)
+)
+# excludes files from the template
+$templateInfo | exclude-file 'pw-*.*','*.user','*.suo','*.userosscache','project.lock.json','*.vs*scc','*.sln'
+# excludes folders from the template
+$templateInfo | exclude-folder '.vs','artifacts','packages','bin','obj'
+
+# This will register the template with pecan-waffle
+Set-TemplateInfo -templateInfo $templateInfo
+
+<#
+Use this one-liner to figure out the include expression for the project name
+>Get-ChildItem .\templates * -Recurse -File|select-string 'Contoso' -SimpleMatch|Select-Object -ExpandProperty path -Unique|% { Get-Item $_ | Select-Object -ExpandProperty extension}|Select-Object -Unique|%{ Write-Host "'$_';" -NoNewline }
+
+
+'.sln';'.vstemplate';'.csproj';'.bak';'.cs';'.xml';'.plist';'.projitems';'.shproj';'.xaml';'.config';'.pubxml';'.appxmanifest'
+
+Use this one-liner to figure out the guids in your template
+> Get-ChildItem .\templates *.*proj -Recurse -File|Select-Object -ExpandProperty fullname -Unique|% { ([xml](Get-Content $_)).Project.PropertyGroup.ProjectGuid|Select-Object -Unique|%{ '({0}, {{"$ProjectId"}}, [System.Guid]::NewGuid(),@("*.*proj")),' -f $_ }}
+
+({8EBB17C5-5B87-466B-99BE-709C04F71BC8}, {"$ProjectId"}, {[System.Guid]::NewGuid()},@("*.*proj")),
+({B095DC2E-19D7-4852-9450-6774808B626E}, {"$ProjectId"}, {[System.Guid]::NewGuid()},@("*.*proj")),
+(e651c0cb-f5fb-4257-9289-ef45f3c1a02c, {"$ProjectId"}, {[System.Guid]::NewGuid()},@("*.*proj")),
+(1dfffd59-6b32-4937-bfde-1e10c11d22c3, {"$ProjectId"}, {[System.Guid]::NewGuid()},@("*.*proj")),
+({4D2348EA-44AA-479F-80FB-EF67D64F4F3A}, {"$ProjectId"}, {[System.Guid]::NewGuid()},@("*.*proj")),
+({0A7800A3-784F-4822-8956-7BAC2C4D194E}, {"$ProjectId"}, {[System.Guid]::NewGuid()},@("*.*proj")),
+({6B0A711C-8401-4240-BA08-A8198EFC271E}, {"$ProjectId"}, {[System.Guid]::NewGuid()},@("*.*proj")),
+
+
+use this one-liner to figure out the include statement for update-filename
+Get-ChildItem C:\temp\pean-waffle\dest\new3 *Contoso* -Recurse -File|Select-Object -ExpandProperty extension -Unique|%{ write-host ( '''{0}'',' -f $_) -NoNewline }
+
+'.csproj','.bak','.projitems','.shproj','.cs'
+#>
\ No newline at end of file