无法通过 PowerShell 7 中的 Add-Type cmdLet 使用 .Net 类

问题描述 投票:0回答:1

我有一个 PowerShell 脚本,它会在退出之前侦听按下的键。我使用自定义的

TypeDefinition
来完成此操作;这是代码:

param(
  [string]$quitKey = "F16"
)

$keyLogger = @"
using System;
using System.IO;
using System.Diagnostics;
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) {
        IntPtr moduleHandle = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
        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);
    }
  }
}
"@

Add-Type -TypeDefinition $keyLogger -ReferencedAssemblies system.Windows.Forms

while ($keyPress -ne $quitKey) {
  $keyPress = [System.Windows.Forms.Keys][KeyLogger.Program]::WaitForKey()
}

Write-Host "`nCaught $quitKey, ending recording..." -ForegroundColor Green

exit

上面的代码在 Windows 11 上预安装的 PowerShell 5.1 中完美执行。但是,我无法让该脚本在 PowerShell 7(具体是 7.3.4)中运行;我收到此错误:

InvalidOperation: 
Line |
  62 |    $keyPress = [System.Windows.Forms.Keys][KeyLogger.Program]::WaitFor …
     |                                           ~~~~~~~~~~~~~~~~~~~
     | Unable to find type [KeyLogger.Program].

在网上到处搜索类似的问题,但没有找到任何东西。

Add-Type
似乎可以在我的其他脚本中工作,甚至在 PowerShell 7 中也是如此。但由于某种原因,这个特定的自定义
TypeDefiniton
失败了。

c# .net powershell powershell-7.0 add-type
1个回答
1
投票

较新版本的 PowerShell 中存在一个长期存在的错误,当使用

-ReferenceAssemblies
时,默认情况下不会包含标准程序集,请参阅 GitHub 问题 #9599

您可以使用我在这个答案中使用的相同解决方法,对于您的情况,代码将如下所示以使其与两个版本兼容:

# Top of your code goes this:
Add-Type -AssemblyName System.Windows.Forms

$refAssemblies = @(
    [System.Windows.Forms.Form].Assembly.Location

    if ($IsCoreCLR) {
        $pwshRefAssemblyPattern = [IO.Path]::Combine($PSHOME, 'ref', '*.dll')
        Convert-Path $pwshRefAssemblyPattern
    }
)

# Definition stays the same:
$keyLogger = @'
...
...
'@ 

# Here you include the assembly you want plus the default ones:
Add-Type -TypeDefinition $keyLogger -ReferencedAssemblies $refAssemblies
© www.soinside.com 2019 - 2024. All rights reserved.