194 lines
5.4 KiB
C#
194 lines
5.4 KiB
C#
using LANCommander.SDK.Helpers;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
|
|
namespace LANCommander.SDK.PowerShell
|
|
{
|
|
public class PowerShellScript
|
|
{
|
|
private string Contents { get; set; } = "";
|
|
private string WorkingDirectory { get; set; } = "";
|
|
private bool AsAdmin { get; set; } = false;
|
|
private bool ShellExecute { get; set; } = false;
|
|
private bool IgnoreWow64 { get; set; } = false;
|
|
private ICollection<PowerShellVariable> Variables { get; set; }
|
|
private Dictionary<string, string> Arguments { get; set; }
|
|
private List<string> Modules { get; set; }
|
|
private Process Process { get; set; }
|
|
|
|
public PowerShellScript()
|
|
{
|
|
Variables = new List<PowerShellVariable>();
|
|
Arguments = new Dictionary<string, string>();
|
|
Modules = new List<string>();
|
|
Process = new Process();
|
|
|
|
Process.StartInfo.FileName = "powershell.exe";
|
|
Process.StartInfo.RedirectStandardOutput = false;
|
|
|
|
AddArgument("ExecutionPolicy", "Unrestricted");
|
|
|
|
var moduleManifests = Directory.EnumerateFiles(Environment.CurrentDirectory, "LANCommander.PowerShell.psd1", SearchOption.AllDirectories);
|
|
|
|
if (moduleManifests.Any())
|
|
AddModule(moduleManifests.First());
|
|
|
|
IgnoreWow64Redirection();
|
|
}
|
|
|
|
public PowerShellScript UseFile(string path)
|
|
{
|
|
Contents = File.ReadAllText(path);
|
|
|
|
return this;
|
|
}
|
|
|
|
public PowerShellScript UseInline(string contents)
|
|
{
|
|
Contents = contents;
|
|
|
|
return this;
|
|
}
|
|
|
|
public PowerShellScript UseWorkingDirectory(string path)
|
|
{
|
|
WorkingDirectory = path;
|
|
|
|
return this;
|
|
}
|
|
|
|
public PowerShellScript UseShellExecute()
|
|
{
|
|
ShellExecute = true;
|
|
|
|
return this;
|
|
}
|
|
|
|
public PowerShellScript AddVariable<T>(string name, T value)
|
|
{
|
|
Variables.Add(new PowerShellVariable(name, value, typeof(T)));
|
|
|
|
return this;
|
|
}
|
|
|
|
public PowerShellScript AddArgument<T>(string name, T value)
|
|
{
|
|
Arguments.Add(name, $"\"{value}\"");
|
|
|
|
return this;
|
|
}
|
|
|
|
public PowerShellScript AddArgument(string name, int value)
|
|
{
|
|
Arguments[name] = value.ToString();
|
|
|
|
return this;
|
|
}
|
|
|
|
public PowerShellScript AddArgument(string name, long value)
|
|
{
|
|
Arguments[name] = value.ToString();
|
|
|
|
return this;
|
|
}
|
|
|
|
public PowerShellScript AddModule(string path)
|
|
{
|
|
Modules.Add(path);
|
|
|
|
return this;
|
|
}
|
|
|
|
public PowerShellScript RunAsAdmin()
|
|
{
|
|
AsAdmin = true;
|
|
|
|
Process.StartInfo.Verb = "runas";
|
|
Process.StartInfo.UseShellExecute = true;
|
|
|
|
return this;
|
|
}
|
|
|
|
public PowerShellScript IgnoreWow64Redirection()
|
|
{
|
|
IgnoreWow64 = true;
|
|
|
|
return this;
|
|
}
|
|
|
|
public int Execute()
|
|
{
|
|
var scriptBuilder = new StringBuilder();
|
|
|
|
var wow64Value = IntPtr.Zero;
|
|
|
|
if (Contents.StartsWith("# Requires Admin"))
|
|
RunAsAdmin();
|
|
|
|
foreach (var module in Modules)
|
|
{
|
|
scriptBuilder.AppendLine($"Import-Module \"{module}\"");
|
|
}
|
|
|
|
foreach (var variable in Variables)
|
|
{
|
|
scriptBuilder.AppendLine($"${variable.Name} = ConvertFrom-SerializedBase64 \"{Serialize(variable.Value)}\"");
|
|
}
|
|
|
|
scriptBuilder.AppendLine(Contents);
|
|
|
|
var path = ScriptHelper.SaveTempScript(scriptBuilder.ToString());
|
|
|
|
AddArgument("File", path);
|
|
|
|
if (IgnoreWow64)
|
|
Wow64DisableWow64FsRedirection(ref wow64Value);
|
|
|
|
foreach (var argument in Arguments)
|
|
{
|
|
Process.StartInfo.Arguments += $" -{argument.Key} {argument.Value}";
|
|
}
|
|
|
|
if (!String.IsNullOrEmpty(WorkingDirectory))
|
|
Process.StartInfo.WorkingDirectory = WorkingDirectory;
|
|
|
|
if (ShellExecute)
|
|
Process.StartInfo.UseShellExecute = true;
|
|
|
|
if (AsAdmin)
|
|
{
|
|
Process.StartInfo.Verb = "runas";
|
|
Process.StartInfo.UseShellExecute = true;
|
|
}
|
|
|
|
Process.Start();
|
|
Process.WaitForExit();
|
|
|
|
if (IgnoreWow64)
|
|
Wow64RevertWow64FsRedirection(ref wow64Value);
|
|
|
|
if (File.Exists(path))
|
|
File.Delete(path);
|
|
|
|
return Process.ExitCode;
|
|
}
|
|
|
|
public static string Serialize<T>(T input)
|
|
{
|
|
// Use the PowerShell serializer to generate XML for our input. Then convert to base64 so we can put it on one line.
|
|
return Convert.ToBase64String(Encoding.UTF8.GetBytes(System.Management.Automation.PSSerializer.Serialize(input)));
|
|
}
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr);
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
static extern bool Wow64RevertWow64FsRedirection(ref IntPtr ptr);
|
|
}
|
|
}
|