I’ve started into my Vista testing in preparation for the next release of Text2Go. Once again, UAC (User Account Control) issues have reared their ugly head. Although not insurmountable, they have required a certain number of contortions.
The first issue discovered involved a new option I’ve added to Text2Go. When you install Text2Go, it places a shortcut in the Windows Startup menu so that it’s launched every time you boot your PC. This great for those who use Text2Go regularly. It means it’s already running when you go to use it. However for those who only use Text2Go occasionally, it’s not worth launching it every time you start your PC.
If you don’t want Text2Go to run at startup, you can easily remove the shortcut from the Startup menu. However this is not very intuitive. It assumes
1. you know Text2Go is launched using a shortcut in the Startup menu.
2. you know how to remove shortcuts from the Windows menu.
Therefore I’ve added a simple checkbox in the Text2Go options that lets you choose whether Text2Go is launched at startup or not (thanks to Stephane Grenier founder of LandLordMax for this suggestion). Behind the scenes all it does is add or remove a shortcut from the Windows Startup menu. This is very simple, except on Vista when you’ve installed Text2Go for all users. Given that the default is to install for all users, I suspect that 99% of people leave it this way. It means Text2Go will be available for all users of the PC. It also means that the current user doesn’t have permission to add/remove this shortcut. In order to successfully perform this operation, the current user must be briefly elevated to Administrator. Fortunately Windows provides a simple way of achieving this. By using the ShellExecute command and passing ‘runas’ as the verb parameter, Vista will run the command elevated, prompting the user for permission as necessary. We use the DOS ‘del’ command to remove the shortcut and ‘copy’ to reinstall the shortcut. Problem 1 solved.
The second problem was a lot subtler and required greater contortions. During every install, the installation process needs to run elevated. If it didn’t it couldn’t even write files to standard locations such as the Program Files folder. At the end of the Text2Go installation process, Internet Explorer is used to display some quickstart tutorials. This serves two purposes. Firstly it ensures that the Text2Go toolbar is made visible in IE. Secondly it makes it very easy for new users to complete the quickstart tutorials and gain an understanding of Text2Go.
One consequence of launching IE during installation is IE also ends up running elevated. This is not ideal from a security perspective. IE will not be running in protected mode and if the user happens to browse to a dodgy website after completing the tutorials, they could potentially be vulnerable to a security exploit. It’s important to note that this only occurs for the one instance of IE that is started during installation. In all other cases Text2Go runs with standard privileges and works quite happily with IE in protected mode.
Security issues aside, this behaviour introduces one subtle problem. As you will recall, Text2Go is also running elevated. The problem occurs when it writes out any of its settings files. Writing the settings files works fine. It’s the security permissions that the file is created with that’s the problem. The current user is given read/write access and all other users are given read only access. This is still correct, except that the current user is actually the administrator, due to the fact that Text2Go is running elevated. This means that the next time Text2Go is started as a standard user, it will not be able to write to its own settings file, effectively freezing all options to their values at install time. They cease to become options at all. Definitely not what was intended.
The solution? IE must be launched as a non-elevated process at install time.
This will ensure that Text2Go is in turn launched as non-elevated and the settings file will be created with read/write access for the correct user. The side benefit is that best practice security-wise will also be observed.
The problem is that Microsoft don’t provide an API call to launch a non-elevated process from an elevated process. Thankfully, Andrei Belogortseff founder of WinAbility Software has come up with a neat solution which he has demonstrated in his VistaElevator 2.0 application. I’ve modified this application so that it can be used to launch any application non-elevated. At the end of the Text2Go installation I use this to launch IE non-elevated.
The third problem is once again related to file permissions. The major new feature in the next release of Text2Go is the ability to edit pronunciation dictionaries from within Text2Go. Not only that, you can share your corrections with other Text2Go users. An automatic update like service is used to upload your contributions to the Text2Go server and download contributions from the rest of the Text2Go community. This means that your local dictionary files will be updated on a regular basis. Unfortunately a standard user doesn’t have permission to write to these files (due to the default permissions set at install time). Now it would be possible to run an elevated instance of Text2Go to perform the update. However this would require the user to confirm this for every update. Not something you want to do on a daily basis. The update service has been designed to run in the background, requiring no user interaction.
The approach I’ve taken is to modify the permissions on the dictionary files at the end of the installation. There doesn’t seem to be a way of doing this in MSI, so I run the CACLS.exe utility at the end of the installation to grant all users read/write access to these files.
The final problem turned out not to be specifically Vista related but because I found it during Vista testing, I’m going to blame Vista anyway:) Normally when testing, I run Vista in a Virtual Machine and launch my setup from a shared drive on the ‘virtual’ network. This works well. However I was finding that if I first copied the setup file to Vista’s local hard drive and then launched the setup, the MSI installer would abort immediately and report an error about an invalid MSI package. Very strange. I’d made minimal changes to the installation script, none of which could cause such a catastrophic failure. When I tried a setup from a build a few weeks earlier, it installed without problem.
The only major change I could think of during this period was an upgrade from VS2005 to VS2008. This had been a very straightforward upgrade, with no problems encountered. Digging into the problem a little further, I was able to find the msiexec installation log. The last line contained an entry stating that the MSI package couldn’t be found. This would be the problem.
The Text2Go installation is packaged as a single Winzip self-extracting archive. This contains two files, a setup.exe and Text2GoSetup.msi. Setup.exe is a special bootstrap application provided by Microsoft that first checks for the necessary installation prerequisites (e.g. the appropriate MSI installer and .NET framework versions) and then launches the MSI. When I created the Winzip self-extracting archive, I told it to automatically run setup.exe. It then waits for setup.exe to complete before deleting setup.exe and Text2GoSetup.msi. This ensures no temporary files are left around after the installation and has worked nicely up until now.
It seems that the behaviour of setup.exe has changed subtly in VS2008. It now exits as soon as it’s issued the command to run the MSI. The Winzip self-extracting archive was detecting this and immediately cleaning up the archive contents, deleting the MSI before it had a chance to run.
The solution – have the Winzip self-extractor wait for the completion of Text2GoSetup.msi rather than setup.exe. You can tell wzse to watch a different application using the -wait argument. Unfortunately it only accepts a filename up to 8 characters in length. Will Windows ever throw off its DOS legacy? The good news is this change fixed the problem. Text2GoSetup.exe once again works from any location.
I suspect that it was a timing issue and just happened to work when the setup was on a shared network drive. Perhaps the network delays allow msiexec just enough time to get a lock on the file before wzse could delete it.
Update: This solution only fixed it for me. The first beta tester I gave the setup to had it fail in exactly the way I described. The real solution – revert back to the VS2005 version of setup.exe
This is nicely described here
Finally, Text2Go is once again in harmony with Windows Vista. Whew!
It should have been easy (famous last words). No uninstall required. Just install over the top and you’re done.
Unfortunately I hit problems immediately. A cryptic error message appeared along the lines of not having permission to access the following key.
This doesn’t make any sense. I’m running XP with full admin rights.
This one error causes the entire installation to abort.
So I thought I’d try removing Winzip 11.1 first. Same error.
However now I’m even worse off. Winzip 11.1 has now been partially removed, so I can no longer access it.
Run Regedit.exe (Start->Run and type regedit.exe) and manually remove the entire parent key
Run the uninstall again.
This time it comes up with the same error but for a different registry key
So I removed that key and tried again.
To cut a long story short, by repeatedly running the uninstall and then manually deleting each key that it complained about (approx. 5 or 6), I was able to get the uninstallation of 11.1 to complete.
I then ran the 11.2 installation which completed without errors.
It could have been much worse. I just hope every Winzip user doesn’t run into this problem or there are going to be a lot of frustrated people out there.