I think a lot of you use the SysInternals tools on your machine. They are great tools at your disposal and have helped me a lot! You can install it using the Microsoft Store method; it will be updated like that, too, but for your management server, it’s nice to have an installer that works without the Microsoft Store 🙂 In this blog post, I will show you how to install or update your SysInternals Suite.

How the script works
Running the script with the -InstallPath parameter will download and install the SysInternals Suite to your specified folder or update an existing installation, showing which files were updated to which version. It downloads the latest version from the website, extracts it to a temporary folder, and then starts the installation or upgrade process. Afterward, it adds the installation folder to your system’s PATH variable for easy command-line access and cleans up the temporary files and folders.
Notes: The script must be run as an administrator.
Running the script
In the example output below, the script updates my current version in c:\Program Files (x86)\SysInterals Suite to the latest version. You can download the script to c:\scripts, for example, and run the Install-SysInternalsSuite function with the -InstallPath parameter (It will prompt you for the path because it’s mandatory).
PS C:\temp> Install-SysInternalsSuite -InstallPath 'c:\Program Files (x86)\SysInterals Suite' Specified installation path c:\Program Files (x86)\SysInterals Suite found, continuing.... No previous download found in C:\Users\HarmV\AppData\Local\Temp\SysInternalsSuite, continuing... Downloading latest version to C:\Users\HarmV\AppData\Local\Temp\SysinternalsSuite.zip Extracting files to C:\Users\HarmV\AppData\Local\Temp\SysInternalsSuite - Updating AccessEnum.exe from version 1.33 to version 1.35- Updating ADExplorer.exe from version 1.51 to version 1.52- Updating ADExplorer64.exe from version 1.51 to version 1.52- Updating Bginfo.exe from version 4.31 to version 4.32- Updating Bginfo64.exe from version 4.31 to version 4.32 - Updating Contig.exe from version 1.81 to version 1.82 - Updating Contig64.exe from version 1.81 to version 1.82 - Updating Coreinfo.exe from version 3.52 to version 3.6 - Updating Coreinfo64.exe from version 3.52 to version 3.6 - Updating handle.exe from version 4.22 to version 5.0 - Updating handle64.exe from version 4.22 to version 5.0 - Updating notmyfault.exe from version 4.20 to version 4.21 - Updating notmyfault64.exe from version 4.20 to version 4.21 - Updating notmyfaultc.exe from version 4.20 to version 4.21 - Updating notmyfaultc64.exe from version 4.20 to version 4.21 - Updating procdump.exe from version 10.11 to version 11.0 - Updating procdump64.exe from version 10.11 to version 11.0 - Updating procexp.exe from version 16.43 to version 17.02 - Updating procexp64.exe from version 16.43 to version 17.02 - Updating Procmon.exe from version 3.91 to version 3.92 - Updating Procmon64.exe from version 3.91 to version 3.92 - Updating RDCMan.exe from version 2.90.1420.0 to version 2.92.1430.0 - Updating Sysmon.exe from version 13.34 to version 14.14 - Updating Sysmon64.exe from version 13.34 to version 14.14 - Updating ZoomIt.exe from version 6.01 to version 6.12 - Updating ZoomIt64.exe from version 6.01 to version 6.12 Adding c:\Program Files (x86)\SysInterals Suite with the SysInternalsSuite to the System Path Cleaning extracted version in C:\Users\HarmV\AppData\Local\Temp Cleaning downloaded SysinternalsSuite.zip file in C:\Users\HarmV\AppData\Local\Temp Updated 26 files in c:\Program Files (x86)\SysInterals Suite from the downloaded 160 files
The script
Below are the contents of the script. Save it to c:\scripts, for example. You can add it to your PowerShell profile for easy access by running the following:
notepad $Profile add ". c:\scripts\Install-SysInternalsSuite.ps1 Save/Quit Start new PowerShell Session
function Install-SysInternalsSuite {
param (
[parameter(Mandatory = $true)][string]$InstallPath
)
# Test admin privileges without using -Requires RunAsAdministrator
if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]"Administrator")) {
Write-Warning ("{0} needs to be started with admin privileges, exiting now...." -f $MyInvocation.MyCommand)
return
}
# Create the installation folder if not already present
if (-not (Test-Path -Path $InstallPath)) {
try {
New-Item -ItemType Directory -Path $InstallPath -ErrorAction Stop | Out-Null
Write-Host ("Specified installation path {0} not found, creating now...." -f $InstallPath) -ForegroundColor Green
}
catch {
Write-Warning ("Install path {0} not found, creating now...." -f $InstallPath)
Write-Warning ("Error creating path {0}, check path and permissions. Exiting now..." -f $InstallPath)
return
}
}
else {
Write-Host ("Specified installation path {0} found, continuing...." -f $InstallPath) -ForegroundColor Green
}
# Check if the previous download folder is present. Remove it first if it is
if (Test-Path -Path $env:temp\SysInternalsSuite) {
Write-Warning ("Previous extracted version found in {0}, removing it now..." -f $env:temp)
Remove-Item -Path $env:temp\SysInternalsSuite -Force:$true -Confirm:$false -Recurse
}
else {
Write-Host ("No previous download found in {0}\SysInternalsSuite, continuing..." -f $env:temp) -ForegroundColor Green
}
# Download and extract the latest version
try {
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$ProgressPreference = "SilentlyContinue"
Invoke-WebRequest -Uri https://download.sysinternals.com/files/SysinternalsSuite.zip -OutFile $ENV:TEMP\SysInternalsSuite.zip -UseBasicParsing -ErrorAction Stop
Write-Host ("Downloading latest version to {0}\SysinternalsSuite.zip" -f $env:temp) -ForegroundColor Green
Expand-Archive -LiteralPath $ENV:TEMP\SysInternalsSuite.zip -DestinationPath $env:temp\SysInternalsSuite -Force:$true -ErrorAction Stop
Write-Host ("Extracting files to {0}\SysInternalsSuite" -f $env:temp) -ForegroundColor Green
}
catch {
Write-Warning ("Error downloading/extracting the SysInternalsSuite, exiting...")
return
}
# Loop through the files and only overwrite older versions and report updated programs on-screen.
# Additional files which were not present in the installation folder will be added
$totalfiles = (Get-ChildItem -Path $env:temp\SysInternalsSuite).count
$updated = 0
foreach ($file in Get-ChildItem -Path $env:temp\SysInternalsSuite) {
if ((Test-Path -Path "$($InstallPath)\$($file.Name)") -and (Test-Path -Path "$($env:temp)\SysInternalsSuite\$($file.name)")) {
$currentversion = (Get-Item "$($InstallPath)\$($file.Name)").VersionInfo
$downloadversion = (Get-Item "$($env:temp)\SysInternalsSuite\$($file.name)").VersionInfo
if ($currentversion.ProductVersion -lt $downloadversion.ProductVersion) {
try {
Copy-Item -LiteralPath "$($env:temp)\SysInternalsSuite\$($file.name)" -Destination "$($InstallPath)\$($file.Name)" -Force:$true -Confirm:$false -ErrorAction Stop
Write-Host ("- Updating {0} from version {1} to version {2}" -f $file.Name, $currentversion.ProductVersion, $downloadversion.ProductVersion) -ForegroundColor Green
++$updated
}
catch {
Write-Warning ("Error overwriting {0}, please check permissions or perhaps the file is in use?" -f $file.name)
}
}
}
else {
try {
Copy-Item -LiteralPath "$($env:temp)\SysInternalsSuite\$($file.name)" -Destination "$($InstallPath)\$($file.Name)" -Force:$true -Confirm:$false -ErrorAction Stop
Write-Host ("- Copying new file {0} to {1}" -f $file.Name, $InstallPath) -ForegroundColor Green
++$updated
}
catch {
Write-Warning ("Error copying {0}, please check permissions" -f $file.name)
}
}
}
# Add installation folder to Path for easy access if not already present
if ((Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).Path -split ';' -notcontains $InstallPath) {
Write-Host ("Adding {0} with the SysInternalsSuite to the System Path" -f $InstallPath) -ForegroundColor Green
$OldPath = (Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).Path
$NewPath = $OldPath + ";$($InstallPath)"
Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH -Value $NewPath
}
else {
Write-Host ("The installation folder {0} is already present in the System Path, skipping adding it..." -f $InstallPath) -ForegroundColor Green
}
# Cleanup files
if (Test-Path -Path $env:temp\SysInternalsSuite) {
Write-Host ("Cleaning extracted version in {0}" -f $env:temp) -ForegroundColor Green
Remove-Item -Path $env:temp\SysInternalsSuite -Force:$true -Confirm:$false -Recurse
}
if (Test-Path -Path $env:temp\SysInternalsSuite.zip) {
Write-Host ("Cleaning downloaded SysinternalsSuite.zip file in {0}" -f $env:temp) -ForegroundColor Green
Remove-Item -Path $env:temp\SysInternalsSuite.zip -Force:$true -Confirm:$false
}
# Display totals and exit
Write-Host ("Updated {0} files in {1} from the downloaded {2} files" -f $updated, $InstallPath, $totalfiles) -ForegroundColor Green
return
}
Download the script(s) from GitHub here
When I click on the above DOWNLOAD SCRIPT FROM GITHUB link, I do see the (Sysinternal) Powershell script. Am I supposed to cut and paste it or is there a convenient downlaod button that I am overlooking?
You can click the file and use the Copy button to copy/paste the contents in c:\scripts\Install-SysInternalsSuite.ps1 or you could use the Go to file button. In the overview of files. search for Install-SysInternalsSuite and Right-Click followed by Save As.
But thanks for your reply.
Dan
But there is a copy button if you click on the link on github… You can also click on the script in my post itself and there’s a hovering menu to copy it too.. Options 😅
When I click on your link: DOWNLOAD THE SCRIPT FROM GITHUB HERE, it sends me to:
‘https://github.com/HarmVeenstra/Powershellisfun/tree/main/Install or update SysInternals Suite’
but I see no convenient copy button for the ‘ps1’ file shown; right-clicking on it (at least in Firefox) only offers a SAVE LINK AS option, no SAVE AS option.
I don’t see a COPY button and though the GOTO button shows the entire script, right-clicking only offers SAVE LINK AS which saves the HTML (3,346 lines!), not the script contents. I know I can cut and paste the script into NOTEPAD but I was hoping Github (which I’m not that familiar with) had an easier way.
I checked it again, it you hover your mouse cursor over the script in this post you will see a floating button containing Raw / Copy / Extern (Only in the first few lines) That should work to copy the lines, otherwise selecting them with your mouse en right-click copy too.
In Github when following the link, you can click on the .ps1 file line which takes you here https://github.com/HarmVeenstra/Powershellisfun/blob/main/Install%20or%20update%20SysInternals%20Suite/Install-SysInternalsSuite.ps1 . In the line that says 99 lines there’s a Copy raw button next to the Raw. and blame button left of the trashcan icon.
Firefox does not show the COPY button but EDGE does (haven’t checked CHROME), so all is well!
Do you anticipate changing your script and if so, am I on your mailing list?
Thanks for your timely replies and more importantly, your script.
Dan
Ah! And I’m using Edge too, didn’t think that Firefox wouldn’t show that button 🙂 And I don’t think it need changes, but you could Follow my blog using your WordPress account (https://wordpress.com/support/following/) for new blogs but I’m not sure it that will give you an email for example if this post changes.
There are a few checkboxes beneath the Reply field, if I update it I will leave a reply and that should get you notified.
No problem, glad to help out the community and usually I can respond pretty quick 🙂
Great! I’ll check the 2 checkboxes and stop in occasionally to see if there is an update (I assume Github will post a date or a version number).
Thanks again for sharing.
Dan
This would be great if the script actually worked. Instead, all it does it throw up a bunch of errors about ampersands being invalid or The ‘<‘ operator is reserved for future use.
Even better, when I finally did get it to run, it tried to download a virus and was stopped by BitDefender: Heur.BZC.ZFV.Boxter.341.F43CE571
I have no idea why the ampersand errors were there, copied the GitHub code again in the blogpost to be sure if there was no error there, but your other remark about the virus?! As you can see in the code, it downloads the file from sysinternals.com which is actually Microsoft since they bought it 😅
I used this Thursday and updated my installation with it and without any problems, you can copy the code from the blog post or github using the link. Hope is fixes the ampersand things. Think Bitdefender scans the download or the temporary extracted files and thinks it’s a virus. What file does it report? Psexec was flagged as a virus many times because of the remote execution possibilities in it…
A cool addendum would be to read a list of Windows Servers and remotely install/upgrade across the environment. Alas, my Powershell skills are lacking, but I may play with that.
Hmmm… That might be an option, you could use invoke-command with a scriptblock for that… Let me know if you need help!
For anyone like me running an older version of PowerShell (5.1) and an older version of Windows 10 (2016 LTSB) I needed to add this line of code:
At the beginning of the “#Download and extract the latest version” try-catch block to make it work.
Also I first added Write-Host $_ to the catch block to see what the actual error was. I suggest that printing the exact error would be useful to power users.
My other suggestion is to add a check or if possible elevate to admin when doing the
“Adding C:\Software\SysInternalsSuite with the SysInternalsSuite to the System Path” so that it doesn’t fail with
Set-ItemProperty : Requested registry access is not allowed.
Otherwise it seems like a decent update script. Thanks!
Thanks for the feedback. I’ve updated the script with an admin check so that it will alert you if it’s not running as an administrator. And I’m not sure what you mean by “I needed to add this line of code: At the beginning of the “#Download and extract the latest version” try-catch block to make it work.” Could you elaborate?
For some reason the line with the code I was referring got missing? I don’t know if it was my mistake, the anti-spam filer or perhaps the line is matching some formatting? Sorry for that, here I will try again:
“For anyone like me running an older version of PowerShell (5.1) and an older version of Windows 10 (2016 LTSB) I needed to add this line of code:
At the beginning of the “#Download and extract the latest version” try-catch block to make it work.”
I don’t see the code 😅 could you email it to my contact address?
Thanks for the email, added [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 to the script to avoid download issues.