Search Unity

SimplePatchTool - open source patching solution for standalone platforms

Discussion in 'Assets and Asset Store' started by yasirkula, Jul 26, 2018.

  1. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    NOTICE: THIS PROJECT IS NO LONGER MAINTAINED.

    Hi there,

    So, I've been working on this project for a very long time and I'm now happy to announce that it is finally released! SimplePatchTool is a C# library for patching standalone applications with binary diff and self patching support.

    Asset Store: https://assetstore.unity.com/packages/tools/network/simple-patch-tool-124296
    Also available at: https://github.com/yasirkula/UnitySimplePatchTool
    Discord: https://discord.gg/UJJt549AaV
    Wiki: https://github.com/yasirkula/UnitySimplePatchTool/wiki
    Support the developer ☕

    FEATURES
    • written completely in C#
    • supports repair patching as well as binary diff patching
    • gives you complete control over where the patch files are stored (you can even host your files on Google Drive™)
    • supports self patching (e.g. launcher patching itself)
    • does not request admin permissions unless necessary
    • supports encrypting/signing important patch files as an additional layer of security
    Currently, this library is only tested on a 64-bit Windows 10 installment. Please note that SimplePatchTool is not yet battle tested thoroughly, so you may encounter unknown issues while integrating it into your projects. Don't hesitate to open an Issue on GitHub when you encounter one!

    Enjoy!







    NOTICE: THIS PROJECT IS NO LONGER MAINTAINED.
     
    Last edited: Oct 28, 2021
    Rotary-Heart, mgear, Mauri and 3 others like this.
  2. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Now live on Asset Store!
     
    hopeful likes this.
  3. Joey_pc

    Joey_pc

    Joined:
    Jul 5, 2015
    Posts:
    2
    any videos Seems to be Lost
    I need To Make Self Updating Lancher
     
  4. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    A written tutorial for self patching apps is available at: https://github.com/yasirkula/UnitySimplePatchTool#examples

    Although patching another app (launcher logic) is very similar to self patching an app (the major difference is to call the patcher.Run function with parameter false), I do plan to add a tutorial for launchers, as well. In the meantime, feel free to ask any questions you have.
     
  5. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    hopeful likes this.
  6. Jayme65

    Jayme65

    Joined:
    Dec 11, 2016
    Posts:
    94
    Thanks so much for offering this patcher free to the community!
    I test it right now!
     
    yasirkula likes this.
  7. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    You are welcome! Let me know if you get stuck at a point.
     
  8. ExpensiveKoala

    ExpensiveKoala

    Joined:
    Sep 20, 2018
    Posts:
    2
    I'm trying to use your SimplePatchTool for a project, but I'm not really understanding how the different files correspond to each other. What exactly goes in the VersionInfo.info file? It's also not really clear how the patches are referenced. Are they referenced in the VersionInfo.info file?

    I'm trying to write a stand-alone application with WPF for this and it's a bit confusing how the different files are supposed to be set up.
    It would help a lot if you had an example somewhere.
     
  9. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    VersionInfo is the heart of the system. Metadata (download links, filesizes, hashes) about all the files in the version as well as metadata about all the incremental patches are stored there; open it with Notepad and you will see. Detailed information about each incremental patch is stored in a separate file called PatchInfo (named version1_version2.info). Before applying an incremental patch, SimplePatchTool downloads the corresponding PatchInfo via the download link found in VersionInfo.

    Basically, you upload all the generated patch files to the server of your choice, update the download links in VersionInfo and then reupload the updated VersionInfo to the server. At runtime, your WPF app downloads VersionInfo from the server, checks for updates and downloads any necessary files via the download links in the VersionInfo, if there is an update.

    Detailed information about all these steps can be found at: https://github.com/yasirkula/SimplePatchTool/wiki. Please let me know if you get stuck at a point so that I can clarify that point.
     
  10. hopeful

    hopeful

    Joined:
    Nov 20, 2013
    Posts:
    5,686
    I agree that the little details and overall concepts on these things can be a bit confusing. A tiny example with like two versions might be helpful.
     
  11. ExpensiveKoala

    ExpensiveKoala

    Joined:
    Sep 20, 2018
    Posts:
    2
    Thanks for the response. I think I understand it now.

    Can I request for a method in PatchUpdater that's the equivalent of UpdateDownloadLinks( string downloadLinksPath ), but by passing in your own Dictionary?


    Also, does this only do incremental patches? Are all repair patches incremental patches? The way the glossary is worded makes it seem like they are two different types of patches. The repair being one that is just a binary containing the update and incremental being a binary of the diff...

    Thanks for this library. It's saved me hours upon hours of work.
     
    Last edited: Sep 21, 2018
  12. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    @hopeful I'll try to create a simple example, thank you for the feedback.

    @ExpensiveKoala Will add the requested method in the next update. Repair patch checks each file one by one and downloads each out-of-date file from the server. There is only one repair patch. Incremental patch stores the changes between two versions of the app, e.g. from version 1.0 to version 1.1. There can be multiple incremental patches, e.g. 1.0->1.1 and 1.1->1.2. Incremental patches are usually cheaper (sometimes much cheaper) than repair patch.
     
    hopeful likes this.
  13. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    @ExpensiveKoala The requested function is now available at the GitHub repository. I've also tried to clarify some of the confusing parts of the wiki. I'll see what else I can do.
     
    hopeful likes this.
  14. duartedd

    duartedd

    Joined:
    Aug 1, 2017
    Posts:
    150
    Hello
    thanks for doing stuff like this!

    I am looking to use this tool for mobile to not only patch a game when i need to but also on first install load the majority of assets like in an asset bundle - can this be done with this? From the tutorial it mentions changing the scene objects and im going to be changing multiple scene info and adding removing assets from the asset bundles /etc

    im just trying to piece it altogether

    create assetbundles and remove them from the game (Scene/Scripts/sprites/prefabs/and all except for the first scene which ill just make a patcher Scene First which calls the simple patch tool then load the next scene which would be another loader scene )
    build game with simple patch tool - v1.0 - publish to play store or w.e
    add asset bundles and scripts and all other scenes - v1.1

    then it should patch?

    This would mean that basically that the game would basically be crap all except a dumb scene maybe a logo or something and the patcher UI prefab and a scenemanager probably and then it downloads EVERYTHING else - (actually this would be an easy thing to code and be a very basic script for ANY project)

    the question is if someone has v1.0 and im on v5.0 will the patch tool be able to update that persons client? if i do incremental patches i dont think it will cause as you state in the tutorial you remove the previous patch files. Which means i would have to do a repair patch for ALL patches just in case someone isnt going from v1.0 to v1.2....know what i mean - let me know your thoughts and if i am totally wrong on this one

    thanks again!
     
  15. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    @duartedd The only big issue here is that, SimplePatchTool supports only standalone platforms, so you can't use it on mobile platforms. But if it was a standalone platform, you could patch the app from any version to the latest version with repair patch (SimplePatchTool uses repair patch automatically if incremental patches don't/can't patch the application to the latest version).
     
  16. BlueTera

    BlueTera

    Joined:
    Jul 19, 2018
    Posts:
    25
    I dont understand how i can get the patcher thing
     
  17. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
  18. BlueTera

    BlueTera

    Joined:
    Jul 19, 2018
    Posts:
    25
    The thing is i cant find the PatchBuilder thing
     
  19. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    You may have to add
    using SimplePatchToolCore;
    to your script(s). To create patches, you can use the Window-Simple Patch Tool window for ease.
     
  20. c-pellet

    c-pellet

    Joined:
    Mar 24, 2018
    Posts:
    3
    Hello, I'm trying the Launcher demo and the patches succeed but I can't download the patches as it throws downloaded file [...] is corrupt. Anyone having the same issue?
     
  21. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Can I see the contents of your VersionInfo? You can PM it to me, if you like.
     
  22. c-pellet

    c-pellet

    Joined:
    Mar 24, 2018
    Posts:
    3
  23. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    When I attempt to download a patch file, it returns 403 forbidden page. Most probably, you forgot to make the parent directory public in Drive. To do so, right click the root directory that holds all the patch files in Drive and select "Get shareable link".
     
  24. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Your VersionInfo is public and is indeed accessible by SimplePatchTool. The patch files, however, are not public. Try clicking one of those download links while you are not logged into your Drive account; it will result in an error page. Most probably, SimplePatchTool downloads that error page while attempting to download a patch file and, surely, downloaded thing's filesize and/or md5 hash don't match the actual values of the file.

    The recommended solution should resolve this issue. It is also mentioned in step A.1.2 at the wiki: https://github.com/yasirkula/SimplePatchTool/wiki/Hosting-Patch-Files#a-google-drive

    P.S. It would be nice if you could truncate your last message :)
     
    Last edited: Nov 5, 2018
  25. BlueTera

    BlueTera

    Joined:
    Jul 19, 2018
    Posts:
    25
    I dont understand the tutorial on the Wiki thing.. :( so i cant understand it could be cool if someone made a video with the
    LauncherDemo becuse thats the one i tryed to use.
     
  26. jgconv

    jgconv

    Joined:
    Nov 8, 2018
    Posts:
    2
    Is it possible to host the patch files on a private server, behind a login?
     
    CloudyVR likes this.
  27. kingbdogz95

    kingbdogz95

    Joined:
    Apr 23, 2017
    Posts:
    4
    Hi I've found that when my game self-patches, it downloads the contents and then the game restarts with the Restart button, but then when the console appears for SelfPatcher.exe, this comes up:


    Code (CSharp):
    1. Updating from v2.0, please don't close this window!
    2. ERROR: System.IO.IOException: Source and destination path must have identical roots. Move will not work across volumes.
    3.   at System.IO.Directory.Move(String sourceDirName, String destDirName)
    4.   at SimplePatchToolSelfPatcher.Program.MoveFiles(String from, String to)
    5.   at SimplePatchToolSelfPatcher.Program.Main(String[] args)
    It seems to be a problem with using Directory.Move instead of copying over and deleting old files. I'm not sure if there's a way to solve this?

    Even if the SelfPatcher executable was fixed - am I kinda screwed since the broken exe is on everyone's downloaded builds? Or if I created a patch with a new SelfPatcher, it would use the new, fixed version?
     
  28. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    @BlueTera I'm looking for ways to clarify the whole patching process; I'll see what I can do.

    @jgconv You can copy the contents of CookieAwareWebClient to a new script (let's say MyWebClient), change MyWebClient as you wish to support downloading files from a private server and call
    UseCustomDownloadHandler( () => new MyWebClient() )
    on your SimplePatchTool object to instruct SimplePatchTool to use MyWebClient for downloading files.

    @kingbdogz95 If your self patcher files reside in a subdirectory called SPPatcher in your build (which is the case by default), creating a new patch with an updated self patcher will resolve the issue, yes. I'll try to fix this self patcher issue as soon as possible. Sorry for the inconvenience and thanks for reporting this issue :)
     
  29. jgconv

    jgconv

    Joined:
    Nov 8, 2018
    Posts:
    2
    That's great! Thanks for the tool and the help!
     
  30. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
  31. kingbdogz95

    kingbdogz95

    Joined:
    Apr 23, 2017
    Posts:
    4
    @yasirkula thank you! Some people have already downloaded the patch with the broken SPPatcher, should I be creating a new version patch or should I be uploading a fixed build of the current version they have downloaded?
     
  32. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    If you are using
    CheckForUpdates(false)
    to check for updates or are simply using
    Run()
    /
    Run(true)
    (i.e. not using CheckForUpdates at all), you can upload a fixed build of the current version; these functions check each file in the application directory to see if a file has changed, so they should detect this change.

    It'd also be fine if you create a new version patch and it would be the only solution if you are using
    CheckForUpdates(true)
    to check for updates.

    P.S. After creating a fixed build of the current version, the filesize/hash of the self patcher will be different than before. So don't forget to upload the new VersionInfo to the server, as well.
     
  33. kingbdogz95

    kingbdogz95

    Joined:
    Apr 23, 2017
    Posts:
    4
    Hi! Thank you so much @yasirkula, your update to SPPatcher fixed the issues. You have been very helpful which I must commend you for!

    Just wanted to open up a discussion and ask a question, as well as maybe a suggestion. I've found that a lot of sharedassets files in our game are quite large (upward of 400mb), and simply changing one thing in that scene will cause the patcher to redownload the updated file of that one sharedassets.

    Do you know of a way to split up the sharedassets files? Or, better yet, allow SPPatcher to only update the relevant modified bytes of that file. That way a small update to a 400mb sharedassets file will only be 1mb at most.

    This is a big problem for us right now as we would like to deploy frequent patches to address recent bugs, but it is difficult to ask our users to continue downloading such big patches for such small changes.
     
    yasirkula likes this.
  34. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    That's what incremental patches are useful for. They contain the binary diff'es of the changed files in that patch and are usually very small for such minor changes.

    To create an incremental patch, you should provide a "Previous version path:" while creating the patch (e.g. for a 1.0->1.1 patch, it should point it to the 1.0 version of the app). Finally, you should allow your SimplePatchTool to use incremental patches via the
    UseIncrementalPatch(true)
    function.
     
    hopeful likes this.
  35. atomicpang123abc

    atomicpang123abc

    Joined:
    Apr 12, 2013
    Posts:
    15
    Hi yasirkula, i'm Michael - the lead developer of kingbdogz team for our project.
    One of our players recently encountered this error when restarting from downloading the latest patch and we've never seen it before.

    Code (CSharp):
    1. ERROR: System.Invalid/Operation Exception : Invoke or BeginInvoke cannot be called on a control until the wondow handle has been created.
    I was wondering if you knew what this error means and how to solve the issue for that player?
     
  36. kingbdogz95

    kingbdogz95

    Joined:
    Apr 23, 2017
    Posts:
    4
    Ahh @yasirkula I was not aware the incremental patches worked through binary diffs. My bad.

    I will say, however, I've noticed that despite setting UseIncrementalPatch() to true (since the very first version), incremental patches only initiate a small percentage of the time. Most times it ends up just downloading each individual file through what I imagine is the repair files. I'm not sure why it only appears some times and not others.
     
  37. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    @atomicpang123abc It looks like an issue with the self patcher executable. I'll try to come up with a solution as soon as possible.

    @kingbdogz95 After a patch is completed (downloaded&processed) but before the self patcher executable is started, can you upload the logs.dat file located at
    AppData\Local\SimplePatchToolDls\{ProjectName}
    to here? You can change its extension to .txt, if Unity forums don't accept .dat attachments.
     
  38. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    @atomicpang123abc I've pushed a bugfix to the GitHub repository. I recommend you to create a new version of your app after updating your SimplePatchTool as soon as you can because due to a rare case that I didn't see or predict before, users that encounter that issue may no longer update their apps to newer versions. I've fixed that rare case in this update as well but am not sure how users encountering that issue can update their apps now because I haven't anticipated this scenario before. Let me know if I can be of any help in this case and sorry for the inconvenience.

    P.S. I mean, it is possible to resolve this issue by manually deleting the *_vers.sptv file located at the installation directory but as you can see, it requires manual intervention. Though, it may also be possible that the self patcher will continue working properly after a few trials.
     
    Last edited: Nov 19, 2018
  39. NyanHeavy

    NyanHeavy

    Joined:
    Dec 14, 2017
    Posts:
    8
    I honestly do not understand how to start using this asset, I think it would be very important a video showing how to start

    I get this error when trying to create a patch

    Code (CSharp):
    1. System.IO.IOException: Sharing violation on path C:\Arquivos\Projetos\MonoLowPoly\Library\ShaderCache.db
    2.   at System.IO.FileStream..ctor (System.String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, Boolean anonymous, FileOptions options) [0x00251] in /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.IO/FileStream.cs:320
    3.   at System.IO.FileStream..ctor (System.String path, FileMode mode, FileAccess access, FileShare share) [0x00000] in <filename unknown>:0
    4.   at (wrapper remoting-invoke-with-check) System.IO.FileStream:.ctor (string,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare)
    5.   at System.IO.File.OpenRead (System.String path) [0x00000] in /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.IO/File.cs:363
    6.   at SimplePatchToolCore.PatchUtils.Md5Hash (System.IO.FileInfo fileInfo) [0x00000] in <filename unknown>:0
    7.   at SimplePatchToolCore.VersionItem..ctor (System.String relativePath, System.IO.FileInfo item) [0x00000] in <filename unknown>:0
    8.   at SimplePatchToolCore.PatchCreator.AddFilesToPatchRecursively (System.IO.DirectoryInfo directory, System.String relativePath) [0x00000] in <filename unknown>:0
    9.   at SimplePatchToolCore.PatchCreator.AddFilesToPatchRecursively (System.IO.DirectoryInfo directory, System.String relativePath) [0x00000] in <filename unknown>:0
    10.   at SimplePatchToolCore.PatchCreator.CreateFileList () [0x00000] in <filename unknown>:0
    11.   at SimplePatchToolCore.PatchCreator.CreatePatch () [0x00000] in <filename unknown>:0
    12.   at SimplePatchToolCore.PatchCreator.ThreadCreatePatchFunction () [0x00000] in <filename unknown>:0
    13. UnityEngine.Debug:Log(Object)
    14. SimplePatchToolUnity.PatcherEditor:OnUpdate() (at Assets/Plugins/SimplePatchTool/Editor/PatcherEditor.cs:235)
    15. UnityEditor.EditorApplication:Internal_CallUpdateFunctions()
    16.  
     
  40. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Did you see the step-by-step guides here: https://github.com/yasirkula/UnitySimplePatchTool

    I'd recommend you to start with the SelfPatchingAppDemo example scene.

    P.S. I'm continuously improving the documentation with your feedback, so it will get better and better over time.
     
  41. jedavis13579

    jedavis13579

    Joined:
    Sep 12, 2018
    Posts:
    4
    I'm following the step-by-step guides for the launcher demo and when I get to the step for creating my first patch this always comes up.

    upload_2018-12-1_17-43-49.png

    Judging by the path in the Error Message: it is ending the path with \https: rather than going to the LauncherBuild directory as it is setup to do. Any idea what could be happening?

    UPDATE: I found out that my issue was that I had my google drive link to a directory in the Output field (thinking i could directly create it there) but I was supposed to instead have an empty local directory selected that I could then copy over to host on the drive. I do have a new problem however which is that I can run the launcher after deleting something in Mono\etc as the tutorial states to test it and the SelfPatcher will display that a new version is available, however when I click Update Now I get ERROR: Mono\etc\mono\config could not be downloaded.
     
    Last edited: Dec 2, 2018
  42. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
  43. jedavis13579

    jedavis13579

    Joined:
    Sep 12, 2018
    Posts:
    4
    Yes I made the PatchFilesServer directory on my Drive public.

    I did attempt to update the download links in the VersionInfo before replacing the dummy one but I'm not 100% sure I did that one correct. It wasn't clear to me if I was supposed to put the link to the VersionInfo file or the link to the PatchFilesServer in the download links field before telling it to update the download links.

    This is how I did it. The link in the download links section is to my PatchFilesServer. Is the done correctly?
    upload_2018-12-2_9-21-36.png
     
  44. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
  45. jedavis13579

    jedavis13579

    Joined:
    Sep 12, 2018
    Posts:
    4
    Thank you so much for the quick replies. I understand why the downloads were failing now. So I have linked the DownloadLinkGenerator to my drive as instructed, got the shareable link on the patch directory, and right clicked to open with DownloadLinkGenerator. Now I'm on the page for it saying pleas wait... it's been processing for about 30 minutes to an hour. Is that normal?
     
  46. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    No, the status should've changed to "finished" in no more than a minute. Can you try opening the patch directory with Download Link Generator again? If the status doesn't change again, check if the browser's developer console has any error messages. You can also try using a different browser to see if it changes anything.
     
  47. jedavis13579

    jedavis13579

    Joined:
    Sep 12, 2018
    Posts:
    4
    Switching from Chrome to Edge worked.

    The patcher is working just as expected! Now that I understand the setup I will go back and get the Launcher demo working. Once I have done so, with your permission as the creator, I would like to utilize this launcher/patcher in our game that we are developing. It's a ways off from release yet but we are passionate about making it.

    Thanks for this great asset and for the awesome and responsive support.
     
    AthrunVLokiz, hopeful and yasirkula like this.
  48. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Of course, feel free to use it in your own projects :)
     
    NyanHeavy, jedavis13579 and hopeful like this.
  49. NyanHeavy

    NyanHeavy

    Joined:
    Dec 14, 2017
    Posts:
    8
    even following the steps of the wiki, I still can not use, not even make the first patch, I still get the same error!
     
  50. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Can I see how Window-Simple Patch Tool looks before it yields the error?