Как получить полный путь запуска процесса?
У меня есть приложение, которое меняет некоторые настройки другого приложения (это простое приложение С#, которое выполняется двойным щелчком (не требуется настройка)).
После изменения настроек мне нужно перезапустить другое приложение, чтобы оно отображало измененные настройки.
Итак, мне нужно убить текущий процесс и снова запустить процесс, но проблема в том, что после убийства я не смог найти этот процесс. (Причина в том, что система не знает, где находится exe файл..)
Есть ли способ узнать путь выполнения процесса или exe, если он работает?
Я не хочу указывать путь вручную, т.е. если он запущен, получите путь, убейте процесс и снова запустите еще... Я обработаю позже
Ответы
Ответ 1
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).
Ответ 2
Что вы можете сделать, это использовать 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 для получения дополнительной информации.
Ответ 3
Я думаю, у вас уже есть объект процесса запущенного процесса (например, GetProcessesByName()). Затем вы можете получить имя исполняемого файла, используя
Process p;
string filename = p.MainModule.FileName;
Ответ 4
Решение для:
- Оба 32-битных и 64-битных процесса
- Только System.Diagnostics (без System.Management)
Я использовал решение Рассела Гантмана и переписал его как метод расширения, который вы можете использовать следующим образом:
var process = Process.GetProcessesByName("explorer").First();
string path = process.GetMainModuleFileName();
// C:\Windows\explorer.exe
С помощью этой реализации:
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;
}
}
Ответ 5
Объединив ответы 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 "";
}
}
}
Это может быть немного медленным и не работает на каждом процессе, который не имеет значка "действительный".
Ответ 6
Вот надежное решение, которое работает как с приложениями 32bit, так и с 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);
Обратите внимание: если вы знаете идентификатор процесса, то этот метод вернет соответствующий ExecutePath.
Дополнительно, для заинтересованных:
Process.GetProcesses()
... даст вам массив всех текущих запущенных процессов и...
Process.GetCurrentProcess()
... предоставит вам текущий процесс, а также их информацию, например. Id и т.д., А также ограниченный контроль, например. Убить и т.д. *
Ответ 7
Вы можете использовать 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;
}
Ответ 8
Try:
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.");
}
Ответ 9
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 );
}
Ответ 10
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();
}
}
Ответ 11
Для других, если вы хотите найти другой процесс с тем же исполняемым файлом, вы можете использовать:
public bool tryFindAnotherInstance(out Process process) {
Process thisProcess = Process.GetCurrentProcess();
string thisFilename = thisProcess.MainModule.FileName;
int thisPId = thisProcess.Id;
foreach (Process p in Process.GetProcesses())
{
try
{
if (p.MainModule.FileName == thisFilename && thisPId != p.Id)
{
process = p;
return true;
}
}
catch (Exception)
{
}
}
process = default;
return false;
}
Ответ 12
В классе Process
есть член StartInfo
, который вы должны проверить:
Ответ 13
Я попал в этот поток, ища текущий каталог исполняемого процесса. В .net 1.1 Microsoft представила:
Directory.GetCurrentDirectory();
Кажется, что он хорошо работает (но не возвращает имя самого процесса).