【问题标题】:Get effective executable filename获取有效的可执行文件名
【发布时间】:2010-08-24 23:37:42
【问题描述】:

.NET 应用程序(托管)在 Windows 7 64 位上运行。它实际上是在 64 位环境下运行的。

应用程序检查位于 c:\windows\syswow64\calc.exe 中的正在运行的进程(例如 calc.exe)。

那么,为什么是函数

Process.MainModule.Filename

返回c:\windows\system32\calc.exe?能否从SYSWOW64目录unredirected获取有效的可执行主模块位置?


有哪些可能的解决方法?我写的最快的是下面的sn-p:

bool iWindows = pFilename.StartsWith(@"c:\windows\", StringComparison.InvariantCultureIgnoreCase);
bool iWindowsSystem32 = pFilename.StartsWith(@"c:\windows\system32\", StringComparison.InvariantCultureIgnoreCase);

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\");

我错过了什么吗?

【问题讨论】:

  • 有完整源代码的最终解决方案吗?

标签: c# windows-7 64-bit filesystems redirect


【解决方案1】:

尝试获取程序集,然后获取程序集位置,例如

System.Reflection.Assembly.GetExecutingAssembly().Location 

【讨论】:

  • 底层进程是外部进程,不是当前执行的。
【解决方案2】:

尝试在使用Process.MainModule.Filename 之前调用Wow64DisableWow64FsRedirection。建议在使用Wow64DisableWow64FsRedirection 之前使用IsWow64ProcessEnvironment.Is64BitOperatingSystem(如果您使用.NET 4.0)验证程序在64 位操作系统上运行。

更新:我确信您的代码中有一个小错误,或者问题可能出在您已安装的 .NET 运行程序上。我针对以下测试代码测试了您的问题

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);
            }
        }
    }
}

在 Vindows 7 64 位 (x64) 上安装了 .NET 4.0 和 Visual Studio 2010。在 Vindows 7 64 位上,calc.exe 有两个版本:C:\Windows\SysWOW64\calc.exe 下的一个 32 位和C:\Windows\system32\calc.exe 下的另一个 64 位。如何轻松验证文件具有不同的文件大小(776,192 和 918.528 字节)。如果我将程序编译为 64 位程序,它会启动 C:\Windows\system32\calc.exeProcess.GetProcessById(processId).MainModule.FileName 也显示正确的文件名。也可以使用Process.GetProcessById() 来获取单独启动的 32 位版本 calc.exe 的正确路径(参见注释行)。所以这个程序的64位版本在我的环境中没有问题。

如果您有 32 位应用程序,您将能够在调用 Wow64DisableWow64FsRedirection 后访问完整的文件系统,但您将能够访问 64 位的内存程序和Process.MainModule 将抛出异常System.ComponentModel.Win32Exception,代码为NativeErrorCode: 299Message: "A 32 bit processes cannot access modules of a 64 bit process." 为了能够获得64 位应用程序的完整文件名,您应该使用API​​ 来获取从64 位生成的结果操作系统组件(如 WMI 等)。但这已经是另一个问题了,因为您编写程序的方式是 64 位程序。

【讨论】:

  • 它不起作用:GetLastError() == ERROR_INVALID_FUNCTION(我认为是因为应用程序是 64 位可执行文件)。
  • 抱歉,您能更准确地描述一下这个场景吗?您是否编写了一个从进程加载的 64 位 .NET 程序集,并且您想知道该进程的完整路径名?您是否编写了 64 位 .NET 应用程序 (EXE) 并尝试检查以“calc.exe”之类的短文件名启动的应用程序的完整路径?或者您的应用程序是 32 位 .NET 应用程序?
  • 我写了一个 64 位的 .NET 应用程序,它调用 Process.GetProcessById(pid) 来检查正在运行的进程(即:calc.exe),它是 64 位的。很抱歉造成混乱。
猜你喜欢
  • 1970-01-01
  • 2021-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-19
  • 1970-01-01
相关资源
最近更新 更多