【问题标题】:Why are my cmdlets imported, exported and then imported again?为什么我的 cmdlet 被导入、导出然后再次导入?
【发布时间】:2016-03-03 09:55:15
【问题描述】:

我有一个带有 .psd1 文件和 .psm1 文件的二进制 PowerShell 模块。 (为什么?Cmdlet 别名和自定义类型加速器,我一辈子都找不到如何在 C# 中执行这些操作。)

现在模块导入并按预期工作,但是当我在 PowerShell 中检查详细输入时。我看到了一些奇怪的东西:

VERBOSE: Loading module from path 'C:\path\to\module\Module.psd1'.
VERBOSE: Loading module from path 'C:\path\to\module\Module.dll'.
VERBOSE: Importing cmdlet 'Cmdlet1'.
VERBOSE: Importing cmdlet 'Cmdlet2'.
VERBOSE: Importing cmdlet 'Cmdlet3'.
VERBOSE: Importing cmdlet 'Cmdlet4'.
VERBOSE: Importing cmdlet 'Cmdlet5'.
VERBOSE: Importing cmdlet 'Cmdlet6'.
VERBOSE: Exporting cmdlet 'Cmdlet1'.
VERBOSE: Exporting cmdlet 'Cmdlet2'.
VERBOSE: Exporting cmdlet 'Cmdlet3'.
VERBOSE: Exporting cmdlet 'Cmdlet4'.
VERBOSE: Exporting cmdlet 'Cmdlet5'.
VERBOSE: Exporting cmdlet 'Cmdlet6'.
VERBOSE: Importing cmdlet 'Cmdlet1'.
VERBOSE: Importing cmdlet 'Cmdlet2'.
VERBOSE: Importing cmdlet 'Cmdlet3'.
VERBOSE: Importing cmdlet 'Cmdlet4'.
VERBOSE: Importing cmdlet 'Cmdlet5'.
VERBOSE: Importing cmdlet 'Cmdlet6'.

这是什么原因造成的,我有什么需要担心的吗?

Psm1 文件

$Accelerators = [PSObject].Assembly.GetType('System.Management.Automation.TypeAccelerators');

# Create accelerators for this module.
$Accelerators::Add('Obj1', 'Company.PowerShell.Module.Object1');
$Accelerators::Add('Obj2', 'Company.PowerShell.Module.Object2');
$Accelerators::Add('Obj3', 'Company.PowerShell.Module.Object3');
...

Set-Alias -Name c1 -Value Cmdlet1
Set-Alias -Name c2 -Value Cmdlet2
...

Psd1 文件

@{
    ModuleToProcess = 'Module.psm1'
    NestedModules   = 'Module.dll'
    ModuleVersion = '1.0.0.0'
    GUID = 'SOME-GUID-VALUE-HERE'
    Author = 'Me'
    CompanyName = 'Company'
    Copyright = '(c) 2016 Company. All rights reserved.'
    Description = 'Module description here.'
    PowerShellVersion = '4.0'
    DotNetFrameworkVersion = '4.5'
    CLRVersion = '4.0'
    ProcessorArchitecture = 'Amd64'
    PrivateData = @{
        Server = 'SOME\SQLSERVERINSTANCE'
        Database = 'DatabaseName'
        Domain = 'DOMAINNAME'
    }
}

【问题讨论】:

  • 模块是如何加载的?它是否安装在 PSModulePath 中?可能是它两次加载模块。你检查过这个吗:类似的:stackoverflow.com/questions/34923792/…
  • 据我所知,它不在模块路径中。它是从 Visual Studio 构建的调试目录中加载的。
  • 关于链接的问题。我在调试文件夹中没有任何子文件夹。我将所有 .dll、.psm1、psd1 和 pdb 文件放在一个目录中。
  • 恕我直言,这是因为您首先将 .dll 导入模块,然后将模块导入全局状态。
  • @PetSerAl,那我应该如何导入它?或者看到某些东西被导入两次是正常行为吗?

标签: c# powershell


【解决方案1】:

首先,回答您的确切问题 - 您无需担心,这是正常行为。

PowerShell 可以将 dll 或 psm1 作为模块加载,因此命令会在任何时候从这些类型的模块中导出。

psd1 也是一个模块,但它本身不能定义任何命令,它依赖于在另一个模块(如 dll 或 psm1)中定义的命令。

因此,在加载模块清单 (psd1) 时,会加载根模块或嵌套模块,并导出它们导出的命令。然后模块清单重新导出模块清单指定的命令。请注意,此列表可以限制 dll/psm1 实际导出的内容。

现在,您正在寻找一种方法来避免需要 psm1+dll。

您可以使用 Alias 属性在二进制模块中定义别名,该属性与用于定义参数别名的属性相同。此功能是在 V4 中添加的。

如果你需要V3,你可以创建一个实现这个接口的类型:https://msdn.microsoft.com/en-us/library/system.management.automation.imoduleassemblyinitializer.onimport(v=vs.85).aspx,如果你用Reflector四处寻找,你可以在Microsoft.Management.Infrastructure.CimCmdlets中找到一个使用这种方式定义别名的例子。 dll,类 Microsoft.Management.Infrastructure.CimCmdlets.CimCmdletsAssemblyInitializer。

【讨论】:

  • 问题解决了一半,类型加速器该怎么办?
  • 如果您使用的是 V5,我会说什么都不做,“使用命名空间”不需要加速器。
  • 否则,您需要添加与 PowerShell 等效的 C#,以便在 IModuleAssemblyInitializer 实现中创建加速器。
  • 本例中是 V4,但我会在 MSDN 上查看该接口。
猜你喜欢
  • 1970-01-01
  • 2011-09-11
  • 2023-01-25
  • 2019-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多