检查特定的exe文件是否正在运行

38

我想知道如何检查特定位置的程序是否正在运行。例如,c:\loc1\test.exe和c:\loc2\test.exe是test.exe的两个不同位置。我只想知道c:\loc1\test.exe是否在运行,而不是所有test.exe实例。

8个回答

60
bool isRunning = Process.GetProcessesByName("test")
                .FirstOrDefault(p => p.MainModule.FileName.StartsWith(@"c:\loc1")) != default(Process);

7
好的回答,但请注意,如果您正在使用类似于 ..StartsWith(new FileInfo(Application.ExecutablePath).DirectoryName) 这样的代码将无法正常工作。这是因为 DirectoryName 返回的路径会使用小写驱动器字母,例如 **c:**。因此,最好将其修改为 ..FileName.ToLower()..StartsWith(@path.ToLower()) - Robin Rye
8
最好进行不区分大小写的比较(例如使用.StartsWith(path, StringComparison.InvariantCultureIgnoreCase)),因为这样不会改变字符串。 - Ben
5
作为良好的惯例,请始终使用OrdinalIgnoreCase来处理文件名等内容。 - Timo

10

这是我的改进后的函数:

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

1
错误:System.ComponentModel.Win32Exception: '拒绝访问。' - DxTx
1
@DxTx 尝试以管理员身份运行它 - 8Unlimited8

6
尝试这个......我用它来确定在启动时是否已有另一个进程使用与我尝试启动的exe相同的名称运行,并且如果该进程已经在运行,则将其带到前台(并聚焦)。您可以修改它以获取进程名称并测试该特定名称... 这将告诉您是否有正在运行具有某个名称的进程,但不知道该进程从哪里加载...
如果存在指定名称的进程运行,则如果该进程具有公开可访问方法返回其被加载的位置,则可以在运行中的进程上调用该方法,否则,我不知道...
但是出于好奇,除非它们不同,否则您为什么关心?如果它们在某种方式下不同,编写代码以使用该差异(无论它是什么)检测已加载哪个。但是,如果它们相同,那么使用哪个磁盘映像文件加载它怎么可能有影响呢?
    [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;
    }

5
你需要遍历所有现有的进程,然后检查它们的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...
   }
}

尝试了你的代码,但是我遇到了32位进程无法访问64位进程的模块的问题,最终使用了https://dev59.com/xG035IYBdhLWcg3wT-NC#5497319中提供的解决方案。 - Adrian C.

4
这个函数可能有帮助:
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


1

类似于这样。GetMainModuleFileName有助于从x86访问x64进程。

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

private bool CheckRunningProcess(string processName, string path) {

    var processes = Process.GetProcessesByName(processName);

    foreach(var process in processes) {

        var name = GetMainModuleFileName(process);
        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;
}

0
你可以使用一个命名互斥锁,它的名称基于程序运行的目录结构。

-1
System.Reflection.Assembly.GetEntryAssembly()

这将为您提供有关入口程序集的大量信息,例如:

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

这将告诉您正在运行的程序集的位置。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接