PowerShell 7中使用Add-Type cmdlet无法调用自定义.NET类问题
问题分析
PowerShell 7基于.NET Core/.NET 6+,和PowerShell 5.1依赖的.NET Framework在Windows Forms支持、API兼容性上存在差异,导致你的脚本出现以下核心问题:
- Windows Forms默认不可用:PowerShell 7不预装
System.Windows.Forms组件,需手动启用兼容性模块。 - 进程模块获取API失效:.NET Core中
Process.MainModule的行为与.NET Framework不同,原代码调用Process.GetCurrentProcess().MainModule.ModuleName会抛出异常,导致Add-Type加载自定义类型失败(无显式报错但类型未实际注册)。 - 钩子初始化逻辑不兼容:部分Win32 API在.NET Core环境下的调用方式需调整。
解决方案
步骤1:安装Windows Forms兼容性模块
在PowerShell 7中执行以下命令(需管理员权限):
Install-Module -Name WindowsFormsCompatibility -Scope CurrentUser -Force
步骤2:使用修复后的脚本
替换原脚本为以下兼容PowerShell 7的版本:
param( [string]$quitKey = "F16" ) # 导入Windows Forms兼容性模块 Import-Module WindowsFormsCompatibility -Force $keyLogger = @" using System; using System.Runtime.InteropServices; using System.Windows.Forms; namespace KeyLogger{ public static class Program { private const int WH_KEYBOARD_LL = 13; private const int WM_KEYDOWN = 0x0100; private static HookProc hookProc = HookCallback; private static IntPtr hookId = IntPtr.Zero; private static int keyCode = 0; [DllImport("user32.dll")] private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); [DllImport("user32.dll")] private static extern bool UnhookWindowsHookEx(IntPtr hhk); [DllImport("user32.dll")] private static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId); [DllImport("kernel32.dll")] private static extern IntPtr GetModuleHandle(string lpModuleName); public static int WaitForKey() { hookId = SetHook(hookProc); Application.Run(); UnhookWindowsHookEx(hookId); return keyCode; } private static IntPtr SetHook(HookProc hookProc) { // .NET Core环境下改用GetModuleHandle(null)获取当前进程主模块句柄 IntPtr moduleHandle = GetModuleHandle(null); return SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, moduleHandle, 0); } private delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam); private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) { if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN) { keyCode = Marshal.ReadInt32(lParam); Application.Exit(); } return CallNextHookEx(hookId, nCode, wParam, lParam); } } }"@ # 加载自定义类型,确保引用Windows Forms程序集 Add-Type -TypeDefinition $keyLogger -ReferencedAssemblies "System.Windows.Forms" while ($keyPress -ne $quitKey) { # 调整转换顺序:先获取原始按键码,再转为Keys枚举 $keyCode = [KeyLogger.Program]::WaitForKey() $keyPress = [System.Windows.Forms.Keys]$keyCode } Write-Host "`nCaught $quitKey, ending recording..." -ForegroundColor Green exit
关键修改说明
- 新增
Import-Module WindowsFormsCompatibility:启用PowerShell 7对Windows Forms的支持。 - 替换进程模块获取逻辑:用
GetModuleHandle(null)替代原Process.MainModule调用,避免.NET Core环境下的异常。 - 调整按键转换顺序:拆分类型转换步骤,避免潜在的类型解析冲突。
内容的提问来源于stack exchange,提问作者ninbura
相关产品推荐
相关产品推荐

