为什么PowerShell类不加载snapin

时间:2013-08-20 15:05:31

标签: c# .net powershell powershell-remoting

我有这个代码,我在其中加载了一个snapin(在这种情况下来自MS Dynamics NAV):

            using (Runspace runspace = RunspaceFactory.CreateRunspace())
        {
            runspace.Open();

            using (var ps = PowerShell.Create())
            {
                ps.Runspace = runspace;

                ps.AddScript("Add-PSSnapin Microsoft.Dynamics.Nav.Management")
                  .AddScript("Get-NAVServerInstance");

                //This does not work. Says unknown cmdlet Get-NAVServerInstance
                //ps.AddCommand("Add-PSSnapin").AddArgument("Microsoft.Dynamics.Nav.Management")
                //  .AddCommand("Get-NAVServerInstance");

                var output = ps.Invoke();
            }
        }

当我使用代码中显示的AddScript方法时,此代码可以正常工作。 但是为什么AddCommand方法不起作用(参见注释代码)?看起来没有加载管理单元,因为错误表明Get-NAVServerInstance cmdlet未知。 这应该如何运作?

我知道我可以使用我已导入snapin的InitialSessionState创建一个运行空间。然后ps.AddCommand(“Get-NAVServerInstance”)正在运行。 但是当我想创建一个远程运行空间会话(使用WSManConnectionInfo)时,我找不到提供initialSessionState的方法。

更新: 因此,当运行空间被打开(或创建?)时,AddCommand似乎只能用于可用的cmdlet。使用带有RunspaceFactory.CreateRunspace(...)的InitialSessionState或RunspaceConfiguration实例可以。所以这段代码有效:

    var config = RunspaceConfiguration.Create();
    PSSnapInException warning;
    config.AddPSSnapIn("Microsoft.Dynamics.Nav.Management", out warning);

    using (Runspace runspace = RunspaceFactory.CreateRunspace(config))
    {
        runspace.Open();

        using (var ps = PowerShell.Create())
        {
            ps.Runspace = runspace;
            ps.AddCommand("Get-NAVServerInstance");
            var output = ps.Invoke();
        }
    }

但我的问题是在那种情况下,我无法指定WSManConnectionInfo实例。

那么如何创建一个带有远程连接的运行空间,并且加载了一个snapin(安装在远程机器上)?如何为远程连接提供配置?

2 个答案:

答案 0 :(得分:4)

我终于找到了如何配置远程会话的提示(参见https://superuser.com/a/518567)。

您需要使用

在远程计算机上注册会话配置
Register-PSSessionConfiguration -Name MyShell -StartupScript 'MyInitScript.ps1'

然后,您可以将WSManConnectionInfo的shellUri参数设置为http://schemas.microsoft.com/powershell/MyShell

以这种方式创建的运行空间将具有MyInitScript.ps1启动脚本导入的可用命令。

所以现在这段代码将起作用:

        string shell = "http://schemas.microsoft.com/powershell/MyShell";
        var target = new Uri("https://myserver:port/wsman");
        var secured = new SecureString();
        foreach (char letter in "password")
        {
            secured.AppendChar(letter);
        }
        secured.MakeReadOnly();

        var credential = new PSCredential("username", secured);
        var connectionInfo = new WSManConnectionInfo(target, shell, credential);

        using (Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo))
        {
            runspace.Open();

            using (var ps = PowerShell.Create())
            {
                ps.Runspace = runspace;
                ps.AddCommand("Get-NAVServerInstance");
                var output = ps.Invoke();
            }
        }

答案 1 :(得分:0)

尝试像这样调用AddScript:

.AddScript("...", false)

这将在全局范围内执行命令,而不是新的本地范围。

我认为正确的方法是使用RunspaceConfiguration类。它有一个AddPSSnapin方法。