Как получить полный путь запущенного процесса?


У меня есть приложение, которое изменяет некоторые настройки другого приложения (это простое приложение C#, которое запускается двойным щелчком (не требуется настройка)).

после изменения настроек мне нужно перезапустить другое приложение, чтобы оно отражало измененные настройки.

чтобы сделать это, я должен убить запущенный процесс и запустить процесс снова, но проблема в том, что после убийства я не могу найти процесс. (Причина в том, что система не знает, где EXE файл..)

есть ли способ узнать путь запущенного процесса или exe, если он работает?

Я не хочу, чтобы дать путь вручную, т. е. если он работает получить путь, убить процесс и начать все заново .... Я разберусь позже

12 81
c#

12 ответов:

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

есть один улов с этим API, если вы используете этот код в 32-разрядном приложении, вы не сможете получить доступ к 64-разрядным путям приложения, поэтому вам придется скомпилировать и запустить приложение как 64-разрядное приложение (свойства проекта → сборка → цель платформы → x64).

что вы можете сделать, это использовать 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
    }
}

обратите внимание, что вы должны будете ссылаться на System.Management.dll сборка и использовать System.Management пространство имен.

для получения дополнительной информации о том, какую еще информацию вы можете извлечь из этих процессов, таких как командная строка, используемая для запуска программы (CommandLine), см. именем Win32_Process класс а WMI .NET для получения дополнительной информации.

Я думаю, у вас уже есть объект process запущенного процесса (например, GetProcessesByName()). Затем вы можете получить имя исполняемого файла с помощью

Process p;
string filename = p.MainModule.FileName;

объединив ответы Sanjeevakumar Hiremath и Jeff Mercado, вы можете фактически обойти проблему при извлечении значка из 64-разрядного процесса в 32-разрядном процессе.

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

Это может быть немного медленно и не работает на каждом процессе, который не имеет "действительный" значок.

здесь-это надежное решение, которое работает с 32bit и 64bit приложения.

добавить эти ссылки:

использование системы.Диагностика;

использование системы.Управление;

добавьте этот метод в свой проект:

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

теперь используйте его так:

int RootProcessId = Process.GetCurrentProcess().Id;

GetProcessPath(RootProcessId);

обратите внимание, что если вы знаете идентификатор процесса, то этот метод будет возвращать соответствующее ExecutePath.

дополнительно, для тех, кто заинтересован:

Process.GetProcesses() 

...даст вам массив всех запущенных в данный момент процессов, и...

Process.GetCurrentProcess()

...даст вам текущий процесс, вместе с их информацию, например, идентификатор, и т. д. а также ограниченный контроль, например, убивать и т. д.*

решение:

  • как 32-разрядные, так и 64-разрядные процессы

вы можете использовать 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;
    }

попробуй:

using System.Diagnostics;

ProcessModuleCollection modules = Process.GetCurrentProcess().Modules;
string processpathfilename;
string processmodulename;
if (modules.Count > 0) {
    processpathfilename = modules[0].FileName;
    processmodulename= modules[0].ModuleName;
} else {
    throw new ExecutionEngineException("Something critical occurred with the running process.");
}
using System;
using System.Diagnostics;

class Program
{
    public static void printAllprocesses()
    {
        Process[] processlist = Process.GetProcesses();

        foreach (Process process in processlist)
        {
            try
            {
                String fileName = process.MainModule.FileName;
                String processName = process.ProcessName;

                Console.WriteLine("processName : {0},  fileName : {1}", processName, fileName);
            }catch(Exception e)
            {
                /* You will get access denied exception for system processes, We are skiping the system processes here */
            }

        }
    }

    static void Main()
    {
        printAllprocesses();
    }

}

The Process класса что вы должны проверить:

private void Test_Click(object sender, System.EventArgs e){
   string path;
   path = System.IO.Path.GetDirectoryName( 
      System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase );
    Console.WriiteLine( path );  
}

Я попал в этот поток при поиске текущего каталога исполняемого процесса. В .net 1.1 Microsoft представила:

Directory.GetCurrentDirectory();

Кажется, работает хорошо (но не возвращает имя самого процесса).