从 [Reflection.Assembly]::Load() 加载的 DLL 导出 Powershell CMDlet
Exporting Powershell CMDlets from DLLs loaded by [Reflection.Assembly]::Load()
我有一个无法将文件写入磁盘的环境,所以我通常在 GAC 中从内存加载 DLL。
虽然加载不是问题,但公开 DLL Commandlet 才是问题。
程序集已加载:
[appdomain]::currentdomain.getassemblies() | sort -property fullname | format-table fullname
FullName
--------
AudioDeviceCmdlets, Version=3.0.0.4, Culture=neutral, PublicKeyToken=null
fl *
CodeBase : file:///C:/WINDOWS/Microsoft.Net/assembly/GAC_64/mscorlib/v4.0_4.0.0.0__b77a5c561934e089/mscorlib.dll
FullName : AudioDeviceCmdlets, Version=3.0.0.4, Culture=neutral, PublicKeyToken=null
EntryPoint :
DefinedTypes : {CoreAudioApi.AudioEndpointVolume, CoreAudioApi.AudioEndpointVolumeCallback, CoreAudioApi.AudioEndpointVolumeChannel, CoreAudioApi.AudioEndpointVolumeChannels...}
Evidence : {<System.Security.Policy.Url version="1">
<Url>file:///C:/WINDOWS/Microsoft.Net/assembly/GAC_64/mscorlib/v4.0_4.0.0.0__b77a5c561934e089/mscorlib.dll</Url>
</System.Security.Policy.Url>
, <System.Security.Policy.Zone version="1">
<Zone>MyComputer</Zone>
</System.Security.Policy.Zone>
}
PermissionSet : {}
SecurityRuleSet : Level2
ManifestModule : AudioDeviceCmdlets.dll
ReflectionOnly : False
Location :
ImageRuntimeVersion : v4.0.30319
GlobalAssemblyCache : False
HostContext : 0
IsDynamic : False
EscapedCodeBase : file:///C:/WINDOWS/Microsoft.Net/assembly/GAC_64/mscorlib/v4.0_4.0.0.0__b77a5c561934e089/mscorlib.dll
ExportedTypes : {CoreAudioApi.AudioEndpointVolume, CoreAudioApi.AudioEndpointVolumeChannel, CoreAudioApi.AudioEndpointVolumeChannels, CoreAudioApi.AudioEndpointVolumeNotificationDelegate...}
IsFullyTrusted : True
CustomAttributes : {[System.Runtime.CompilerServices.CompilationRelaxationsAttribute((Int32)8)], [System.Runtime.CompilerServices.RuntimeCompatibilityAttribute(WrapNonExceptionThrows = True)],
[System.Diagnostics.DebuggableAttribute((System.Diagnostics.DebuggableAttribute+DebuggingModes)2)], [System.Reflection.AssemblyTitleAttribute("AudioDeviceCmdlets")]...}
Modules : {<unknown>}
..但 CMDLet 未导出..当然我肯定遗漏了一些东西。
相同的 DLL,以 'regular' 方式加载:
load-module AudioDeviceCmdlets.dll
正确导出多个 CmdLets,例如 Get-AudioDevice 和 Set-AudioDevice.
关于在 dll 中公开 Cmdlet 时缺少哪些步骤的任何提示?
使用Import-Module -Assembly
:
$assembly = [Reflection.Assembly]::Load($UncompressedFileBytes)
Import-Module -Assembly $assembly
或者,创建一个加载程序集的模块清单,然后导入它:
New-ModuleManifest .\AudioDeviceCmdlets.psd1 -RequiredAssemblies AudioDeviceCmdlets
Import-Module .\AudioDeviceCmdlets.psd1
虽然这看起来很粗鲁,(我仍然愿意接受更好的答案!)
这有效:
1) Select 可用程序集的第一个实例(因为可能有多个,或者更具体地找到您要加载的那个):
$Assembly=([System.AppDomain]::CurrentDomain.GetAssemblies()|? FullName -Match "AudioDeviceCmdlets")[0]
2) 使用 Import-Module 导入程序集,但不要指定要加载的 dll,而是直接引用程序集。 没有manifest,会默认导出所有的变量和其中的所有函数
Import-Module -Assembly $Assembly
瞧,现在 Commandlet 已正确导出! :)
我有一个无法将文件写入磁盘的环境,所以我通常在 GAC 中从内存加载 DLL。
虽然加载不是问题,但公开 DLL Commandlet 才是问题。 程序集已加载:
[appdomain]::currentdomain.getassemblies() | sort -property fullname | format-table fullname
FullName
--------
AudioDeviceCmdlets, Version=3.0.0.4, Culture=neutral, PublicKeyToken=null
fl *
CodeBase : file:///C:/WINDOWS/Microsoft.Net/assembly/GAC_64/mscorlib/v4.0_4.0.0.0__b77a5c561934e089/mscorlib.dll
FullName : AudioDeviceCmdlets, Version=3.0.0.4, Culture=neutral, PublicKeyToken=null
EntryPoint :
DefinedTypes : {CoreAudioApi.AudioEndpointVolume, CoreAudioApi.AudioEndpointVolumeCallback, CoreAudioApi.AudioEndpointVolumeChannel, CoreAudioApi.AudioEndpointVolumeChannels...}
Evidence : {<System.Security.Policy.Url version="1">
<Url>file:///C:/WINDOWS/Microsoft.Net/assembly/GAC_64/mscorlib/v4.0_4.0.0.0__b77a5c561934e089/mscorlib.dll</Url>
</System.Security.Policy.Url>
, <System.Security.Policy.Zone version="1">
<Zone>MyComputer</Zone>
</System.Security.Policy.Zone>
}
PermissionSet : {}
SecurityRuleSet : Level2
ManifestModule : AudioDeviceCmdlets.dll
ReflectionOnly : False
Location :
ImageRuntimeVersion : v4.0.30319
GlobalAssemblyCache : False
HostContext : 0
IsDynamic : False
EscapedCodeBase : file:///C:/WINDOWS/Microsoft.Net/assembly/GAC_64/mscorlib/v4.0_4.0.0.0__b77a5c561934e089/mscorlib.dll
ExportedTypes : {CoreAudioApi.AudioEndpointVolume, CoreAudioApi.AudioEndpointVolumeChannel, CoreAudioApi.AudioEndpointVolumeChannels, CoreAudioApi.AudioEndpointVolumeNotificationDelegate...}
IsFullyTrusted : True
CustomAttributes : {[System.Runtime.CompilerServices.CompilationRelaxationsAttribute((Int32)8)], [System.Runtime.CompilerServices.RuntimeCompatibilityAttribute(WrapNonExceptionThrows = True)],
[System.Diagnostics.DebuggableAttribute((System.Diagnostics.DebuggableAttribute+DebuggingModes)2)], [System.Reflection.AssemblyTitleAttribute("AudioDeviceCmdlets")]...}
Modules : {<unknown>}
..但 CMDLet 未导出..当然我肯定遗漏了一些东西。
相同的 DLL,以 'regular' 方式加载:
load-module AudioDeviceCmdlets.dll
正确导出多个 CmdLets,例如 Get-AudioDevice 和 Set-AudioDevice.
关于在 dll 中公开 Cmdlet 时缺少哪些步骤的任何提示?
使用Import-Module -Assembly
:
$assembly = [Reflection.Assembly]::Load($UncompressedFileBytes)
Import-Module -Assembly $assembly
或者,创建一个加载程序集的模块清单,然后导入它:
New-ModuleManifest .\AudioDeviceCmdlets.psd1 -RequiredAssemblies AudioDeviceCmdlets
Import-Module .\AudioDeviceCmdlets.psd1
虽然这看起来很粗鲁,(我仍然愿意接受更好的答案!) 这有效:
1) Select 可用程序集的第一个实例(因为可能有多个,或者更具体地找到您要加载的那个):
$Assembly=([System.AppDomain]::CurrentDomain.GetAssemblies()|? FullName -Match "AudioDeviceCmdlets")[0]
2) 使用 Import-Module 导入程序集,但不要指定要加载的 dll,而是直接引用程序集。 没有manifest,会默认导出所有的变量和其中的所有函数
Import-Module -Assembly $Assembly
瞧,现在 Commandlet 已正确导出! :)