Is there a way to programmatically get the FileInfo/Path of the ildasm.exe/ilasm.exe executables? I'm attempting to decompile and recompile a dll/exe file appropriately after making some alterations to it (I'm guessing PostSharp does something similar to alter the IL after the compilation).
I found a blog post that pointed to:
var pfDir = Environment.GetFolderPath(Environment.SpecialFolders.ProgramFiles));
var sdkDir = Path.Combine(pfDir, @"Microsoft SDKs\Windows\v6.0A\bin");
...
However, when I ran this code the directory did not exist (mainly because my SDK version is 7.1), so on my local machine the correct path is @"Microsoft SDKs\Windows\v7.1\bin"
. How do I ensure I can actually find the ildasm.exe?
Similarly, I found another blog post on how to get access to ilasm.exe as:
string windows = Environment.GetFolderPath(Environment.SpecialFolder.System);
string fwork = Path.Combine(windows, @"..\Microsoft.NET\Framework\v2.0.50727");
...
While this works, I noticed that I have Framework and Framework64, and within Framework itself I have all of the versions up to v4.0.30319 (same with Framework64). So, how do I know which one to use? Should it be based on the .NET Framework version I'm targetting?
Summary:
It will find ildasm.exe in i.e. c:\Program Files (x86)\Microsoft SDKs\Windows\v8. 0A\bin\NETFX 4.0 Tools\ .
To use the GUI, type ildasm at the command line without supplying the PEfilename argument or any options. From the File menu, you can navigate to the PE file that you want to load into Ildasm.exe. To save the metadata and disassembled code displayed for the selected PE, select the Dump command from the File menu.
You can use Ilasm.exe in conjunction with its companion tool, Ildasm.exe. Ildasm.exe takes a PE file that contains IL code and creates a text file suitable as input to Ilasm.exe. This is useful, for example, when compiling code in a programming language that does not support all the runtime metadata attributes.
You can use the Ildasm.exe (IL Disassembler) to view Microsoft intermediate language (MSIL) information in a file. If the file being examined is an assembly, this information can include the assembly's attributes and references to other modules and assemblies.
One option would be to reference Microsoft.Build.Utilities.Core
and use:
var ildasm = Microsoft.Build.Utilities.ToolLocationHelper.GetPathToDotNetFrameworkSdkFile("ildasm.exe", TargetDotNetFrameworkVersion.VersionLatest);
var ilasm = Microsoft.Build.Utilities.ToolLocationHelper.GetPathToDotNetFrameworkFile("ilasm.exe", TargetDotNetFrameworkVersion.VersionLatest);
Right now on my machine this returns:
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
I recently needed to do this so I trawled the interwebs for all the possible paths of the Windows SDK and search through those in most recent known order. I also check for whether the OS and process is 64bit and then just use that version by looking in the appropriate Program Files folders. I don't think choosing 64-bit over the 32-bit versions of the tools has any great significance. The x86 version of ILAsm can happily assemble 64-bit preferred assemblies without a hitch, it's all IL and not actually executing any of the code.
ILDasm is part of the Windows SDK where ILAsm is just the .NET Framework SDK so here are some static methods to hunt them down with. The code is baked for .NET 4.0 but you could make some minor tweaks to get it building on .NET 2.0 if you want.
// 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;
}
You can augment this by passing in the executable you are looking for and change Directory.Exists with File.Exists as well, up to you. You could also take the possible lists and put them in a config file so you can add more without recompiling.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With