如何全局加载PowerShell模块中的类?

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

我已经读过这个问题,尽管它有很多来回,我尽力遵循建议,但仍然不确定如何解决这个问题。

我在

ScriptsToProcess
.ps1
文件中定义了多个类,如下所示:

https://github.com/HotCakeX/Harden-Windows-Security/blob/WDACConfig-v0.3.4/WDACConfig/WDACConfig%20Module%20Files/Preloader.ps1

问题是,当我将模块文件复制到干净状态的虚拟机并尝试使用 cmdlet 时,我收到一条错误消息,指出未找到类型,但如果我关闭并重新打开 PowerShell 或使用

Import-Module
-Force
参数然后一切都好。

我需要知道如何解决这个问题而不引入太多重复代码。

我正在使用 PowerShell 7.5

powershell class types powershell-core powershell-7.4
1个回答
0
投票

我不完全理解与VM相关的问题,但也许以下方法绕过问题:

  • class
    定义为脚本模块 (
    *.psm1
    ) 的一部分,而不是通过模块的
    *.ps1
    清单条目加载到调用者作用域中的
    ScriptsToProcess
    文件。

  • 本身,这使得您的类只能用于使用解析时

    using module
    语句导入模块的调用者。

  • 但是,about_Classes帮助主题的使用类型加速器导出类部分描述了一个解决方法,它使您选择的类在所有作用域和运行空间中全局会话可用。

  • 下面的示例代码演示了这种方法,但有以下注意事项

    • 与基于

      using module
      的方法一样,您将无法在给定会话中重新加载修改的
      class
      定义 - 而是启动一个新会话。

    • 与基于

      using module
      的方法不同(您仍然可以选择与建议的方法组合),(可能是隐式的)导入器不得依赖
      class
      es 在解析时可用 .

    • 因为建议的方法(可能)也将

      class

      暴露给 
      其他运行空间,所以 classes
       应使用 
      [NoRunspaceAffinity()
      属性进行装饰,该属性在
      v7.4+ 中可用仅有的。也就是说,只要仅使用 single 运行空间(默认运行空间),该方法就可以安全地在早期版本中使用。

    • 链接的帮助主题还包括基于事件的代码,用于在卸载模块时尝试

      remove导出的class

      定义 (
      Remove-Module
      ),但是,这
      不起作用(从 PowerShell 7.4.1 开始) ,因此在下面的代码中被省略。

示例

*.psm1

内容:

# Since the quasi-exported class will be available *process-wide* # and therefore also in *other runspaces*, be sure to define it with # the [NoRunspaceAffinity()] attribute. # Caveat: **v7.4+ only** [NoRunspaceAffinity()] class SomeClass { # Note: 'SomeClass' is both its .Name and .FullName. [int] Get() { return 42 } } # Define the types to export with type accelerators. $exportableTypes = @( [SomeClass] ) # Get the non-public TypeAccelerators class for defining new accelerators. $typeAcceleratorsClass = [psobject].Assembly.GetType('System.Management.Automation.TypeAccelerators') # Add type accelerators for every exportable type. $existingTypeAccelerators = $typeAcceleratorsClass::Get foreach ($type in $exportableTypes) { # !! $TypeAcceleratorsClass::Add() quietly ignores attempts to redefine existing # !! accelerators with different target types, so we check explicitly. $existing = $existingTypeAccelerators[$type.FullName] if ($null -ne $existing -and $existing -ne $type) { throw "Unable to register type accelerator [$($type.FullName)], because it is already defined with a different type ([$existing])." } $typeAcceleratorsClass::Add($type.FullName, $type) }
与此 

*.psm1

 关联的模块的任何(可能是隐式的)导入程序都将在运行时
使用
[SomeClass]
类。

© www.soinside.com 2019 - 2024. All rights reserved.