Get effective executable filename
A .NET application (managed) runs on Windows 7 64 bit. It is actually running on a 64 bit environment.
The application inspect running process (for example, calc.exe) which is located in c:\windows\syswow64\calc.exe.
So, why the function
Process.MainModule.Filename
returns c:\windows\system32\calc.exe? Is it possible to get the effective executable main module location, when is unredirected from SYSWOW64 directory?
What are possible workarounds? The quickest I wrote is the following snippet:
bool iWindows = pFilename.StartsWith(@"c:\windows\", StringComparison.InvariantCultureIgnoreCase);
bool iWindowsSystem32 = pFilename.StartsWith(@"c:\windows\system32\", StringComparison.Invar开发者_运维知识库iantCultureIgnoreCase);
if ((iWindows == true) || (iWindowsSystem32 == true)) {
string pActualFileName;
if (iWindowsSystem32 == true)
pActualFileName = pFilename.Replace(@"c:\windows\system32\", @"c:\windows\syswow64\");
else
pActualFileName = pFilename.Replace(@"c:\windows\", @"c:\windows\syswow64\");
Am I missing something?
Try getting the assembly and then getting the assembly location, such as
System.Reflection.Assembly.GetExecutingAssembly().Location
Try to call Wow64DisableWow64FsRedirection before the usage of Process.MainModule.Filename
. Verifying that the program are running on 64-bit operation system with IsWow64Process or Environment.Is64BitOperatingSystem (if you use .NET 4.0) before usage of Wow64DisableWow64FsRedirection is recommended.
UPDATED: I am sure that you have a small error in your code or the problem can be on .NET runtines which you have installed. I tested your problem with respect of the following test code
using System;
using System.Diagnostics;
namespace Win64ProcesPath {
class Program {
static void Main (string[] args) {
Process myProcess = new Process ();
try {
myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.FileName = "calc.exe";
myProcess.StartInfo.CreateNoWindow = true;
myProcess.Start ();
System.Threading.Thread.Sleep (1000);
Console.WriteLine ("{0}", myProcess.MainModule.FileName);
Process p = Process.GetProcessById (myProcess.Id);
Console.WriteLine ("{0}", p.MainModule.FileName);
//Process p32 = Process.GetProcessById (8048);
//Console.WriteLine ("{0}", p32.MainModule.FileName);
}
catch (Exception e) {
Console.WriteLine (e.Message);
}
}
}
}
with .NET 4.0 and Visual Studio 2010 installed on Vindows 7 64-bit (x64). On Vindows 7 64-bit there are two version of calc.exe
: one 32-bit under C:\Windows\SysWOW64\calc.exe
and another 64-bit under C:\Windows\system32\calc.exe
. How can easy verify the files has different file size (776,192 and 918.528 bytes). If I compile the program as 64-bit program it starts C:\Windows\system32\calc.exe
and Process.GetProcessById(processId).MainModule.FileName
shows also correct file name. One can also use Process.GetProcessById()
to get correct path of 32-bit version of calc.exe which are started separately (see commented lines). So 64-bit versin of this program has no problem in my envoronment.
If you do have 32-bit application you will be able to access to the full filesystem after the call of Wow64DisableWow64FsRedirection, but you will not be able to access the memory of 64-bit programs and Process.MainModule
will throw the excepion System.ComponentModel.Win32Exception
with the code NativeErrorCode: 299
and the Message: "A 32 bit processes cannot access modules of a 64 bit process."
To be able to get the full filename of 64-bit application you should use API with get you results produced from a 64-bit operation system component (like WMI and so on). But it's already another probelm, because how you wrote your program is 64-bit program.
精彩评论