-1

I have a WPF application in which I am starting a Powershell process and redirecting the standard output to a textbox. I am facing a problem in which when the Powershell process is started, the Powershell window opens up but stays blank. The process is executing in the background however, the textbox is only updated when the Powershell window is closed. I would like for the text box to update and the process to move forward simultaneously.

How can I achieve this? My code is like this:

private async void btnStartPowershell(object sender, RoutedEventArgs e)
{
    string powershellPath = @"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe";
    Thread psThread = new Thread(() =>
    {
        string cOut = OpenPowershell(powershellPath, Installer, logPath, "Config Builder");
        if (cOut.Contains("error"))
        {
            ErrorStatusStack.Visibility = Visibility.Visible;
        }
        Action action = () => doUIUpgrade(cOut, logPath);
        this.BeginInvoke(action);
    });
    psThread.Start();
    txtboxCompletedProcess.Text = $"Powershell Scripts Completed. Please see the logs for details.";
}

private void doUIUpgrade(string cOut, string logPath)
{
    PSOutputTextBlock.Text = cOut;
    if (cOut.Contains("OCMS INSTALLATION STARTED"))
    {
        Console.WriteLine("YES");
    }
    InstallationStartedTextBlock.Text = $"Installation started. Please do not close this window. More details can be found at {logPath}";
}

private string OpenPowershell(string path, string script)
{
        try
        {
            bool is64 = IntPtr.Size == 8;
            var ENV = "Get-ItemProperty HKLM:\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\* "
                   + (is64 ? ",HKLM:\\Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*" : "")
                   + " | Select-Object DisplayName";
            ProcessStartInfo startPowershell = new ProcessStartInfo(path, ENV);
            startPowershell.UseShellExecute = false;
            startPowershell.Arguments = script;
            startPowershell.RedirectStandardOutput = true;
            startPowershell.EnvironmentVariables.Add("RedirectStandardOutput", "true");
            startPowershell.EnvironmentVariables.Add("RedirectStandardError", "true");
            startPowershell.EnvironmentVariables.Add("UseShellExecute", "false");
            startPowershell.EnvironmentVariables.Add("CreateNoWindow", "true");
            Process psProcess = Process.Start(startPowershell);
            string output = psProcess.StandardOutput.ReadToEnd();
            psProcess.WaitForExit();
            return output;
        }
        catch (Exception error)
        {
            MessageBox.Show(error.Message);
            return error.ToString();
        }
}

I have tried doing string output = psProcess.StandardOutput.ReadLine(); instead of string output = psProcess.StandardOutput.ReadToEnd(); but I still only get the text box updated when the entire script is completed and not before.

I'll appreciate any help here.

1 Answers1

-1

you should create another thread for your psProcess's getting stdout and update by timers. it could helps you

WSW
  • 1
  • 4
  • he started a thread to invoke powershell. why do you think powersehll runs in ui(main) thread? – Lei Yang Mar 30 '22 at 06:26
  • sry i wirite not correctly! Big way: 1. psProcess result in 2.psThread thread usend only after the 3. psProcess.WaitForExit and afterwords 4. BeginInvoke doUIUpgrade . To make true way: change 'thread for WaitForExit of process' to 'thread for read lines of process stdout, while process alive' – WSW Mar 30 '22 at 06:53