简体   繁体   中英

What is the Windows equivalent of “pidof” from Linux?

In a batchscript, I need to get a list of process IDs with given binary path C:\\path\\to\\binary.exe . In Linux, I can just do pidof /path/to/binary .

Is there a Win32 executable which does the same, supported from WinXP Home to Win7 (tasklist won't work)?

The package which includes this has to be portable, so a 10MB download is not what I'm looking for.

Is there a C function available which does this and is supported from WinXP to Win7? Note: I want to match a process path, not a filename which could be used by other applications too.

wmic.exe is available on XP, Vista and 7 and can do this. However, it does not come with Windows XP Home edition.

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

If you want support for Windows XP Home too, you can use EnumProcess and GetModuleFileNameEx . The downside here is that you won't be able to query names of processes running by another user if you're not running as administrator. QueryFullProcessImageName will probably do the trick here, but it's Vista+.

If that's not enough, you'll need Process32First (swatkat's code). For each process you need to call Module32First and then get MODULEENTRY32->szExePath . Note that even this is not completely portable and will not work well on x64 where you'll need QueryFullProcessImageName .

You can use Toolhelp APIs to enumerate processes, get their full path and compare it with the required process name. You need to walk the modules list for each process. The first module in the list is the process executable itself. Here's a sample code:

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;
}

PowerShell can solve your problems, if is buit in in Win 7, and downloadable on the other OSs.

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

This script will receive one parameter, the filename you are looking for, and it will output the filename of its executable.

You can call this from a bat file by doing:

powershell -Command "& {Get-Process | where -FilterScript {$_.MainModule.FileName -eq %FILENAME%}"

You can write a small C# application which first calls Process.GetProcessesByName(String) , then go over the results and print the Id property of each one when the MainModule. FileName is equal to the path you are looking for.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM