Как получить полный путь запущенного процесса?
У меня есть приложение, которое изменяет некоторые настройки другого приложения (это простое приложение C#, которое запускается двойным щелчком (не требуется настройка)).
после изменения настроек мне нужно перезапустить другое приложение, чтобы оно отражало измененные настройки.
чтобы сделать это, я должен убить запущенный процесс и запустить процесс снова, но проблема в том, что после убийства я не могу найти процесс. (Причина в том, что система не знает, где EXE файл..)
есть ли способ узнать путь запущенного процесса или exe, если он работает?
Я не хочу, чтобы дать путь вручную, т. е. если он работает получить путь, убить процесс и начать все заново .... Я разберусь позже
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()
...даст вам текущий процесс, вместе с их информацию, например, идентификатор, и т. д. а также ограниченный контроль, например, убивать и т. д.*
вы можете использовать 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(); } }