Powershell

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

安装

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());
        }

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

Set-ExecutionPolicy RemoteSigned -Scope CurrentUser -Confirm

参考

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)

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}");
    }
  }
}

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

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;
}