首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在Visual中的xsd.exe社区任务BeforeBuild步骤期间,无法在路径中找到BeforeBuild

在Visual中的xsd.exe社区任务BeforeBuild步骤期间,无法在路径中找到BeforeBuild
EN

Stack Overflow用户
提问于 2017-04-26 17:05:27
回答 3查看 1.4K关注 0票数 0

在Visual中,我使用MSBuild社区任务作为构建的一部分运行Xsd.exe,如下所示:

代码语言:javascript
运行
复制
<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解决方案中,但对我来说,这似乎是一种廉价的解决办法。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 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“作为参数,您应该可以使用。

如果该方法不返回所需的路径,则还有其他方法用于返回各种路径及其基于注册表的路径,因此它比设置显式路径更可移植。

票数 2
EN

Stack Overflow用户

发布于 2017-12-16 19:36:17

为此,我已经使用了多年的解决方案是使用内联任务来设置项目文件中的路径。

代码语言:javascript
运行
复制
 <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:&quot;%(XsdClasses.RelativeDir).&quot;" />
  </Target>

  <!-- Configure class generation from xsd to occur before build. -->
  <Target Name="BeforeBuild" DependsOnTargets="GenerateXsdClasses"/>
票数 0
EN

Stack Overflow用户

发布于 2022-11-29 15:57:08

这个答案对我从一个XSD.EXE项目调用Microsoft.NET.Sdk非常有帮助。

我已经在Visual解决方案中使用了一个PostBuild目标,所以我对我的项目进行了2次更改。

  1. 将对ToolLocationHelper的引用添加为使用任务。(见其他答案)
  2. 将对XSD.EXE的引用更改为函数调用。

我的整个解决方案项目现在如下所示:

代码语言:javascript
运行
复制
<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="&quot;$([Microsoft.Build.Utilities.ToolLocationHelper]::GetPathToDotNetFrameworkSdkFile(`xsd.exe`))&quot;  $(TargetPath) -outputdir:$(ProjectDir)" />
  </Target>
</Project>

神奇的是对GetPathToDotNetFrameworkSdkFile的内联调用。

请参阅https://learn.microsoft.com/en-us/visualstudio/msbuild/property-functions?view=vs-2022

基本上:

  • $(.) <--用于内联评估某物的语法
  • Fully.Qualified.Class <--对我们要调用的类的静态引用
  • * method () <--静态调用方法的名称
  • text <-文字文本,(考虑C#中的双引号)

因此,这在我的机器上扩展为:

C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\xsd.exe

因为我基本上是在构建一个动态批处理文件,所以我将其括在引号中,并且命令按预期工作。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43640465

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档