Community
    • Login

    Upgrading notepad++ with one click.

    Scheduled Pinned Locked Moved Notepad++ & Plugin Development
    14 Posts 5 Posters 4.2k Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • mkupperM
      mkupper @Oliver Maag
      last edited by

      @Oliver-Maag said in Upgrading notepad++ with one click.:

      Hi
      Often when I start notepad++ it asks to upgrade to the latest version. And I always have to answer the same questions again…
      Would it be possible to get a one click upgrade?

      While a one click upgrade is technically possible it would require adding components to Notepad++ that are very much against against the existing practice of keeping the application as lightweight as possible in terms of system resources used.

      If you rarely use Notepad++ then you may be ok with disabling the check for updates and instead doing manual checks for updates. There are a couple of ways to do this. The next time you get the “Update available” prompt then click the [Never] button. Or, under Settings / Preferences / MISC. you can uncheck the Enable Notepad++ auto-updater configuration setting.

      1 Reply Last reply Reply Quote 5
      • mpheathM
        mpheath @Oliver Maag
        last edited by

        @Oliver-Maag Pass the /S argument to the installer with PythonScript to make the install silent.

        # https://community.notepad-plus-plus.org/topic/23039/faq-how-to-install-and-run-a-script-in-pythonscript
        # https://community.notepad-plus-plus.org/topic/25817/upgrading-notepad-with-one-click
        from Npp import notepad, MENUCOMMAND
        
        import os, subprocess, tempfile
        import xml.etree.ElementTree
        
        if sys.version_info.major == 2:
            import urllib
            import urllib2
            urllib.request = urllib
        else:
            import urllib.request
        
        
        def main():
            # Check for update
            version = notepad.getVersion()
            version = '.'.join(str(i) for i in version)
        
            url = 'https://notepad-plus-plus.org/update/getDownloadUrl.php?version=' + version
        
            if sys.version_info.major == 2:
                r = urllib2.urlopen(url)
                content = r.read().decode('utf-8')
            else:
                with urllib.request.urlopen(url) as r:
                    content = r.read().decode('utf-8')
        
            dic = {'NeedToBeUpdated': 'no', 'Version': '', 'Location': ''}
        
            root = xml.etree.ElementTree.fromstring(content)
        
            for child in root:
                if child.tag in dic:
                    dic[child.tag] = child.text
        
            if dic['NeedToBeUpdated'] == 'yes':
                reply = notepad.messageBox('Update to Notepad++ v' + dic['Version'],
                                           'NppUpdate',
                                           MESSAGEBOXFLAGS.ICONQUESTION|
                                           MESSAGEBOXFLAGS.YESNO|
                                           MESSAGEBOXFLAGS.DEFBUTTON2)
        
                if reply == MESSAGEBOXFLAGS.RESULTNO:
                    return
            else:
                notepad.messageBox('No update', 'NppUpdate')
                return
        
            # Download and install
            tempDir = tempfile.mkdtemp(prefix='NppUpdate_')
        
            installerName = dic['Location'].split('/')[-1]
            installerPath = os.path.join(tempDir, installerName)
            urllib.request.urlretrieve(dic['Location'], installerPath)
        
            command = ('ping -n 6 localhost&'
                       '"{}" /S&'
                       'rd /s /q "{}"').format(installerPath, tempDir)
        
            subprocess.Popen(command, shell=True)
            notepad.menuCommand(MENUCOMMAND.FILE_EXIT)
        
        main()
        

        Suggest to disable builtin auto updater as @mkupper mentions. Run this script every month or two to check for new version and update Notepad++ if a newer version exists.

        It will check the version, if update is yes, download the new installer, it will exit Notepad++, wait 5 seconds and then run the installer with argument /S to install silently.

        If your happy with the default options for installation then a silent install might be suitable. If option selection is preferred, then silent install may not be a good option.

        Tested the script with PythonScript 2.0 and 3.0.18.

        1 Reply Last reply Reply Quote 3
        • mpheathM mpheath referenced this topic on
        • mpheathM
          mpheath @Oliver Maag
          last edited by

          The script I posted previous downloads x86 installer. Seems GUP.exe does some kind of get/post messages to the server to get the x64 installer. The changes to the new script will check notepad.exe if x86 or x64 (not arm, arm64 as I cannot test these installers) and will modify the installer name to download.

          If anyone installed Notepad++ with the previous script expecting x64, I am sorry for the event.

          from Npp import notepad, MENUCOMMAND
          
          import os, subprocess, tempfile
          import xml.etree.ElementTree
          
          if sys.version_info.major == 2:
              import urllib
              import urllib2
              urllib.request = urllib
          else:
              import urllib.request
          
          
          def main():
              def getExeBitness(file):
                  with open(file, 'rb') as r:
                      pos = r.read(1024).find(b'PE')
                      r.seek(pos + 4, 0)
                      char = r.read(1)
          
                  if char == b'd':
                      return 'x64'
                  elif char == b'L':
                      return 'x86'
          
              # Check for update
              version = notepad.getVersion()
              version = '.'.join(str(i) for i in version)
          
              url = 'https://notepad-plus-plus.org/update/getDownloadUrl.php?version=' + version
          
              if sys.version_info.major == 2:
                  r = urllib2.urlopen(url)
                  content = r.read().decode('utf-8')
              else:
                  with urllib.request.urlopen(url) as r:
                      content = r.read().decode('utf-8')
          
              dic = {'NeedToBeUpdated': 'no', 'Version': '', 'Location': ''}
          
              root = xml.etree.ElementTree.fromstring(content)
          
              for child in root:
                  if child.tag in dic:
                      dic[child.tag] = child.text
          
              if dic['NeedToBeUpdated'] == 'yes':
                  reply = notepad.messageBox('Update to Notepad++ v' + dic['Version'],
                                             'NppUpdate',
                                             MESSAGEBOXFLAGS.ICONQUESTION|
                                             MESSAGEBOXFLAGS.YESNO|
                                             MESSAGEBOXFLAGS.DEFBUTTON2)
          
                  if reply == MESSAGEBOXFLAGS.RESULTNO:
                      return
              else:
                  notepad.messageBox('No update', 'NppUpdate')
                  return
          
              # Get bitness.
              nppPath = os.path.join(notepad.getNppDir(), 'notepad++.exe')
              nppBitness = getExeBitness(nppPath)
          
              if not nppBitness:
                  notepad.messageBox('Notepad++.exe get bitness failed', 'NppUpdate')
                  return
          
              if nppBitness == 'x64':
                  dic['Location'] = dic['Location'].replace('er.exe', 'er.x64.exe')
          
              # Download and install
              tempDir = tempfile.mkdtemp(prefix='NppUpdate_')
          
              installerName = dic['Location'].split('/')[-1]
              installerPath = os.path.join(tempDir, installerName)
              urllib.request.urlretrieve(dic['Location'], installerPath)
          
              command = ('ping -n 6 localhost&'
                         '"{}" /S&'
                         'rd /s /q "{}"').format(installerPath, tempDir)
          
              subprocess.Popen(command, shell=True)
              notepad.menuCommand(MENUCOMMAND.FILE_EXIT)
          
          main()
          
          mkupperM 1 Reply Last reply Reply Quote 3
          • mkupperM
            mkupper @mpheath
            last edited by

            @mpheath said in Upgrading notepad++ with one click.:

            The script I posted previous downloads x86 installer. Seems GUP.exe does some kind of get/post messages to the server to get the x64 installer. The changes to the new script will check notepad.exe if x86 or x64 (not arm, arm64 as I cannot test these installers) and will modify the installer name to download.

            Use param=x64 to ask for the URL of the 64-bit download. For example, https://notepad-plus-plus.org/update/getDownloadUrl.php?version=8.65&param=x64 It’s an HTTP GET.

            Use param=arm64 for the ARM CPU.

            If the param is not defined or is not recognized then you will get the URL of the Windows 32-bit version of Notepad++'s installer.

            mpheathM 1 Reply Last reply Reply Quote 3
            • mpheathM
              mpheath @mkupper
              last edited by

              @mkupper said in Upgrading notepad++ with one click.:

              Use param=x64 to ask for the URL of the 64-bit download. For example, https://notepad-plus-plus.org/update/getDownloadUrl.php?version=8.65&param=x64 It’s an HTTP GET.

              Thanks @mkupper , it certainly helps to improve the script.

              Use param=arm64 for the ARM CPU.

              ARM is not supported by the script. Have no ARM device to test, identify and offer support. Anyone can update the script to add ARM support if they want.

              One last final (fingers-crossed) one click to update script:

              msgbox.png

              Click Yes to download and install the update silently.

              # https://community.notepad-plus-plus.org/topic/23039/faq-how-to-install-and-run-a-script-in-pythonscript
              # https://community.notepad-plus-plus.org/topic/25817/upgrading-notepad-with-one-click
              from Npp import notepad, MENUCOMMAND
              
              import os, subprocess, sys, tempfile
              import xml.etree.ElementTree
              
              if sys.version_info.major == 2:
                  import urllib
                  import urllib2
              else:
                  import urllib.request
              
              
              def main():
                  # Check for update
                  version = notepad.getVersion()
                  version = '.'.join(str(i) for i in version)
              
                  url = ('https://notepad-plus-plus.org/update/'
                         'getDownloadUrl.php?version={}&param={}'
                         .format(version, 'x64' if sys.maxsize > 2**31-1 else ''))
              
                  if sys.version_info.major == 2:
                      r = urllib2.urlopen(url)
                      content = r.read().decode('utf-8')
                  else:
                      with urllib.request.urlopen(url) as r:
                          content = r.read().decode('utf-8')
              
                  dic = {'NeedToBeUpdated': 'no', 'Version': '', 'Location': ''}
              
                  root = xml.etree.ElementTree.fromstring(content)
              
                  for child in root:
                      if child.tag in dic:
                          dic[child.tag] = child.text
              
                  installerName = dic['Location'].split('/')[-1]
              
                  if dic['NeedToBeUpdated'] == 'yes':
                      reply = notepad.messageBox(('"{}"\n is available to download.\n\n'
                                                  'Update to Notepad++ v{}?'
                                                  .format(installerName, dic['Version'])),
                                                 'NppUpdate',
                                                 MESSAGEBOXFLAGS.ICONQUESTION|
                                                 MESSAGEBOXFLAGS.YESNO|
                                                 MESSAGEBOXFLAGS.DEFBUTTON2)
              
                      if reply == MESSAGEBOXFLAGS.RESULTNO:
                          return
                  else:
                      notepad.messageBox('No update', 'NppUpdate')
                      return
              
                  # Download and install
                  tempDir = tempfile.mkdtemp(prefix='NppUpdate_')
                  installerPath = os.path.join(tempDir, installerName)
              
                  if sys.version_info.major == 2:
                      urlsave = urllib.urlretrieve
                  else:
                      urlsave = urllib.request.urlretrieve
              
                  urlsave(dic['Location'], installerPath)
              
                  command = ('ping -n 6 localhost&'
                             '"{}" /S&'
                             'rd /s /q "{}"').format(installerPath, tempDir)
              
                  subprocess.Popen(command, shell=True)
                  notepad.menuCommand(MENUCOMMAND.FILE_EXIT)
              
              main()
              

              Thanks everyone for the help and support to achieve this stress relieving one click update Notepad++ script.

              xomxX 1 Reply Last reply Reply Quote 4
              • mpheathM mpheath referenced this topic on
              • xomxX
                xomx @mpheath
                last edited by

                @mpheath

                Thanks for this very useful script.

                I tested it also for some non-standard installations (even for a portable N++) and found a problem - it can upgrade different N++ than the one, from which the script is launched. Here is the fixed part:

                   nppDir = notepad.getNppDir()
                
                   command = ('ping -n 6 localhost&'
                              '"{}" /S /D={}&'
                              'rd /s /q "{}"').format(installerPath, nppDir, tempDir)
                
                mpheathM 2 Replies Last reply Reply Quote 1
                • mpheathM
                  mpheath @xomx
                  last edited by

                  @xomx said in Upgrading notepad++ with one click.:

                  I tested it also for some non-standard installations (even for a portable N++)

                  The script enforces no restrictions. My testing has been done from a portable N++.

                  it can upgrade different N++ than the one, from which the script is launched.

                  Yes it can upgrade not on the current path, but as a system wide install. The intention is not to upgrade a portable or upgrade one of multiple installations.

                  Forcing the /D= argument could make the situation problematic, not just for launching from a portable location, but in an environment where multiple installation can exist brings up the question of why that would be done. Is it because the installer allows this intentionally as being a good idea? Upgrading a portable to installed could be a bad event if done by accident.

                  The script could check if doLocalConf.xml exists in nppDir and if not exist, safely add the /D= argument. This would prevent portable Notepad++ being installed over with an upgrade install. Do you consider that as ok with your fix? If yes, that means from a portable is a default install in the predefined location that the installer chooses. If no, please define a possible solution.

                  I have previously thought about a portable upgrade with a portable zip download though it has not been attempted yet and not sure if a good idea, though some users may like the concept and it may be just as convenient as an install usually is for users.

                  I am not sure of how chocolately and other systems do this with silent installs though might be wise to work with their behaviour so any suggestions are welcome to clarify the best result. I am open to ideas to solve this.

                  Thanks for the participation and appreciation in the script.

                  xomxX 1 Reply Last reply Reply Quote 1
                  • mpheathM
                    mpheath @xomx
                    last edited by PeterJones

                    @xomx Thanks, I have implemented your fix with /D= into this version now that the portable zip is supported.

                    # https://community.notepad-plus-plus.org/topic/23039/faq-how-to-install-and-run-a-script-in-pythonscript
                    # https://community.notepad-plus-plus.org/topic/25817/upgrading-notepad-with-one-click
                    from Npp import notepad, MENUCOMMAND
                    
                    import os, subprocess, sys, tempfile, zipfile
                    import xml.etree.ElementTree
                    
                    if sys.version_info.major == 2:
                        import urllib
                        import urllib2
                    else:
                        import urllib.request
                    
                    
                    def main():
                        # Check for update
                        version = notepad.getVersion()
                        version = '.'.join(str(i) for i in version)
                    
                        nppDir = notepad.getNppDir()
                        localConfigFile = os.path.join(nppDir, 'doLocalConf.xml')
                    
                        portable = os.path.isfile(localConfigFile)
                    
                        url = ('https://notepad-plus-plus.org/update/'
                               'getDownloadUrl.php?version={}&param={}'
                               .format(version, 'x64' if sys.maxsize > 2**31-1 else ''))
                    
                        if sys.version_info.major == 2:
                            r = urllib2.urlopen(url)
                            content = r.read().decode('utf-8')
                        else:
                            with urllib.request.urlopen(url) as r:
                                content = r.read().decode('utf-8')
                    
                        dic = {'NeedToBeUpdated': 'no', 'Version': '', 'Location': ''}
                    
                        root = xml.etree.ElementTree.fromstring(content)
                    
                        for child in root:
                            if child.tag in dic:
                                dic[child.tag] = child.text
                    
                        installerName = dic['Location'].split('/')[-1]
                    
                        if portable:
                            parts = installerName.split('.')
                    
                            for i, part in enumerate(parts):
                                if part.lower() == 'installer':
                                    parts[i] = 'portable'
                                elif part == 'exe':
                                    parts[i] = 'zip'
                    
                            installerName = '.'.join(parts)
                            dic['Location'] = dic['Location'].rsplit('/', 1)[0] + '/' + installerName
                    
                    
                        if dic['NeedToBeUpdated'] == 'yes':
                            reply = notepad.messageBox(('"{}"\n is available to download.\n\n'
                                                        'Update to Notepad++ v{}?'
                                                        .format(installerName, dic['Version'])),
                                                       'NppUpdate',
                                                       MESSAGEBOXFLAGS.ICONQUESTION|
                                                       MESSAGEBOXFLAGS.YESNO|
                                                       MESSAGEBOXFLAGS.DEFBUTTON2)
                    
                            if reply == MESSAGEBOXFLAGS.RESULTNO:
                                return
                        else:
                            notepad.messageBox('No update', 'NppUpdate')
                            return
                    
                        # Download and install
                        tempDir = tempfile.mkdtemp(prefix='NppUpdate_')
                        installerPath = os.path.join(tempDir, installerName)
                    
                        if sys.version_info.major == 2:
                            urlsave = urllib.urlretrieve
                        else:
                            urlsave = urllib.request.urlretrieve
                    
                        urlsave(dic['Location'], installerPath)
                    
                        if portable:
                            with zipfile.ZipFile(installerPath, 'r') as z:
                                names = z.namelist()
                    
                                for item in ('config.xml',
                                             'contextMenu.xml',
                                             'doLocalConf.xml',
                                             'nppLogNulContentCorruptionIssue.xml',
                                             'shortcuts.xml',
                                             'toolbarIcons.xml',
                                             'autoCompletion/',
                                             'functionList/',
                                             'localization/',
                                             'themes/',
                                             'userDefineLangs/'):
                    
                                    for name in names[:]:
                                        if '/' in item:
                                            if name.startswith(item):
                                                names.remove(name)
                                        elif item == name:
                                            names.remove(name)
                    
                                z.extractall(tempDir + '\\zip', members=names)
                    
                            command = ('ping -n 6 localhost&'
                                       'robocopy /s /e /move /r:2 /np /xx'
                                       ' "/log:{1}\\update.log" "{2}\\zip" "{1}"&'
                                       'rd /s /q "{2}"').format(installerPath, nppDir, tempDir)
                        else:
                            command = ('ping -n 6 localhost&'
                                       '"{}" /S /D={}&'
                                       'rd /s /q "{}"').format(installerPath, nppDir, tempDir)
                    
                        subprocess.Popen(command, shell=True)
                        notepad.menuCommand(MENUCOMMAND.FILE_EXIT)
                    
                    main()
                    

                    For x86 and x64 only. No support for ARM.

                    • If Notepad++ is portable then it downloads the zip and extracts to a temporary folder.
                    • If Notepad++ is installed, downloads the installer to a temporary folder.
                    • Control will be handed over to CMD just before Notepad++ is closed.
                    • Waits 5 seconds, install or unzip and move files and then removes the temporary folder.

                    Due to zip users may customize means that some root files and many subfolders will not be extracted from the zip as a precaution.

                    —
                    moderated fixed the version = line, per mpheath’s request

                    mpheathM 1 Reply Last reply Reply Quote 0
                    • mpheathM mpheath referenced this topic on
                    • xomxX
                      xomx @mpheath
                      last edited by xomx

                      @mpheath said in Upgrading notepad++ with one click.:

                      Forcing the /D= argument could make the situation problematic, not just for launching from a portable location, but in an environment where multiple installation can exist brings up the question of why that would be done.

                      I would expect - the N++ installation, I am running the script from, to be updated.

                      @mpheath said in Upgrading notepad++ with one click.:

                      The script could check if doLocalConf.xml exists in nppDir and if not exist, safely add the /D= argument.

                      Yes, I am for it.

                      @mpheath said in Upgrading notepad++ with one click.:

                      This would prevent portable Notepad++ being installed over with an upgrade install. Do you consider that as ok with your fix?

                      Ok. I do not want to update the portable N++ setup to the installed one either.

                      @mpheath said in Upgrading notepad++ with one click.:

                      If yes, that means from a portable is a default install in the predefined location that the installer chooses. If no, please define a possible solution.

                      No. For a solution - see below.

                      @mpheath said in Upgrading notepad++ with one click.:

                      I have previously thought about a portable upgrade with a portable zip download

                      Yes, this could be the solution for the portable N++:

                      1. detection by the aforementioned doLocalConf.xml check
                      2. if portable N++, changing the ‘NeedToBeUpdated’ message to something like:
                        “npp.8.6.7.portable.x64.zip” update is is available for your portable Notepad++ setup. Do you want to download this file to “%USERPROFILE%\Downloads” ? (for the portable setups an automatic update is not currently available)"

                      As the portable installations cannot be simply updated by directly overwriting from the downloaded archive (overwriting of the N++ settings…), I would left that job on the users now - after all, if a user was able to manually get a portable installation up and running, they should also be able to manually update it after.

                      There is also another problem with this script - the possible N++ multi-instance mode (multiple running N++ instances …). But it can be easily solved if my new PR for the NSIS N++ installer is accepted.

                      Edit: I wrote my reply without seeing your new post.

                      mpheathM 1 Reply Last reply Reply Quote 1
                      • mpheathM
                        mpheath @xomx
                        last edited by mpheath

                        @xomx said in Upgrading notepad++ with one click.:

                        But it can be easily solved if my new PR for the NSIS N++ installer is accepted.

                        Good. I’ll take it for granted that the PR works perfect, so gave the PR a thumbs up.

                        I consider I have met your expectations with your last reply with the last posted script. The portable needed some protection from the installer which I considered as quite important with using the /D= argument. So again thanks for suggesting the fix. Let me know if you have anymore issues with the script.

                        xomxX 1 Reply Last reply Reply Quote 1
                        • xomxX
                          xomx @mpheath
                          last edited by xomx

                          @mpheath

                          Perfect! I tested the new portable update and so far so good.

                          1 Reply Last reply Reply Quote 0
                          • mpheathM
                            mpheath @mpheath
                            last edited by

                            Thanks @PeterJones for the fix.

                            I rigged the version with '0'# to always prompt to upgrade with the last script. Peter was nice enough to fix it for me. So anyone who copied the last script, please do so again else you will update even if you have the latest version. I have copied and tested the script and now tells me that No update so the mistake is fixed.

                            @xomx Perfect now, well hope to be close as possible.

                            I have upgraded my existing portable many times and still working well. I have not used the backup that I zipped up before testing yet, so it seems good.

                            1 Reply Last reply Reply Quote 2
                            • Кирилл ФроловК
                              Кирилл Фролов
                              last edited by

                              You can use WingetUI
                              9afa65b2-3420-4133-a5f0-bea9be1e1836-image.png

                              1 Reply Last reply Reply Quote 1
                              • First post
                                Last post
                              The Community of users of the Notepad++ text editor.
                              Powered by NodeBB | Contributors