Windows中与Linux中的"pidof"命令等效的命令是什么?

3
在批处理脚本中,我需要获取给定二进制路径 C:\path\to\binary.exe 的进程 ID 列表。在 Linux 中,我只需执行 pidof /path/to/binary 即可。
有没有 Win32 可执行文件可以做同样的事情,支持从 WinXP Home 到 Win7(tasklist 不起作用)?
包含此功能的软件包必须是便携式的,因此我不想要一个 10MB 的下载。
是否有可用的 C 函数,可以在 WinXP 到 Win7 上使用,并匹配进程路径,而不是其他应用程序也可能使用的文件名?
5个回答

5

wmic.exe 可在 XP、Vista 和 7 上使用,并可执行此操作。但是,它不随 Windows XP Home 版本一起提供。

wmic process where ExecutablePath='C:\\windows\\system32\\notepad.exe' get ProcessId

如果您也想支持Windows XP Home,可以使用EnumProcessGetModuleFileNameEx。这里的缺点是,如果您不以管理员身份运行,则无法查询另一个用户正在运行的进程名称。 QueryFullProcessImageName可能会解决这个问题,但它只适用于Vista+。
如果这还不够,您将需要Process32First(swatkat的代码)。对于每个进程,您需要调用Module32First,然后获取MODULEENTRY32->szExePath。请注意,即使如此,这也不是完全可移植的,在x64上效果不佳,您将需要QueryFullProcessImageName

2

您可以使用Toolhelp API枚举进程,获取其完整路径并与所需的进程名称进行比较。您需要遍历每个进程的模块列表。列表中的第一个模块是进程自身的可执行文件。以下是示例代码:

int main( int argc, char* argv[] )
{

    if( argc > 1 )
    {
        printf( "\nGetting PID of: %s\n", argv[1] );
        HANDLE hProcSnapshot = ::CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
        if( INVALID_HANDLE_VALUE != hProcSnapshot )
        {
            PROCESSENTRY32 procEntry = {0};
            procEntry.dwSize = sizeof(PROCESSENTRY32);
            if( ::Process32First( hProcSnapshot, &procEntry ) )
            {
                do
                {
                    HANDLE hModSnapshot = ::CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, procEntry.th32ProcessID );
                    if( INVALID_HANDLE_VALUE != hModSnapshot )
                    {
                        MODULEENTRY32 modEntry = {0};
                        modEntry.dwSize = sizeof( MODULEENTRY32 );
                        if( Module32First( hModSnapshot, &modEntry ) )
                        {
                            if( 0 == stricmp( argv[1], modEntry.szExePath ) )
                            {
                                printf( "\nPID: %ld\n", procEntry.th32ProcessID );
                                ::CloseHandle( hModSnapshot );
                                break;
                            }
                        }
                        ::CloseHandle( hModSnapshot );
                    }
                }
                while( ::Process32Next( hProcSnapshot, &procEntry ) );
            }
            ::CloseHandle( hProcSnapshot );
        }
    }
    return 0;
}

谢谢,这正是我所需要的。我已经看到::很多次了,那是C++的东西吗?现在我会尝试使用Unicode名称(如中文)让它工作。 - Lekensteyn
通过小的修改,它可以适用于所有进程。现在它也可以处理特殊字符,例如中文。为了使其正常工作,系统必须是中文,否则会显示? - Lekensteyn

1

如果PowerShell内置于Win 7中,并可在其他操作系统上下载,它可以解决您的问题。

param($fileName)
Get-Process | where -FilterScript {$_.MainModule.FileName -eq $fileName}

此脚本将接收一个参数,即你要寻找的文件名,并输出其可执行文件的文件名。
你可以通过以下方式从 bat 文件中调用它: powershell -Command "& {Get-Process | where -FilterScript {$_.MainModule.FileName -eq %FILENAME%}"

我希望它是可移植的,而不需要安装很多东西。无论如何,感谢您的回答。 - Lekensteyn
好的。请记住,PowerShell 只是一个东西,对于 Windows Vista 下载大小为 5MB,对于 Windows XP 下载大小为 1.6MB。它也内置在 win 7 中。来源:http://www.microsoft.com/windowsserver2003/technologies/management/powershell/download.mspx - David Reis
这不是和原帖要求完全相反吗?他想知道在给定的可执行文件上打开了哪些pid,而不是在给定的pid上打开了哪个可执行文件。 - JUST MY correct OPINION

1

那只返回进程名称,例如GetModuleFileName或CreateToolhelp32Snapshot。是否有一个函数可以在WinXP到Win7上工作并返回路径? - Lekensteyn
@Lekensteyn - 你是对的,我编辑了答案以获取路径。 - rkellerm

0
我使用pidof命令,参数是进程名称。以前我不需要可执行路径。我使用的方式是:
pidof php

只返回正在运行的进程的PID。同样,使用PowerShell时,我可以按照以下方式使用它:
(get-process php).id

它返回的PID与pidof相同。

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