Back to Basics – Running Command Line Tools from PowerShell

Every now and then you may find that the PowerShell cmdlet for what you are trying to do is simply missing, or that the one that does exist are missing features compared to the command line tool equivalent, or that the PowerShell cmdlet simply have a bug(s) that renders a parameter useless.

Such as an example are the various DISM cmdlets, intended to replace diskpart.exe. Well guess what, the PowerShell cmdlets are not a solid as the diskpart.exe tool itself. Meaning it becomes the perfect example.

Running a Command Line Tool from PowerShell with a bit of Error Handling

In the below example I'm using PowerShell to run diskpart.exe to clean a hard drive from within WinPE. I added in some basic error handling into the mix as well. Hopefully the script comments are documentation enough, but don't hesitate to reach out if you have any feedback.

# Define location of main log file
$Logfile = "$env:TEMP\Diskpart.log"

# Delete any existing log file if it exists
If (Test-Path $Logfile){Remove-Item $Logfile -Force -ErrorAction SilentlyContinue -Confirm:$false}

# Super simple logging function with date stamp
Function Write-Log{
    param (
        [Parameter(Mandatory = $true)]
        [string]$Message
    )
   $TimeGenerated = $(Get-Date -UFormat "%D %T")
   $Line = "$TimeGenerated : $Message"
   Add-Content -Value $Line -Path $LogFile -Encoding Ascii
}

# Request temporary files for RedirectStandardOutput and RedirectStandardError
$RedirectStandardOutput = [System.IO.Path]::GetTempFileName()
$RedirectStandardError = [System.IO.Path]::GetTempFileName()
$DPScript = "$env:TEMP\Diskpart.txt"

# Disk Number to clean
$DiskNumber = "0"

# Diskpart script 
$DPScriptContent = @(
    "select disk $DiskNumber"
    "Clean"
    "Exit"
) 

# Save diskpart script to text file 
Write-Log -Message "Saving Diskpart Script to file: $DPScript"
$DPScriptContent | Out-File $DPScript -Encoding ASCII -Force

# Save diskpart script content to main log file  
Write-Log -Message "----------- Diskpart: Begin Diskpart Script Content -----------"
foreach ($line in $DPScriptContent){
    Write-Log -Message $Line 
}
Write-Log -Message "----------- Diskpart: End Diskpart Script Content -----------"

# Start diskpart.exe
Write-Log -Message "About to run diskpart.exe /s $DPScript"
$Diskpart = Start-Process diskpart.exe "/s $DPScript" -NoNewWindow -Wait -PassThru -RedirectStandardOutput $RedirectStandardOutput -RedirectStandardError $RedirectStandardError

# Log the diskpart Standard Output, skip the empty lines diskpart creates
If ((Get-Item $RedirectStandardOutput).length -gt 0){
    Write-Log -Message "----------- Diskpart: Begin Standard Output -----------"
    $CleanedRedirectStandardOutput = Get-Content $RedirectStandardOutput | Where-Object {$_.trim() -ne "" } 
    foreach ($row in $CleanedRedirectStandardOutput){
         Write-Log -Message $row
    }
    Write-Log -Message "----------- Diskpart: End Standard Output -----------"
}

# Log the diskpart Standard Error, skip the empty lines diskpart creates
If ((Get-Item $RedirectStandardError).length -gt 0){
    Write-Log -Message "----------- Diskpart: Begin Standard Error -----------"
    $CleanedRedirectStandardError = Get-Content $RedirectStandardError | Where-Object {$_.trim() -ne "" } 
    foreach ($row in $CleanedRedirectStandardError){
         Write-Log -Message $row
    }
    Write-Log -Message "----------- Diskpart: End Standard Error -----------"
}

# Diskpart error handling
if ($diskpart.ExitCode -eq 0) {
	Write-Log -Message  "Disk $DiskIndex has been successfully processed by diskpart.exe."
} elseif ($diskpart.ExitCode -gt 0) {
	return Write-Log "Exit code is $($diskpart.ExitCode)"
} else {
	return Write-Log "An unknown error occurred."
}
About the author

Johan Arwidmark

0 0 votes
Article Rating
Subscribe
Notify of
guest
2 Comments
Newest
Oldest Most Voted
Inline Feedbacks
View all comments
John Delise
John Delise
1 month ago

I love the style of this script, leveraging built-in command-line tools, and avoiding re-inventing the wheel. This means time and thus MONEY is saved. I have always wanted to use PowerShell to "Rationalize" the output of the gpresult /r command when I was troubleshooting group policy and wanted to know if a certain line was there and what section it was in, because eyeballing the standard output can be quite tedious and difficult in a complex GP environment. Perhaps I shall after seeing this.

S.K. Atterbrainz
S.K. Atterbrainz
1 month ago

vay vay nice! 😀


>