Search code examples
powershelltranscriptiondismsfc

Powershell DISM and SFC Script with Transcript


Write-Host "DISM and SFC" -ForegroundColor Cyan
Start-Transcript C:\DISM_SFC.txt
Start-Process -FilePath "dism.exe" -ArgumentList '/online /cleanup-image /analyzecomponentstore' -Wait -NoNewWindow
Start-Process -FilePath "dism.exe" -ArgumentList '/online /cleanup-image /startcomponentcleanup' -Wait -NoNewWindow
Start-Process -FilePath "dism.exe" -ArgumentList '/online /cleanup-image /checkhealth' -Wait -NoNewWindow
Start-Process -FilePath "dism.exe" -ArgumentList '/online /cleanup-image /scanhealth' -Wait -NoNewWindow
Start-Process -FilePath "dism.exe" -ArgumentList '/online /cleanup-image /restorehealth' -Wait -NoNewWindow
Start-Process -FilePath "sfc.exe" -ArgumentList '/scannow' -Wait -NoNewWindow
Stop-Transcript
Write-Host "DISM and SFC completed"`n -ForegroundColor Magenta

I'm trying to add Start-Transcript/Stop-Transcript to my tune-up script and I can't get it to work properly. It performs the commands, creates the text file, but doesn't add the results in the text file.

I think the issue is related to the -NoNewWindow but I'm kind of lost.


Solution

  • dism.exe and sfc.exe are console-subsystem Windows applications.

    To invoke them synchronously, with their output streams (stdout, stderr) connected to PowerShell's output streams , invoke them directly; e.g.:

    dism.exe/online /cleanup-image /analyzecomponentstore
    # ...
    sfc.exe /scannow
    

    Note:

    • If your executable name or path were quoted or expressed via variable references, you'd need to prepend &, the call operator (e.g., $exe = 'dism.exe'; & $exe ...)

    This is the prerequisite for output to show up in your transcripts.

    By contrast, if you use Start-Process's -NoNewWindow switch, the program's output prints directly to the console, with no ability to capture it in PowerShell.

    An additional advantage of direct, synchronous execution is that the executable's process exit code will be reflected in the automatic $LASTEXITCODE variable


    For regular invocations without special requirements - such as wanting to run in a new window, with elevation, or as a different user - Start-Process is usually the wrong tool.

    While you can use it to make a call to a GUI(-subsystem) application synchronous (such applications run asynchronously by default), namely with -Wait, a trick allows you to use direct invocation there as well: Pipe to Out-Null (or, in the rare event that your GUI application explicitly attaches to the caller's console and produces output, to Write-Output); e.g.:

    # Opens Notepad and waits until it's closed.
    Notepad.exe | Out-Null
    
    • See this answer for more information about this technique.

    GitHub docs issue #6239 provides guidance on when use of Start-Process is and isn't appropriate.