C#:如何获得正在运行的进程的完整path?
我有一个应用程序正在改变其他应用程序的一些设置(这是一个简单的C#应用程序,通过双击运行(无需设置))。
更改设置后,我需要重新启动其他应用程序,以便它反映更改的设置。
所以要做,我必须杀死正在运行的进程,并重新启动进程,但问题是在杀死后我无法find进程。 (原因是系统不知道exe文件在哪里..)
有没有办法find正在运行的进程或exe的path,如果它正在运行?
我不想手动给path,即如果它正在运行得到path,杀死进程,并再次启动….我会稍后处理
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位应用程序path,所以你必须编译和运行你的应用程序为64位应用程序。 (项目属性 – >生成 – >平台目标 – > x64)
你可以做的是使用WMI来获取path。 这将允许您获取path,无论它是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以获取更多信息。
我想你已经有运行过程的进程对象(例如通过GetProcessesByName())。 然后您可以使用获取可执行文件的名称
Process p; string filename = p.MainModule.FileName;
通过结合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 ""; } } }
这可能有点慢,不适用于每个缺乏“有效”图标的进程。
这是一个可靠的解决scheme,适用于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; }
现在像这样使用它:
int RootProcessId = Process.GetCurrentProcess().Id; GetProcessPath(RootProcessId);
注意,如果你知道进程的id,那么这个方法将返回相应的ExecutePath。
额外,对于那些感兴趣的:
Process.GetProcesses()
…会给你一个所有正在运行的进程的数组,并…
Process.GetCurrentProcess()
…会给你当前的过程,连同他们的信息,如身份证等,也有限的控制,如杀死等*
尝试:
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(); } }
您可以使用pInvoke和本地调用,如下所示。 这似乎没有32/64位的限制(至less在我的testing)
这是代码
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; }
Process
类有一个成员StartInfo
,你应该检查出来:
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中微软介绍:
Directory.GetCurrentDirectory();
似乎工作正常(但不返回进程本身的名称)。