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

时间:2012-11-28 17:02:25

标签: c# .net filepath ilasm ildasm

有没有办法以编程方式获取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进行编译?

2 个答案:

答案 0 :(得分:14)

一种选择是引用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

答案 1 :(得分:6)

我最近需要这样做,所以我搜索了Windows SDK的所有可能路径的互联网,并搜索最近已知顺序的那些路径。我还检查操作系统和进程是否为64位,然后通过查看相应的Program Files文件夹来使用该版本。我不认为在32位版本的工具上选择64位有任何重要意义。 IL86m的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;
}

您可以通过传入您要查找的可执行文件来扩充此功能,并使用 File.Exists 更改 Directory.Exists ,由您决定。您还可以获取可能的列表并将它们放在配置文件中,这样您就可以添加更多而无需重新编译。