Проверьте, запущен ли конкретный exe-файл

Я хочу знать, как я могу проверить программу в определенном месте, если она запущена. Например, существует два места для файла test.exe: c:\loc1\test.exe и c:\loc2\test.exe. Я только хотел знать, запущен ли c:\loc1\test.exe, а не все экземпляры test.exe.


person murasaki5    schedule 16.11.2009    source источник


Ответы (8)


Это моя улучшенная функция:

private bool ProgramIsRunning(string FullPath)
{
    string FilePath =  Path.GetDirectoryName(FullPath);
    string FileName = Path.GetFileNameWithoutExtension(FullPath).ToLower();
    bool isRunning = false;

    Process[] pList = Process.GetProcessesByName(FileName);

    foreach (Process p in pList) {
        if (p.MainModule.FileName.StartsWith(FilePath, StringComparison.InvariantCultureIgnoreCase))
        {
            isRunning = true;
            break;
        }
    }

    return isRunning;
}

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

ProgramIsRunning(@"c:\loc1\test.exe");
person 8Unlimited8    schedule 20.12.2015
comment
Ошибка: System.ComponentModel.Win32Exception: 'Access is denied.' - person DxTx; 30.05.2020
comment
@DxTx попробуйте запустить его от имени администратора - person 8Unlimited8; 27.06.2020

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

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

Но просто из любопытства, какое тебе дело, если они не разные? И если они каким-то образом отличаются, используйте код для использования этой разницы (какой бы она ни была) для определения того, что загружено. Но если они одинаковые, какая разница, какой образ на диске использовался для его загрузки?

    [DllImport("user32.dll")]
    private static extern bool SetForegroundWindow(IntPtr hWnd);
    [DllImport("user32.dll")]
    private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
    [DllImport("user32.dll")]
    private static extern bool IsIconic(IntPtr hWnd);

    private const int SW_HIDE = 0;
    private const int SW_SHOWNORMAL = 1;
    private const int SW_SHOWMINIMIZED = 2;
    private const int SW_SHOWMAXIMIZED = 3;
    private const int SW_SHOWNOACTIVATE = 4;
    private const int SW_RESTORE = 9;
    private const int SW_SHOWDEFAULT = 10;

 private static bool IsAlreadyRunning()
    {
        // get all processes by Current Process name
        Process[] processes = 
            Process.GetProcessesByName(
                Process.GetCurrentProcess().ProcessName);

        // if there is more than one process...
        if (processes.Length > 1) 
        {
            // if other process id is OUR process ID...
            // then the other process is at index 1
            // otherwise other process is at index 0
            int n = (processes[0].Id == Process.GetCurrentProcess().Id) ? 1 : 0;

            // get the window handle
            IntPtr hWnd = processes[n].MainWindowHandle;

            // if iconic, we need to restore the window
            if (IsIconic(hWnd)) ShowWindowAsync(hWnd, SW_RESTORE);

            // Bring it to the foreground
            SetForegroundWindow(hWnd);
            return true;
        }
        return false;
    }
person Charles Bretana    schedule 16.11.2009

Вы должны перебрать все существующие процессы, а затем проверить их свойство MainModule на предмет имени файла, который вы ищете. Что-то вроде этого

using System.Diagnostics;
using System.IO;

//...

string fileNameToFilter = Path.GetFullPath("c:\\loc1\\test.exe");

foreach (Process p in Process.GetProcesses())
{
   string fileName = Path.GetFullPath(p.MainModule.FileName);

   //cehck for equality (case insensitive)
   if (string.Compare(fileNameToFilter, fileName, true) == 0)
   {
      //matching...
   }
}
person Frank Bollack    schedule 16.11.2009
comment
Попробовал ваш код, но я запустил A 32 bit processes cannot acess modules of a 64 bit process и в итоге использовал решение из http://stackoverflow.com/questions/5497064/c-how-to-get-the-full-path-of-running-процесс/5497319#5497319. - person Adrian C.; 07.10.2016

Эта функция может помочь:

using System.Diagnostics;

public bool IsProcessOpen(string name)
{
    foreach (Process clsProcess in Process.GetProcesses()) {
        if (clsProcess.ProcessName.Contains(name))
        {
            return true;
        }
    }
    return false;
} 

Источник: http://www.dreamincode.net/code/snippet1541.htm

person Alex Musayev    schedule 16.11.2009

Что-то вроде этого. GetMainModuleFileName помогает получить доступ к процессу x64 из x86.

  [DllImport("kernel32.dll")]
  public static extern bool QueryFullProcessImageName(IntPtr hprocess, int dwFlags, StringBuilder lpExeName, out int size);

  private bool CheckRunningProcess(string processName, string path) {

  Process[] processes = Process.GetProcessesByName(processName);
  foreach(Process p in processes) {
    var name = GetMainModuleFileName(p);
    if (name == null)
      continue;
    if (string.Equals(name, path, StringComparison.InvariantCultureIgnoreCase)) {
      return true;
    }
  }
  return false;
}

// Get x64 process module name from x86 process
private static string GetMainModuleFileName(Process process, int buffer = 1024) {

  var fileNameBuilder = new StringBuilder(buffer);
  int bufferLength = fileNameBuilder.Capacity + 1;
  return QueryFullProcessImageName(process.Handle, 0, fileNameBuilder, out bufferLength) ?
      fileNameBuilder.ToString() :
      null;
}
person vik_78    schedule 30.08.2018

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

person JustLoren    schedule 16.11.2009

System.Reflection.Assembly.GetEntryAssembly()

Это принесет вам много информации о входной сборке, например:

System.Reflection.Assembly.GetEntryAssembly().CodeBase;

Это подскажет расположение ходовой сборки.

person jonaspp    schedule 16.11.2009

person    schedule
comment
Хороший ответ, хотя обратите внимание, что если вы используете что-то похожее на ..StartsWith(new FileInfo(Application.ExecutablePath).DirectoryName), это не сработает. Это связано с тем, что DirectoryName возвращает путь с буквой диска в нижнем регистре, например c:. Таким образом, рекомендуется изменить его как ..FileName.ToLower() и ..StartsWith(@path.ToLower()). - person Robin Rye; 10.07.2012
comment
Лучше делать сравнение без учета регистра (например, используя .StartsWith(path, StringComparison.InvariantCultureIgnoreCase)), так как оно не требует изменения строк. - person Ben; 08.05.2013
comment
И, как хорошая практика, всегда используйте OrdinalIgnoreCase для имен файлов и т.п. - person Timo; 28.01.2015