连接到远程计算机后运行PowerShell脚本

时间:2019-02-25 02:42:03

标签: c# powershell remote-access

我有一个C#控制台应用程序。我想从中访问远程计算机,然后在退出会话之前使用相同的会话运行一些PowerShell脚本文件(在远程计算机中可用)。

我现在可以通过参考此post连接远程计算机。这是我尝试过的代码...

ConnectionOptions options = new ConnectionOptions();
options.Username = "user1";
options.Password = "password123";
options.Impersonation = System.Management.ImpersonationLevel.Impersonate;

ManagementScope scope = new ManagementScope("\\\\compName\\root\\cimv2", options);
scope.Connect();

//Query system for Operating System information
ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_OperatingSystem");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);

ManagementObjectCollection queryCollection = searcher.Get();
foreach (ManagementObject m in queryCollection)
{
    // Display the remote computer information
    Console.WriteLine("Computer Name     : {0}", m["csname"]);
    Console.WriteLine("Windows Directory : {0}", m["WindowsDirectory"]);
}

但是我被困于运行其他PowerShell脚本文件。我不知道如何继续执行下一步以运行远程计算机中的.ps1文件。

1 个答案:

答案 0 :(得分:1)

该控制台应用只是在复制PowerShell Remoting在做什么或MS SysInternals psexec在做什么。

为什么要重新创建?

我明白这是必要条件,但长期而言,这是您不必处理的过度复杂的问题。

这听起来像未启用PSRemoting,因此是使用此控制台应用程序的原因。

无论如何,您仍将实例化PowerShell主机以运行PowerShell的东西。因此,您只是在C#应用程序中托管PowerShell。

从C#运行PowerShell是很平常的事情,并且有据可查。快速搜索可以为您提供大量的匹配数据和示例。

How to run PowerShell scripts from C#

Calling C# code in Powershell and vice versa

  

添加以下“ using”语句以导入所需的类型:

using System.Collections.ObjectModel;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
  

以下代码块显示了执行所有   努力工作。它接受脚本文本,执行该文本,然后返回   结果作为字符串。

private string RunScript(string scriptText)
{
    // create Powershell runspace

    Runspace runspace = RunspaceFactory.CreateRunspace();

    // open it

    runspace.Open();

    // create a pipeline and feed it the script text

    Pipeline pipeline = runspace.CreatePipeline();
    pipeline.Commands.AddScript(scriptText);

    // add an extra command to transform the script
    // output objects into nicely formatted strings

    // remove this line to get the actual objects
    // that the script returns. For example, the script

    // "Get-Process" returns a collection
    // of System.Diagnostics.Process instances.

    pipeline.Commands.Add("Out-String");

    // execute the script

    Collection<psobject /> results = pipeline.Invoke();

    // close the runspace

    runspace.Close();

    // convert the script result into a single string

    StringBuilder stringBuilder = new StringBuilder();
    foreach (PSObject obj in results)
    {
        stringBuilder.AppendLine(obj.ToString());
    }

    return stringBuilder.ToString();
}
  

如何让脚本与程序交互

     

在使用pipeline.Invoke()调用执行脚本之前,它是   通过使用以下命令可以将程序的对象暴露给脚本   方法runspace.SessionStateProxy.SetVariable(“ someName”,   someObject)。

     

这将创建脚本可以访问的命名变量   (获取/设置属性,甚至调用方法)。

     

作为一个例子,假设我们将样本的主要形式暴露给   通过添加SetVariable()调用来编写脚本,如下所示:

...
// open it

runspace.Open();
runspace.SessionStateProxy.SetVariable("DemoForm", this);
....
Then, the following script would print the caption of the window:

$DemoForm.Text
The following script would show all the properties and methods of the window:

$DemoForm | Get-Member
  

但是请注意,脚本对对象的任何调用   将来自另一个线程上下文,如pipeline.Invoke()似乎   启动自己的工作线程。这意味着您暴露的物体会   必须是线程安全的。

这甚至可以看作是此问答的重复内容

Run PowerShell-Script from C# Application

OP的更新

至于...

  

需要c#控制台应用程序像中心一样处理   几个.ps1脚本文件,

因此,C#应用程序是C&C,取代了PSRemoting / PSExec会话。 但是,您没有说脚本文件在哪里,也没有计划如何将它们导入远程系统。

  

但是首先它需要首先访问远程计算机。

PSRemoting是什么……

$s = New-PSSession -ComputerName (Get-Content Servers.txt) -Credential Domain01\Admin01
Invoke-Command -Session $s -ScriptBlock {
# Run these PowerShell commands or scripts.
Get-Process PowerShell
}

或作为后台工作

$s = New-PSSession -ComputerName (Get-Content Servers.txt) -Credential Domain01\Admin01 
Invoke-Command -Session $s -ScriptBlock {
# Run these PowerShell commands or scripts.
Get-Process PowerShell
} -AsJob

PSExec确实如此。

psexec \ RemotePCName [-u用户名[-p密码]]命令[参数]

至于...

  

仅在所有.ps1文件成功运行之后,才应将其注销   从远程计算机上将所有输出返回到控制台。

同样,PSRemoting和PSExec所做的事情。

  

这就是为什么我在考虑先使用c#进行远程连接,然后   然后调用所有.ps1文件。

您的控制台应用程序只需执行上述操作。正如这些问答所指出的那样,这是可行的,好吧,仅使用命令而不是调用脚本,但是适用相同的规则...

Execute powershell script on a remote computer using C#

Invoke remote powershell command from C#

示例:

InitialSessionState initial = InitialSessionState.CreateDefault();
Runspace runspace = RunspaceFactory.CreateRunspace(initial);
runspace.Open();
PowerShell ps = PowerShell.Create();
ps.Runspace = runspace;
ps.AddCommand("invoke-command");
ps.AddParameter("ComputerName", "mycomp.mylab.com");
ScriptBlock filter = ScriptBlock.Create("Get-childitem C:\\windows");
ps.AddParameter("ScriptBlock", filter);
foreach (PSObject obj in ps.Invoke())
{
   // Do Something
}

但同样,它只是复制上面的内容。因此,Yeppers,这是一个选择。使用PSRemoting,使用PSExec,构建其他解决方案。