PowerShell:如何以编程方式从SnapIn安装驱动器

时间:2023-01-26 21:52:48

I am creating a suite of custom cmdlets and providers in C#. I also have a PowerShell SnapIn that takes care of registering the cmdlets and providers. I have exported a console session so that I can start PowerShell with the -PSConsoleFile parameter to automatically load my snap in.

我在C#中创建了一套自定义cmdlet和提供程序。我还有一个PowerShell SnapIn,负责注册cmdlet和提供程序。我已导出控制台会话,以便我可以使用-PSConsoleFile参数启动PowerShell以自动加载我的快照。

I also want to mount a drive whenever I run PS with the snap in. Effectively, I want the following to run at the start of the PS session:

每当我使用快照输入PS时,我也想安装一个驱动器。实际上,我希望在PS会话开始时运行以下命令:

new-psdrive -name [drivename] -psprovider FileSystem -root [path to a folder on local file system]

new-psdrive -name [drivename] -psprovider FileSystem -root [本地文件系统上文件夹的路径]

I have tried putting the above command in a .ps1 file and starting PS with -command and the path to the .ps1 file, also specifying the -NoExit flag. The script does run, but the drive is not mapped in the subsequent session.

我已经尝试将上面的命令放在.ps1文件中并使用-command和.ps1文件的路径启动PS,同时指定-NoExit标志。该脚本确实运行,但驱动器未在后续会话中映射。

Is there a simple way to create a new psdrive in the snap in? I also looked into deriving from the FileSystemProvider but it is sealed. I looked into running the NewPSDriveCommand programmatically but that does not appear to be supported.

是否有一种简单的方法可以快速创建新的psdrive?我也研究了从FileSystemProvider派生但它是密封的。我考虑以编程方式运行NewPSDriveCommand,但似乎不支持。

Am I missing something simple here?

我错过了一些简单的东西吗?

Thanks!

Edit: I forgot to mention that I don't want to use the the profile file to accomplish this if possible. I want to distribute this snap in to others and I would rather they didn't have to edit their profiles to get everything to work.

编辑:我忘了提到我不想使用配置文件来尽可能地完成此操作。我想将此快照分发给其他人,我希望他们不必编辑他们的个人资料以使一切工作。

4 个解决方案

#1


You can create a PSDrive in you snapin. There is a method that you can override, InitializeDefaultDrives, as part of your provider.

您可以在snapin中创建一个PSDrive。有一种方法可以覆盖InitializeDefaultDrives,作为提供者的一部分。

Example:

protected override Collection<PSDriveInfo> InitializeDefaultDrives()
        {
            Collection<PSDriveInfo> drives = new Collection<PSDriveInfo>();

            drives.Add(new PSDriveInfo(
                "YourDriveName",
                ProviderInfo,
                "YourDriveRoot",
                "Description of Your Drive",
                null));

            return drives;
        }

After re-reading you question and comment: You might be able to get the reference to the filesystem providerinfo object from the Microsoft.PowerShell.Core namespace... I haven't tested that yet though...

重新阅读之后的问题和评论:您可以从Microsoft.PowerShell.Core命名空间获取对文件系统providerinfo对象的引用...我还没有测试过,但是......

The FileSystem provider information from PowerShell is:

PowerShell的FileSystem提供程序信息是:

PS C:\scripts\PowerShell> Get-PSProvider filesystem | fl *


ImplementingType : Microsoft.PowerShell.Commands.FileSystemProvider
HelpFile         : System.Management.Automation.dll-Help.xml
Name             : FileSystem
PSSnapIn         : Microsoft.PowerShell.Core
ModuleName       : Microsoft.PowerShell.Core
Module           :
Description      :
Capabilities     : Filter, ShouldProcess
Home             : H:\
Drives           : {C, A, D, H...}

#2


You might try adding the statements to your Powershell global or environment profile. Both are located at %username%\My Documents\WindowsPowerShell. Your global profile is named profile.ps1 and your environment profile is named for each shell (Microsoft.PowerShell_profile.ps1 for the default Powershell environment).

您可以尝试将语句添加到Powershell全局或环境配置文件中。两者都位于%username%\ My Documents \ WindowsPowerShell。您的全局配置文件名为profile.ps1,并且为每个shell命名了您的环境配置文件(默认的Powershell环境为Microsoft.PowerShell_profile.ps1)。

I have a couple of new-psdrive statements in my profile.ps1 file. The downfall to this method is waiting on Powershell to connect all of those PSDrives if they are on a slow server.

我在profile.ps1文件中有几个new-psdrive语句。这种方法的缺点是等待Powershell连接所有这些PSDrives,如果它们在慢速服务器上。

#3


You can put the command in the ps1 file and add the option -scope Global.

您可以将命令放在ps1文件中并添加选项-scope Global。

#4


Are you talking about creating a : function so that you can switch to that drive as you can with the file system drives like c: ?

你在谈论创建一个:函数,以便你可以像c:那样使用文件系统驱动器切换到该驱动器吗?

I have the following code at the end of my NewDrive method.

我在NewDrive方法的末尾有以下代码。

// create the <drive>: alias
string func = string.Format("function {0}: {{ set-location {0}: }}", drive.Name);
this.InvokeCommand.InvokeScript(
       func
       , false
       , System.Management.Automation.Runspaces.PipelineResultTypes.None
       , null
       , null);

And then a matching remove call in the RemoveDrive method that removes the matching function.

然后在RemoveDrive方法中匹配删除调用,删除匹配的函数。

string func = string.Format("function {0}: {{ remove-item function:\ {0}: }}"
       , drive.Name);
this.InvokeCommand.InvokeScript(
       func
       , false
       , System.Management.Automation.Runspaces.PipelineResultTypes.None
       , null
       , null);

#1


You can create a PSDrive in you snapin. There is a method that you can override, InitializeDefaultDrives, as part of your provider.

您可以在snapin中创建一个PSDrive。有一种方法可以覆盖InitializeDefaultDrives,作为提供者的一部分。

Example:

protected override Collection<PSDriveInfo> InitializeDefaultDrives()
        {
            Collection<PSDriveInfo> drives = new Collection<PSDriveInfo>();

            drives.Add(new PSDriveInfo(
                "YourDriveName",
                ProviderInfo,
                "YourDriveRoot",
                "Description of Your Drive",
                null));

            return drives;
        }

After re-reading you question and comment: You might be able to get the reference to the filesystem providerinfo object from the Microsoft.PowerShell.Core namespace... I haven't tested that yet though...

重新阅读之后的问题和评论:您可以从Microsoft.PowerShell.Core命名空间获取对文件系统providerinfo对象的引用...我还没有测试过,但是......

The FileSystem provider information from PowerShell is:

PowerShell的FileSystem提供程序信息是:

PS C:\scripts\PowerShell> Get-PSProvider filesystem | fl *


ImplementingType : Microsoft.PowerShell.Commands.FileSystemProvider
HelpFile         : System.Management.Automation.dll-Help.xml
Name             : FileSystem
PSSnapIn         : Microsoft.PowerShell.Core
ModuleName       : Microsoft.PowerShell.Core
Module           :
Description      :
Capabilities     : Filter, ShouldProcess
Home             : H:\
Drives           : {C, A, D, H...}

#2


You might try adding the statements to your Powershell global or environment profile. Both are located at %username%\My Documents\WindowsPowerShell. Your global profile is named profile.ps1 and your environment profile is named for each shell (Microsoft.PowerShell_profile.ps1 for the default Powershell environment).

您可以尝试将语句添加到Powershell全局或环境配置文件中。两者都位于%username%\ My Documents \ WindowsPowerShell。您的全局配置文件名为profile.ps1,并且为每个shell命名了您的环境配置文件(默认的Powershell环境为Microsoft.PowerShell_profile.ps1)。

I have a couple of new-psdrive statements in my profile.ps1 file. The downfall to this method is waiting on Powershell to connect all of those PSDrives if they are on a slow server.

我在profile.ps1文件中有几个new-psdrive语句。这种方法的缺点是等待Powershell连接所有这些PSDrives,如果它们在慢速服务器上。

#3


You can put the command in the ps1 file and add the option -scope Global.

您可以将命令放在ps1文件中并添加选项-scope Global。

#4


Are you talking about creating a : function so that you can switch to that drive as you can with the file system drives like c: ?

你在谈论创建一个:函数,以便你可以像c:那样使用文件系统驱动器切换到该驱动器吗?

I have the following code at the end of my NewDrive method.

我在NewDrive方法的末尾有以下代码。

// create the <drive>: alias
string func = string.Format("function {0}: {{ set-location {0}: }}", drive.Name);
this.InvokeCommand.InvokeScript(
       func
       , false
       , System.Management.Automation.Runspaces.PipelineResultTypes.None
       , null
       , null);

And then a matching remove call in the RemoveDrive method that removes the matching function.

然后在RemoveDrive方法中匹配删除调用,删除匹配的函数。

string func = string.Format("function {0}: {{ remove-item function:\ {0}: }}"
       , drive.Name);
this.InvokeCommand.InvokeScript(
       func
       , false
       , System.Management.Automation.Runspaces.PipelineResultTypes.None
       , null
       , null);