在 32 位 powershell 中按路径查找/杀死 64 位进程

Posted

技术标签:

【中文标题】在 32 位 powershell 中按路径查找/杀死 64 位进程【英文标题】:Find/Kill 64 bit processes by path in 32 bit powershell 【发布时间】:2021-07-16 22:01:23 【问题描述】:

我有一个应用程序的 PowerShell 清理脚本。理想情况下,进程是通过它们的路径发现的,以免鲁莽地杀死系统上可能具有相似名称的其他进程。我们注意到一些进程没有被检测/杀死,经过大量实验后意识到比特是问题所在。为了兼容性,该脚本以 32 位自举,但有些进程不是。

Get-Process 可以在 32 位 PowerShell 中调用并返回包括 64 位在内的所有进程,但如 This Ref 中所述:

在运行 64 位版本 Windows 的计算机上,64 位版本的 PowerShell 仅获取 64 位进程模块,而 32 位版本的 PowerShell 仅获取 32 位进程模块。

确实,当发现进程时,进程模块信息(包括进程的路径)对于位数与 shell 不匹配的进程不可用。

这个问题有一些讨论:How can I get the executable path of a 64-bit process given its PID from a 32-bit process?

建议的Get-WmiObject 查询对我不起作用,如图所示,它返回缺少ExecutablePath 信息的64 位进程,与Get-Process 基本相同。

所以我的问题是:是否可以从 PowerShell 脚本中调用 QueryFullProcessImageName()GetModuleFileNameEx() 等 WinAPI 函数作为获取此信息的解决方法?或者有没有其他我没有考虑的方法?

【问题讨论】:

用你的命令调用 64bit powershell.exe ? 【参考方案1】:

为了满足这个需求,这是我拼凑起来的。也许它会帮助别人。欢迎批评。

$pinvoke = Add-Type -PassThru -Name pinvoke -MemberDefinition @'
    [DllImport("kernel32.dll", SetLastError=true)]
    private static extern bool CloseHandle(
        IntPtr hObject);

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern IntPtr OpenProcess(
        uint processAccess,
        bool bInheritHandle,
        int processId);

    [DllImport("kernel32.dll", SetLastError=true)]
    private static extern bool QueryFullProcessImageName(
        IntPtr hProcess,
        int dwFlags,
        System.Text.StringBuilder lpExeName,
        ref int lpdwSize);
    private const int QueryLimitedInformation = 0x00001000;

    public static string GetProcessPath(int pid)
    
        var size = 1024;
        var sb = new System.Text.StringBuilder(size);
        var handle = OpenProcess(QueryLimitedInformation, false, pid);
        if (handle == IntPtr.Zero) return null;
        var success = QueryFullProcessImageName(handle, 0, sb, ref size);
        CloseHandle(handle);
        if (!success) return null;
        return sb.ToString();
    
'@

然后你可以通过

得到一个32位或64位进程的路径
$pinvoke::GetProcessPath($pid)

过滤进程而不是:

Get-Process | Where-Object $_.Path -like "*$filePath*"

32/64位有问题,可以用

Get-Process | Where-Object $pinvoke::GetProcessPath($_.Id) -like "*$filePath*"

将它输入到 Stop-Process 或任何你想用它做的事情中。

【讨论】:

以上是关于在 32 位 powershell 中按路径查找/杀死 64 位进程的主要内容,如果未能解决你的问题,请参考以下文章

64 位 PowerShell 调用 32 位 DLL

linux中按路径查找并替换某字符串的命令

Xamarin Forms Android 10 及更高版本在公共外部存储中按文件名查找视频并获取路径

CMake 在错误的路径上查找库

C中按位运算的模运算

从 ispc 导出的函数中按值返回结构?