无论.NET版本/环境如何,找到ildasm.exe和ilasm.exe文件路径的保证方法是什么?

11

有没有方法通过编程获取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,因此目录不存在(主要原因是SDK版本不同),因此在我的本地计算机上,正确的路径为@"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进行编译?

这并不简单,不同版本的VS有不同的方法来定位SDK目录。它最终从注册表HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows键中读取。VS2008使用CurrentInstallFolder值,而VS2010和VS2012直接使用子键。这最终设置了%WindowsSdkDir%环境变量,但你的代码运行在什么上下文中并不清楚。 - Hans Passant
@HansPassant:听到没有特定的方法访问ildasm.exe确实令人沮丧。那ilasm.exe文件呢?如果我假设使用VS2012呢? - myermian
2个回答

23

一个选择是引用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);

在我的计算机上,这将返回:

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

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


如果你的目标是 .NET Framework,那么这个类型也存在于 Microsoft.Build.Utilities.v4.0 程序集中。 - Gael Fraiteur
对我来说,这返回的是 C:\Windows\Microsoft.NET\Framework\v4.0.30319\corflags.exe - 一个不存在的文件。所以,不行。 - N73k

6
我最近需要做这个,所以我在互联网上搜索了所有可能的 Windows SDK 路径,并按照最近已知的顺序进行了搜索。我还检查操作系统和进程是否为 64 位,然后只需查找相应的 Program Files 文件夹中的版本即可。我认为,在工具的 32 位版本和 64 位版本之间选择 64 位版本并没有任何重大意义。ILAsm 的 x86 版本可以轻松地组装 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 来增强此功能,这取决于您。您还可以将可能的列表放在配置文件中,以便在不重新编译的情况下添加更多内容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接