我有一个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文件。
答案 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,构建其他解决方案。