C# 为什么要导入、导出并再次导入我的cmdlet?

C# 为什么要导入、导出并再次导入我的cmdlet?,c#,powershell,C#,Powershell,我有一个带有.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\Mod

我有一个带有.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
...
@{
    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'
    }
}
Psd1文件

$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
...
@{
    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'
    }
}

首先,回答你的确切问题——你没有什么可担心的,这是正常的行为

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

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

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

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

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


如果您需要V3,您可以创建一个实现此接口的类型:,如果您使用Reflector,您可以在Microsoft.Management.Infrastructure.CIMCmdlet.dll类Microsoft.Management.Infrastructure.CIMCmdlet.CimCmdletsAssemblyInitializer中找到使用此方法定义别名的示例。

模块是如何加载的?它是否安装在PSModulePath中?可能是它加载了两次模块。你检查过这个了吗:类似:就我所见,它不在模块路径中。它正在从Visual Studio生成的调试目录加载。关于链接问题。调试文件夹中没有任何子文件夹。我将所有的.dll、.psm1、psd1和pdb文件都放在一个目录中。IMHO,这是因为您首先将.dll导入模块,然后将模块导入全局状态。@PetSerAl,那么我应该如何导入它呢?或者,看到某个东西被导入两次是正常行为吗?这就是问题解决的一半,我该如何处理类型加速器?如果您使用的是V5,我会说什么都不做,“使用名称空间”会使加速器变得不必要。否则,您需要在IModuleAssemblyInitializer实现中添加与PowerShell相当的C#版本,您必须在IModuleAssemblyInitializer实现中创建加速器。在本例中,它是V4,但我将在MSDN上查看该接口。