Keep in-sync with SysInternals tools

September 6, 2008


As you already know, all SysInternals utilities are available as a file share. Meaning you can run the tools directly from the Internet (e.g$\<toolName>), navigate to them with your browser or even map a drive on your local computer.

The SysInternals tools suite is a must have on any sysadmin machine. On my computer I keep them in a special directory (c:\sysint). From time to time the tools get updated or new tools get published and you might not know when it happens.

This is where Get-SysInternals comes into place. It lists the file share and compares each file’s last modified date to the corresponding file on the local directory (if exists). If the ‘live’ file is newer, it is copied to the local directory and a yellow message in echoed to the console, new tools are painted in green. A log file is also generated into the specified directory by the name of changes.log.

At first I thought to compare the utilities file version info, but as you can see from the below, not all files have a version so I used the last modified date (lastWriteTime) instead.

PS > dir \\\Tools -filter *.exe | select -expand vrsionInfo | ft @{l=”Name”;e={split-path $_.fileName -leaf}},FileVersion -auto

Name FileVersion
—- ———–
accesschk.exe 4.20
AccessEnum.exe 1.32
ADExplorer.exe 1.01
ADInsight.exe 1.01
Autologon.exe 2.10
autoruns.exe 9.33
autorunsc.exe 9.33
Bginfo.exe 4, 14, 0, 0
Contig.exe 1.54
Dbgview.exe 4.75
Desktops.exe 1.00
diskext.exe 1.1
Diskmon.exe 2.01
du.exe 1.31
Filemon.exe 7.04
handle.exe 3.41

The default local destination directory for the files is ‘c:\sysint’ and it will be created automatically if it doesn’t exist. If you want another directory of your choice then simply run it like so: ‘Get-SysInternals D:\otherDirName’  

function Get-SysInternals {

param ( $sysIntDir=”c:\sysint” )

if(!(Test-Path -Path $sysIntDir -PathType Container))
$null = New-Item -Type Directory -Path $sysIntDir -Force

$log = join-path $sysIntDir “changes.log”
Add-Content -force $log -value “`n`n[$(get-date)]SysInternals sync has been started”

dir \\\tools -recurse | foreach {

$fileName = $
$localFile = join-path $sysIntDir $
$exist = test-path $localFile

$msgNew = “new utility found: $fileName , downloading…”
$msgUpdate = “file : $fileName is newer, updating…”
$msgNoChange = “nothing changed for: $fileName”


if($_.lastWriteTime -gt (Get-Item $localFile).lastWriteTime)
Copy-Item $_.fullname $sysIntDir -force
Write-Host $msgUpdate -fore yellow
Add-Content -force $log -value $msgUpdate
Add-Content $log -force -value $msgNoChange
Write-Host $msgNoChange
if($_.extension -eq “.exe”)
Write-Host $msgNew -fore green
Add-Content -force $log -value $msgNew

Copy-Item $_.fullname $sysIntDir -force


And a sample output

PS > Get-SysInternals

File: accesschk.exe is newer, updating…
File: AccessEnum.exe is newer, updating…

New utility found: accvio.EXE, downloading…
File: AdExplorer.chm is newer, updating…
File: ADExplorer.exe is newer, updating…
File: ADInsight.chm is newer, updating…
File: ADInsight.exe is newer, updating…
File: adrestore.exe is newer, updating…
File: Autologon.exe is newer, updating…
File: autoruns.chm is newer, updating…
File: autoruns.exe is newer, updating…
File: autorunsc.exe is newer, updating…
File: Bginfo.exe is newer, updating…
File: Cacheset.exe is newer, updating…
File: Clockres.exe is newer, updating…
File: Contig.exe is newer, updating…
File: ctrl2cap.amd.sys is newer, updating…
File: ctrl2cap.exe is newer, updating…
File: ctrl2cap.nt4.sys is newer, updating…
File: ctrl2cap.nt5.sys is newer, updating…
File: dbgview.chm is newer, updating…
File: Dbgview.exe is newer, updating…

New utility found: DEFRAG.EXE, downloading…
New utility found: Desktops.exe, downloading…

File: diskext.exe is newer, updating…
File: Diskmnt.exe is newer, updating…
File: Diskmnt.hlp is newer, updating…
File: Diskmon.exe is newer, updating…

Now all that is left to do is run it once in a while (I run it on every Sunday) and see if there were any changes to the live share. This is what I use to *schedule* it, put it in your PowerShell profile and wait for next Sunday ;-):

if( (get-date -f dddd) -eq “sunday”) { Get-SysInternals }

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>



  1. Vegard HSeptember 8, 2008 讘 05:13

    Thank you very much 馃檪

    This will make it a LOT! easier to keep updated.

  2. LooserSeptember 9, 2008 讘 04:25

    I did something similar with robocopy as a oneliner.

  3. Aaron PerraultSeptember 22, 2008 讘 17:24

    For some reason, i cannot get this to run. I have copied the above script and saved it as get-sysinternals.ps1 but when i run it, either from PS v2 CTP or from PowerGui or even PrimalScript, all it gives me is a messages:

    PowerShell Script Finished

    But it doesnt create the folder, nor does it download the files. Do i need to have something in that folder to begin with?

    thanks much


  4. ScriptFanaticSeptember 22, 2008 讘 17:49

    Hi Aaron,

    You can copy the function as is into your $profile, restart powershell and call the function from the console:

    PS > Get-SysInternals

    Or with its parameter:

    PS > Get-SysInternals -sysIntDir=”d:\foo”

    You can also paste the function into a ps1 file and dot-source it:

    # it the script is in the working directory

    PS > . .\Get-SysInternals.ps1

    # or with the full path to the file

    PS > . c:\scripts\Get-SysInternals.ps1

    Now you can call it the same way as above.

    Another option is to remove the ‘function Get-SysInternals {‘ line and the last ‘}’ (e.g at the bottom of the script), save it to a ps1 file

    and call it like so:

    PS > .\Get_SysInternals.ps1 -sysIntDir=”d:\foo”


  5. cobeFebruary 5, 2009 讘 18:39

    Why not simply

    cmd /c robocopy \\\tools c:\YOURPATH

    as a scheduled task ??

  6. ScriptFanaticFebruary 5, 2009 讘 19:00

    Because I’m a PowerShell guy 馃槈

  7. Lars-UTDecember 16, 2009 讘 02:00

    What about machines that have never previously had the sysinternals tools run? Do you use a script to set the registry properties for the EULA?

    It’s no fun when you’re running remote console commands that call a GUI EULA prompt before they can execute.

  8. ScriptFanaticDecember 16, 2009 讘 10:25

    You can run the tools with the /accepteula switch to bypass the eula dialog.

  9. AjorgeDecember 9, 2010 讘 02:07

    It麓s a great idea.

    You can also schedule the execution of the ps file.

  10. ajhJuly 10, 2011 讘 08:51

    I continually get this error everytime i run the function using pwoershell or robocopy \\… etc

    PS C:\> Get-SysInternals
    Get-ChildItem : Cannot find path ‘\\\Tools’ because it does not exist.

  11. ScriptFanaticJuly 12, 2011 讘 12:12


    Few things you should check:

    1. Does it work from cmd.exe?

    CMD > dir \\\Tools

    2. Make sure the WebClient is running.

    3. Is there a firewall (anti-virus software) in between that mught be blocking traffic?

    4. File and Printer Sharing Does Not Work (

  12. PenraAugust 18, 2011 讘 00:17

    This would be sweet to add to group policy for application on every server in the datacenter.