开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜