10

有没有办法以编程方式获取 ildasm.exe/ilasm.exe 可执行文件的 FileInfo/Path?在对 dll/exe 文件进行一些更改后,我正在尝试对其进行适当的反编译和重新编译(我猜 PostSharp 做了类似的事情来在编译后更改 IL)。

我发现一篇博客文章指出:

var pfDir = Environment.GetFolderPath(Environment.SpecialFolders.ProgramFiles));
var sdkDir = Path.Combine(pfDir, @"Microsoft SDKs\Windows\v6.0A\bin");

...

但是,当我运行此代码时,该目录不存在(主要是因为我的 SDK 版本是 7.1),所以在我的本地机器上,正确的路径是@"Microsoft SDKs\Windows\v7.1\bin". 如何确保我可以真正找到 ildasm.exe?

同样,我发现了另一篇关于如何访问 ilasm.exe 的博客文章:

string windows = Environment.GetFolderPath(Environment.SpecialFolder.System);
string fwork = Path.Combine(windows, @"..\Microsoft.NET\Framework\v2.0.50727");

...

虽然这可行,但我注意到我有 Framework 和 Framework64,并且在 Framework 本身内我有所有版本,直到 v4.0.30319(与 Framework64 相同)。那么,我怎么知道该使用哪一个呢?它应该基于我所针对的 .NET Framework 版本吗?

概括:

  • 如何适当地保证找到 ildasm.exe 的正确路径?
  • 如何正确选择正确的 ilasm.exe 进行编译?
4

2 回答 2

21

一种选择是参考Microsoft.Build.Utilities.Core和使用:

var ildasm = Microsoft.Build.Utilities.ToolLocationHelper.GetPathToDotNetFrameworkSdkFile("ildasm.exe", TargetDotNetFrameworkVersion.VersionLatest);
var ilasm = Microsoft.Build.Utilities.ToolLocationHelper.GetPathToDotNetFrameworkFile("ilasm.exe", TargetDotNetFrameworkVersion.VersionLatest);

现在在我的机器上返回:

伊达斯姆 =C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6 Tools\ildasm.exe

伊斯兰=C:\Windows\Microsoft.NET\Framework\v4.0.30319\ilasm.exe

于 2015-02-15T20:28:22.473 回答
6

我最近需要这样做,所以我在互联网上搜索了 Windows SDK 的所有可能路径,并以最近已知的顺序搜索这些路径。我还检查操作系统和进程是否为 64 位,然后通过查看相应的 Program Files 文件夹来使用该版本。我不认为选择 64 位而不是 32 位版本的工具有什么重大意义。x86 版本的 ILAsm 可以轻松地组装 64 位首选程序集,这完全是 IL,实际上并不执行任何代码。

ILDasm 是 Windows SDK 的一部分,而 ILAsm 只是 .NET Framework SDK,所以这里有一些静态方法可以用来追踪它们。该代码是为 .NET 4.0 编写的,但如果需要,您可以进行一些小的调整以使其在 .NET 2.0 上构建。

// ILDasm.exe will be somewhere in here
private static string FindPathForWindowsSdk()
{
  string[] windowsSdkPaths = new[]
  {
    @"Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\",
    @"Microsoft SDKs\Windows\v8.0A\bin\",
    @"Microsoft SDKs\Windows\v8.0\bin\NETFX 4.0 Tools\",
    @"Microsoft SDKs\Windows\v8.0\bin\",
    @"Microsoft SDKs\Windows\v7.1A\bin\NETFX 4.0 Tools\",
    @"Microsoft SDKs\Windows\v7.1A\bin\",
    @"Microsoft SDKs\Windows\v7.0A\bin\NETFX 4.0 Tools\",
    @"Microsoft SDKs\Windows\v7.0A\bin\",
    @"Microsoft SDKs\Windows\v6.1A\bin\",        
    @"Microsoft SDKs\Windows\v6.0A\bin\",
    @"Microsoft SDKs\Windows\v6.0\bin\",
    @"Microsoft.NET\FrameworkSDK\bin"
  };

  foreach (var possiblePath in windowsSdkPaths)
  {
    string fullPath = string.Empty;

    // Check alternate program file paths as well as 64-bit versions.
    if (Environment.Is64BitProcess)
    {
      fullPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), possiblePath, "x64");
      if (Directory.Exists(fullPath))
      {
        return fullPath;
      }

      fullPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), possiblePath, "x64");
      if (Directory.Exists(fullPath))
      {
        return fullPath;
      }
    }

    fullPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), possiblePath);
    if (Directory.Exists(fullPath))
    {
      return fullPath;
    }

    fullPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), possiblePath);
    if (Directory.Exists(fullPath))
    {
      return fullPath;
    }
  }

  return null;
}

// ILAsm.exe will be somewhere in here
private static string FindPathForDotNetFramework()
{
  string[] frameworkPaths = new[]
  {
    @"Microsoft.NET\Framework\v4.0.30319",
    @"Microsoft.NET\Framework\v2.0.50727"
  };

  foreach (var possiblePath in frameworkPaths)
  {
    string fullPath = string.Empty;

    if (Environment.Is64BitProcess)
    {
      fullPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), possiblePath.Replace(@"\Framework\", @"\Framework64\"));
      if (Directory.Exists(fullPath))
      {
        return fullPath;
      }
    }

    fullPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), possiblePath);
    if (Directory.Exists(fullPath))
    {
      return fullPath;
    }
  }

  return null;
}

您可以通过传入您正在寻找的可执行文件来增强它,并将Directory.Exists更改为File.Exists,这取决于您。您还可以获取可能的列表并将它们放入配置文件中,这样您就可以在不重新编译的情况下添加更多列表。

于 2013-10-08T18:20:54.843 回答