如何获得运行过程的完整路径?

Paw*_*anS 100 c#

我有一个应用程序正在更改其他应用程序的某些设置(它是一个简单的C#应用​​程序,通过双击运行(无需安装)).

更改设置后,我需要重新启动其他应用程序,以便它反映更改的设置.

所以要做,我必须杀死正在运行的进程并再次启动进程,但问题是在杀死后我无法找到进程.(原因是系统不知道exe文件在哪里..)

有没有办法找出运行进程或exe的路径,如果它正在运行?

我不想手动给路径,即如果它正在运行获取路径,杀死进程并再次启动....我将稍后处理

San*_*ath 140

 using System.Diagnostics;
 var process = Process.GetCurrentProcess(); // Or whatever method you are using
 string fullPath = process.MainModule.FileName;
 //fullPath has the path to exe.
Run Code Online (Sandbox Code Playgroud)

这个API有一个问题,如果您在32位应用程序中运行此代码,您将无法访问64位应用程序路径,因此您必须编译并运行您的应用程序作为64位应用程序(项目属性→构建→平台目标→x64).

  • 根据我的测量,调用`process.Modules [0]`比调用`process.MainModule`慢**50倍. (12认同)
  • @GAPS:我确定他的意思是"获得你的流程实例,但是你得到它." (11认同)
  • 我没有将Platform Target更改为x64,而是将Platform Target更改为Any并取消选中**Prefer 32 bit**选项 (7认同)
  • 它给出了问题访问被拒绝的行`string fullPath = process.Modules [0] .FileName;`有什么想法吗? (4认同)

Jef*_*ado 105

你可以做的是使用WMI来获取路径.这将允许您获取路径,无论它是32位还是64位应用程序.这是一个展示如何获得它的示例:

// include the namespace
using System.Management;

var wmiQueryString = "SELECT ProcessId, ExecutablePath, CommandLine FROM Win32_Process";
using (var searcher = new ManagementObjectSearcher(wmiQueryString))
using (var results = searcher.Get())
{
    var query = from p in Process.GetProcesses()
                join mo in results.Cast<ManagementObject>()
                on p.Id equals (int)(uint)mo["ProcessId"]
                select new
                {
                    Process = p,
                    Path = (string)mo["ExecutablePath"],
                    CommandLine = (string)mo["CommandLine"],
                };
    foreach (var item in query)
    {
        // Do what you want with the Process, Path, and CommandLine
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,您必须引用System.Management.dll程序集并使用System.Management命名空间.

有关您可以从这些进程中获取的其他信息的更多信息,例如用于启动程序的命令行(CommandLine),请参阅Win32_Process类和WMI .NET以获取更多信息.

  • 也许对于这个问题,这可能是一个过度杀手,但由于32/64位独立性,当我想从正在运行的32位进程中获取[64位进程信息]时,这种方法非常方便(http://stackoverflow.com/问题/ 9501771 /如何对避免-A-Win 32的异常时,访问进程-mainmodule文件名-在-C). (3认同)
  • 如果 Visual Studio 抱怨缺少对 `Process.GetProcesses()` 和 `results.Cast&lt;&gt;` 的引用,您还需要添加 `using System.Linq` 指令。 (2认同)

Tha*_*lur 23

我猜你已经有了正在运行的进程的进程对象(例如,通过GetProcessesByName()).然后,您可以使用获取可执行文件名

Process p;
string filename = p.MainModule.FileName;
Run Code Online (Sandbox Code Playgroud)

  • 如果不使用: var p = Process.GetCurrentProcess(); 字符串文件名 = p.MainModule.FileName; (2认同)
  • "A 32位进程无法访问64位进程的模块." 不幸的是,这里也有限制. (2认同)

Bru*_*ell 13

解决方案:

  • 32位和64位进程
  • 仅限System.Diagnostics (无System.Management)

我使用了Russell Gantman解决方案并将其重写为可以使用的扩展方法,如下所示:

var process = Process.GetProcessesByName("explorer").First();
string path = process.GetMainModuleFileName();
// C:\Windows\explorer.exe
Run Code Online (Sandbox Code Playgroud)

有了这个实现:

internal static class Extensions {
    [DllImport("Kernel32.dll")]
    private static extern bool QueryFullProcessImageName([In] IntPtr hProcess, [In] uint dwFlags, [Out] StringBuilder lpExeName, [In, Out] ref uint lpdwSize);

    public static string GetMainModuleFileName(this Process process, int buffer = 1024) {
        var fileNameBuilder = new StringBuilder(buffer);
        uint bufferLength = (uint)fileNameBuilder.Capacity + 1;
        return QueryFullProcessImageName(process.Handle, 0, fileNameBuilder, ref bufferLength) ?
            fileNameBuilder.ToString() :
            null;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 存在权限问题:“System.ComponentModel.Win32Exception:‘访问被拒绝’”。 (2认同)

小智 8

通过结合Sanjeevakumar Hiremath和Jeff Mercado的答案,您可以在某种程度上解决在32位进程中从64位进程中检索图标时的问题.

using System;
using System.Management;
using System.Diagnostics;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            int processID = 6680;   // Change for the process you would like to use
            Process process = Process.GetProcessById(processID);
            string path = ProcessExecutablePath(process);
        }

        static private string ProcessExecutablePath(Process process)
        {
            try
            {
                return process.MainModule.FileName;
            }
            catch
            {
                string query = "SELECT ExecutablePath, ProcessID FROM Win32_Process";
                ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);

                foreach (ManagementObject item in searcher.Get())
                {
                    object id = item["ProcessID"];
                    object path = item["ExecutablePath"];

                    if (path != null && id.ToString() == process.Id.ToString())
                    {
                        return path.ToString();
                    }
                }
            }

            return "";
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这可能有点慢,并且不适用于缺少"有效"图标的每个进程.


Kni*_*ins 6

这是一个可靠的解决方案,适用于32位64位应用程序.

添加以下参考:

使用System.Diagnostics;

使用System.Management;

将此方法添加到您的项目:

public static string GetProcessPath(int processId)
{
    string MethodResult = "";
    try
    {
        string Query = "SELECT ExecutablePath FROM Win32_Process WHERE ProcessId = " + processId;

        using (ManagementObjectSearcher mos = new ManagementObjectSearcher(Query))
        {
            using (ManagementObjectCollection moc = mos.Get())
            {
                string ExecutablePath = (from mo in moc.Cast<ManagementObject>() select mo["ExecutablePath"]).First().ToString();

                MethodResult = ExecutablePath;

            }

        }

    }
    catch //(Exception ex)
    {
        //ex.HandleException();
    }
    return MethodResult;
}
Run Code Online (Sandbox Code Playgroud)

现在使用它如下:

int RootProcessId = Process.GetCurrentProcess().Id;

GetProcessPath(RootProcessId);
Run Code Online (Sandbox Code Playgroud)

请注意,如果您知道进程的id,那么此方法将返回相应的ExecutePath.

额外的,对于有兴趣的人:

Process.GetProcesses() 
Run Code Online (Sandbox Code Playgroud)

...将为您提供所有当前正在运行的进程的数组,并...

Process.GetCurrentProcess()
Run Code Online (Sandbox Code Playgroud)

...将为您提供当前流程,以及他们的信息,例如Id等,以及有限的控制,例如Kill等.*


Rus*_*man 5

您可以使用 pInvoke 和本机调用,如下所示。这似乎没有 32 / 64 位限制(至少在我的测试中)

这是代码

using System.Runtime.InteropServices;

    [DllImport("Kernel32.dll")]
    static extern uint QueryFullProcessImageName(IntPtr hProcess, uint flags, StringBuilder text, out uint size);

    //Get the path to a process
    //proc = the process desired
    private string GetPathToApp (Process proc)
    {
        string pathToExe = string.Empty;

        if (null != proc)
        {
            uint nChars = 256;
            StringBuilder Buff = new StringBuilder((int)nChars);

            uint success = QueryFullProcessImageName(proc.Handle, 0, Buff, out nChars);

            if (0 != success)
            {
                pathToExe = Buff.ToString();
            }
            else
            {
                int error = Marshal.GetLastWin32Error();
                pathToExe = ("Error = " + error + " when calling GetProcessImageFileName");
            }
        }

        return pathToExe;
    }
Run Code Online (Sandbox Code Playgroud)