在*PowerShell 中实现 PowerShell PSProvider

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

我希望在 PowerShell 中实现 PowerShell 提供程序。 我一直在想,如果我只是定义类型,然后将它们导入到我的会话(导入模块)中,我应该能够让它们可用。

例如,这

不起作用

,但它沿着我想要实现的路径。 我显然错过了很多......有人知道这是否可能吗?

# EnvironmentProvider.ps1 $reference_assemblies = ( "System.Management.Automation, Version=1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" # "System.Configuration.Install, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" ) $source = @" namespace Providers { using System.Management.Automation; using System.Management.Automation.Provider; [CmdletProvider("Environments", ProviderCapabilities.None)] public class EnvironmentProvider : DriveCmdletProvider { protected override PSDriveInfo NewDrive(PSDriveInfo drive) { return new EnvironmentDriveInfo(drive); } protected override object NewDriveDynamicParameters() { return base.NewDriveDynamicParameters(); } } public class EnvironmentDriveInfo : PSDriveInfo { public EnvironmentDriveInfo(PSDriveInfo driveInfo) : base(driveInfo) { } } } "@ # -ea silentlycontinue in case its already loaded # add-type -referencedassemblies $referenced_assemblies -typedefinition $source -language CSharp -erroraction silentlycontinue

导入模块后,我尝试创建驱动器“环境”:

new-psdrive -psprovider Environments -name "Environments" -root ""

错误:

New-PSDrive : Cannot find a provider with the name 'Environments'.

假设提供程序确实有效,也许让它返回环境列表:开发、质量保证、登台、生产。

然后我希望能够通过以下方式重复使用它:

c:\adminlib>import-module .\EnvironmentProvider.ps1 c:\adminlib>environments: environments:>ls dev qa staging production environments:> cd production environments\production> [execute actions against production] environments\production:> cd dev environments\dev:> [execute actions against dev, etc]

	
powershell powershell-2.0
3个回答
6
投票
http://psprovider.codeplex.com/


2
投票

包含提供程序的程序集需要使用 Import-Module 导入(而不仅仅是包含添加类型声明的模块)。这可以通过两种方式完成:

选项1: 使用 Add-Type 的参数将运行时程序集构建为 .dll 文件并导入该文件。

选项2: 从内存导入运行时程序集。这就是我使用标准 msdn 示例的方法:

[appdomain]::CurrentDomain.GetAssemblies() | Where {$_.ExportedTypes -ne $null} | Where {($_.ExportedTypes | Select -ExpandProperty "Name") -contains "AccessDBProvider"} | Import-Module

将 where 过滤器中的提供商名称替换为您自己的名称。

干杯, 弗雷德


0
投票

到目前为止,问题中代码的翻译对我有用。

class EnvironmentDriveInfo : System.Management.Automation.PSDriveInfo { EnvironmentDriveInfo ([System.Management.Automation.PSDriveInfo] $driveInfo) : base($driveInfo) {} } [System.Management.Automation.Provider.CmdletProvider('Environments', [System.Management.Automation.Provider.ProviderCapabilities]::None)] class EnvironmentProvider : System.Management.Automation.Provider.DriveCmdletProvider { [System.Management.Automation.PSDriveInfo] NewDrive ([System.Management.Automation.PSDriveInfo] $drive) { return [EnvironmentDriveInfo]::new($drive) } [Object] NewDriveDynamicParameters () { return ([System.Management.Automation.Provider.DriveCmdletProvider]$this).NewDriveDynamicParameters() } } $sessionStateProviderEntry = [System.Management.Automation.Runspaces.SessionStateProviderEntry]::new('Environments', [EnvironmentProvider], $null) $pipelineType = [PowerShell].Assembly.GetType('System.Management.Automation.Runspaces.LocalPipeline') $method = $pipelineType.GetMethod('GetExecutionContextFromTLS', [System.Reflection.BindingFlags]'Static,NonPublic') $context = $method.Invoke($null, [System.Reflection.BindingFlags]'Static,NonPublic', $null, $null, (Get-Culture)) $internalType = [PowerShell].Assembly.GetType('System.Management.Automation.SessionStateInternal') $constructor = $internalType.GetConstructor([System.Reflection.BindingFlags]'Instance,NonPublic', $null, $context.GetType(), $null) $sessionStateInternal = $constructor.Invoke($context) $method = $internalType.GetMethod('AddSessionStateEntry', [System.Reflection.BindingFlags]'Instance,NonPublic', $null, $sessionStateProviderEntry.GetType(), $null) $method.Invoke($sessionStateInternal, $sessionStateProviderEntry) New-PSDrive -Name Environments -PSProvider Environments -Root ''

New-PSDrive

完成且没有错误,尽管我不知道我会在真正的提供商那里遇到什么样的麻烦。当然,

using
语句可以使代码更具可读性。为了让事情简单明了,我没有在这里。
    

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