Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Installer: Improve minor-upgrade experience #321

Open
Rondom opened this issue Aug 24, 2016 · 4 comments
Open

Installer: Improve minor-upgrade experience #321

Rondom opened this issue Aug 24, 2016 · 4 comments

Comments

@Rondom
Copy link
Contributor

Rondom commented Aug 24, 2016

I am sorry that I do not have any concrete suggestions here. I think this is a good issue for a downstream user of Dokan without any kernel skills to contribute to the project ;-).

Updating from one version, e.g. 1.x.x to another minor (1.y.z) or minor-minor (1.x.y) version is currently not very smooth.

Current behaviour is:

  • Installation fails with error message telling him what to do
  • User needs to go to Programs/Features to uninstall the old version
  • Reboot
  • Install new version

We cannot reliably replace the running Dokan driver, even if the driver supported unloading/PnP, because there might still be volumes mounted.

I am not familiar with MSI, but maybe it possible to automate this. Contributions welcome ;-)
Back from my dusty memory I remember a mechanism to exchange files during boot to avoid the Windows-problem of not being able to replace files that are in use. At least that is how it worked in Windows 9x/ME using WININIT.EXE/INI (there you see how outdated my knowledge is....).

I think that 20 years later maybe MSI provides a transaction-safe way of accomplishing a clean upgrade i.e. automating the upgrade/reinstall making sure that everything is consistent i.e. in case of failure either the old or new version are installed and not a mish-mash of both.

@js69
Copy link

js69 commented Aug 24, 2016

See answer to #322 - this should be handled in a custom bootstrapper.

For my own application's bundle I have created a IsDokanInstalled method to show a warning in case an older Dokan version than the one in the bundle is detected.

@Rondom
Copy link
Contributor Author

Rondom commented Aug 24, 2016

Ooooh 😢 I guess I was too naïve 😄

Maybe we can leave those issues open nonetheless? I mean, maybe some of the downstream users are willing to contribute a solution Dokan can use for its bootstrapper as well? Downstream projects can then decide whether to use the Dokan bootstrapper or to incorporate a similar mechanism into their bootstrapper.

Here is what my googling found:
http://stackoverflow.com/questions/16166186/wix-burn-after-restart-force-reboot-continuing-installation

@Rondom
Copy link
Contributor Author

Rondom commented Aug 24, 2016

For example I see that @keybase (@zanderz, @taruti) has some code in their bootstrapper for detecting old versions. Which versions, I don't know...

https://github.com/keybase/client/blob/master/packaging/windows/WIXInstallers/KeybaseBundle/Bundle.wxs

@Rondom Rondom changed the title Installer: Improve upgrade-experience Installer: Improve minor-upgrade experience Aug 24, 2016
@js69
Copy link

js69 commented Aug 24, 2016

They Keybase stuff searches for a fixed product code which means it finds only a very specific Dokan setup version.
Stub code for what my custom bootstrapper does to check Dokan1 installs generically:

string windowspath = Environment.GetEnvironmentVariable("windir");
string dokansyspath = Path.Combine(windowspath, @"System32\drivers\dokan1.sys");
if (Environment.Is64BitOperatingSystem)
{
    dokansyspath = Path.Combine(windowspath, @"Sysnative\drivers\dokan1.sys");
}
bool dokan1SysExists = MyFileExists(dokansyspath);
if (dokan1SysExists)
{
    Log(LogLevel.Verbose, "Dokan driver file exists: " + dokansyspath);
}

string dokanProductCode = FindUninstallProductCode("Dokan Library");
string dokanDisplayVersion = String.Empty;
string dokanFullVersion = String.Empty;
string dokanSetupVersion = GetBundleString("DokanVersion");

if (!String.IsNullOrEmpty(dokanProductCode))
{
    dokanFullVersion = GetRegvalueContent("HKLM", @"Software\Microsoft\Windows\CurrentVersion\Uninstall\" + dokanProductCode, "DisplayVersion");
    if (String.IsNullOrEmpty(dokanFullVersion))
    {
        dokanFullVersion = GetRegvalueContent("HKLM", @"Software\Microsoft\Windows\CurrentVersion\Uninstall\" + dokanProductCode, "FullVersion");
        Log(LogLevel.Verbose, "Dokan FullVersion=" + dokanFullVersion);
    }
    else
    {
        Log(LogLevel.Verbose, "Dokan DisplayVersion=" + dokanFullVersion);
    }

    if (String.IsNullOrEmpty(dokanFullVersion))
    {
        Log(LogLevel.Verbose, "No Dokan DisplayVersion of FullVersion found");
    }
    else
    {
        if (!String.IsNullOrEmpty(dokanSetupVersion))
        {
            Log(LogLevel.Verbose, "Bundle DokanVersion=" + dokanSetupVersion);
            Version installedDokanVersion = new Version(dokanFullVersion);
            Version setupDokanVersion = new Version(dokanSetupVersion);
            var compareresult = setupDokanVersion.CompareTo(installedDokanVersion);
            if (compareresult == 0)
            {
                Log(LogLevel.Verbose, "Same DokanVersion installed and in Bundle, will be skipped during setup");
                dokan1SysExists = false;
            }
            else if (compareresult > 0)
            {
                Log(LogLevel.Verbose, "Newer DokanVersion in Bundle than already installed");
                string errorMessage = ResolveText("ErrorDokanDetected");
                BootstrapperDispatcher.BeginInvoke(new Action(() => FatalErrorMessage("DokanVersionError", errorMessage)));
            }
            else if (compareresult < 0)
            {
                Log(LogLevel.Verbose, "Older DokanVersion in Bundle than already installed");
                dokan1SysExists = false;
            }
        }
        else
        {
            Log(LogLevel.Verbose, "No Bundle DokanVersion found");
        }
    }
}
else
{
    Log(LogLevel.Verbose, "No Dokan ProductCode found");
}

if (dokan1SysExists)
{
    string errorMessage = ResolveText("ErrorDokanDetected");

    // show warning, then terminate
    BootstrapperDispatcher.BeginInvoke(new Action(() => FatalErrorMessage("DokanVersionError", errorMessage)));
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants