-->

我应该如何引用SN.EXE中的MSBuild脚本?(How should I reference s

2019-08-01 05:57发布

我需要重新注册我的组件构建完成后(我已经做了一些其他的事情吧),所以我就开始通过增加一个<Exec>任务调用C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\sn.exe 。 这有可能对其他开发人员/环境下工作,所以我希望我可以只复制sn.exesn.exe.config从该文件夹,并将其存储在我们的代码库,所以我总是可以从已知的调用它的公共版本地点。

sn.exe崩溃隔离SDK目录之外的,所以我不知道我怎么可以参考它不知道它会是什么路径下。 不同的人有不同的环境(86 VS 64,不同的安装目录,不同的版本),所以我想应该可以轻松地引用最新版本的工具(或者任何版本)的。 似乎是一个很简单的工具,也许还有另一种方式签署与其他工具/命令/ MSBuild任务的组件? 任何帮助,将不胜感激。

Answer 1:

要正确地引用类似的工具snsqlmetal中,将针对大多数人的工作方式一个MSBuild脚本(我是谁)后,你必须考虑到工作环境和框架实施的考虑不同方面。 Microsoft Windows和Microsoft的实施框架,然后一切(我指的是单声道/ UNIX):有两种主要情况是。 支持我能想到的,结束时所列情形的正确方法的一个例子。

微软

找到正确的方法,其中sn或其他类似的工具住在Windows与启动GetFrameworkSdkPath任务 ,如已经提到 。

然而,由于这个问题表明,该FrameworkSdkPath中的准确位置sn或其他工具生命无法直接确定。 该参考答案表明,FrameworkSdkPath下唯一可能的文件夹工具驻留在是binbin/NETFX 4.0 Tools 。 然而,其他值是可能的(Visual Studio的2013预览使用bin/NETFX 4.5.1 Tools )。 因此,要搜索的唯一有道sn是使用全局正则表达式或递归搜索。 我有麻烦搞清楚怎么办水珠扩张与MSBuild的和内置的MSBuild任务似乎并不支持FrameworkSdkPath下寻找特定的工具。 然而,CMD的WHERE具有此功能,可以用来做搜索。 其结果是一样的东西下面的MSBuild代码:

<Target Name="GetSNPath" BeforeTargets="AfterBuild">
  <GetFrameworkSdkPath>
    <Output TaskParameter="Path" PropertyName="WindowsSdkPath" />
  </GetFrameworkSdkPath>
  <Exec Command="WHERE /r &quot;$(WindowsSdkPath.TrimEnd('\\'))&quot; sn &gt; sn-path.txt"  />
  <ReadLinesFromFile File="sn-path.txt">
    <Output TaskParameter="Lines" PropertyName="SNPath"/>
  </ReadLinesFromFile>
  <Delete Files="sn-path.txt" />
  <PropertyGroup>
    <SNPath>$([System.Text.RegularExpressions.Regex]::Replace('$(SNPath)', ';.*', ''))</SNPath>
  </PropertyGroup>
</Target>

(参见属性函数 ,看看为什么我可以使用String.TrimEnd这里。 WHERE不喜欢尾随斜线编辑:我添加使用属性函数的访问Regex.Replace()删除所有,但第一个找到的路径在SNPath财产我的一位朋友的机器的的WHERE某些命令调用将输出多个结果,并打破任何企图<Exec/>的喜欢的工具。这种变化确保只有一个结果被发现,那<Exec/> 5事实上成功。)

现在,你可以调用sn<Exec Command="&quot;$(SNPath)&quot;" /> <Exec Command="&quot;$(SNPath)&quot;" />

手提

不出所料,解决的路径sn比Windows之外的任何操作系统上要简单得多。 在Mac OSX和Linux的任何分配,我发现sn在PATH中。 使用GetFrameworkSdkPath在这样的情况没有帮助; 事实上,这似乎返回其下一个路径sn不能发现,至少对于旧版本的单2.10的我同时使用xbuild测试:

  • 在Mac OSX FrameworkSdkPath/Library/Frameworks/Mono.framework/Versions/2.10.5/lib/mono/2.0/usr/bin/sn是一个符号链接/Library/Frameworks/Mono.framework/Commands/sn
  • 在一定Linux下安装, FrameworkSdkPath/usr/lib64/mono/2.0sn/usr/bin/sn (这是一个shell脚本调用/usr/lib64/mono/4.0/sn.exemono )。

因此,我们需要做的就是尝试执行sn 。 任何UNIX用户把他们的sn实现非规范的地方已经知道适当地更新路径,所以构建脚本已经没有必要不断寻找它。 此外, WHERE不存在UNIX。 因此,在UNIX的情况下,我们要替换的第一<Exec/>调用的东西,将输出只sn在UNIX和还是做全搜索时,在Windows上运行。 为了区分类Unix和Windows环境中,我们使用了一招,其利用Unix外壳的快捷方式,为true条命令和CMD的标签语法。 作为一个小例子,下面的脚本将输出I'm unix! 在UNIX shellout和I'm Windows :-/在Windows shellout。

:; echo 'I’m unix!'; exit $?
echo I’m Windows :-/

趁着这一点,我们得到的GetSNPath任务是这样的:

<Target Name="GetSNPath" BeforeTargets="AfterBuild">
  <GetFrameworkSdkPath>
    <Output TaskParameter="Path" PropertyName="WindowsSdkPath" />
  </GetFrameworkSdkPath>
  <Exec Command=":; echo sn &gt; sn-path.txt; exit $?
WHERE /r &quot;$(WindowsSdkPath.TrimEnd('\\'))&quot; sn &gt; sn-path.txt"  />
  <ReadLinesFromFile File="sn-path.txt">
    <Output TaskParameter="Lines" PropertyName="SNPath"/>
  </ReadLinesFromFile>
  <Delete Files="sn-path.txt" />
  <PropertyGroup>
    <SNPath>$([System.Text.RegularExpressions.Regex]::Replace('$(SNPath)', ';.*', ''))</SNPath>
  </PropertyGroup>
</Target>

其结果是用于查找调用所需的字符串一便携式方法sn 。 这最后的解决方案让您同时支持微软和它的MSBuild使用xbuild所有其他平台。 它还克服了硬编码bin\NETFX 4.0 Tools到.csproj的文件,同时支持微软的工具未来和当前版本。



Answer 2:

原来,有一个名为“GetFrameworkSdkPath”的任务,将获得Windows SDK的位置。 从那里,我不得不测试,看看是否SN.EXE直接在已有的bin文件夹,或者如果它在bin\NETFX 4.0 Tools\ 。 似乎可靠至今。

<PropertyGroup>
  <SNExePath>NotSet</SNExePath>
</PropertyGroup>

<!-- Sometimes theres nothing in the WindowsSdkPath dir and there's stuff in a deeper folder called 'NETFX 4.0 Tools'. -->
<Target Name="GetSNPath" BeforeTargets="AfterBuild">
  <GetFrameworkSdkPath>
    <Output TaskParameter="Path" PropertyName="WindowsSdkPath" />
  </GetFrameworkSdkPath>
  <PropertyGroup>
    <SNExePath>$(WindowsSdkPath)bin\sn.exe</SNExePath>
  </PropertyGroup>
  <PropertyGroup>
    <SNExePath Condition="!Exists($(SNExePath))">$(WindowsSdkPath)bin\NETFX 4.0 Tools\sn.exe</SNExePath>
  </PropertyGroup>
</Target>  

<Target Name="AfterBuild">
  <Exec Command="$(SNExePath) -R $(TargetPath) $(SignatureFile)" />
</Target>


Answer 3:

我使用的是目前该方法包括使用属性函数来执行的SN.EXE框架SDK路径下搜索 - ALA:

<GetFrameworkSDKPath>
  <Output TaskParameter="Path" PropertyName="DotNetFrameworkDir"/>
</GetFrameworkSDKPath>

<PropertyGroup>
  <SNPath>$([System.IO.Directory]::GetFiles("$(DotNetFrameworkDir)", "sn.exe", SearchOption.AllDirectories)[0])</SNPath>
</PropertyGroup>

到目前为止,我只在Visual Studio的测试2013这一个人,但文档意味着它应该回到工作到Visual Studio 2010。



Answer 4:

您可以创建每个开发机器引用的可执行文件,它的MSBuild可以让你引用一个属性上的环境变量。

因此,通过系统属性的高级选项卡中创建环境变量。 我通常只是建立一个系统环境变量,而不是一个仅限当前用户。 你将不得不重新启动Visual Studio它把它捡起来。

然后,引用它的MSBuild:

<Exec Command="$(SnExe)">

其中SnExe是你定义的环境变量。



Answer 5:

对于什么它值得$(SDK40ToolsPath)可变类似的情况为我工作。 这否定了需要知道其中的工具的特定版本安装例如:

  <PropertyGroup>
    <XsdExePath>$(SDK40ToolsPath)xsd.exe</XsdExePath>
  </PropertyGroup>
  <Target Name="BeforeBuild">
    <ItemGroup>
      <xsd Include="Objects.xsd" />
    </ItemGroup>
    <Exec Command="&quot;$(XsdExePath)&quot; @(xsd) /c /namespace:Blah.Objects" />
  </Target>


文章来源: How should I reference sn.exe in msbuild script?