How to force close the powershell.exe console after script completion

rated by 0 users
This post has 5 Replies | 2 Followers

Top 500 Contributor
Posts 8
dharric Posted: 05-05-2012 2:24 PM

Hi Don I've tried using the exit and Exit-PSSession commands at the end of my script to do this but its not working. In my case the scenario is a little more complex because I am using the line &"$env:WINDIR\syswow64\windowspowershell\v1.0\powershell.exe" -NonInteractive -NoProfile $myInvocation.Line in order to force my script to run in 32bit mode. I suspect this may be causing my console window to stay open at the end of my script run. I also am launching my script from C# and need the call to Invoke that I am using to execute the script to return so that I can take the output of the script and do some stuff on it. Do you have any idea how I can get my script to return properly?

Top 10 Contributor
Posts 640

Well, normally, the shell will close automatically if you use -Command to run a script. I think you're right in that it's the technique you're using.

I'm curious, though - if you're in C#, why are you shelling out to run a script, rather than just instantiating PowerShell's .NET engine directly in code? The way you're doing it is definitely not what Microsoft intended or built to work...

Top 500 Contributor
Posts 8

Thanks for responding to my query. Its really quite nice of you to take the time on a weekend. Now if I understand your question, I actually am using the System.Management.Automation namespace in my .Net app and calling the powershell script using Invoke. However the scenario that I have is I am using powershell to update a 32bit access file (we're stuck on Office 2007), but our .Net app is 64bit. So I needed a way to switch my powershell environment to 32bit at runtime, which is that one line I showed you before.

Maybe if I show you some of the code I'm running this will make more sense. But to reiterate the strangeness here is that on my local dev box this code returns without issue. Its only on a 2008 server that it does this weird not returning thing. I think I may have to revert to using .Net's commandline console launcher to execute my powershell script. But I'm hoping you'll show me a way around this. Thanks again.

This is the C# code that calls my script:

System.Management.Automation.Runspaces.Runspace lRunspace = System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace();
            lRunspace.Open();

            using (System.Management.Automation.RunspaceInvoke lRunspaceInvoker = new System.Management.Automation.RunspaceInvoke(lRunspace))
            {
                lRunspaceInvoker.Invoke("Set-ExecutionPolicy RemoteSigned");

                using (System.Management.Automation.PowerShell lPowershell = System.Management.Automation.PowerShell.Create())
                {
                    bool lDoDebug = true;
                    try
                    {
                        LogWriter.LogInfo("LaunchPowershell Setting up powershell script execution.");
                        var lAppSettings = System.Configuration.ConfigurationManager.AppSettings;
                        string lAccessScriptPath = lAppSettings["MtpAccessScriptPath"];
                        string lMtpXmlScriptPath = lAppSettings["MtpXmlDestinationPath"] + "\\MtpToPertrac.xml";
                        string lPowershellScriptPath = lAppSettings["MtpPowershellScriptPath"];
                        string lDoDebugStr = lAppSettings["MtpToPertracDebug"];
                        lDoDebug = lDoDebugStr == "True" ? true : false;
                        lPowershell.Runspace = lRunspace;
                        lPowershell.Commands.AddScript(lPowershellScriptPath);

                        Collection<System.Management.Automation.PSObject> lResults = new Collection<System.Management.Automation.PSObject>();
                        Collection<System.Management.Automation.ErrorRecord> lErrors = new Collection<System.Management.Automation.ErrorRecord>();

                        try
                        {
                            LogWriter.LogInfo("LaunchPowershell beginning to Invoke powershell.");
                            lResults = lPowershell.Invoke();
                            lErrors = lPowershell.Streams.Error.ReadAll();
                            LogWriter.LogInfo("LaunchPowershell powershell script was invoked");
                        }
                        catch (Exception ex)
                        {
                            lResults.Add(new System.Management.Automation.PSObject((object)ex.Message));
                            LogWriter.LogException(ex);
                        }

                        if (lDoDebug) // if in debug mode write log file
                        {
                            StringBuilder lStr = new StringBuilder();
                            foreach (var obj in lResults)
                            {
                                lStr.AppendLine(obj.ToString());
                            }
                            foreach (var obj in lErrors)
                            {
                                lStr.AppendLine(obj.ToString());
                            }

                            string lLog = lStr.ToString();
                            if (!string.IsNullOrEmpty(lLog))
                            {
                                using (MemoryStream lMs = new MemoryStream())
                                {
                                    TextWriter lTxt = new StreamWriter(lMs);
                                    lTxt.Write(lLog);
                                    lTxt.Flush();

                                    if (lLog.Contains("Error") || lLog.Contains("Exception"))
                                    {
                                        var lPossibleErrors = lStr.ToString();
                                        MemoryStream lEmailMs = new MemoryStream(lMs.ToArray()); // needed as send email can close the stream
                                        SendInfoEmail(lPossibleErrors, lAppSettings["EmailMtpToPertracInfo"], lEmailMs);
                                    }

                                    byte[] lBuffer = null;
                                    lMs.Position = 0;
                                    BinaryReader lReader = new BinaryReader(lMs);
                                    long lTotalBytes = lMs.Length;
                                    lBuffer = lReader.ReadBytes((int)lTotalBytes);
                                    lReader.Close();
                                    lTxt.Close();

                                    LogWriter.LogInfo("LaunchPowershell log file created");

                                    return lBuffer;
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        LogWriter.LogException(ex);
                    }
                    finally
                    {
                        lRunspace.Close();
                    }                   
                }
            }

            return null;

This is the powershell script section that does the switch to 32bit:

if($env:Processor_Architecture -ne "x86")
{
    write-warning "Running x86 Powershell ...."
    &"$env:WINDIR\syswow64\windowspowershell\v1.0\powershell.exe" -NonInteractive -NoProfile $myInvocation.Line
    exit
}

Top 10 Contributor
Posts 640

You're unfortunately out of my depth. The forum here mainly handles admin-level questions; you're firmly in the dev world. I'd suggest StackOverflow.com - I know a lot of the other PowerShell MVPs (with more of a dev focus) hang out there. Keith Hill, in particular, might have some good suggestions. You might also cross-post here to Tobias' forum - he understands the dev side a lot better than I.

Top 500 Contributor
Posts 8

Ok thanks

Top 500 Contributor
Posts 8

Don just an fyi. I switched to executing a cmd process. Although it did not resolve my issue I did discover with greater detail what was happening. Basically the .Net call was hanging waiting for Standard Output to finish. This is why my script powershell.exe console never returned. So now I don't read that output and just send my results to a log file using Out-File and Write-Output. But now I'm having other issues with Write-Output. If you get a moment please take a look at my other posting thanks again!

Page 1 of 1 (6 items) | RSS
Copyright 2012 PowerShell.com. All rights reserved.