【问题标题】:Powershell: Use user32.dll in .psd1 filePowershell:在 .psd1 文件中使用 user32.dll
【发布时间】:2021-02-24 20:45:29
【问题描述】:

环境:Win 10 64位,PS 7.1版

我有一个模块,我决定将所有内容都移到基于类中。要使用程序集,我需要通过解决方法 psd1 文件加载 .dll 等。

看帖后:Powershell: Unable to find type when using PS 5 classes

**根据@mklement0 的评论,.dll 无法像组件“System.Windows.Forms”一样加载

根据@mklement0 的建议进行了更新,但仍然无效 这是更新后的样子:

H:\PowerShell\Modules\TestUtils

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---           2/26/2021  6:25 AM           4168 TestUtils.psd1
-a---           2/26/2021  6:22 AM            449 TestUtils.psm1

TestUtils.psd1 是由命令创建的:

New-ModuleManifest TestUtils.psd1 -RootModule TestUtils.psm1 .psm1中的内容如下:

Add-Type -name NativeMethods -namespace Win32 -MemberDefinition @'
    [DllImport("user32.dll")]
    public static extern void mouse_event(int flags, int dx, int dy, int cButtons, int info);
    [DllImport("user32.dll")]
    public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
'@  

Class MyWinUtils
{
    
    Static [Void] ClickLeftMouse([int]$x,[int]$y)
    {
      [Win32.NativeMethods]::mouse_event(6,0,0,0,0) 
    }
}

当我加载模块时弹出错误:

using module TestUtils
InvalidOperation: At TestUtils.psm1:15 char:5
+       [Win32.NativeMethods]::mouse_event(6,0,0,0,0)
+        ~~~~~~~~~~~~~~~~~~~
Unable to find type [Win32.NativeMethods].

谢谢

【问题讨论】:

  • PS 5.1 中的 FWIW 我有 psm1 文件,其中包含类,当您使用 using module 语法而不是 Import-Module 时,它们可以正常加载。
  • 我总是使用 Add-Type -TypeDefinition 添加 Win32 类型。我还看到 C# 代码缺少使用 PInvoke 所需的 using 语句(DllImport 需要 System.Runtime.InteropServices。)
  • @bluuf,不必 必须添加这些 using 语句并且不必 不必显式定义封闭类是-MemberDefinition 的便利提供 - 它的主要用途是促进公开基于 P/Invoke 的方法。

标签: powershell


【解决方案1】:

您不能要求 user32.dll 作为一个程序集,因为它不是一个:它是一个非托管 DLL,与 .NET 无关

改为:

  • 仅使用RequiredAssemblies = 'System.Windows.Forms', 'System.Drawing' 来确保这些托管 DLL(程序集)被加载。

  • 还将*.psm1 文件添加到您的模块目录,使用与模块目录相同的名称作为基本名称。

  • 从模块清单的 RootModule 属性中引用 *.psm1 文件 - 仅按文件 名称

  • Add-Type -MemberDefinition 调用直接放在*.psm1 文件的顶级范围内。

    • 传递给该调用的 C# 代码能够定位非托管 user32.dll DLL,因为它位于标准 SYSTEM32 目录中。

然后,当您的模块被导入时,Add-Type -MemberDefinition 命令会被执行,并将[Win32.NativeMethod] 类及其静态mouse_event()ShowWindowAsync() 方法添加到您的会话中。


您问题的更新揭示了一个其他、不相关的问题

  • 您正在尝试在同一文件中定义的 PowerShell 自定义类 的上下文中使用 Add-Type-added .NET 类型。

  • 但是,PowerShell 在 parse 时而不是在 runtime 解析类定义,这意味着它需要在 class 定义中引用的类型已加载到会议事先

解决方法

  • Add-Type -MemberDefinition 调用放在模块目录中的一个单独 *.psm1 文件中,例如helper.psm1,并从清单中的NestedModules 属性中引用该文件 (NestedModules = @('helper') )。

嵌套模块在主(根)模块(RootModule 属性)之前处理,因此在解析MyWinUtils 类定义时,[Win32.NativeMethods] 类型已经被加载.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-14
    • 2012-03-23
    • 2018-10-30
    • 2012-02-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多