2

I'd like to see the "live" output of an application when I call it.

When I call it in a function, it works properly, as if I would call it directly. I can cancel the application with Ctrl+C and the "progress bar" the application outputs is updated:

function Test()
{
    dism.exe /online /Cleanup-Image /AnalyzeComponentStore
}

Test
[===                        5.5%                           ]

When I call it in a method however, there is no output visible. I can work around that by writing & dism.exe /online /Cleanup-Image /AnalyzeComponentStore 2>&1 | Write-Host but for this example, it would not update the progress bar but instead write a new line whenever there's a progress update:

class TestC
{
    Test()
    {
        & dism.exe /online /Cleanup-Image /AnalyzeComponentStore 2>&1 | Write-Host
    }
}

$testC = [TestC]::new()
$testC.Test()
[=                          3.3%                           ]

[===                        5.5%                           ]

I also cannot cancel the application with Ctrl+C, instead only the script would be cancelled and the called application continues in the background.

Is there an explanation for this? And a working workaround? :)

Thank you!

1
  • Good question, but I'd be surprised if Ctrl-C didn't also terminate the external program when called from a method. Commented May 10, 2020 at 12:53

2 Answers 2

4

You can use the Start-Process cmdlet with the -NoNewWindow parameter:

Start-Process dism.exe -ArgumentList "/online /Cleanup-Image /AnalyzeComponentStore" -NoNewWindow -Wait
Sign up to request clarification or add additional context in comments.

1 Comment

What's a bit unfortunate is that when I cancel the process with Ctrl+C, it continues with the output after the script has already ended: PS C:\Users\Administrator> C:\APPS\Scripts\Tools.ps1 Deployment Image Servicing and Management tool Version: 10.0.17763.771 Image Version: 10.0.17763.1131 [========= 16.4% ] PS C:\Users\Administrator> Error: 1223 Operation was incomplete because of a cancel request. The DISM log file can be found at C:\Windows\Logs\DISM\dism.log
3

To complement Thomas' helpful answer with some background information:

You cannot use direct invocation in PowerShell classes if you want to invoke external console applications with pass-through display output.

Methods produce (success) output only via the return statement (and to report errors via throw).

Note that - both with your Write-Host attempt and with Start-Process -NoNewWindow (which is the only way to pass output through to the display, albeit invariably) - you won't be able to capture or redirect the external program's output.[1]

If you do want to return an external program's output as data from a class method, you'll have to define it as follows:

class TestC
{
  [string[]] Test()
  {
    return dism.exe /online /Cleanup-Image /AnalyzeComponentStore 2>&1
  }
}

Note the [string[]] return type and the use of return.

This outputs the external program's output lines in a streaming fashion to the caller, allowing further programmatic processing.

Of course, outputting progress messages this way won't be useful.


[1] Technically, you can capture Write-Host output since PowerShell 5, namely via the information stream (6), which in your case would require $output = & { $testC.Test() } 6>&1 - see this answer.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.