I have a C# program that I want to deploy with InstallSheild LE. I know how to make a setup.exe file to install the application and I know how to create a new installer that can upgrade a current installation.
Currently, I have my application get its version number from the installation log. It checks its version number (which is initially and empty string). If the version number is a an empty string, the application goes to the %TEMP% directory and reads the newest installation LOG file looking for the line that states the installation was successful and the line with the version information. The version information is saved in the application settings and used to detect if upgrades are available. To detect an update, it compares its version number to the version number of the setup.exe in the update location (on a network drive).
This implementation works, however, there are a few aspects of this that worry me and i would like to know if there is a better way to tell the application what version it is and saving this information (preferably not in a file that can be deleted). Obviously, the information would need to be update-able and preserved between runs. Ideally, I would like to be able to internally set the version number in my C# application without having to make assumptions about files being created, or file locations, etc to get it.
Thoughts??
I appreciate your suggestions!
I found that the easiest way was to hardcode the version number in the application. I then would preform a check, during program execution, for the version of the installer in the update location on the network drive. If the version of the installer in the network drive was greater than the hardcoded version in the application, the program would download the new installer, execute it via another process, and close the application so that the necessary files could be updated.
In order to do this you pretty much have to hardcode something in addition to the update location. The question then becomes what's best to hardcode. Here are some ideas, assuming that your installation's ProductVersion property contains the version you need to compare:
The version in question, per your answer
The ProductCode of your installation
A registry location (specific to major versions)
The UpgradeCode of your installation series
A registry location (independent of major versions)
Those, in order, are each less likely to change than the one before it, and it should be trivial to have the installer write its version into a chosen registry location (put [ProductVersion] in a registry key's value) so that's my recommendation. Then the only required update is to change ProductVersion when you update your installation.
There is one other approach that could work without any special a priori knowledge. I'll sketch it out in Win32 API because I'm not familiar enough with the DTF wrappers:
Use MsiEnumComponents or MsiEnumComponentsEx to look at all the installed components on the machine - this could take a while
Use MsiEnumClients or MsiEnumClientsEx to identify the product (or products) that installed each component
Use MsiGetComponentPath or MsiGetComponentPathEx on each product-component pair to identify whether that pair installed your exe file (the location from which you are currently running)
Use MsiGetProductInfo or MsiGetProductInfoEx to retrieve the ProductVersion; if there was more than one client, you'll have to decide how to handle it - perhaps by using the largest version
(If you hardcode the UpgradeCode you can use MsiEnumRelatedProducts in place of steps 1-3; if you hardocde the ProductCode you can jump directly to step 4. Typically you only need to call the Ex variants if you need to search per-user installations.)
Related
Input from someone who had to qualify an application for being a Microsoft Gold Partner would be especially welcome here.
We are running our software through Microsoft Platform Ready Test Tool. Its installer was made with the latest stable version of WiX. The gist of the test is, while the tool is running, you install, run, and uninstall your application and the Test Tool says whether it's behaving well or not. It fails the test because of leftover files and registry keys, but I haven't a clue how we could possibly clean those up reliably.
EDIT: this is the application in question: https://github.com/modulogrc/modSIC
Our software sets up a Windows service, which is correctly removed on uninstall. The offending leftover files are like this:
Under the logged-in user's Local\Temp directory, four DLLs with 8-character random names (different at each install) and many .tmp files with names starting with "wbk" (and one starting with "vgx")
A lot of .rbf files under C:\Config.Msi
C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys\{a very long name}
Another long-named file under the user's AppData\Local\Microsoft\Windows\Caches directory -- and under some other user's, too. (That other user wasn't doing anything while I was testing)
Many under C:\Users\Public\Documents\MPR -- well, those ones are left by the Test Tool itself, and I suppose we can justify that with a waiver when certifying.
The offending registry keys:
Many under HKU{Various IDs} under folders named "MuiCache"
Many under HKU{Various IDs} under folders named "UserAssist"
These intriguing ones, also under HKU{various IDs}\Software\Microsoft\Windows\CurrentVersion:
ImmersiveShell\StateStore\ItemsStateStoreLastWrite
UFH\SHC\8
Explorer\GlobalAssocChangedCounter
Many under HKU{Some ID}\Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\Bags\AllFolders\Shell\Microsoft.Windows.ControlPanel
SessionIdHigh and SessionIdLow, under HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing
HKEY_LOCAL_MACHINE\SYSTEM\RNG\Seed
The ones below, and the same thing with CurrentControlSet instead of ControlSet001 (it's a link, I believe)
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\FastCache\Data\Volatile
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\MUI\StringCacheSettings\StringCacheGeneration
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Session
The files left under the MPR folder tells me the Test Tool does complain about things it shouldn't, so I'm inclined to submit the app anyway. But if there's something, anything I could ameliorate with tweaks in the WiX project's Product.wxs file (some of the other criteria of the MPR test were indeed met by changing it), I'm all ears.
Just as the title states, is there an Adobe equivalent to the Java deployment.properties file?
I am writing a c# application to test installations of application in our network. The top three on my boss's list are java, flash, and reader. I need to be able to find out what versions of each application are installed on a machine for the reports im going to generate (force the user to update/etc).
I know i can check version number and confirm the ability of IE to access my JRE by checking "\Sun\Java\Deployment\deployment.properties". What file would I check to confirm the same for adobe reader and flash?
Thanks in advance for any help given or links provided to more info.
edit: I need to do this from the browser.
This is not a very clean solution, but since the only "official" way seems to be to check it from the Windows registries perhaps this will help:
We know that the flash files are located are in the (windows directory)\system32\Macromed\Flash (or SysWow64\Macromed\Flash on 64 bit systems).
Each time a flash updates it keeps the track of the progress in the log files. Depending on the flash version you will either have a) install.log (very old versions of flash) or b) FlashInstall.log
a) If you browse through the file you see various entires and one type goes like this:WriteRegStr: "HKEY_CURRENT_USER\SOFTWARE\Macromedia\FlashPlayer" "FlashPlayerVersion"="10.0.45.2".
Now you can just go through that file bottom-top and match the "FlashPlayerVersion"= string to get the most recent version.
However, this is for a really old versions of flash and the install.log file never got deleted from this directory, so make sure you check for the FlashInstall.log too!
b) Use a similar approach, except the new install logs don't keep the "WriteRegStr" information. Now you can instead look for the dll file name itself, for example my last update created an install log 0009 [I] 00000014 C:\WINDOWS\system32\Macromed\Flash\NPSWF32_11_5_502_146.dll, meaning my flash version is 11.5.502.146
another options are to
check the plugin core files creation date and compare with the versions release dates (quite unreliable in case someone somehow manages to install an older version)
check the actual property of the NPSWF[..version..].dll file. You can see all the complete and precise version details in the "Version" tab. however, I don't know how to access the rightclick->properties from inside a script, so you'll have to find out by yourself if you decide to go for this option
ask the unicorns
I'm writing a program that needs to access a file inside of c:\program files\program_name\.
My target file will always be inside of \program_name\program_name\bin\something.exe
However, because the program is extracted from an archive, if the user unpacks it improperly, it'll be simply \program_name\bin\something.exe, skipping a whole level.
Currently I'm basically getting the contents of c:\program files\, collecting the names of all folders that contain program_name, then adding them to the list and then using the list to loop through each one of those seeing if there's a program_name inside of it, etc, which should eventually lead me to the result.
Basically I'm creating large chunks of code for each individual possibility. Is there a smarter way to go about this?
Sounds like you could benefit from having an installer that writes to the registry. Then you'll know where all the files and folders are, even if the user installs to a weird location.
To expand on what Charlie said -- you could wrap the original app in some kind of unified installer type thing that would write the registry and extract the app to whatever place the user decides. The installer would prompt the user for the location to install to, and would extract to that location. InnoSetup can be configured to write the uninstall info, put uninstall links, etc. You can customize the uninstaller part of the InnoSetup script to do whatever cleanup you need, and/or call other external programs, if necessary.
InnoSetup allows you to package stuff in the actual installer exe, so you only have to distribute one flle. I can verify that this works -- although I've never tried it for packing huge files.
Here's a link to InnoSetup: http://www.jrsoftware.org/isinfo.php
I would like to add an "Uninstall" button to my program that will start the uninstaller to remove the program and then immediately quit. What's the best way to a) determine if there is an uninstaller present, and b) find the correct uninstaller and launch it?
Can I use the registry in a reliable manner? I recall using the registry before to fix some broken installations and was thinking I could iterate over the entries and identify the appropriate one, but I worry that using the registry might not be reliable and/or work on all systems?
Another thought is that I could actually store the uninstall information to the registry during the installation itself, and then use that information to somehow find the correct uninstaller. That seems like it would be the most reliable method, but is there such an identifier that I could store that I could then pass back to Windows Installer?
Since you taged this with windows-installer, I will assume that you are distributing your application using an MSI. That said, you can call msiexec /x {ProductCode} from your application to initial the uninstall. You can obtain the product code by having the installer write to a registry key/value that your application can read or you can hard code it or your UpgradeCode in your application. If you hard code the UpgradeCode you'll have to call into the Windows Installer API to find out the installed ProductCode for that UpgradeCode.
Just a quick question:
I'm in the finalizing state of my current C# project, and I'd like to send a version out to people that has 90% of the features initially requested, but it'll be a version of the software that will do all they need - they need the software as soon as possible, basically.
Therefore I'm going to be using the online install option in VS2008 that will use updating to add the final few features, as well as additional things, later. What I'm wondering is the following:
The program will come packaged with a .mdf file. When I create a new version of the program however, I don't want to change all of the data that has been added to the database already. My question is how do I go about doing this?
Thanks!
How are you planning to distribute the update? An installer will have flags indicating when a file should be replaced. (Date, version etc)
One-Click installation has the ability to check for changes on program startup.