跳到主要内容

Powershell使用Microsoft.PowerShell.SDK执行Powershell脚本

安装

Powershell默认不支持运行脚本,需要首先执行指令

参考

Windows PowerShell SDK - PowerShell | Microsoft Docs

为 .NET 项目选择正确的 PowerShell NuGet 包 - PowerShell | Microsoft Docs

How to run PowerShell Core scripts from .NET Core applications – 1.21 kilobytes (keithbabinec.com)

c# - How to call Powershell script using web API (cs or asp.net) - Stack Overflow

Microsoft.PowerShell.SDK
public Collection<PSObject> Execute(string command)
{
using var ps = PowerShell.Create();
return ps.AddScript(command).Invoke();
}
[TestMethod]
public async Task 运行Test()
{
var command =
@"cd F:\Xiang\Docs
$commitInfo = get-date -format ""yyyy年MM月dd日 自动提交""
git add .
git commit -m $commitInfo
git push origin master";
var res = Execute(command);
TestCenter.WriteJson(res.Select(m=>m.ToString()).ToList());
}
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser -Confirm
using System;
using System.Collections.Generic;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Threading.Tasks;

namespace CustomRunspaceStarter
{
/// <summary>
/// Contains functionality for executing PowerShell scripts.
/// </summary>
public class HostedRunspace
{
/// <summary>
/// The PowerShell runspace pool.
/// </summary>
private RunspacePool RsPool { get; set; }

/// <summary>
/// Initialize the runspace pool.
/// </summary>
/// <param name="minRunspaces"></param>
/// <param name="maxRunspaces"></param>
public void InitializeRunspaces(int minRunspaces, int maxRunspaces, string[] modulesToLoad)
{
// create the default session state.
// session state can be used to set things like execution policy, language constraints, etc.
// optionally load any modules (by name) that were supplied.

var defaultSessionState = InitialSessionState.CreateDefault();
defaultSessionState.ExecutionPolicy = Microsoft.PowerShell.ExecutionPolicy.Unrestricted;

foreach (var moduleName in modulesToLoad)
{
defaultSessionState.ImportPSModule(moduleName);
}

// use the runspace factory to create a pool of runspaces
// with a minimum and maximum number of runspaces to maintain.

RsPool = RunspaceFactory.CreateRunspacePool(defaultSessionState);
RsPool.SetMinRunspaces(minRunspaces);
RsPool.SetMaxRunspaces(maxRunspaces);

// set the pool options for thread use.
// we can throw away or re-use the threads depending on the usage scenario.

RsPool.ThreadOptions = PSThreadOptions.UseNewThread;

// open the pool.
// this will start by initializing the minimum number of runspaces.

RsPool.Open();
}

/// <summary>
/// Runs a PowerShell script with parameters and prints the resulting pipeline objects to the console output.
/// </summary>
/// <param name="scriptContents">The script file contents.</param>
/// <param name="scriptParameters">A dictionary of parameter names and parameter values.</param>
public async Task RunScript(string scriptContents, Dictionary<string, object> scriptParameters)
{
if (RsPool == null)
{
throw new ApplicationException("Runspace Pool must be initialized before calling RunScript().");
}

// create a new hosted PowerShell instance using a custom runspace.
// wrap in a using statement to ensure resources are cleaned up.

using (PowerShell ps = PowerShell.Create())
{
// use the runspace pool.
ps.RunspacePool = RsPool;

// specify the script code to run.
ps.AddScript(scriptContents);

// specify the parameters to pass into the script.
ps.AddParameters(scriptParameters);

// subscribe to events from some of the streams
ps.Streams.Error.DataAdded += Error_DataAdded;
ps.Streams.Warning.DataAdded += Warning_DataAdded;
ps.Streams.Information.DataAdded += Information_DataAdded;

// execute the script and await the result.
var pipelineObjects = await ps.InvokeAsync().ConfigureAwait(false);

// print the resulting pipeline objects to the console.
Console.WriteLine("----- Pipeline Output below this point -----");
foreach (var item in pipelineObjects)
{
Console.WriteLine(item.BaseObject.ToString());
}
}
}

/// <summary>
/// Handles data-added events for the information stream.
/// </summary>
/// <remarks>
/// Note: Write-Host and Write-Information messages will end up in the information stream.
/// </remarks>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Information_DataAdded(object sender, DataAddedEventArgs e)
{
var streamObjectsReceived = sender as PSDataCollection<InformationRecord>;
var currentStreamRecord = streamObjectsReceived[e.Index];

Console.WriteLine($"InfoStreamEvent: {currentStreamRecord.MessageData}");
}

/// <summary>
/// Handles data-added events for the warning stream.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Warning_DataAdded(object sender, DataAddedEventArgs e)
{
var streamObjectsReceived = sender as PSDataCollection<WarningRecord>;
var currentStreamRecord = streamObjectsReceived[e.Index];

Console.WriteLine($"WarningStreamEvent: {currentStreamRecord.Message}");
}

/// <summary>
/// Handles data-added events for the error stream.
/// </summary>
/// <remarks>
/// Note: Uncaught terminating errors will stop the pipeline completely.
/// Non-terminating errors will be written to this stream and execution will continue.
/// </remarks>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Error_DataAdded(object sender, DataAddedEventArgs e)
{
var streamObjectsReceived = sender as PSDataCollection<ErrorRecord>;
var currentStreamRecord = streamObjectsReceived[e.Index];

Console.WriteLine($"ErrorStreamEvent: {currentStreamRecord.Exception}");
}
}
}
public void RunWithParameters()
{
// create empty pipeline
PowerShell ps = PowerShell.Create();

// add command
ps.AddCommand("test-path").AddParameter("Path", Environment.CurrentDirectory); ;

var obj = ps.Invoke();
}

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();
}
public static int RunPowershellScript(string ps)
{
int errorLevel;
ProcessStartInfo processInfo;
Process process;

processInfo = new ProcessStartInfo("powershell.exe", "-File " + ps);
processInfo.CreateNoWindow = true;
processInfo.UseShellExecute = false;

process = Process.Start(processInfo);
process.WaitForExit();

errorLevel = process.ExitCode;
process.Close();

return errorLevel;
}