在Visual中,我使用MSBuild社区任务作为构建的一部分运行Xsd.exe,如下所示:
<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)..\Tools\vsvars32.bat'" /-->
<XSD Sources="MySchema.xsd" GenerateFromSchema="classes" Language="CS" />
</Target>
Common.targets和这里一样。
但是,在生成过程中,我会得到以下错误:
"XSD“任务意外失败。 Microsoft.Build.Shared.InternalErrorException: MSB0001:内部MSBuild错误: xsd.exe意外地不是根路径
在MSDN论坛这里上给出了一种解决方案,即向xsd.exe添加一个路径到 path 环境变量。但是,正如Pico的答案所指出的,这是不可维护的,因为它依赖于版本,并且要求每个开发人员执行一个额外的步骤来构建,仅仅是因为Xsd.exe。
我找到了另一个解决方案这里,就是提前调用这里。这是上面代码中的注释行。这不起作用,所以我找到了一个解决方案这里,我希望它能使它工作,这就是用/useenv
参数调用DEVENV。
然后我找到了另一个解决方案这里,就是将<xs:include schemaLocation="MSBuild\MSBuild.Community.Tasks.xsd"/>
添加到<xs:include schemaLocation="MSBuild\MSBuild.Community.Tasks.xsd"/>
中。也没起作用。
所以,现在我没有主意了。如何使MSBuild社区任务XSD任务工作,而不需要devs通过使用/useenv
解决方案或其他解决方案来更新其路径变量?我知道我可以将xsd.exe放在Visual解决方案中,但对我来说,这似乎是一种廉价的解决办法。
发布于 2017-04-27 14:21:32
我必须做一些研究才能记住我在另一个线程上发布的关于这个问题的评论,但是您可以通过从XSD任务派生并重写GenerateFullPathToTool()方法来实现任务的自定义搜索路径。
当您查看DotPeek中的XSD任务时,可以看到它是从Microsoft.Build.Utilities.ToolTask派生的。ToolTask包含一个名为"GenerateFullPathToTool()“的方法。如其名称所示,调用此方法以返回该工具的完整路径。
可以使用Microsoft.Build.Utilities类中的Microsoft.Build.Utilities查找安装的xsd.exe的适当位置。
它包含一个名为GetPathToDotNetFrameworkSdkFile的方法,它将为dot提供fileName的位置。将"xsd.exe“作为参数,您应该可以使用。
如果该方法不返回所需的路径,则还有其他方法用于返回各种路径及其基于注册表的路径,因此它比设置显式路径更可移植。
发布于 2017-12-16 19:36:17
为此,我已经使用了多年的解决方案是使用内联任务来设置项目文件中的路径。
<ItemGroup>
<!-- Configure XSD files by using the XsdClasses custom item type. All files of this type are converted by the GenerateXsdClasses target. -->
<XsdClasses Include="Data\XsdFile1.xsd">
<SubType>Designer</SubType>
</XsdClasses>
<XsdClasses Include="Data\XsdFile2.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 SDKs\Windows\v10.0A\bin\NETFX 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"/>
发布于 2022-11-29 15:57:08
这个答案对我从一个XSD.EXE项目调用Microsoft.NET.Sdk
非常有帮助。
我已经在Visual解决方案中使用了一个PostBuild目标,所以我对我的项目进行了2次更改。
ToolLocationHelper
的引用添加为使用任务。(见其他答案)我的整个解决方案项目现在如下所示:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<UsingTask TaskName="ToolLocationHelper" AssemblyName="Microsoft.Build.Utilities.Core" />
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command=""$([Microsoft.Build.Utilities.ToolLocationHelper]::GetPathToDotNetFrameworkSdkFile(`xsd.exe`))" $(TargetPath) -outputdir:$(ProjectDir)" />
</Target>
</Project>
神奇的是对GetPathToDotNetFrameworkSdkFile
的内联调用。
请参阅https://learn.microsoft.com/en-us/visualstudio/msbuild/property-functions?view=vs-2022
基本上:
text
<-文字文本,(考虑C#中的双引号)因此,这在我的机器上扩展为:
C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\xsd.exe
因为我基本上是在构建一个动态批处理文件,所以我将其括在引号中,并且命令按预期工作。
https://stackoverflow.com/questions/43640465
复制相似问题