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.
    • Oliver MaagO
      Oliver Maag
      last edited by

      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?
      Cheers, Oliver

      mkupperM mpheathM 3 Replies Last reply Reply Quote 0
      • 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