如何执行使用C#远程处理的PS脚本

时间:2012-09-01 16:09:29

标签: c# powershell powershell-v2.0 powershell-remoting

我有一系列功能齐全的PowerShell脚本,可以利用我希望能够从C#WinForm调用的远程处理。这是我到目前为止的代码

    private void button1_Click(object sender, EventArgs e)
    {
        _runspace = RunspaceFactory.CreateRunspace();
        _runspace.Open();
        _ps = PowerShell.Create();

        _ps.Runspace = _runspace;

        var output = new PSDataCollection<PSObject>();
        output.DataAdded += DataAdded;

        _ps.AddScript(@"C:\projects\Acme\trunk\PowerShell\deploy-qa-p5.ps1");
        _invokeResult = _ps.BeginInvoke<PSObject, PSObject>(null, output);

    }

当我运行此代码时,我发现我脚本中针对远程会话执行的所有powershell命令实际上都在我的本地PC上执行。

例如,直接从Powershell.exe执行此代码时,会从远程服务器卸载应用程序。从上面的C#代码运行时,相同的代码会在我的本地计算机上卸载所述应用程序

Invoke-Command -Session $remoteSession -scriptblock $uninstallScript -ArgumentList $applicationGuid

同样,我的C#代码中引用的完全相同的PS脚本,当直接从powershell.exe执行时,可以按预期对远程服务器工作。

通过谷歌搜索,我发现如何从C#创建远程运行空间。但是,这需要我重构我的PS脚本以取出任何远程代码,这些代码将转移到C#。由于我仍然需要能够以独立模式运行我的PS脚本(即直接从powershell.exe运行),这不是一个可行的解决方案。

任何人都可以建议一个解决这个问题的方法,不需要重新调整我的PS脚本吗?

1 个答案:

答案 0 :(得分:-1)

创建Runspace对象时,需要将WSManConnectionInfo对象传递给它以创建远程运行空间。这个MSDN article详细介绍了如何执行此操作。与本主题中的示例不同,请确保使用WSManConnectionInfo构造函数,该构造函数接受允许您指定远程终结点的参数,例如。

_runspace = RunspaceFactory.CreateRunspace("http://ComputerName:5985/wsman");

抱歉,我误解了这个问题。调用正在执行远程处理的脚本应该与从PowerShell控制台调用时一样好。以下稍微修改过的版本在我的家庭工作组中对我来说很合适:

private void button1_Click(object sender, EventArgs e)
{
    _runspace = RunspaceFactory.CreateRunspace();
    _runspace.Open();
    _ps = PowerShell.Create();

    _ps.Runspace = _runspace;

    var output = new PSDataCollection<PSObject>();
    //output.DataAdded += DataAdded;

    var netCreds = new System.Net.NetworkCredential("Keith", Settings.Default.Password);
    var creds = new PSCredential(netCreds.UserName, netCreds.SecurePassword);

    _ps.AddScript("param($creds) Invoke-Command -cn Kids-PC -Scriptblock {hostname} -Credential $creds").AddArgument(creds);
    _invokeResult = _ps.BeginInvoke<PSObject, PSObject>(null, output);
    _invokeResult.AsyncWaitHandle.WaitOne();
    _ps.EndInvoke(_invokeResult);
    textBox1.Text = output[0].ToString();
}

BTW不确定为什么你将DataAdded添加到脚本的输出集合中?我评论说出来了。我也必须传递凭据,因为我在工作组而不是域。

为了调试它,当它失败时,请查看调试器中的_ps.Streams.Error对象。滚动到底部并打开Results View