While writing a utility, I needed a feature that it would run at startup. I also wanted to ensure that it is a configurable setting. Seemed like a pretty easy thing to do… and went for it, only to realize that it is not as easy as it looks initially. First up, creating a shortcut itself tends to be difficult in C# without using Interop. I chose to avoid Interop completely and I will share my thoughts in this post.
Without blabbering further, based on my research I found that the best way to go about this is…
Have the Installer create the shortcut inside your startup folder
In your application write code to move this shortcut away to a location of your choice [Application Data maybe]
In your application write code to move this back to Startup when required
Seems pretty easy, right? well the first two steps are indeed! The tricky part is the 3rd step above. When you try to do this using code, you will get Access Denied due to UAC. The dirty way is to run this Application as an Administrator and avoid this prompt.
A better approach, in my humble opinion is to elevate when required. Hence, when you do the setting change Windows should prompt you for this action. Here is how you can do all this in code.
This method will create a file called move.bat dynamically with appropriate paths. Then it will call a method called RunElevated, that method will runas administrator, and Windows Vista onwards should prompt you with a screen. I am doing this batch file thingy, you can use the 2nd Application of your choice. The idea is to run the main application with lesser power, and go fully elevated when required.
private void OnStartWithWindows(bool _StartWithWindows)
{
this.StartWithWindows = _StartWithWindows;
string startupPath = @"C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\YOUR_APP_LINK.lnk";
string appPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
try
{
using (StreamWriter sw = new StreamWriter(appPath + "\\move.bat", false))
{
if(!_StartWithWindows)
sw.WriteLine(string.Format("move /y \"{0}\" \"{1}\"", startupPath, appPath));
else
sw.WriteLine(string.Format("move /y \"{0}\" \"{1}\"", appPath + \\YOUR_APP_LINK.lnk,
startupPath));
sw.Close();
}
RunElevated(appPath + "\\move.bat");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private static bool RunElevated(string fileName)
{
ProcessStartInfo processInfo = new ProcessStartInfo();
processInfo.Verb = "runas";
processInfo.FileName = fileName;
try
{
Process.Start(processInfo);
MessageBox.Show("NAME OF YOUR APPLICATION will run automatically when Windows Restarts!");
return true;
}
catch (Win32Exception)
{
//This could be left blank, since it will be called only when the end user clicks Cancel
//MessageBox.Show(ex.Message);
}
return false;
}
Hope that helps,
Rahul
Quote of the day:
Personally I'm always ready to learn, although I do not always like being taught. - Sir Winston Churchill