main.cs
// Simple PowerShell host created by Ingo Karstein (http://blog.karstein-consulting.com)
// Reworked and GUI support by Markus Scholtes // Updated for PowerShell Core by Fabien Tschanz using System; using System.Collections.Generic; using System.Text; using System.Management.Automation; using System.Management.Automation.Runspaces; using System.Globalization; using System.Management.Automation.Host; using System.Security; using System.Reflection; using System.Runtime.InteropServices; {{usingWinForms}}{{usingVersioning}} [assembly:AssemblyTitle("{{Title}}")] [assembly:AssemblyProduct("{{Product}}")] [assembly:AssemblyCopyright("{{Copyright}}")] [assembly:AssemblyTrademark("{{Trademark}}")] {{AssemblyVersion}} // not displayed in details tab of properties dialog, but embedded to file [assembly:AssemblyDescription("{{Description}}")] [assembly:AssemblyCompany("{{Company}}")] {{TargetFramework}} namespace ModuleNameSpace { {{CredentialForm}} public class MainModuleRawUI : PSHostRawUserInterface { {{StoreConsoleColors}} {{GUITitle}} {{ConsoleSetup}} public override ConsoleColor BackgroundColor { get { {{GetConsoleBackground}} } set { {{SetConsoleBackground}} } } public override System.Management.Automation.Host.Size BufferSize { get { {{GetBufferSize}} } set { {{SetBufferSize}} } } public override Coordinates CursorPosition { get { {{GetCursorPosition}} } set { {{SetCursorPosition}} } } public override int CursorSize { get { {{GetCursorSize}} } set { {{SetCursorSize}} } } {{InvisibleForm}} public override void FlushInputBuffer() { {{FlushInputBuffer}} } public override ConsoleColor ForegroundColor { get { {{GetForegroundColor}} } set { {{SetForegroundColor}} } } public override BufferCell[,] GetBufferContents(System.Management.Automation.Host.Rectangle rectangle) { {{BufferContent}} } public override bool KeyAvailable { get { {{GetKeyAvailable}} } } public override System.Management.Automation.Host.Size MaxPhysicalWindowSize { get { {{GetMaxPhysicalWindowSize}} } } public override System.Management.Automation.Host.Size MaxWindowSize { get { {{GetMaxWindowSize}} } } public override KeyInfo ReadKey(ReadKeyOptions options) { {{ReadKey}} } public override void ScrollBufferContents(System.Management.Automation.Host.Rectangle source, Coordinates destination, System.Management.Automation.Host.Rectangle clip, BufferCell fill) { // no destination block clipping implemented {{ScrollBufferContents}} } public override void SetBufferContents(System.Management.Automation.Host.Rectangle rectangle, BufferCell fill) { {{SetBufferContents1}} } public override void SetBufferContents(Coordinates origin, BufferCell[,] contents) { {{SetBufferContents2}} } public override Coordinates WindowPosition { get { Coordinates s = new Coordinates(); {{GetWindowPosition}} return s; } set { {{SetWindowPosition}} } } public override System.Management.Automation.Host.Size WindowSize { get { System.Management.Automation.Host.Size s = new System.Management.Automation.Host.Size(); {{GetWindowSize}} return s; } set { {{SetWindowSize}} } } public override string WindowTitle { get { {{GetWindowTitle}} } set { {{SetWindowTitle}} } } } {{DialogBoxes}} public class MainModuleUI : PSHostUserInterface { private MainModuleRawUI rawUI = null; public ConsoleColor ErrorForegroundColor = ConsoleColor.Red; public ConsoleColor ErrorBackgroundColor = ConsoleColor.Black; public ConsoleColor WarningForegroundColor = ConsoleColor.Yellow; public ConsoleColor WarningBackgroundColor = ConsoleColor.Black; public ConsoleColor DebugForegroundColor = ConsoleColor.Yellow; public ConsoleColor DebugBackgroundColor = ConsoleColor.Black; public ConsoleColor VerboseForegroundColor = ConsoleColor.Yellow; public ConsoleColor VerboseBackgroundColor = ConsoleColor.Black; public ConsoleColor ProgressForegroundColor = {{ProgressForegroundColor}}; public ConsoleColor ProgressBackgroundColor = ConsoleColor.DarkCyan; public MainModuleUI() : base() { rawUI = new MainModuleRawUI(); {{baseColorSetup}} } public override Dictionary<string, PSObject> Prompt(string caption, string message, System.Collections.ObjectModel.Collection<FieldDescription> descriptions) { {{Prompt}} } public override int PromptForChoice(string caption, string message, System.Collections.ObjectModel.Collection<ChoiceDescription> choices, int defaultChoice) { {{PromptForChoice}} } public override PSCredential PromptForCredential(string caption, string message, string userName, string targetName, PSCredentialTypes allowedCredentialTypes, PSCredentialUIOptions options) { {{PromptForCredential1}} } public override PSCredential PromptForCredential(string caption, string message, string userName, string targetName) { {{PromptForCredential2}} } public override PSHostRawUserInterface RawUI { get { return rawUI; } } {{MessageBoxMessage}} public override string ReadLine() { {{ReadLine}} {{ReadLineExit}} } private System.Security.SecureString getPassword() { System.Security.SecureString pwd = new System.Security.SecureString(); while (true) { ConsoleKeyInfo i = Console.ReadKey(true); if (i.Key == ConsoleKey.Enter) { Console.WriteLine(); break; } else if (i.Key == ConsoleKey.Backspace) { if (pwd.Length > 0) { pwd.RemoveAt(pwd.Length - 1); Console.Write("\b \b"); } } else if (i.KeyChar != '\u0000') { pwd.AppendChar(i.KeyChar); Console.Write("*"); } } return pwd; } public override System.Security.SecureString ReadLineAsSecureString() { System.Security.SecureString secstr = new System.Security.SecureString(); {{GetPassword}} return secstr; } // called by Write-Host public override void Write(ConsoleColor foregroundColor, ConsoleColor backgroundColor, string value) { {{Write1}} } public override void Write(string value) { {{Write2}} } // called by Write-Debug public override void WriteDebugLine(string message) { {{WriteDebugLine}} } // called by Write-Error public override void WriteErrorLine(string value) { {{WriteErrorLine}} } public override void WriteLine() { {{WriteLine1}} } public override void WriteLine(ConsoleColor foregroundColor, ConsoleColor backgroundColor, string value) { {{WriteLine2}} } {{WriteLineInternal}} // called by Write-Output public override void WriteLine(string value) { {{WriteLine3}} } {{ProgressForm}} public override void WriteProgress(long sourceId, ProgressRecord record) { {{WriteProgress}} } // called by Write-Verbose public override void WriteVerboseLine(string message) { {{WriteVerboseLine}} } // called by Write-Warning public override void WriteWarningLine(string message) { {{WriteWarningLine}} } } public class MainModule : PSHost { private MainAppInterface parent; private MainModuleUI ui = null; private CultureInfo originalCultureInfo = System.Threading.Thread.CurrentThread.CurrentCulture; private CultureInfo originalUICultureInfo = System.Threading.Thread.CurrentThread.CurrentUICulture; private Guid myId = Guid.NewGuid(); public MainModule(MainAppInterface app, MainModuleUI ui) { this.parent = app; this.ui = ui; } public class ConsoleColorProxy { private MainModuleUI _ui; public ConsoleColorProxy(MainModuleUI ui) { if (ui == null) throw new ArgumentNullException("ui"); _ui = ui; } public ConsoleColor ErrorForegroundColor { get { return _ui.ErrorForegroundColor; } set { _ui.ErrorForegroundColor = value; } } public ConsoleColor ErrorBackgroundColor { get { return _ui.ErrorBackgroundColor; } set { _ui.ErrorBackgroundColor = value; } } public ConsoleColor WarningForegroundColor { get { return _ui.WarningForegroundColor; } set { _ui.WarningForegroundColor = value; } } public ConsoleColor WarningBackgroundColor { get { return _ui.WarningBackgroundColor; } set { _ui.WarningBackgroundColor = value; } } public ConsoleColor DebugForegroundColor { get { return _ui.DebugForegroundColor; } set { _ui.DebugForegroundColor = value; } } public ConsoleColor DebugBackgroundColor { get { return _ui.DebugBackgroundColor; } set { _ui.DebugBackgroundColor = value; } } public ConsoleColor VerboseForegroundColor { get { return _ui.VerboseForegroundColor; } set { _ui.VerboseForegroundColor = value; } } public ConsoleColor VerboseBackgroundColor { get { return _ui.VerboseBackgroundColor; } set { _ui.VerboseBackgroundColor = value; } } public ConsoleColor ProgressForegroundColor { get { return _ui.ProgressForegroundColor; } set { _ui.ProgressForegroundColor = value; } } public ConsoleColor ProgressBackgroundColor { get { return _ui.ProgressBackgroundColor; } set { _ui.ProgressBackgroundColor = value; } } } public override PSObject PrivateData { get { if (ui == null) return null; return _consoleColorProxy ?? (_consoleColorProxy = PSObject.AsPSObject(new ConsoleColorProxy(ui))); } } private PSObject _consoleColorProxy; public override System.Globalization.CultureInfo CurrentCulture { get { return this.originalCultureInfo; } } public override System.Globalization.CultureInfo CurrentUICulture { get { return this.originalUICultureInfo; } } public override Guid InstanceId { get { return this.myId; } } public override string Name { get { return "PSRunspace-Host"; } } public override PSHostUserInterface UI { get { return ui; } } public override Version Version { get { return new Version(0, 5, 0, 32); } } public override void EnterNestedPrompt() { } public override void ExitNestedPrompt() { } public override void NotifyBeginApplication() { return; } public override void NotifyEndApplication() { return; } public override void SetShouldExit(int exitCode) { this.parent.ShouldExit = true; this.parent.ExitCode = exitCode; } } public interface MainAppInterface { bool ShouldExit { get; set; } int ExitCode { get; set; } } public class MainApp : MainAppInterface { private bool shouldExit; private int exitCode; public bool ShouldExit { get { return this.shouldExit; } set { this.shouldExit = value; } } public int ExitCode { get { return this.exitCode; } set { this.exitCode = value; } } {{AllocConsole}} {{ApartmentState}} public static int Main(string[] args) { {{SetupConHost}} {{OutputEncoding}} {{Culture}} {{VisualStyles}} MainApp me = new MainApp(); bool paramWait = false; string extractFN = string.Empty; MainModuleUI ui = new MainModuleUI(); MainModule host = new MainModule(me, ui); System.Threading.ManualResetEvent mre = new System.Threading.ManualResetEvent(false); AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); try { using (Runspace myRunSpace = RunspaceFactory.CreateRunspace(host)) { {{RunspaceApartmentState}} myRunSpace.Open(); using (PowerShell posh = PowerShell.Create()) { {{CancelKeyPress}} posh.Runspace = myRunSpace; posh.Streams.Error.DataAdded += new EventHandler<DataAddedEventArgs>(delegate(object sender, DataAddedEventArgs e) { ui.WriteErrorLine(((PSDataCollection<ErrorRecord>)sender)[e.Index].Exception.Message); }); PSDataCollection<string> colInput = new PSDataCollection<string>(); if (Console.IsInputRedirected) { // read standard input string sItem = ""; while ((sItem = Console.ReadLine()) != null) { // add to powershell pipeline colInput.Add(sItem); } } colInput.Complete(); PSDataCollection<PSObject> colOutput = new PSDataCollection<PSObject>(); colOutput.DataAdded += new EventHandler<DataAddedEventArgs>(delegate(object sender, DataAddedEventArgs e) { ui.WriteLine(((PSDataCollection<PSObject>)sender)[e.Index].ToString()); }); int separator = 0; int idx = 0; bool bHelp = false; string sHelp = ""; foreach (string s in args) { if (string.Compare(s, "-wait", true) == 0) paramWait = true; else if (s.StartsWith("-extract", StringComparison.InvariantCultureIgnoreCase)) { string[] s1 = s.Split(new string[] { ":" }, 2, StringSplitOptions.RemoveEmptyEntries); if (s1.Length != 2) { {{ExtractNotification}} return 1; } extractFN = s1[1].Trim(new char[] { '\"' }); } else if (string.Compare(s, "-end", true) == 0) { separator = idx + 1; break; } else if (string.Compare(s, "-?", true) == 0) { bHelp = true; } else if (bHelp) { if ((string.Compare(s, "-detailed", true) == 0) || (string.Compare(s, "-examples", true) == 0) || (string.Compare(s, "-full", true) == 0)) { sHelp = s; } } else if (string.Compare(s, "-debug", true) == 0) { System.Diagnostics.Debugger.Launch(); break; } idx++; } Assembly executingAssembly = Assembly.GetExecutingAssembly(); using (System.IO.Stream scriptstream = executingAssembly.GetManifestResourceStream("{{ResourcePrefix}}" + "{{FileName}}")) { using (System.IO.StreamReader scriptreader = new System.IO.StreamReader(scriptstream, System.Text.Encoding.UTF8)) { string script = scriptreader.ReadToEnd(); if (!string.IsNullOrEmpty(extractFN)) { System.IO.File.WriteAllText(extractFN, script); return 0; } if (bHelp) { // help selected posh.AddScript("function " + System.AppDomain.CurrentDomain.FriendlyName + "{" + script + "}; Get-Help " + System.AppDomain.CurrentDomain.FriendlyName + " " + sHelp + " | Out-String"); } else { // execution selected posh.AddScript(script); } } } if (!bHelp) { // only if no help selected // parse parameters string argbuffer = null; // regex for named parameters System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(@"^-([^: ]+)[ :]?([^:]*)$"); for (int i = separator; i < args.Length; i++) { System.Text.RegularExpressions.Match match = regex.Match(args[i]); double dummy; if ((match.Success && match.Groups.Count == 3) && (!Double.TryParse(args[i], out dummy))) { // parameter in powershell style, means named parameter found if (argbuffer != null) // already a named parameter in buffer, then flush it posh.AddParameter(argbuffer); if (match.Groups[2].Value.Trim() == "") { // store named parameter in buffer argbuffer = match.Groups[1].Value; } else // caution: when called in powershell $true gets converted, when called in cmd.exe not if ((match.Groups[2].Value == "$true") || (match.Groups[2].Value.ToUpper() == "\x24TRUE")) { // switch found posh.AddParameter(match.Groups[1].Value, true); argbuffer = null; } else // caution: when called in powershell $false gets converted, when called in cmd.exe not if ((match.Groups[2].Value == "$false") || (match.Groups[2].Value.ToUpper() == "\x24"+"FALSE")) { // switch found posh.AddParameter(match.Groups[1].Value, false); argbuffer = null; } else { // named parameter with value found posh.AddParameter(match.Groups[1].Value, match.Groups[2].Value); argbuffer = null; } } else { // unnamed parameter found if (argbuffer != null) { // already a named parameter in buffer, so this is the value posh.AddParameter(argbuffer, args[i]); argbuffer = null; } else { // position parameter found posh.AddArgument(args[i]); } } } if (argbuffer != null) posh.AddParameter(argbuffer); // flush parameter buffer... // convert output to strings posh.AddCommand("Out-String"); // with a single string per line posh.AddParameter("Stream"); } posh.BeginInvoke<string, PSObject>(colInput, colOutput, null, new AsyncCallback(delegate(IAsyncResult ar) { if (ar.IsCompleted) mre.Set(); }), null); while (!me.ShouldExit && !mre.WaitOne(100)) { }; posh.Stop(); if (posh.InvocationStateInfo.State == PSInvocationState.Failed) ui.WriteErrorLine(posh.InvocationStateInfo.Reason.Message); } myRunSpace.Close(); } } catch (Exception ex) { {{CatchException}} } if (paramWait) { {{WaitForExit}} } return me.ExitCode; } static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { throw new Exception("Unhandled exception in " + System.AppDomain.CurrentDomain.FriendlyName); } } } |