Public/Get-PsExec.ps1
function Get-PsExec { [CmdletBinding(ConfirmImpact = 'High', SupportsShouldProcess = $true)] param( [Parameter(Mandatory = $true, Position = 0)] [String] $OutPath, [Switch] $Force ) begin { $url = 'https://download.sysinternals.com/files/PSTools.zip' } process { # Shell.Application object wil need this to have a .zip extension in order to recognize it as an archive $tempFile = '{0}.zip' -f [System.IO.Path]::GetTempFileName() $tempExe = Join-Path -Path $env:TEMP -ChildPath 'PsExec.exe' if (Test-Path -Path $tempExe) { Remove-Item -Path $tempExe -Force } $client = New-Object -TypeName 'System.Net.WebClient' try { Write-Verbose "Dowloading PsTools.zip from URL [$url] to path [$tempFile]" $client.DownloadFile($url, $tempFile) } catch { throw "Error downloading PsExec.exe: $_" } Unblock-File -Path $tempFile # PS 2.0 compatibility...newer versions can use System.IO.Compression namespace $shell = New-Object -ComObject 'Shell.Application' $zipFile = $shell.NameSpace($tempFile) foreach ($z in $zipFile.Items()) { if ($z.Name -eq 'PsExec.exe') { Write-Verbose "Extracting file [$($z.Name)]" $shell.NameSpace($env:TEMP).CopyHere($z) # CopyHere() is asynchronous, so we may need to wait for it to complete on slower systems. PsExec is usually only about 300 KB, though $i = 0 while (-not (Test-Path -Path $tempExe)) { if ($i -gt 9) { throw "Failed to extract PsExec.exe from path [$tempFile] to path [$tempExe]. These files have not been deleted." } Write-Verbose "Waiting for PsExec.exe to be extracted ($i of 10)..." Start-Sleep -Seconds 3 $i++ } } } if (-not (Test-Path -Path $OutPath)) { Write-Verbose "Creating directory [$OutPath]" New-Item -Path $OutPath -ItemType Directory -Force | Out-Null } $outFile = Join-Path -Path $OutPath -ChildPath 'PsExec.exe' if ($Force -or (-not (Test-Path -Path $OutFile)) -or $PSCmdlet.ShouldProcess($OutFile, "Overwrite existing file")) { Move-Item -Path $tempExe -Destination $OutFile -Force } else { Write-Verbose "The file exists, and the user denied the confirmation prompt. Existing file will not be modified." } Write-Verbose "Removing temporary files" Remove-Item -Path $tempFile -Force } } |