Announcement

Collapse
No announcement yet.

Uninstall Needing Reboot

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Uninstall Needing Reboot

    I have my installer set to run the uninstaller in silent mode first, if available, and that works fine. However, I have found a case where a problem can result. If a component is in use when you go to install an update, it seems that uninstaller in silent mode does not set _NeedsReboot or anything that I can identify to indicate that it has set a file for deletion on restart. After the uninstall completes and the installer goes to install new files, it will pop a warning that the file is in use and you can close some other app and click retry and then it works. However, that file has already been marked for deletion on reboot before this point, so after the installation is complete, when you do reboot, it actually deletes a file that is needed and now the application does not run.

    I have been trying to find a way for the silent uninstaller to inform the parent installer that a reboot is needed so it can inform the user and abort, but _NeedsReboot is not set. Should it be? I can see a potential problem here as it seems to always mark a few folders for removal on reboot. They don't get deleted because they are not empty when the system reboots, but if this also set the _NeedsReboot flag, then you would always need to restart.

    Is there some way to intercept the prompt for file in use that you don't see when you are running in silent mode? Is there a way to make a fake silent mode that doesn't pop warnings for every shared file or display anything except file in use warnings?

    Is there some other way to deal with this that I'm just missing entirely?

    Thanks

    Scott

  • #2
    Have you checked the exit code of the uninstaller? From the documentation, it could be that it returns 500 - "One or more files could not be removed by the uninstall program". I have not tested this here, but if the exit code of the uninstaller is working as the documentation suggests, you could stop the installer right there, schedule it to run automatically at the restart, and ask the user to confirm the reboot...

    Ulrich

    Comment


    • #3
      I did check that and it appears to return 0. I also checked the _NeedsReboot flag and added an Info line to show the status of that. This is some of what I see in the log file:

      [03/01/2021 16:02:24] Success Unregister COM file: C:\Windows\system32\ActBar2.ocx
      [03/01/2021 16:02:24] Success Remove file on reboot: C:\Windows\system32\ActBar2.ocx
      [03/01/2021 16:02:27] Success Unregister COM file: C:\Windows\system32\VSFlex7.ocx
      [03/01/2021 16:02:27] Success Remove file on reboot: C:\Windows\system32\VSFlex7.ocx
      [03/01/2021 16:02:30] Info Restart NOT needed
      [03/01/2021 16:02:30] Success Run uninstall event: On Shutdown
      [03/01/2021 16:02:30] Notice Exit uninstall process (Return code: 0)

      Comment


      • #4
        Okay, so this does not work. But here is something what could help. Once you have the target folder defined (here I assume that it is stored in %AppFolder%), you can check if there is a pending file rename/delete operation for this location. If there is something, you could stop the setup before the new files are deployed. Here is some code I put together:

        Code:
        -- Some helper functions
        
        function Registry.DoesValueExist(MainKey, SubKey, Value)
           local bFound = false;
           if Registry.DoesKeyExist(MainKey, SubKey) then
              local tblValues = Registry.GetValueNames(MainKey, SubKey);
              if (tblValues ~= nil) then
                 for index, sValueName in pairs(tblValues) do
                    if (String.Compare(sValueName, Value) == 0) then
                       bFound = true;
                       break;
                    end
                 end
              end
           end
           return bFound;
        end
        
        function DelimitedStringToTable(DelimitedString, Delimiter)
           tbReturn = {};
           local strWorking;
           local nPos = nil;
           local strData;
           local nTableIndex = 1;
           local nDelimiterLength = String.Length(Delimiter);
        
           if (nDelimiterLength < 1) then
              tbReturn[nTableIndex] = DelimitedString;
              return tbReturn;
           end
        
           strWorking = DelimitedString;
           nPos = String.Find(strWorking,Delimiter);
           while (nPos ~= -1) do
              strData = String.Left(strWorking,nPos-1);
              tbReturn[nTableIndex] = strData;
              nTableIndex = nTableIndex + 1;
              local nLength = String.Length(strWorking);
              strWorking = String.Right(strWorking,nLength - (nPos + (nDelimiterLength-1)));
              nPos = String.Find(strWorking,Delimiter);
           end
        
           if (strWorking ~= "") then
              tbReturn[nTableIndex] = strWorking;
           end
        
           return tbReturn;
        end
        
        -- Check if there is a pending deletion or rename operation
        
        local bPendingFileOperation = false;
        
        if Registry.DoesValueExist(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Session Manager", "PendingFileRenameOperations") then
           local sData = Registry.GetValue(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Session Manager", "PendingFileRenameOperations", true);
           if (#sData > 0) then
              local tData = DelimitedStringToTable(sData, "|");
              for i = 1, #tData do
                 if tData[i] ~= nil then
                    if String.Find(tData[i], SessionVar.Expand("%AppFolder%"), 5, false) ~= -1 then
                       bPendingFileOperation = true;
                       break;
                    end
                 end
              end
           end
        end
        
        if bPendingFileOperation then
           Dialog.Message("Warning", SessionVar.Expand("There is a pending file operation (deletion) scheduled for %AppFolder%.\r\nPlease restart the device before installing this product."), MB_OK, MB_ICONSTOP);
        end
        Ulrich

        Comment


        • #5
          Thank you. I'm not sure this will help though, because the files causing the issue are all shared third-party components that are in the windows system32 folder. I thought of maybe grabbing the contents of that pending operations registry key before and after the uninstaller is run and see if there has been any change to it, but to be accurate, it would have to pick out just the new entries and see if any of them are file (not folder) operations. It seems to always add a few folder removals too, but they don't actually hurt anything because those folders are not empty.

          Comment


          • #6
            Assuming that the number of controls is not too big and the file names are known, you can modify this code with the String.Find() and check just for the files known to give you issues.

            Ulrich

            Comment


            • #7
              Can we expect this to be fixed in a Setup Factory update so it is clear that files were marked for delete on reboot without having to review this registry key?

              Comment


              • #8
                Is the option to suppress the "in use" notice checked for the controls, or the folder reference, if you use one to add these controls to the installer? If it is not, please use this and rebuild the installer, then try again.

                Click image for larger version

Name:	SCRN-2021-03-02-01.png
Views:	68
Size:	21.5 KB
ID:	306270

                Ulrich

                Comment

                Working...
                X