在32位powershell中通过路径查找/终止64位进程



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

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

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

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

这个问题有一些讨论:如何从32位进程中获得给定PID的64位进程的可执行路径?

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

所以我的问题是:是否可以从PowerShell脚本中调用像QueryFullProcessImageName()GetModuleFileNameEx()这样的WinAPI函数作为获取这些信息的变通方法?或者还有其他我不考虑的方法吗?

为了满足这一需求,这是我拼凑而成的。也许它会帮助其他人。欢迎批评。

$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或任何你想用它做的事情。

最新更新