Published in Articles on by Michiel van Oosterhout ~ 5 min read

If you are a software developer or a system administrator, or if you just want to get a better understanding of the inner workings of Windows, then you should install Sysinternals. This is a suite of CLI and GUI programs that help you find and fix problems, as well as do things easily that may be difficult or impossible otherwise. An example of the first is finding out which program is keeping you from deleting a file using handle.exe, and an example of the latter is creating NTFS junctions using junction.exe. Both of these are command-line programs, but the suite also contains GUI programs, like Process Explorer, a powerful tool that can replace Windows' built-in Task Manager, offering a lot more information about the processes running on your system.

Sysinternals' Process Explorer on Windows 11 ARM
Sysinternals' Process Explorer on Windows 11 ARM

Installation

Microsoft does not provide an installer for Sysinternals, and only a few tools are offered through Windows Package Manager, so you have to download the files yourself, move them to a directory in %ProgramFiles%, add that directory to your path, and create shortcuts to the GUI tools in the Start menu. Luckily we can automate all of that using a script.

The Windows PowerShell script below downloads Sysinternals for Windows ARM, and then installs 2 tools. You should adjust the list of tools you want to install, this list is just given as an example. (Although Eula.txt is required by almost all tools, so make sure to include it in your list.)

(This script requires an elevated Windows PowerShell session.)

# Download the archive file
$downloadsPath = "$Env:USERPROFILE\Downloads"
$zipFileName = "SysinternalsSuite-ARM64.zip"
$zipFilePath = "$downloadsPath\$zipFileName"
$url = "https://download.sysinternals.com/files/$zipFileName"
Invoke-WebRequest -Uri $url -OutFile $zipFilePath

# Expand, then delete, the archive file
$expandedDirectoryPath = "$downloadsPath\SysinternalsSuite-ARM64"
Expand-Archive -Path $zipFilePath -Destination $expandedDirectoryPath
Remove-Item -Force -Path $zipFilePath

# Ensure the program files directory exists
$programFilesDirectoryPath = "$Env:ProgramFiles\Sysinternals"
if (-not (Test-Path -Path $programFilesDirectoryPath))
{
    $_ = New-Item -Force -ItemType Directory -Path $programFilesDirectoryPath
}

# Ensure the Start menu directory exists
$startMenuDirectoryPath = "$Env:ProgramData\Microsoft\Windows\Start Menu\Programs\Sysinternals"
if (-not (Test-Path -Path $startMenuDirectoryPath))
{
    $_ = New-Item -Force -ItemType Directory -Path $startMenuDirectoryPath
}

# Ensure the app data directory exists
$appDataDirectoryPath = "$Env:LocalAppData\Sysinternals"
if (-not (Test-Path -Path $appDataDirectoryPath))
{
    $_ = New-Item -Force -ItemType Directory -Path $appDataDirectoryPath
}

# Add path to the PATH environment variable
$keyPath = "HKLM:\System\CurrentControlSet\Control\Session Manager\Environment"
$value = (Get-ItemProperty -Path $keyPath -Name "Path").Path.Trim(";") + ";%ProgramFiles%\Sysinternals"
Set-ItemProperty -Path $keyPath -Name "Path" -Value $value

# List of files to copy
$files = @(
    @{ FileName = "Eula.txt" }
    @{
        FileName = "Autoruns64a.exe"
        DisplayName = "Autoruns"
        Registry = @{
            Key = "Autoruns"
            Values = @{
                EulaAccepted = $true
                Theme = "DarkTheme"
            }
        }
    }
    @{
        FileName = "Winobj64a.exe"
        DisplayName = "WinObj"
        Registry = @{
            Key = "WinObj"
            Values = @{
                EulaAccepted = $true
            }
        }
        Ini = @{
            File = "WinObj.ini"
            Values = @{
                Theme = "DarkTheme"
            }
        }
    }
)

# Create the Shell's automation object
$shell = New-Object -ComObject "WScript.Shell"

# Copy the files we want
foreach ($file in $files)
{
    $path = "$expandedDirectoryPath\$($file.FileName)"
    $destination = "$programFilesDirectoryPath\$($file.FileName.Replace("64a.exe", ".exe"))"

    Move-Item -Path $path -Destination $destination

    if ($file.DisplayName)
    {
        # Create a shortcut in the Start menu        
        $shortcut = $shell.CreateShortcut("$startMenuDirectoryPath\$($file.DisplayName).lnk")
        $shortcut.Description = $file.DisplayName
        $shortcut.TargetPath = $destination
        $shortcut.WorkingDirectory = $programFilesDirectoryPath
        $shortcut.Save()
    }

    if ($file.Registry)
    {
        # Ensure registry key exists
        $keyPath = "HKCU:\Software\Sysinternals\$($file.Registry.Key)"
        if (-not (Test-Path -Path $keyPath))
        {
            $_ = New-Item -Force -ItemType Directory -Path $keyPath
        }

        # Set registry values
        foreach ($entry in $file.Registry.Values.GetEnumerator())
        {
            $type = "DWord"
            $value = $entry.Value
            if ($value -is [bool])
            {
                $value = [int]$value
            }
            elseif ($value -is [string])
            {
                $type = "String"
            }

            Set-ItemProperty -Path $keyPath -Name $entry.Name -Value $value -Type $type
        }
    }

    if ($file.Ini)
    {
        # Ensure file exists
        $filePath = "$appDataDirectoryPath\$($file.Ini.File)"
        $_ = New-Item -Force -ItemType File -Path $filePath

        Set-Content -Path $filePath -Value "[General]"

        foreach ($entry in $file.Ini.Values.GetEnumerator())
        {
            Add-Content -Path $filePath -Value "$($entry.Key)=$($entry.Value)"
        }
    }
}

# Delete the remaining files and folder
Remove-Item -Force -Path $expandedDirectoryPath -Recurse

The script moves executable files to a directory in %ProgramFiles%, adds the path to that directory to the PATH environment variable, so that the command-line programs can easily be used in a Windows Command Processor or Windows PowerShell session, and adds shortcuts to the Start menu.

Sysinternals in the Windows 11 Start menu
Sysinternals in the Windows 11 Start menu

For each tool, the script makes changes to the Windows Registry as specified by its entry in $files. This can be used to adjust the settings for each tool. For example: most tools require acceptance of the end-user license agreement, which we accept by adding a value to the registry.

The GUI tools all have theming support, but only Process Explorer sets its theme automatically based on Windows' current them, so if you want to use a dark theme for the other GUI tools you will have to configure it. This is done using a registry value, except for TCPView and WinObj, which use a configuration file.

Summary

The Sysinternals tools are indispensable, but there is no installer, so we have to install each tool manually. Writing a script to automate this is not very difficult, and it has the added benefit that we can automate some of the settings for the tools as well.