Announcement

Collapse
No announcement yet.

Use one install multiple times to different folders (side-by-side)

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

  • Use one install multiple times to different folders (side-by-side)

    Hi,
    I can do an install twice, to different folder names, and using different shortcut folder names, but the desktop shortcuts are replaced with the last install, and the uninstall is replaced by the last install. Then, when the uninstall is run, the second version is uninstalled, but the second desktop items remain and are orphaned.

    Any way of getting two sets of desktop icons, one set for each install, and separate uninstalls? The uninstall in particular is fairly critical.

    Thanks for any help.

  • #2
    If you wish to be able to install a product multiple times, into different folders on the same computer, and need to uninstall each of these instances individually and in any order, you need to follow this:
    • Each installed instance of your files need its own copy of the uninstaller files (the executable, *.dat and *.xml, and possibly plugins and support files).
    • Each uninstaller needs it own "Unique registry key", or the last installed entry will overwrite the previous one.
    • For clarity, each entry in the "Programs and Features" applet should have a slightly different description, so you can select which one you wish to uninstall.


    See this dialog:
    Click image for larger version

Name:	SCRN-2015-03-28-01.png
Views:	1
Size:	39.5 KB
ID:	284285

    Here, I define the location of the uninstaller with the aid of a custom Session Variable, named %UninstallerFolder%. The content of this variable will be set at runtime, see below. Also, see this:
    Click image for larger version

Name:	SCRN-2015-03-28-02.png
Views:	1
Size:	44.4 KB
ID:	284286

    Each entry in the Control Panel will have its own description, using the name of the target folder to identify individually each instance which was installed. Also, each entry in the Control Panel needs to have a unique registry key, so an existing entry isn't overwritten, and that is why I use another custom Session Variable, named %UniqueRegKey%.

    Before the deployment of the files starts, for example in the On Preload event script of the "Ready to Install" screen, the Session Variables need to be defined. I set this:
    Code:
    SessionVar.Set("%UninstallerFolder%", SessionVar.Expand("%AppFolder%\\Uninstaller"));
    SessionVar.Set("%UniqueRegKey%", Crypto.MD5DigestFromString(SessionVar.Expand("%UninstallerFolder%")));
    The setting of the contents of %UninstallerFolder% should be obvious, as the files required for each uninstaller are placed into a sub folder of the installation folder (the %AppFolder%).
    The unique registry key does not need to be something readable, but it needs to be unique for each instance. To make sure that each instance gets its own registry key, avoiding that the entries are overwritten in the "Programs and Features" applet in the Control Panel, I simply use an MD5 checksum of the folder name where the uninstaller will be installed. Different folder name, different description, different key.

    Placing this code on the "Ready to Install" screen allows you to add these Session Variables to the screen for debugging purposes and inspect their contents before actually deploying the files:
    Click image for larger version

Name:	SCRN-2015-03-28-03.png
Views:	1
Size:	34.2 KB
ID:	284287
    Now each instance can be uninstalled individually. Tweak this to fit your needs.

    Ulrich

    Comment


    • #3
      Hi Ulrich,

      That works! Great, very clear instructions!

      The desktop icons still get overwritten by the second install, unless I rename them first. In that case no icons are created by the second install. But that is a minor issue compared to the uninstall problem, so I am happy.

      Thanks again.

      Comment


      • #4
        If you want multiple desktop icons, then you can use a Session Variable as the description of the shortcut. As long as the descriptions differ for each installation, they won't overwrite themselves.
        Click image for larger version

Name:	SCRN-2015-03-29-02.png
Views:	1
Size:	41.6 KB
ID:	284289

        The question is what you should use as a description... I suggest something like this to begin with, place this somewhere once the %AppFolder% was defined, like in the On Next script of the "Select Install Folder" screen, for example.
        Code:
        -- path to your application
        local tPath = String.SplitPath(SessionVar.Expand("%AppFolder%\\EasyBackup.exe"));
        -- remove trailing backslash
        local sPath = String.Left(tPath.Folder, #tPath.Folder - 1);
        -- extract the parent folder name
        local sFoldername = String.Mid(sPath,  String.ReverseFind(sPath, "\\") + 1, -1);
        -- set the content of the Session Variable referring the folder name
        SessionVar.Set("%DesktopCaption%", SessionVar.Expand("%ProductName% in ") .. sFoldername);
        This will set the %DesktopCaption% with the name of the parent folder used for the deployment of the application. For example, installing the test application into a folder named "MyTestFolder01":
        Click image for larger version

Name:	SCRN-2015-03-29-03.png
Views:	1
Size:	58.0 KB
ID:	284290
        Then you see the folder names and the unique registry key for the Control Panel:
        Click image for larger version

Name:	SCRN-2015-03-29-07.png
Views:	1
Size:	60.9 KB
ID:	284291

        Finally, a shortcut is created on the desktop, with the caption "Easy Backup in MyTestFolder01":
        Click image for larger version

Name:	SCRN-2015-03-29-05.png
Views:	1
Size:	25.4 KB
ID:	284292

        These instructions should allow you to make the changes you need in your project and customize it further.

        Ulrich

        Comment


        • #5
          Hi Ulrich,

          Fantastic - you've done it again!

          This works perfectly. I have two desktop icons for each install, but I could easily duplicate your code for each icon, changing the variable names to suit.

          Thanks again.

          Comment


          • #6
            Suggested treatment of "Former install found" screen

            If the methods described above by Ulrich are used, the "Former install found" scripts will never find a previous install when another install is done to the same folder, as we have changed the install instance name.

            To overcome this, do the following:

            Move the "Former install found" screen to appear after the "Select Shortcut Folder" screen.

            Move Ulrich's uninstall code from the "On Preload" script of the "Ready to Install" screen to the "On Preload" script of the "Former install found" screen, and modifying the existing script.
            Note that I changed %UniqueRegKey% to be the same as %DesktopCaption% (used in the second Ulrich post), but you could change it back to the Crypto-generated version:

            Code:
            SessionVar.Set("%UninstallerFolder%", SessionVar.Expand("%AppFolder%\\Uninstaller"));
            -- SessionVar.Set("%UniqueRegKey%", Crypto.MD5DigestFromString(SessionVar.Expand("%UninstallerFolder%")));
            SessionVar.Set("%UniqueRegKey%", SessionVar.Expand("%UniqueRegKey%"));
            
            local keys = Registry.GetKeyNames(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall");
            local len = String.Length(SessionVar.Expand("%UniqueRegKey%"));
            local found = false;
            local sFoundKeyName;
            
            for i, keyname in pairs(keys) do
            	if (String.Compare(String.Left(keyname, len), SessionVar.Expand("%UniqueRegKey%")) == 0) then
            		SetupData.WriteToLogFile("Info\tFound previous installation: " .. keyname .. "\r\n", true);
            		found = true;
            		sFoundKeyName = keyname;
            		break;
            	end
            end
            
            if (found) then
            	-- offer to uninstall
            	local regvalue = Registry.GetValue(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\"..sFoundKeyName, "UninstallString", true)
            	sMyUninstallInfo = {};
            	local i = 1;
            	for s in string.gfind(regvalue, '"([^%"]+)"') do
            	  sMyUninstallInfo[i] = s;
            	  i = i + 1;
            	end
            
            	SetupData.WriteToLogFile("Info\tUninstall Program: " .. sMyUninstallInfo[1] .. "\r\n", true);
            	SetupData.WriteToLogFile("Info\tUninstall Argument: " .. sMyUninstallInfo[2] .. "\r\n", true);
            else
            	-- check for per-user installation (added in Setup Factory 9.0.3.1)
            	keys = Registry.GetKeyNames(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall");
            	if (keys ~= nil) then
            		for i, keyname in pairs(keys) do
            			if (String.Compare(String.Left(keyname, len), SessionVar.Expand("%UniqueRegKey%")) == 0) then
            				SetupData.WriteToLogFile("Info\tFound previous installation: " .. keyname .. "\r\n", true);
            				found = true;
            				sFoundKeyName = keyname;
            				break;
            			end
            		end
            		if (found) then
            			-- offer to uninstall
            			local regvalue = Registry.GetValue(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\"..sFoundKeyName, "UninstallString", true)
            			sMyUninstallInfo = {};
            			local i = 1;
            			for s in string.gfind(regvalue, '"([^%"]+)"') do
            			  sMyUninstallInfo[i] = s;
            			  i = i + 1;
            			end
            		
            			SetupData.WriteToLogFile("Info\tUninstall Program: " .. sMyUninstallInfo[1] .. "\r\n", true);
            			SetupData.WriteToLogFile("Info\tUninstall Argument: " .. sMyUninstallInfo[2] .. "\r\n", true);
            		else
            			-- jump to next screen and don't display this one
            			SetupData.WriteToLogFile("Info\tPrevious installation not found\r\n", true);
            			Screen.Next();
            		end
            	else
            		-- no per-user installations located
            		SetupData.WriteToLogFile("Info\tPrevious installation not found\r\n", true);
            		Screen.Next();
            	end
            end
            Now the Uninstall screen will appear, but only when installing to a previously-installed folder.

            Comment

            Working...
            X