Windows 10 Upgrade Tool

Upgrade to target build of Windows 10


I have accepted a position at a company that does
not use Kaseya. I no longer have access to the
platform, or the email attached to this account.
Anyone who wishes to take this code and build
upon it for your own tools, feel free to do so.

Upgrade any device running Windows Home or Pro (7, 8, 8.1, 10) to any target build of Windows 10.

• Windows x64 only
• P2P / Direct download methods
• Safety checks for free space, AC power, correct OS version and Bitlocker
• Caches Bitlocker recovery key to Kaseya prior to implementing
• Supports creation of "cache" instance on any target device which will permanently host an Aria2 instance to distribute files over LAN (only works with Hybrid P2P script)

**If this procedure fails, check the procedure logs, found at Agent>Agent Logs>Agent Admin Logs>Procedure History.**
**If this procedure succeeds, but 4 hours after running the target device is not on the target build, see the Windows Upgrade logs in C:/Temp/WinLogs**

This script makes use of the following software.
Aria 2 (Supports hybrid P2P downloading):
7 Zip (Zip / ISO extraction):
WinSW (Runs executable as a Windows service, used for Aria2 Cache):

Includes 3 procedures: cache, hybrid P2P download, and direct download.

Detects technology that would block p2p, and will failover to direct HTTP download. Obviously this negates the LAN caching features.

Can be updated to any build of 10 by simply replacing the target file URL's and the variable for target build.

6.21.19: 1.0.1 Added separate script that skips the usage of torrents altogether. Clarified notes and documentation. Added check for the term "core" in the OS identification to avoid false block on Windows home instances.

  • Name: Quinn Van Order
  • Company:
  • Website:
  • Contact Developer
  • Summary
  • Windows 10 Upgrade Tool
  • Version: 1.0.1
  • Released on June 12th, 2019
  • Reviews
    Gravatar for Jeffrey
    by Jeffrey on July 17th, 2019

    Works like a charm. I personally use the direct download via HTTP(S) version. Although it does not make use of LAN cache, it does work well with spotty connections.

    Gravatar for Sam James
    Sam James over 1 year ago

    Having a play with this now. I have my .torrent and .iso on sharepoint with a direct download link. 

    Whats the correct order in which to apply? In regards to the cache machine - do we do that last if that also needs updating? 

    Gravatar for Trung Ngo
    Trung Ngo over 1 year ago

    Do we need to do to do the Torrent part?

    Gravatar for Sam James
    Sam James over 1 year ago

    I don't think so (mine doesn't work) so it downloads from Http (sharepoint in my case) - its got the iso but then fails on other checks (not able to find the .iso when its there)

    Can anyone confirm it does work or is it a dev job? I had to add to check for the word "core" too as it was failing on the Home/Pro check - for some reason some windows 10 home were showing as core edition. 

    Gravatar for Quinn Van Order
    Quinn Van Order over 1 year ago

    Hey All,

    Thanks for your comments and feedback.

    @Sam: The cache procedure is designed to not necessarily be run against any workstation to upgrade. Our designed use case was to toss this at the backup servers we maintain at each client, as this is our hardware we lease out. Then you just toss the upgrade at any workstations. If the cache fails, or is not present, everything will continue to function but in a less efficient manner.

    @Trung: theoretically no, though I haven't tested it. Essentially you would want to delete lines 94, 100-108, and then bring lines 109 and 110 in one level of indentation. That kills the attempt to use a torrent at all.

    @Sam again: out of curiosity, what is the name of the ISO file. It occurs to me that this script is hardcoded to look for "#ROOT#\ISO\Windows.iso" as the value, so if its named something like "Windows 1809.iso" then that would fail the presence check.

    Beyond that, great catch on the "core" as a potential variable for home, totally missed that. I will update my script to reflect this, and clarify some of my documentation regarding order and intended use. Beyond that, I will see if I can just put a flag in place that overrides attempts to use torrents to make that easier.

    Gravatar for Quinn Van Order
    Quinn Van Order over 1 year ago


    New version just submitted, should be reviewed within the next 2 days. Includes fix for "Core" and a new script that completely avoids torrents, as well as some more clarified procedure descriptions. Let me know if you run into any other issues!

    Gravatar for Sam James
    Sam James about 1 year ago

    Importing doesn't seem to work - seems to have the wrong folder location in the .xml - I edited the location it would import to and it worked. Without doing so the Cache procedure does import correctly but the other two do not. Will test new version! 

    Gravatar for Sam James
    Sam James about 1 year ago

    I've had my first lot of successful updates thanks! However it does say using p2p mode but I get no torrent traffic. Can you clarify how the cache mode works - does it predownload the .iso and then distribute or does it do it only when another machine runs the p2p upgrade policy? It downloads my .torrent (I have hosted on a seedbox) but it seems no aria2 traffic on the cache host in task manager but each machine running the p2p procedure does have network activity making me think each machine is fetching its own .iso and not using the torrent? 

    Gravatar for Quinn Van Order
    Quinn Van Order about 1 year ago

    Can you clarify what you mean by wrong folder location?

    If you run resmon and point it at aria2 with p2p or direct you should see traffic, as either download method will use the same payload.

    As mentioned above, the cache mode is designed to be run against our servers in the same LAN. It creates a persistent Aria2 instance running as a service. (note that if you run resmon on a cache instance, you should see 2 different aria2 applications, only 1 of which is using network traffic) The cache procedure is designed to fully reinstall the cache instance every time it is run, so if you need to upload the payload you simply give the procedure a new torrent file, and re-run it to update what it is hosting.The cache is basically just a super lightweight torrent client in permanent seeder mode, so it will hand out packets whenever it is asked for them.

    If you are seeing no aria2 traffic, something is wrong. Does your procedure report success? What do the procedure logs have to say? Assuming torrents are wholly nonfunctional, you should see a massive single traffic connection to your direct download host. If torrents are functional, when you trace aria2, you should see a ton of different network connections, assuming you have a ton of caching instances.

    If you are only getting direct download behavior, its possible you have networking in place that blocks p2p. Beyond that, ensure you can DNS lookup your cache on LAN, and ensure your tracker is reachable. I had much better results when I created a personal tracker instance to coordinate p2p traffic than when using public trackers, but the complexity of setting up and maintaining a torrent tracker is a bit out of scope here. That said, as you know the word 'seedbox' you are clearly in the correct circles! The short version is we setup a uTorrent instance set to a persistent port in tracker mode, and setup the needed port-forwarding and DNS rules to allow this to function. We opted for a UDP tracker over a HTTP tracker.

    At a low level, it may be wise to manually try the downloads with aria2 prior to moving to procedures. Go to their github to pull the payload, and try doing a direct download with http:

    <Path to aria2 exe> <URL for direct download> --dir=<Directory to place download>

    Try doing a torrent only download:

    <Path to aria2 exe> -T <Path to Torrent File> --dir=<Directory to place download> --seed-time=0 --bt-enable-lpd=true --bt-external-ip=<External connection gateway>

    And then try doing a hybrid download:

    <Path to aria2 exe> -T <Path to Torrent File> <URL for direct download> --dir=<Directory to place download> --seed-time=0 --bt-enable-lpd=true --bt-external-ip=<External connection gateway>

    Gravatar for Sam James
    Sam James about 1 year ago

    Hey thanks for the reply.

    When I import the procedure .xml only the cache one successfully imports. The other two man procedures do not actually appear within the folders. I modified the XML to use the same folder as the cache procedure and they appeared correctly.

    Re: the torrent. I have an internal server machine in my workshop I have set to be cache. It has the aria2.exe running and it has an .iso file in the folder of the correct size (however this seems to appear instantly so not sure if its just a placeholder file to check for correct amount of space available?)

    Anyway, it seems that internally in my environment even though torrents can run it is still grabbing from WAN (download is capped at my WAN speed). Just to help me troubleshoot - when I run cache procedure on anything, the machine should download and unpack aria2 - do the usual checks and should it then download the .iso via the torrent and store in the aria2 folder? If I am seeing the Windows.iso file instantly something weird is going on?



    Gravatar for Sam James
    Sam James about 1 year ago

    Answered my own question - it does create a "placeholder" by default. That answers that. However it does look like torrents aren't working in my case. So each machine is just grabbing the HTTP by default. Need to figure out what is blocking it my end. 

    Is there anything you can script to detect the torrent on the cache not working? Ideas for expansion would be a removal script on both cache and the p2p updaters. Perhaps an email saying the cache has finished the pre-seed and you are ready to deploy (if everything is running on torrent I guess the machines on lan will all grab different bits so you don't necessarily need to preseed).

    Thanks for an impressive script 

    Gravatar for Sam James
    Sam James about 1 year ago

    So I ran the .torrent file in QBittorrent and it works flawlessly. So the issue lies in how Aria connects out and how Qbittorrent does it differently. Does Aria require ports open on the router whereas Qbittorrent uses UPnP perhaps?

    Gravatar for Quinn Van Order
    Quinn Van Order about 1 year ago

    Hey Sam,

    I will look into the xml paths and see if I cant clear that up, Kaseya exporting can be weird!

    Yes, as you found Aria2 pre-allocates space when downloading. This behavior can be overwritten with custom flags should you so desire, but I find its best to use default behavior there.

    As for detecting failure, the script will terminate should aria2 report any failure clause and log the cause. The problem you are running into is that aria2 is designed to be highly failure tolerant so while torrents are failing on LAN, it is able to resolve either using WAN torrent seeds, or WAN direct download sources.

    To be honest, this begins to run into the limits of my understanding of the torrent protocol, however I have seen DNS resolution failing to the seeder on LAN impact the ability to prioritize a LAN client. Aria2 has pretty exhaustive documentation on their github, so if you or anyone else on here have suggestions for alternate flags to use to improve LAN behavior, I would be all ears!

    As for ports, the hybrid and cache scripts opens 6881-6999 (tcp/udp bidirectional) while running, and removes said rules after the download completes. It is possible it would be helpful to open these on your firewall as well, though I have not tested this.

    As for the idea of a removal script, that is solid! I'll will whip that up shortly. However when you say "both cache and p2p updaters" what do you mean? If you are referring to the script that runs on workstations, should it succeed it wipes itself out other than the windows ISO components immediately prior to update. Do you want a script that just cleans out the ISO unpack directory? I considered having that happen automatically some 4 hours post execution of the upgrade script, however I opted not to with the reasoning that a technician may want to manually run through the upgrade GUI in the event of a failure to see any warnings and address them manually.

    It appears Aria2 does not support UPnP ( )

    Gravatar for Aleks Stolevski
    Aleks Stolevski about 1 year ago

    Can you run JUST the hyrbid script, or do you need to run "cache' script before running the hybrid script?  What would the Torrent URL be in the hybrid script?  (i.e. our public download location or the location on the "seed" server)


    Gravatar for Quinn Van Order
    Quinn Van Order about 1 year ago

    The purpose of the Cache script is to ensure there is an active seeder in LAN prior to running the upgrade. For a one off install, the benefit provided is minimal. The true value is if you plan on upgrading multiple devices, as this removes duplicate traffic on your WAN. You can indeed just run the hybrid script, it would then download over WAN, connecting to both the direct download and your torrent seeders as possible to acquire the file.

    As for “what would the torrent URL be in the hybrid script” the idea is to take your target ISO and upload it to any direct download provider such as DropBox, and to also create and host a torrent of the same file. Then you also upload that torrent file to the same direct download provider. The script then downloads the torrent file first, and then uses that and the URL to the direct download to initiate a hybrid download, one that uses the block level hashing of the torrent to verify file integrity.

    The true value of the Cache is for an MSP where you have hardware under your control at each network. If you cache across many devices, you end up with a very powerful set of seeders who can allow for extremely fast download speeds. If your use case is to have a single torrent seeder, there is little benefit to using the hybrid procedure versus the direct download one.

    Gravatar for Jeffrey
    Jeffrey about 1 year ago

    Amazing, thanks. A remark for other people using this - The language on the ISO must match the system locale. This is not the same as the Display Language. This could be checked on the client via the Powershell command "Get-WinSystemLocale". 

    Gravatar for Al Alper
    Al Alper about 1 year ago

    Used Direct Download; worked terrifically. A few notes, NOT issues:

    -Apparently it was attempted earlier by someone else on the team, WinLogs folder was empty. Found the 'attempted' txt file in the kworking dir.
    -'Last Exec Status' shows succeeded even tho it falied
    -no 'Completed' email
    -initial review and cannot determine how long the process started

    Will continue to poke around for more info and will test other variants (Hybrid and Cache)

    Gravatar for Thomas Withey
    Thomas Withey about 1 year ago

    Does this require the pc to be logged in?

    Gravatar for Juan Sanchez
    Juan Sanchez about 1 year ago

    Hi Al Alper,

    do you mind sharing what the XML file looks like for this that work for you? are you trying uploading this file to a Dropbox...?

    Gravatar for Quinn Van Order
    Quinn Van Order about 1 year ago

    Hey all, general note here: I have accepted a position elsewhere, and wont be able to have access to a Kaseya system for much longer. I will be working on a final release that includes cleanup tools (for instance to wipe out the installer files after success or to remove the "attempted" file)

    I will update the procedure description on my last day to indicate it is no longer being supported. That said, with some minor tinkering this should work moving forward on its own.

    Gravatar for Al Alper
    Al Alper about 1 year ago

    @Juan...We use our own sharefile link. Here's our link

    Gravatar for Juan Sanchez
    Juan Sanchez about 1 year ago

    @Al Alper, Unfortunately the ISO never downloads not sure where to from here. I thoughts?