创建 Visual Studio 项目模板扩展 Zip 问题的 PowerShell 脚本 [英] PowerShell Script to Create Visual Studio Project Template Extension Zip Issue
问题描述
我正在尝试编写一个 PowerShell 脚本来编写一个 Visual Studio 扩展,该扩展将简单地添加一个项目模板.这是脚本的精简版本以演示问题:
# 添加程序集添加类型 -Assembly System.IO.Compression.FileSystem# 为 zip 档案创建临时目录[System.IO.Directory]::CreateDirectory("扩展名")[System.IO.Directory]::CreateDirectory("模板")# 构建模板文件的内容$templateContent = "<?xml version="1.0`" encoding="utf-8`"?>`r`n"$templateContent += "<VSTemplate Version="3.0.0`" Type="Project`" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005`" xmlns:sdk=`"http://schemas.microsoft.com/developer/vstemplate-sdkextension/2010`">`r`n"$templateContent += " <TemplateData>`r`n"$templateContent += " <Name>MyExtension</Name>`r`n"$templateContent += " <Description>MyExtension</Description>`r`n"$templateContent += " <Icon>MyExtension.ico</Icon>`r`n"$templateContent += " <ProjectType>CSharp</ProjectType>`r`n"$templateContent += " <ProjectSubType></ProjectSubType>`r`n"$templateContent += " <RequiredFrameworkVersion>2.0</RequiredFrameworkVersion>`r`n"$templateContent += " <SortOrder>1000</SortOrder>`r`n"$templateContent += " <TemplateID>61251892-9605-4816-846b-858352383c38</TemplateID>`r`n"$templateContent += " <CreateNewFolder>true</CreateNewFolder>`r`n"$templateContent += " <DefaultName>MyExtension</DefaultName>`r`n"$templateContent += " <ProvideDefaultName>true</ProvideDefaultName>`r`n"$templateContent += " </TemplateData>`r`n"$templateContent += " <TemplateContent>`r`n"$templateContent += " <Project File="MyExtension.csproj`" ReplaceParameters="true`"></Project>`r`n"$templateContent += " </TemplateContent>`r`n"$templateContent += "</VSTemplate>"# 保存模板文件$templateContent |Out-File ([System.IO.Path]::Combine("Template", "MyExtension.vstemplate")) -Encoding "UTF8" -NoNewline# 构建proj文件的内容$projContent = "<?xml version="1.0`" encoding="utf-8`"?>`r`n"$projContent += "<Project ToolsVersion="4.0`" DefaultTargets="Build`" xmlns="http://schemas.microsoft.com/developer/msbuild/2003`">`r`n"$projContent += " <Import Project="`$(MSBuildExtensionsPath)\`$(MSBuildToolsVersion)\Microsoft.Common.props`" Condition="Exists('`$(MSBuildExtensionsPath)\`$(MSBuildToolsVersion)\Microsoft.Common.props')`"/>`r`n"$projContent += " `r`n"$projContent += " <Configuration Condition=`" '`$(Configuration)' == '' `">Debug</Configuration>`r`n"$projContent += " <Platform Condition=`" '`$(Platform)' == '' `">AnyCPU</Platform>`r`n"$projContent += " <ProductVersion>`r`n"$projContent += " </ProductVersion>`r`n"$projContent += " 2.0 `r`n"$projContent += " <ProjectGuid>{403C08FA-9E44-4A8A-A757-1662142E1334}</ProjectGuid>`r`n"$projContent += " <ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuid$projContent += " <OutputType>Library</OutputType>`r`n"$projContent += " <AppDesignerFolder>Properties</AppDesignerFolder>`r`n"$projContent += " <RootNamespace>`$safeprojectname`$</RootNamespace>`r`n"$projContent += " <AssemblyName>`$safeprojectname`$</AssemblyName>`r`n"$projContent += " <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>`r`n"$projContent += " <UseIISExpress>false</UseIISExpress>`r`n"$projContent += " <IISExpressSSLPort/>`r`n"$projContent += " <IISExpressAnonymousAuthentication/>`r`n"$projContent += " <IISExpressWindowsAuthentication/>`r`n"$projContent += " <IISExpressUseClassicPipelineMode/>`r`n"$projContent += " </PropertyGroup>`r`n"$projContent += " <PropertyGroup Condition=`" '`$(Configuration)|`$(Platform)' == 'Debug|AnyCPU' `">`r`n"$projContent += " <DebugSymbols>true</DebugSymbols>`r`n"$projContent += " <DebugType>full</DebugType>`r`n"$projContent += " <Optimize>false</Optimize>`r`n"$projContent += " <OutputPath>bin\</OutputPath>`r`n"$projContent += " <DefineConstants>DEBUG;TRACE</DefineConstants>`r`n"$projContent += " <ErrorReport>prompt</ErrorReport>`r`n"$projContent += " <WarningLevel>4</WarningLevel>`r`n"$projContent += " </PropertyGroup>`r`n"$projContent += " <PropertyGroup Condition=`" '`$(Configuration)|`$(Platform)' == 'Release|AnyCPU' `">`r`n"$projContent += " <DebugType>pdbonly</DebugType>`r`n"$projContent += " <Optimize>true</Optimize>`r`n"$projContent += " <OutputPath>bin\</OutputPath>`r`n"$projContent += " <DefineConstants>TRACE</DefineConstants>`r`n"$projContent += " <ErrorReport>prompt</ErrorReport>`r`n"$projContent += " <WarningLevel>4</WarningLevel>`r`n"$projContent += " </PropertyGroup>`r`n"$projContent += " `r`n"$projContent += " <Reference Include="Microsoft.CSharp`"/>`r`n"$projContent += " <Reference Include="System.ServiceModel`"/>`r`n"$projContent += " <Reference Include="System.Transactions`"/>`r`n"$projContent += " <Reference Include="System.Web.DynamicData`"/>`r`n"$projContent += " <Reference Include="System.Web.Entity`"/>`r`n"$projContent += " <Reference Include="System.Web.ApplicationServices`"/>`r`n"$projContent += " <Reference Include="System.ComponentModel.DataAnnotations`"/>`r`n"$projContent += " <Reference Include="System`"/>`r`n"$projContent += " <Reference Include="System.Data`"/>`r`n"$projContent += " <Reference Include="System.Core`"/>`r`n"$projContent += " <Reference Include="System.Data.DataSetExtensions`"/>`r`n"$projContent += " <Reference Include="System.Web.Extensions`"/>`r`n"$projContent += " <Reference Include="System.Xml.Linq`"/>`r`n"$projContent += " <Reference Include="System.Drawing`"/>`r`n"$projContent += " <Reference Include="System.Web`"/>`r`n"$projContent += " <Reference Include="System.Xml`"/>`r`n"$projContent += " <Reference Include="System.Configuration`"/>`r`n"$projContent += " <Reference Include="System.Web.Services`"/>`r`n"$projContent += " <Reference Include="System.EnterpriseServices`"/>`r`n"$projContent += " </ItemGroup>`r`n"$projContent += " `r`n"$projContent += " <VisualStudioVersion Condition="'`$(VisualStudioVersion)' == ''`">10.0</VisualStudioVersion>`r`n"$projContent += " <VSToolsPath Condition=`"'`$(VSToolsPath)' == ''`">`$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v`$(VisualStudioVersion)</VSToolsPath>`r`n"$projContent += " </PropertyGroup>`r`n"$projContent += " <Import Project="`$(MSBuildBinPath)\Microsoft.CSharp.targets`"/>`r`n"$projContent += " <Import Project="`$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets`" Condition=`"'`$(VSToolsPath)' != ''`"/>`r`n"$projContent += " <Import Project=`"`$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets`" Condition=`"false`"/>`r`n"$projContent += " <ProjectExtensions>`r`n"$projContent += " <VisualStudio>`r`n"$projContent += " <FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}`">`r`n"$projContent += " <WebProjectProperties>`r`n"$projContent += " <UseIIS>False</UseIIS>`r`n"$projContent += " <AutoAssignPort>True</AutoAssignPort>`r`n"$projContent += " <DevelopmentServerPort>58060</DevelopmentServerPort>`r`n"$projContent += " <DevelopmentServerVPath>/</DevelopmentServerVPath>`r`n"$projContent += " `r`n"$projContent += " </IISUrl>`r`n"$projContent += " <NTLMAuthentication>False</NTLMAuthentication>`r`n"$projContent += " <UseCustomServer>True</UseCustomServer>`r`n"$projContent += " <CustomServerUrl>http://localhost/</CustomServerUrl>`r`n"$projContent += " <SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>`r`n"$projContent += " </WebProjectProperties>`r`n"$projContent += " </FlavorProperties>`r`n"$projContent += " </VisualStudio>`r`n"$projContent += " </ProjectExtensions>`r`n"$projContent += " <!-- 要修改您的构建过程,请将您的任务添加到以下目标之一中并取消注释.`r`n"$projContent += " 其他类似的扩展点存在,参见 Microsoft.Common.targets.`r`n"$projContent += " <Target Name="BeforeBuild`">`r`n"$projContent += " </Target>`r`n"$projContent += " <Target Name="AfterBuild`">`r`n"$projContent += " </Target>`r`n"$projContent += " -->`r`n"$projContent += "</Project>"# 保存项目文件$projContent |Out-File ([System.IO.Path]::Combine("Template", "MyExtension.csproj")) -Encoding "UTF8" -NoNewline# 创建模板zip文件[System.IO.Directory]::CreateDirectory("Extension\ProjectTemplates\CSharp\Web\1033")[System.IO.Compression.ZipFile]::CreateFromDirectory("Template", "Extension\ProjectTemplates\CSharp\Web\1033\MyExtension.zip")# 创建content types xml文件(不存在会报错)$conentTypesContent = "<?xml version="1.0`" encoding="utf-8`"?><Types xmlns="http://schemas.openxmlformats.org/package/2006/content-类型`"><默认扩展=`"vsixmanifest`" ContentType="text/xml`"/><默认扩展=`"zip`" ContentType="application/zip`"/><;/类型>"# 保存内容类型文件$conentTypesContent |Out-File -literalPath "Extension\[Content_Types].xml" -Encoding "UTF8" -NoNewline# 现在为 Visual Studio 模板创建一个扩展清单$extensionContent = "<PackageManifest Version="2.0.0`" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011`">`r`n"$extensionContent += " <元数据>`r`n"$extensionContent += " <Identity Id="MyExtension - 1`" Version="0.1.0`" Language="en-US`" Publisher="MyExtension.net Ltd`"/>`r`n"$extensionContent += " <DisplayName>MyExtension 项目模板</DisplayName>`r`n"$extensionContent += " <Description xml:space="preserve`">MyExtension 项目模板扩展</Description>`r`n"$extensionContent += " </Metadata>`r`n"$extensionContent += " <安装>`r`n"$extensionContent += " <InstallationTarget Id="Microsoft.VisualStudio.Community`" Version="[14.0]`"/>`r`n"$extensionContent += " </Installation>`r`n"$extensionContent += " <Dependencies>`r`n"$extensionContent += " <Dependency Id="Microsoft.Framework.NDP`" DisplayName="Microsoft .NET Framework`" Version="[4.5,)`"/>`r`n"$extensionContent += " </Dependencies>`r`n"$extensionContent += " <Assets>`r`n"$extensionContent += " <Asset Type="Microsoft.VisualStudio.ProjectTemplate`" Path="ProjectTemplates`"/>`r`n"$extensionContent += " </Assets>`r`n"$extensionContent += "</PackageManifest>"# 保存扩展文件$extensionContent |输出文件Extension\extension.vsixmanifest"-编码UTF8"-NoNewline# 创建扩展zip文件[System.IO.Compression.ZipFile]::CreateFromDirectory("Extension", "MyExtension.vsix")# 删除临时目录[System.IO.Directory]::Delete("Extension", $true)[System.IO.Directory]::Delete("Template", $true)
当我运行脚本时,它成功生成了一个 MyExtension.vsix 文件.当我执行该文件时,它会安装扩展,但如果我现在打开 Visual Studio 2015 并创建一个新项目,则项目模板 (C# -> Web) 不存在.
但是,如果您执行以下步骤,则它可以正常工作(请确保您已先卸载旧扩展):
- 将 MyExtension.vsix 文件重命名为 MyExtension.zip,然后解压到一个目录
- 进入该目录并选择所有文件,右键单击并选择发送到压缩文件夹
- 将生成的 zip 文件重命名为 MyExtension.vsix
- 执行此文件以安装扩展
我花了几个小时才注意到这种情况解决了这个问题.然而,这是一个黑客,从长远来看,它会变得非常乏味.我想知道是否有人知道如何更改我的 PowerShell 脚本以解决此问题.
谢谢
由于某种原因,[System.IO.Compression.ZipFile]::CreateFromDirectory 不会创建一个正常工作的 zip/vsix 文件,即使它会显示为已安装.该模板未显示在新项目 UI 中.
改用 7zip 来创建 zip 文件.
虽然我试图调查这个问题,但我不喜欢代码没有使用完全限定的路径,而且字符串很难看.我重构了你的代码.
根据我的测试,这现在按预期工作.
代码
<预><代码><#http://stackoverflow.com/questions/40462544/powershell-script-to-create-visual-studio-project-template-extension-zip-issue出于某种原因, [System.IO.Compression.ZipFile]::CreateFromDirectory 不会创建一个正常工作的 zip/vsix 文件,即使它会显示为已安装.该模板不会显示在新项目 UI 中.改用 7zip 来创建 zip 文件.#>Set-StrictMode -Version 最新$VerbosePreference = [System.Management.Automation.ActionPreference]::Continue# 使从 ISE 调试更容易.如果 ($PSScriptRoot -eq ""){$root = Split-Path -Parent $psISE.CurrentFile.FullPath}别的{$root = $PSScriptRoot}设置位置 $root<#创建一个 zip 文件,其中包含 zip 文件根目录中 Path 下的项目.#>function New-ZipFile([string]$Path, [string]$FileName){$zipExe = 'C:\Program Files\7-Zip\7z.exe'$currentLocation = 获取位置设置位置 $Path&$zipExe a -tzip $FileName * -r设置位置 $currentLocation}# 为 zip 档案创建临时目录扩展"、模板" |% {New-Item (Join-Path $root $_) -ItemType Directory}# 构建模板文件的内容$templateContent = @'<?xml version="1.0" encoding="utf-8"?><VSTemplate Version="3.0.0" Type="Project" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" xmlns:sdk="http://schemas.microsoft.com/developer/vstemplate-sdkextension/2010"><模板数据><名称>我的分机</名称><Description>MyExtension</Description><Icon>MyExtension.ico</Icon><ProjectType>CSharp</ProjectType><ProjectSubType></ProjectSubType><RequiredFrameworkVersion>2.0</RequiredFrameworkVersion><SortOrder>1000</SortOrder><TemplateID>61251892-9605-4816-846b-858352383c38</TemplateID><CreateNewFolder>true</CreateNewFolder><DefaultName>MyExtension</DefaultName><ProvideDefaultName>true</ProvideDefaultName></模板数据><模板内容><Project File="MyExtension.csproj" ReplaceParameters="true"></Project></模板内容></VSTemplate>'@# 保存模板文件$templateContent |Out-File (Join-Path $root "Template\MyExtension.vstemplate") -Encoding "UTF8" #-NoNewline# 构建proj文件的内容$projContent = @'<?xml version="1.0" encoding="utf-8"?><Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"><导入项目="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')"/><属性组><Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration><Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform><产品版本></ProductVersion><SchemaVersion>2.0</SchemaVersion><ProjectGuid>{403C08FA-9E44-4A8A-A757-1662142E1334}</ProjectGuid><ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids><OutputType>库</OutputType><AppDesignerFolder>属性</AppDesignerFolder><RootNamespace>$safeprojectname$</RootNamespace><AssemblyName>$safeprojectname$</AssemblyName><TargetFrameworkVersion>v4.5</TargetFrameworkVersion><UseIISExpress>false</UseIISExpress><IISExpressSSLPort/><IISExpressAnonymousAuthentication/><IISExpressWindowsAuthentication/><IISExpressUseClassicPipelineMode/></PropertyGroup><PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "><DebugSymbols>true</DebugSymbols><DebugType>full</DebugType><Optimize>false</Optimize><OutputPath>bin\</OutputPath><DefineConstants>调试;跟踪</DefineConstants><ErrorReport>提示</ErrorReport><WarningLevel>4</WarningLevel></PropertyGroup><PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "><DebugType>pdbonly</DebugType><Optimize>true</Optimize><OutputPath>bin\</OutputPath><DefineConstants>TRACE</DefineConstants><ErrorReport>提示</ErrorReport><WarningLevel>4</WarningLevel></PropertyGroup><项目组><Reference Include="Microsoft.CSharp"/><Reference Include="System.ServiceModel"/><Reference Include="System.Transactions"/><Reference Include="System.Web.DynamicData"/><Reference Include="System.Web.Entity"/><Reference Include="System.Web.ApplicationServices"/><Reference Include="System.ComponentModel.DataAnnotations"/><Reference Include="系统"/><Reference Include="System.Data"/><Reference Include="System.Core"/><Reference Include="System.Data.DataSetExtensions"/><Reference Include="System.Web.Extensions"/><Reference Include="System.Xml.Linq"/><Reference Include="System.Drawing"/><Reference Include="System.Web"/><Reference Include="System.Xml"/><Reference Include="System.Configuration"/><Reference Include="System.Web.Services"/><Reference Include="System.EnterpriseServices"/></项目组><属性组><VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion><VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath></PropertyGroup><导入项目="$(MSBuildBinPath)\Microsoft.CSharp.targets"/><导入项目="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''"/><Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false"/><项目扩展><VisualStudio><FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}"><WebProjectProperties><UseIIS>假</UseIIS><AutoAssignPort>True</AutoAssignPort><DevelopmentServerPort>58060</DevelopmentServerPort><DevelopmentServerVPath>/</DevelopmentServerVPath><IISUrl></IISUrl><NTLMAuthentication>假</NTLMAuthentication><UseCustomServer>True</UseCustomServer><CustomServerUrl>http://localhost/</CustomServerUrl><SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile></WebProjectProperties></FlavorProperties></VisualStudio></ProjectExtensions><!-- 要修改您的构建过程,请将您的任务添加到以下目标之一中并取消注释.存在其他类似的扩展点,请参阅 Microsoft.Common.targets.<目标名称="BeforeBuild"></目标><目标名称="AfterBuild"></目标>--></项目>'@# 保存项目文件$projContent |Out-File (Join-Path $root "Template\MyExtension.csproj") -Encoding "UTF8" #-NoNewline# 创建模板zip文件New-Item (Join-Path $root "Extension\ProjectTemplates\CSharp\Web\1033") -ItemType 目录New-ZipFile (Join-Path $root "Template") (Join-Path $root "Extension\ProjectTemplates\CSharp\Web\1033\MyExtension.zip")# 创建content types xml文件(不存在会报错)$conentTypesContent = @'<?xml version="1.0" encoding="utf-8"?><Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><默认扩展名="vsixmanifest" ContentType="text/xml"/><Default Extension="zip" ContentType="application/zip"/></Types>'@# 保存内容类型文件$conentTypesContent |Out-File -literalPath (Join-Path $root "Extension\[Content_Types].xml") -Encoding "UTF8" #-NoNewline# 现在为 Visual Studio 模板创建一个扩展清单$extensionContent = @'<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011"><元数据><Identity Id="MyExtension - 1" Version="0.1.0" Language="en-US" Publisher="MyExtension.net Ltd"/><DisplayName>MyExtension 项目模板</DisplayName><Description xml:space="preserve">MyExtension 项目模板扩展</Description></元数据><安装><InstallationTarget Id="Microsoft.VisualStudio.Community" 版本="[14.0]"/></安装><依赖项><Dependency Id="Microsoft.Framework.NDP" DisplayName="Microsoft .NET Framework" Version="[4.5,)"/></依赖项><资产><Asset Type="Microsoft.VisualStudio.ProjectTemplate" Path="ProjectTemplates"/></资产></PackageManifest>'@# 保存扩展文件$extensionContent |Out-File (Join-Path $root "Extension\extension.vsixmanifest") -Encoding "UTF8" #-NoNewline# 创建扩展zip文件New-ZipFile (Join-Path $root "Extension") (Join-Path $root "MyExtension.vsix")# 删除临时目录扩展"、模板" |% {Remove-Item (Join-Path $root $_) -Recurse -Force}I'm trying to write a PowerShell script to write a Visual Studio extension which will simply add a project template. Here is a trimmed down version of the script to demonstrate the problem:
# Add the assemblies
Add-Type -Assembly System.IO.Compression.FileSystem
# Create temporary directories for the zip archives
[System.IO.Directory]::CreateDirectory("Extension")
[System.IO.Directory]::CreateDirectory("Template")
# Build up the contents of the template file
$templateContent = "<?xml version=`"1.0`" encoding=`"utf-8`"?>`r`n"
$templateContent += "<VSTemplate Version=`"3.0.0`" Type=`"Project`" xmlns=`"http://schemas.microsoft.com/developer/vstemplate/2005`" xmlns:sdk=`"http://schemas.microsoft.com/developer/vstemplate-sdkextension/2010`">`r`n"
$templateContent += " <TemplateData>`r`n"
$templateContent += " <Name>MyExtension</Name>`r`n"
$templateContent += " <Description>MyExtension</Description>`r`n"
$templateContent += " <Icon>MyExtension.ico</Icon>`r`n"
$templateContent += " <ProjectType>CSharp</ProjectType>`r`n"
$templateContent += " <ProjectSubType></ProjectSubType>`r`n"
$templateContent += " <RequiredFrameworkVersion>2.0</RequiredFrameworkVersion>`r`n"
$templateContent += " <SortOrder>1000</SortOrder>`r`n"
$templateContent += " <TemplateID>61251892-9605-4816-846b-858352383c38</TemplateID>`r`n"
$templateContent += " <CreateNewFolder>true</CreateNewFolder>`r`n"
$templateContent += " <DefaultName>MyExtension</DefaultName>`r`n"
$templateContent += " <ProvideDefaultName>true</ProvideDefaultName>`r`n"
$templateContent += " </TemplateData>`r`n"
$templateContent += " <TemplateContent>`r`n"
$templateContent += " <Project File=`"MyExtension.csproj`" ReplaceParameters=`"true`"></Project>`r`n"
$templateContent += " </TemplateContent>`r`n"
$templateContent += "</VSTemplate>"
# Save the template file
$templateContent | Out-File ([System.IO.Path]::Combine("Template", "MyExtension.vstemplate")) -Encoding "UTF8" -NoNewline
# Build up the contents of the proj file
$projContent = "<?xml version=`"1.0`" encoding=`"utf-8`"?>`r`n"
$projContent += "<Project ToolsVersion=`"4.0`" DefaultTargets=`"Build`" xmlns=`"http://schemas.microsoft.com/developer/msbuild/2003`">`r`n"
$projContent += " <Import Project=`"`$(MSBuildExtensionsPath)\`$(MSBuildToolsVersion)\Microsoft.Common.props`" Condition=`"Exists('`$(MSBuildExtensionsPath)\`$(MSBuildToolsVersion)\Microsoft.Common.props')`" />`r`n"
$projContent += " <PropertyGroup>`r`n"
$projContent += " <Configuration Condition=`" '`$(Configuration)' == '' `">Debug</Configuration>`r`n"
$projContent += " <Platform Condition=`" '`$(Platform)' == '' `">AnyCPU</Platform>`r`n"
$projContent += " <ProductVersion>`r`n"
$projContent += " </ProductVersion>`r`n"
$projContent += " <SchemaVersion>2.0</SchemaVersion>`r`n"
$projContent += " <ProjectGuid>{403C08FA-9E44-4A8A-A757-1662142E1334}</ProjectGuid>`r`n"
$projContent += " <ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>`r`n"
$projContent += " <OutputType>Library</OutputType>`r`n"
$projContent += " <AppDesignerFolder>Properties</AppDesignerFolder>`r`n"
$projContent += " <RootNamespace>`$safeprojectname`$</RootNamespace>`r`n"
$projContent += " <AssemblyName>`$safeprojectname`$</AssemblyName>`r`n"
$projContent += " <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>`r`n"
$projContent += " <UseIISExpress>false</UseIISExpress>`r`n"
$projContent += " <IISExpressSSLPort />`r`n"
$projContent += " <IISExpressAnonymousAuthentication />`r`n"
$projContent += " <IISExpressWindowsAuthentication />`r`n"
$projContent += " <IISExpressUseClassicPipelineMode />`r`n"
$projContent += " </PropertyGroup>`r`n"
$projContent += " <PropertyGroup Condition=`" '`$(Configuration)|`$(Platform)' == 'Debug|AnyCPU' `">`r`n"
$projContent += " <DebugSymbols>true</DebugSymbols>`r`n"
$projContent += " <DebugType>full</DebugType>`r`n"
$projContent += " <Optimize>false</Optimize>`r`n"
$projContent += " <OutputPath>bin\</OutputPath>`r`n"
$projContent += " <DefineConstants>DEBUG;TRACE</DefineConstants>`r`n"
$projContent += " <ErrorReport>prompt</ErrorReport>`r`n"
$projContent += " <WarningLevel>4</WarningLevel>`r`n"
$projContent += " </PropertyGroup>`r`n"
$projContent += " <PropertyGroup Condition=`" '`$(Configuration)|`$(Platform)' == 'Release|AnyCPU' `">`r`n"
$projContent += " <DebugType>pdbonly</DebugType>`r`n"
$projContent += " <Optimize>true</Optimize>`r`n"
$projContent += " <OutputPath>bin\</OutputPath>`r`n"
$projContent += " <DefineConstants>TRACE</DefineConstants>`r`n"
$projContent += " <ErrorReport>prompt</ErrorReport>`r`n"
$projContent += " <WarningLevel>4</WarningLevel>`r`n"
$projContent += " </PropertyGroup>`r`n"
$projContent += " <ItemGroup>`r`n"
$projContent += " <Reference Include=`"Microsoft.CSharp`" />`r`n"
$projContent += " <Reference Include=`"System.ServiceModel`" />`r`n"
$projContent += " <Reference Include=`"System.Transactions`" />`r`n"
$projContent += " <Reference Include=`"System.Web.DynamicData`" />`r`n"
$projContent += " <Reference Include=`"System.Web.Entity`" />`r`n"
$projContent += " <Reference Include=`"System.Web.ApplicationServices`" />`r`n"
$projContent += " <Reference Include=`"System.ComponentModel.DataAnnotations`" />`r`n"
$projContent += " <Reference Include=`"System`" />`r`n"
$projContent += " <Reference Include=`"System.Data`" />`r`n"
$projContent += " <Reference Include=`"System.Core`" />`r`n"
$projContent += " <Reference Include=`"System.Data.DataSetExtensions`" />`r`n"
$projContent += " <Reference Include=`"System.Web.Extensions`" />`r`n"
$projContent += " <Reference Include=`"System.Xml.Linq`" />`r`n"
$projContent += " <Reference Include=`"System.Drawing`" />`r`n"
$projContent += " <Reference Include=`"System.Web`" />`r`n"
$projContent += " <Reference Include=`"System.Xml`" />`r`n"
$projContent += " <Reference Include=`"System.Configuration`" />`r`n"
$projContent += " <Reference Include=`"System.Web.Services`" />`r`n"
$projContent += " <Reference Include=`"System.EnterpriseServices`" />`r`n"
$projContent += " </ItemGroup>`r`n"
$projContent += " <PropertyGroup>`r`n"
$projContent += " <VisualStudioVersion Condition=`"'`$(VisualStudioVersion)' == ''`">10.0</VisualStudioVersion>`r`n"
$projContent += " <VSToolsPath Condition=`"'`$(VSToolsPath)' == ''`">`$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v`$(VisualStudioVersion)</VSToolsPath>`r`n"
$projContent += " </PropertyGroup>`r`n"
$projContent += " <Import Project=`"`$(MSBuildBinPath)\Microsoft.CSharp.targets`" />`r`n"
$projContent += " <Import Project=`"`$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets`" Condition=`"'`$(VSToolsPath)' != ''`" />`r`n"
$projContent += " <Import Project=`"`$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets`" Condition=`"false`" />`r`n"
$projContent += " <ProjectExtensions>`r`n"
$projContent += " <VisualStudio>`r`n"
$projContent += " <FlavorProperties GUID=`"{349c5851-65df-11da-9384-00065b846f21}`">`r`n"
$projContent += " <WebProjectProperties>`r`n"
$projContent += " <UseIIS>False</UseIIS>`r`n"
$projContent += " <AutoAssignPort>True</AutoAssignPort>`r`n"
$projContent += " <DevelopmentServerPort>58060</DevelopmentServerPort>`r`n"
$projContent += " <DevelopmentServerVPath>/</DevelopmentServerVPath>`r`n"
$projContent += " <IISUrl>`r`n"
$projContent += " </IISUrl>`r`n"
$projContent += " <NTLMAuthentication>False</NTLMAuthentication>`r`n"
$projContent += " <UseCustomServer>True</UseCustomServer>`r`n"
$projContent += " <CustomServerUrl>http://localhost/</CustomServerUrl>`r`n"
$projContent += " <SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>`r`n"
$projContent += " </WebProjectProperties>`r`n"
$projContent += " </FlavorProperties>`r`n"
$projContent += " </VisualStudio>`r`n"
$projContent += " </ProjectExtensions>`r`n"
$projContent += " <!-- To modify your build process, add your task inside one of the targets below and uncomment it. `r`n"
$projContent += " Other similar extension points exist, see Microsoft.Common.targets.`r`n"
$projContent += " <Target Name=`"BeforeBuild`">`r`n"
$projContent += " </Target>`r`n"
$projContent += " <Target Name=`"AfterBuild`">`r`n"
$projContent += " </Target>`r`n"
$projContent += " -->`r`n"
$projContent += "</Project>"
# Save the proj file
$projContent | Out-File ([System.IO.Path]::Combine("Template", "MyExtension.csproj")) -Encoding "UTF8" -NoNewline
# Create the template zip file
[System.IO.Directory]::CreateDirectory("Extension\ProjectTemplates\CSharp\Web\1033")
[System.IO.Compression.ZipFile]::CreateFromDirectory("Template", "Extension\ProjectTemplates\CSharp\Web\1033\MyExtension.zip")
# Create a content types xml file (an error will be thrown if this does not exist)
$conentTypesContent = "<?xml version=`"1.0`" encoding=`"utf-8`"?><Types xmlns=`"http://schemas.openxmlformats.org/package/2006/content-types`"><Default Extension=`"vsixmanifest`" ContentType=`"text/xml`" /><Default Extension=`"zip`" ContentType=`"application/zip`" /></Types>"
# Save the content types file
$conentTypesContent | Out-File -literalPath "Extension\[Content_Types].xml" -Encoding "UTF8" -NoNewline
# Now create an extension manifest for the visual studio template
$extensionContent = "<PackageManifest Version=`"2.0.0`" xmlns=`"http://schemas.microsoft.com/developer/vsx-schema/2011`">`r`n"
$extensionContent += " <Metadata>`r`n"
$extensionContent += " <Identity Id=`"MyExtension - 1`" Version=`"0.1.0`" Language=`"en-US`" Publisher=`"MyExtension.net Ltd`" />`r`n"
$extensionContent += " <DisplayName>MyExtension Project Template</DisplayName>`r`n"
$extensionContent += " <Description xml:space=`"preserve`">MyExtension Project Template Extension</Description>`r`n"
$extensionContent += " </Metadata>`r`n"
$extensionContent += " <Installation>`r`n"
$extensionContent += " <InstallationTarget Id=`"Microsoft.VisualStudio.Community`" Version=`"[14.0]`" />`r`n"
$extensionContent += " </Installation>`r`n"
$extensionContent += " <Dependencies>`r`n"
$extensionContent += " <Dependency Id=`"Microsoft.Framework.NDP`" DisplayName=`"Microsoft .NET Framework`" Version=`"[4.5,)`" />`r`n"
$extensionContent += " </Dependencies>`r`n"
$extensionContent += " <Assets>`r`n"
$extensionContent += " <Asset Type=`"Microsoft.VisualStudio.ProjectTemplate`" Path=`"ProjectTemplates`" />`r`n"
$extensionContent += " </Assets>`r`n"
$extensionContent += "</PackageManifest>"
# Save the extension file
$extensionContent | Out-File "Extension\extension.vsixmanifest" -Encoding "UTF8" -NoNewline
# Create the extension zip file
[System.IO.Compression.ZipFile]::CreateFromDirectory("Extension", "MyExtension.vsix")
# Delete the temporary directories
[System.IO.Directory]::Delete("Extension", $true)
[System.IO.Directory]::Delete("Template", $true)
When I run the script it successfully produces a MyExtension.vsix file. When I execute that file it installs the extension but if I now open Visual Studio 2015 and create a new project the project template (C# -> Web) doesn't exist.
However if you do the following steps then it works fine (make sure you have uninstalled the old extension first):
- Rename the MyExtension.vsix file to MyExtension.zip and then extract to a directory
- Go into that directory and select all the files, right click and select Send to Compressed Folder
- Rename the generated zip file to MyExtension.vsix
- Execute this file to install the extension
It's taken me hours to even notice this scenario fixes the issue. However this is a hack and in the long run it's going to become quite tedious. I was wondering if anyone knew how my PowerShell script can be changed to fix this.
Thanks
For some reason, [System.IO.Compression.ZipFile]::CreateFromDirectory will not create a zip/vsix file that works correctly, even though it will show as installed. The template does not show in the new project UI.
Use 7zip instead to create zip files.
While I tried to investigate this issue, I did not like that the code was not using fully qualified paths, and the strings were hard to look at. I refactored your code a bit.
Based on my testing, this now works as expected.
CODE
<#
http://stackoverflow.com/questions/40462544/powershell-script-to-create-visual-studio-project-template-extension-zip-issue
For some reason, [System.IO.Compression.ZipFile]::CreateFromDirectory will not create a zip/vsix file that works correctly,
even though it will show as installed. The template does not show in the new project UI.
Use 7zip instead to create zip files.
#>
Set-StrictMode -Version Latest
$VerbosePreference = [System.Management.Automation.ActionPreference]::Continue
# Makes debugging from ISE easier.
if ($PSScriptRoot -eq "")
{
$root = Split-Path -Parent $psISE.CurrentFile.FullPath
}
else
{
$root = $PSScriptRoot
}
Set-Location $root
<#
Create a zip file with items under Path in the root of the zip file.
#>
function New-ZipFile([string]$Path, [string]$FileName)
{
$zipExe = 'C:\Program Files\7-Zip\7z.exe'
$currentLocation = Get-Location
Set-Location $Path
& $zipExe a -tzip $FileName * -r
Set-Location $currentLocation
}
# Create temporary directories for the zip archives
"Extension", "Template" | % {New-Item (Join-Path $root $_) -ItemType Directory}
# Build up the contents of the template file
$templateContent = @'
<?xml version="1.0" encoding="utf-8"?>
<VSTemplate Version="3.0.0" Type="Project" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" xmlns:sdk="http://schemas.microsoft.com/developer/vstemplate-sdkextension/2010">
<TemplateData>
<Name>MyExtension</Name>
<Description>MyExtension</Description>
<Icon>MyExtension.ico</Icon>
<ProjectType>CSharp</ProjectType>
<ProjectSubType></ProjectSubType>
<RequiredFrameworkVersion>2.0</RequiredFrameworkVersion>
<SortOrder>1000</SortOrder>
<TemplateID>61251892-9605-4816-846b-858352383c38</TemplateID>
<CreateNewFolder>true</CreateNewFolder>
<DefaultName>MyExtension</DefaultName>
<ProvideDefaultName>true</ProvideDefaultName>
</TemplateData>
<TemplateContent>
<Project File="MyExtension.csproj" ReplaceParameters="true"></Project>
</TemplateContent>
</VSTemplate>
'@
# Save the template file
$templateContent | Out-File (Join-Path $root "Template\MyExtension.vstemplate") -Encoding "UTF8" #-NoNewline
# Build up the contents of the proj file
$projContent = @'
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>
</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{403C08FA-9E44-4A8A-A757-1662142E1334}</ProjectGuid>
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>$safeprojectname$</RootNamespace>
<AssemblyName>$safeprojectname$</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<UseIISExpress>false</UseIISExpress>
<IISExpressSSLPort />
<IISExpressAnonymousAuthentication />
<IISExpressWindowsAuthentication />
<IISExpressUseClassicPipelineMode />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.Transactions" />
<Reference Include="System.Web.DynamicData" />
<Reference Include="System.Web.Entity" />
<Reference Include="System.Web.ApplicationServices" />
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Core" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Drawing" />
<Reference Include="System.Web" />
<Reference Include="System.Xml" />
<Reference Include="System.Configuration" />
<Reference Include="System.Web.Services" />
<Reference Include="System.EnterpriseServices" />
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" />
<ProjectExtensions>
<VisualStudio>
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
<WebProjectProperties>
<UseIIS>False</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>58060</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>
</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>True</UseCustomServer>
<CustomServerUrl>http://localhost/</CustomServerUrl>
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
</WebProjectProperties>
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
'@
# Save the proj file
$projContent | Out-File (Join-Path $root "Template\MyExtension.csproj") -Encoding "UTF8" #-NoNewline
# Create the template zip file
New-Item (Join-Path $root "Extension\ProjectTemplates\CSharp\Web\1033") -ItemType Directory
New-ZipFile (Join-Path $root "Template") (Join-Path $root "Extension\ProjectTemplates\CSharp\Web\1033\MyExtension.zip")
# Create a content types xml file (an error will be thrown if this does not exist)
$conentTypesContent = @'
<?xml version="1.0" encoding="utf-8"?><Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="vsixmanifest" ContentType="text/xml" /><Default Extension="zip" ContentType="application/zip" /></Types>
'@
# Save the content types file
$conentTypesContent | Out-File -literalPath (Join-Path $root "Extension\[Content_Types].xml") -Encoding "UTF8" #-NoNewline
# Now create an extension manifest for the visual studio template
$extensionContent = @'
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011">
<Metadata>
<Identity Id="MyExtension - 1" Version="0.1.0" Language="en-US" Publisher="MyExtension.net Ltd" />
<DisplayName>MyExtension Project Template</DisplayName>
<Description xml:space="preserve">MyExtension Project Template Extension</Description>
</Metadata>
<Installation>
<InstallationTarget Id="Microsoft.VisualStudio.Community" Version="[14.0]" />
</Installation>
<Dependencies>
<Dependency Id="Microsoft.Framework.NDP" DisplayName="Microsoft .NET Framework" Version="[4.5,)" />
</Dependencies>
<Assets>
<Asset Type="Microsoft.VisualStudio.ProjectTemplate" Path="ProjectTemplates" />
</Assets>
</PackageManifest>
'@
# Save the extension file
$extensionContent | Out-File (Join-Path $root "Extension\extension.vsixmanifest") -Encoding "UTF8" #-NoNewline
# Create the extension zip file
New-ZipFile (Join-Path $root "Extension") (Join-Path $root "MyExtension.vsix")
# Delete the temporary directories
"Extension", "Template" | % {Remove-Item (Join-Path $root $_) -Recurse -Force}
这篇关于创建 Visual Studio 项目模板扩展 Zip 问题的 PowerShell 脚本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!