在Visual Studio中的MSBuild社区任务BeforeBuild步骤期间找不到路径中的xsd.exe
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Visual Studio中的MSBuild社区任务BeforeBuild步骤期间找不到路径中的xsd.exe相关的知识,希望对你有一定的参考价值。
我正在使用MSBuild社区任务来运行Xsd.exe作为我在Visual Studio中构建的一部分,因为:
<Import Project="$(SolutionDir)Common.targets" />
<PropertyGroup>
<MSBuildCommunityTasksPath>$(SolutionDir)TeamBuildTypes</MSBuildCommunityTasksPath>
</PropertyGroup>
<Import Project="$(MSBuildCommunityTasksPath)MSBuild.Community.Tasks.Targets" />
<UsingTask TaskName="XSD" AssemblyFile="$(VCTargetsPath)$(CPPTasks)" />
<Target Name="BeforeBuild">
<!--Exec Command="'$(DevEnvDir)..Toolsvsvars32.bat'" /-->
<XSD Sources="MySchema.xsd" GenerateFromSchema="classes" Language="CS" />
</Target>
Common.targets是根据here。
但是,我在构建期间收到以下错误:
“XSD”任务意外失败。
Microsoft.Build.Shared.InternalErrorException:MSB0001:内部MSBuild错误:xsd.exe意外不是root路径
已经在MSDN论坛here上给出了一个解决方案,即将xsd.exe的路径添加到路径环境变量中。但是,正如Pico Ohms的回答所指出的那样,这是不可维护的,因为它依赖于版本,并且需要每个开发人员为了构建而执行额外的步骤,仅仅因为Xsd.exe。
我找到了另一个解决方案here,它预先调用vsvars32.bat。这是上面代码中注释掉的行。这没有用,所以我找到了一个解决方案here,我希望它可以使它工作,这是用/useenv
参数调用DEVENV。
然后我找到了另一个解决方案here,它将<xs:include schemaLocation="MSBuildMSBuild.Community.Tasks.xsd"/>
添加到Microsoft.Build.xsd。也没用。
所以,现在我没有想法了。如何使用/useenv
解决方案或其他解决方案,无需开发人员更新其路径变量,从而使MSBuild社区任务XSD任务正常工作?我知道我可以将xsd.exe放在Visual Studio解决方案中,但这对我来说似乎是一种廉价的解决方法。
我不得不做一些研究来记住我在另一个帖子上发布的comment,但你可以通过从XSD任务派生并覆盖GenerateFullPathToTool()方法为你的任务实现自定义搜索路径。
当您查看DotPeek中的XSD任务时,您可以看到它派生自Microsoft.Build.Utilities.ToolTask。 ToolTask包含一个名为“GenerateFullPathToTool()”的方法。调用此方法以返回工具的完整路径,顾名思义。
Microsoft.Build.Utilities类中的ToolLocationHelper可用于查找已安装的xsd.exe的相应位置。
它包含一个名为GetPathToDotNetFrameworkSdkFile的方法,它将为您提供dot net sdk的fileName位置。把“xsd.exe”作为参数,你应该好好去。
如果该方法没有返回您需要的路径,则还有其他方法可以返回各种路径,并且它基于注册表,因此它比设置显式路径更具可移植性。
我多年来一直使用的解决方案是使用inline task来设置项目文件中的路径。
<ItemGroup>
<!-- Configure XSD files by using the XsdClasses custom item type. All files of this type are converted by the GenerateXsdClasses target. -->
<XsdClasses Include="DataXsdFile1.xsd">
<SubType>Designer</SubType>
</XsdClasses>
<XsdClasses Include="DataXsdFile2.xsd">
<SubType>Designer</SubType>
</XsdClasses>
</ItemGroup>
<!-- In-line task to add a folder to the current path if not already in it. -->
<UsingTask TaskName="AddToPath" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)Microsoft.Build.Tasks.v4.0.dll">
<ParameterGroup>
<FolderPath ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Code Type="Fragment" Language="c#"><![CDATA[
const string PathEnvironmentVariableName = "PATH";
string currentPath = Environment.GetEnvironmentVariable(PathEnvironmentVariableName);
if(!currentPath.ToLower().Contains(FolderPath.ToLower()))
{
currentPath = currentPath.TrimEnd(';');
string newPath = string.Format("{0};{1}", currentPath, FolderPath);
Environment.SetEnvironmentVariable(PathEnvironmentVariableName, newPath);
}
]]></Code>
</Task>
</UsingTask>
<!-- Reference the Xsd task. -->
<UsingTask TaskName="XSD" AssemblyFile="$(VCTargetsPath)Microsoft.Build.CppTasks.Common.dll" />
<!-- Set the default path to Xsd.exe - this will be added to the current path using the above inline task. Can be overridden per client by setting a user or machine environment variable with the same name. -->
<PropertyGroup>
<NetFxToolsPath Condition="'$(NetFxToolsPath)' == ''">C:Program Files (x86)Microsoft SDKsWindowsv10.0AinNETFX 4.7 Tools</NetFxToolsPath>
</PropertyGroup>
<!-- Generate classes from xsd files configured with 'XsdClasses' item type. -->
<Target Name="GenerateXsdClasses" Inputs="@(XsdClasses)" Outputs="@(XsdClasses->'%(RelativeDir)%(Filename).cs')">
<Message Importance="high" Text="Building %(XsdClasses.Filename)" />
<AddToPath FolderPath="$(NetFxToolsPath)" />
<!-- Note the trailing . in the outputdir because the folder ends with a / -->
<XSD MinimalRebuildFromTracking="true" Sources="%(XsdClasses.Identity)" GenerateFromSchema="classes" Namespace="XsdClassesNamespace" SuppressStartupBanner="true" AdditionalOptions="/outputdir:"%(XsdClasses.RelativeDir)."" />
</Target>
<!-- Configure class generation from xsd to occur before build. -->
<Target Name="BeforeBuild" DependsOnTargets="GenerateXsdClasses"/>
以上是关于在Visual Studio中的MSBuild社区任务BeforeBuild步骤期间找不到路径中的xsd.exe的主要内容,如果未能解决你的问题,请参考以下文章
Visual Studio 2012 解决方案 TeamCity 中的 MSBuild
在 Linux 中的 Mono 下,在 Visual Studio / msbuild 中编译的二进制文件是不是 100% 兼容?
MSBuild + Visual Studio:为解决方案中的所有项目自定义默认“复制本地”