I want to catch first run of the application after installation. I know that I can use user settings. for example:
if(Properties.Settings.Default.CheckFirstTime == true)
{
MessageBox.Show("1st run");
Properties.Settings.Default.CheckFirstTime = false;
Properties.Settings.Default.Save();
}
else
{
MessageBox.Show("Later run");
}
But in this case, it is not possible to catch first run when the user uninstalls and reinstalls the application again.
Also, I don't want to use a database, because it may be replaced with a manipulated database.
What's the best way to ensure catching the first run of the application after installation?
Depending on your installation method, it could be worth using the registry for this.
When the program is initially installed, there will be no registry keys to store the properties.
If they are not present, write them into the registry as it's assumed to be the first run.
Using this approach, the keys will not be removed when uninstalling as the program manages them itself rather than allowing the installer to handle it.
The following link describes interacting with the registry in C#.
https://www.codeproject.com/Articles/3389/Read-write-and-delete-from-registry-with-C
If you're using MSI for the installer package, you can configure it to leave behind the registry data when uninstalling, which will work around the issue. This is configured differently depending on the tool you use to create the MSI, but as it's supported by the format, it should be implemented in most installation builders than support generating an MSI.
If using install shield, the following section of the documentation describes how to create and remove registry keys - http://helpnet.flexerasoftware.com/installshield23helplib/helplibrary/IHelpRegistryKeys.htm
Related
I've written a WPF application with an accompanying Windows setup project. The application has an option to 'Run on startup', at which point a key is added to the SOFTWARE\Microsoft\Windows\CurrentVersion\Run registry. The setup project doesn't create this key by default because the option is disabled by default; however, I want to make sure if someone uninstalls the application the registry key will be removed.
Is this possible? Also, what is the behavior if the key isn't removed? I've assumed Windows will try to run the application and nothing will happen but I have yet to test this situation.
Edit - As requested, the registry key is set up from code as follows:
using (var key = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true))
{
if (key != null)
{
key.SetValue("MyApp", "\"" + System.Reflection.Assembly.GetExecutingAssembly().Location + "\"");
}
}
It is done this way because by default, I don't want the app to run on startup; thus, the registry key shouldn't be created until the user opts to use that setting.
If you created that key data with an install custom action, then you'll need to create an uninstall custom action to remove it. Strictly speaking you should also include a rollback custom action to remove it in case your install fails and rolls back.
An MSI file is a database of changes to the system - that's why anything in there can be uninstalled, but it doesn't keep track of changes you make with your code.
I'd be tempted to make this an option somewhere in the application cofiguration, not the install, so the app could have an option "start at logon time" that the user could turn on and off. Currently anyone that wants to change that setting has to fiddle with the registry or re-install the app, depending on how smart they might be about this stuff.
With other install tools you get more choices. For example, Visual Studio doesn't do multiple features. With another tool (such as WiX) you could create a feature that the user checks if the Start is required, and that feature contains the component that creates the registry key using Windows Installer registry entries instead of code. Apart from there being no coding, the entry gets removed at uninstall time; the user can go into maintenance mode and uninstall (or add) the feature at any time; install failure will clean it up automatically. And that's just one way of providing the functionality.
Visual Studio setups are relatively easy to use because they expose only a limited set of Windows Installer features, so you get some simplicity but you pay for it if you want to go beyond the capabilities that VS setups provide. But you also get involved more deeply in Windows Installer.
I'm working on an application (A) that has to react and do something when a specific program (B) is installed on the system.
I've been seeing a lot of examples about listing programs already installed using the registry keys and some code to monitor status changes on programs and services using WMI.
I'm thinking I could use those combined to do what I want, say:
1. When my application (A) is started, check on the registry if my program (B) is installed or not (initial condition).
2. Then, monitor for service changes on the local machine from my application (A).
3. And every time a report of status changes comes from service "msiserver", re-check if my program (B) has been installed/uninstalled (initial condition has changed), and do something if so.
This sounds to me like I'm trying to reinvent the wheel here, and I wonder if any of you know if there's a more "natural " or "immediate" way to catch the moment/event when a specific program has been installed on the system ...or not :/
Additional considerations: The default location where the program (B) can be installed is variable, so monitoring for folders (like C:\Program Files) is not an option.
Thanks!
I'm not aware of any mechanism that would allow you to subscribed to an OnInstalled type event. You'd have to loop and detect the installation status change. Perhaps using the Microsoft.Deployment.WindowsInstaller (DTF) library to enum products and/or components. Don't use WMI... the Win32_Product class is horribly slow and querying it causes reinstalls of applications. (Don't ask... it just sucks).
I'm using .NET user settings feature and I'm facing a problem.
When the application is uninstalled, then installed back, the user settings are lost.
I understand it's by design, and I want to be able to give the choice to the user in the installer.
Could you please give me some pointers to articles or documentation that will helps me?
Thanks a lot
.NET User Settings are not removed on uninstall. In fact the settings of all previous versions of the software are preserved in Local Settings directory.
When the new version is installed, a new version of the settings is created and default settings are used.
To ensure your application will merge new settings with previous configuration, you have to call Settings.Default.Upgrade() method.
So the solution is to manually remove settings on uninstall if we don't want to preserve them. Since what I needed was preserving previous settings, all I do now is creating a new setting called UpgradeRequired with true has the default value, then add this code at application startup:
if (Properties.Settings.Default.UpdateRequired)
{
Properties.Settings.Default.Upgrade();
Properties.Settings.Default.UpdateRequired = false;
}
You could possibly write the settings you wish to save out to the registry or write them as an XML file to a location that won't be impacted by the uninstall.
If you want to keep using User Settings i would suggest writing a custom installer class, and implement the onUninstalling method, to go find the file and copy it to another location known to the onInstall method of your custom installer. So that the next time the installer runs it could find the file.
I don't think you want to actually persist data on the users machine after an uninstall. Leaving files around is an evil practice, a big no-no. You should expose a feature in the application itself to either export those settings to a location of their choice and to then import it again after re-installing the app or to synchronize those settings onto a server so they're automatically available upon re-install, etc. On an uninstall you should leave no trace behind.
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.
How do I force a windows application, with a setup project being added to it, to install so that it will start everytime someone logs into windows?
Edit: I'm aware of the registry settings, but specifically, I am looking for a solution which will allow for the installer to set the registry values.
Open your registry and find the key
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run].
For each program you want to start automatically create a new string value using a descriptive name, and set the value of the string to the program executable.
For example, to automatically start Notepad, add a new entry of
"Notepad"="c:\windows\notepad.exe".
Remove a startup application
If you're trying to remove a program and can not find it in the StartUp folder (usually C:\WINDOWS\Start Menu\Programs\StartUp), then it may be launching from one of the registry keys below. To remove it, delete the value associated with the program you want to remove.
[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run]
[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce]
[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunServices]
[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunServicesOnce]
[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\Userinit]
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run]
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce]
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunServices]
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunServicesOnce]
[HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows]
Source: http://www.pctools.com/guides/registry/detail/109/
If you really need your application to start when Windows is started as opposed to when someone logs in you need to create it as service and on install set the service to "Automatic".
There are many places on the web that will give you information about this:
Microsoft Support Knowledge Base
Developer.com
C# Corner
are the first three I found, but do some research and find the resource that works for you.
UPDATE
I see from the updated question that the requirement is for the program to run when someone logs in so this answer is (to a certain degree) redundant. However, I will leave it here in case someone wants to go the service root.
You can add a shortcut to your winforms program in the Startup Folder. The setup project's File System is where you need to look.
Technically you can't make a WinForms app start when "windows is started"; however, you can start it when someone logs into Windows. To perform that you do one of the three:
Place a shortcut in the current user's startup folder.
Place a shortcut in the the "All Users" startup folder.
Write a registry key to HKLM/Software/Microsoft/Windows/CurrentVersion/Run
Update: as Chris points out I missed the HKCU path.
To run everytime Windows starts you should build your program as a Windows Service (or perhaps lauch it from a Service).