1

我有一系列功能齐全的 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#。由于我仍然需要能够以独立模式(即直接从 powershell.exe)运行我的 PS 脚本,因此这不是一个可行的解决方案。

任何人都可以提出一个不需要重新调整我的 PS 脚本的解决方案吗?

4

1 回答 1

-1

创建Runspace对象时,需要向它传递一个WSManConnectionInfo对象以创建远程运行空间。这篇MSDN 文章详细介绍了如何执行此操作。与本主题中的示例不同,请确保您使用 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();
}

顺便说一句,不确定为什么要添加DataAdded到脚本的输出集合中?我把它注释掉了。由于我在工作组而不是域中,因此我还必须传递凭据。

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

于 2012-09-03T16:44:24.047 回答