Skip to content

Instantly share code, notes, and snippets.

@patriksvensson
Created March 8, 2016 09:20
Show Gist options
  • Save patriksvensson/2123d6f5dd7a090c5da8 to your computer and use it in GitHub Desktop.
Save patriksvensson/2123d6f5dd7a090c5da8 to your computer and use it in GitHub Desktop.
Run PowerShell scripts from Cake
// Tools and addins
#addin "nuget:?package=System.Management.Automation&version=6.1.7601.17515"
using System.Collections;
using System.Management.Automation;
using System.Management.Automation.Internal;
using System.Management.Automation.Runspaces;
using System.Threading;
///////////////////////////////////////////////////////////////////////////////
// NOTE: One might think that the following lines could be generalized...
///////////////////////////////////////////////////////////////////////////////
private void OnOutputDataAdded(object sender, DataAddedEventArgs e)
{
var data = sender as PSDataCollection<PSObject>;
if(data != null) {
var results = data.ReadAll();
foreach (var item in results) {
Information(item.ToString());
}
}
}
private void OnWarningDataAdded(object sender, DataAddedEventArgs e)
{
var data = sender as PSDataCollection<WarningRecord>;
if(data != null) {
var results = data.ReadAll();
foreach (var item in results) {
Warning(item.Message);
}
}
}
private void OnErrorDataAdded(object sender, DataAddedEventArgs e)
{
var data = sender as PSDataCollection<ErrorRecord>;
if(data != null) {
var results = data.ReadAll();
foreach (var item in results) {
Error(item.ErrorDetails.Message);
}
}
}
private void OnVerboseDataAdded(object sender, DataAddedEventArgs e)
{
var data = sender as PSDataCollection<VerboseRecord>;
if(data != null) {
var results = data.ReadAll();
foreach (var item in results) {
Verbose(item.Message);
}
}
}
private void OnDebugDataAdded(object sender, DataAddedEventArgs e)
{
var data = sender as PSDataCollection<DebugRecord>;
if(data != null) {
var results = data.ReadAll();
foreach (var item in results) {
Debug(item.Message);
}
}
}
///////////////////////////////////////////////////////////////////////////////
public void RunPowerShellScript(FilePath script, IDictionary<string, string> arguments)
{
using(var powershell = PowerShell.Create())
{
// Set the execution policy and location for the script.
var runspaceInvoker = new RunspaceInvoke(powershell.Runspace);
runspaceInvoker.Invoke("Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned -Force");
runspaceInvoker.Invoke("Set-Location -Path " + script.GetDirectory().FullPath);
// Script command.
Command command = new Command(script.FullPath);
foreach (var argument in arguments) {
var parameter = new CommandParameter(argument.Key, argument.Value);
command.Parameters.Add(parameter);
}
command.Parameters.Add(new CommandParameter("Verbose"));
command.Parameters.Add(new CommandParameter("Debug"));
powershell.Commands.AddCommand(command);
// Handle non output data.
powershell.Streams.Verbose.DataAdded += OnVerboseDataAdded;
powershell.Streams.Warning.DataAdded += OnWarningDataAdded;
powershell.Streams.Debug.DataAdded += OnDebugDataAdded;
powershell.Streams.Error.DataAdded += OnErrorDataAdded;
// Setup output collection.
var output = new PSDataCollection<PSObject>();
output.DataAdded += OnOutputDataAdded;
// Subscribe to changes in invocation state.
var handle = new ManualResetEvent(false);
powershell.InvocationStateChanged += (s, e) => {
if (e.InvocationStateInfo.State == PSInvocationState.Completed ||
e.InvocationStateInfo.State == PSInvocationState.Failed)
{
handle.Set();
}
};
try
{
// Execute PowerShell script and wait for it to finish.
var result = powershell.BeginInvoke<PSObject, PSObject>(null, output);
handle.WaitOne();
powershell.EndInvoke(result);
}
catch(RuntimeException ex)
{
Error("The PowerShell script '{0}' exited with an error.", script.FullPath);
throw new CakeException(ex.Message, ex);
}
catch(Exception ex)
{
Error("An error occured when executing PowerShell script '{0}'.", script.FullPath);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment