Writing Run (on startup) registry key - c#

My goal is to have my application run on startup.
My problem is my application is not writing to 'Run' in regedit.
I have this code
RegistryKey rWrite = Registry.CurrentUser.OpenSubKey(#"HKey_Current_User\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
and I believe what this is suppose to do is write my application to
HKey_Current_User\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\run
However, this is not writing anything to regedit.
Things to note:
My application forces the user to run in administrator. It essentially checks if they have ran in administrator and if they haven't it displays a messagebox then closes the program with
Environment.Exit(0);

You got the Key with write access (Probably does not exist because you got CurrentUser inside CurrentUser), but you are not setting any values inside. If you want your program to start, you need to set your application path inside. Here's how you would do it:
var rWrite = Registry.CurrentUser.OpenSubKey(#"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
rWrite.SetValue("YourOwnKeyForYourApp",
AppDomain.CurrentDomain.BaseDirectory + AppDomain.CurrentDomain.FriendlyName);

Related

Setting a C# WPF program to start on boot [duplicate]

I have a small application with a CheckBox option that the user can set if they want the app to start with Windows.
My question is how do I actually set the app to run at startup.
ps: I'm using C# with .NET 2.0.
Thanks to everyone for responding so fast.
Joel, I used your option 2 and added a registry key to the "Run" folder of the current user.
Here's the code I used for anyone else who's interested.
using Microsoft.Win32;
private void SetStartup()
{
RegistryKey rk = Registry.CurrentUser.OpenSubKey
("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
if (chkStartUp.Checked)
rk.SetValue(AppName, Application.ExecutablePath);
else
rk.DeleteValue(AppName,false);
}
Several options, in order of preference:
Add it to the current user's Startup folder. This requires the least permissions for your app to run, and gives the user the most control and feedback of what's going on. The down-side is it's a little more difficult determining whether to show the checkbox already checked next time they view that screen in your program.
Add it to the HKey_Current_User\Software\Microsoft\Windows\CurrentVersion\Run registry key. The only problem here is it requires write access to the registry, which isn't always available.
Create a Scheduled Task that triggers on User Login
Add it to the HKey_Local_Machine\Software\Microsoft\Windows\CurrentVersion\Run registry key. The only problem here is it requires write access to the registry, which isn't always available.
Set it up as a windows service. Only do this if you really mean it, and you know for sure you want to run this program for all users on the computer.
This answer is older now. Since I wrote this, Windows 10 was released, which changes how the Start Menu folders work... including the Startup folder. It's not yet clear to me how easy it is to just add or remove a file in that folder without also referencing the internal database Windows uses for these locations.
Here is all way to add your program to startup for Windows Vista, 7, 8, 10
File path
C:\Users\Bureau Briffault\AppData\Roaming\Microsoft\Windows\Start
Menu\Programs\Startup (Visible from task manager, Running on current
user login success, No admin privileges required)
C:\Users\Default\AppData\Roaming\Microsoft\Windows\Start
Menu\Programs\Startup (Visible from task manager, Running on all user
login success, Admin privileges required)
Registry path
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
(Visible from task manager, Running on current user login success, No
admin privileges required)
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce
(Not visible from task manager, Running on current user login success,
Running for one login time, No admin privileges required)
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
(Visible from task manager, Running on all user login success, Admin
privileges required)
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce
(Not visible from task manager, Running on all user login success,
Running for one login time, Admin privileges required)
Task scheduler
Microsoft.Win32.Taskscheduler.dll (Not visible from task manager,
Running on windows boot, Running as admin, Admin privileges required)
It`s a so easy solution:
To Add
Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
key.SetValue("Your Application Name", Application.ExecutablePath);
To Remove
Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
key.DeleteValue("Your Application Name", false);
In addition to Xepher Dotcom's answer, folder path to Windows Startup should be coded that way:
var Startup = Environment.GetFolderPath(Environment.SpecialFolder.Startup);
/// <summary>
/// Add application to Startup of windows
/// </summary>
/// <param name="appName"></param>
/// <param name="path"></param>
public static void AddStartup(string appName, string path)
{
using (RegistryKey key = Registry.CurrentUser.OpenSubKey
("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true))
{
key.SetValue(appName, "\"" + path + "\"");
}
}
/// <summary>
/// Remove application from Startup of windows
/// </summary>
/// <param name="appName"></param>
public static void RemoveStartup(string appName)
{
using (RegistryKey key = Registry.CurrentUser.OpenSubKey
("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true))
{
key.DeleteValue(appName, false);
}
}
You can create a registry entry in "HKCU\Software\Microsoft\Windows\CurrentVersion\Run", just be aware that it may work differently on Vista. Your setting might get "virtualized" because of UAC.
If an application is designed to start when Windows starts (as opposed to when a user logs in), your only option is to involve a Windows Service. Either write the application as a service, or write a simple service that exists only to launch the application.
Writing services can be tricky, and can impose restrictions that may be unacceptable for your particular case. One common design pattern is a front-end/back-end pair, with a service that does the work and an application front-end that communicates with the service to display information to the user.
On the other hand, if you just want your application to start on user login, you can use methods 1 or 2 that Joel Coehoorn listed.
if you using wpf, the "ExecutablePath" don't work. So i made a code that work on wpf too.
using (RegistryKey key = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true))
{
key.SetValue(
"AutoStart.exe",
"\"" + System.Reflection.Assembly.GetExecutingAssembly().Location + "\""
);
}
I found adding a shortcut to the startup folder to be the easiest way for me. I had to add a reference to "Windows Script Host Object Model" and "Microsoft.CSharp" and then used this code:
IWshRuntimeLibrary.WshShell shell = new IWshRuntimeLibrary.WshShell();
string shortcutAddress = Environment.GetFolderPath(Environment.SpecialFolder.Startup) + #"\MyAppName.lnk";
System.Reflection.Assembly curAssembly = System.Reflection.Assembly.GetExecutingAssembly();
IWshRuntimeLibrary.IWshShortcut shortcut = (IWshRuntimeLibrary.IWshShortcut)shell.CreateShortcut(shortcutAddress);
shortcut.Description = "My App Name";
shortcut.WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory;
shortcut.TargetPath = curAssembly.Location;
shortcut.IconLocation = AppDomain.CurrentDomain.BaseDirectory + #"MyIconName.ico";
shortcut.Save();
You can do this with the win32 class in the Microsoft namespace
using Microsoft.Win32;
using (RegistryKey key = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true))
{
key.SetValue("aldwin", "\"" + Application.ExecutablePath + "\"");
}
Important addition to other's answers using Application.ExecutablePath: if one of the folders containing your exe contains some strange chars (like mine had C# name) then Application.ExecutablePath will return path with different slashes which will result in it not working.
Application.ExecutablePath.Replace('/', '\\') is more appropriate
Add an app to run automatically at startup in Windows 10
Step 1: Select the Windows Start button and scroll to find the app you want to run at startup.
Step 2: Right-click the app, select More, and then select Open file location. This opens the location where the shortcut to the app is saved. If there isn't an option for Open file location, it means the app can't run at startup.
Step 3: With the file location open, press the Windows logo key + R, type shell:startup, then select OK. This opens the Startup folder.
Step 4: Copy and paste or Create the shortcut to the app from the file location to the Startup folder.

Launch Windows Form Program on Startup

I am using below code for launch my program on startup:
RegistryKey rk = Registry.CurrentUser.OpenSubKey
("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
rk.SetValue(AppName, Application.ExecutablePath);
but when run my project this error occourrs:
System.UnauthorizedAccessException: 'Attempted to perform an unauthorized operation.'
There was this issue a long time ago.
first you need to set registry in HKCU\Software\Microsoft\Windows\CurrentVersion\Run make sure you have enough permissions!:
using (RegistryKey key = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true))
{
key.SetValue(AppName, Application.ExecutablePath);
}
Then follow the steps from this post:
Add it to the current user's Startup folder. This requires the least permissions for your app to run, and gives the user the most
control and feedback of what's going on. The down-side is that it's a
little more difficult determining whether to show the checkbox already
checked next time they view that screen in your program.
Add it to the HKey_Current_User\Software\Microsoft\Windows\CurrentVersion\Run
registry key. The only problem here is that it requires write access
to the registry, which isn't always available.
Create a Scheduled Task that triggers on User Login
Add it to the HKey_Local_Machine\Software\Microsoft\Windows\CurrentVersion\Run
registry key. The only problem here is that it requires write access
to the registry, which isn't always available.
Set it up as a windows service. Only do this if you really mean it, and you know for sure you want to run this program for all
users on the computer.

Preventing registry entry code from requiring admin previliges

In my application, I am trying to set my application as startup by adding registry entry using the following code:
RegistryKey startupapp = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
startupapp.SetValue("App", "\"" + Assembly.GetExecutingAssembly().Location + "\"" +" -start");
But the problem is the registry is added only when I run my application as an administrator. Is there any way I could avoid this this thing, so that my application could add/delete registry entries for the startup app?
That is because HKLM requires admin rights to write to. HKCU doesn't require that.
RegistryKey startupapp = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
startupapp.SetValue("App", "\"" + Assembly.GetExecutingAssembly().Location + "\"" +" -start");
Since you want to set the application to run on startup for all users, no, you cannot get around requiring some kind of administrator access.
Why is this? Well, as a thought experiment, let's say that Windows allowed applications to set programs to run on startup without requiring an administrator password. But this would defeat the purpose of a lot of the security improvements in Vista, with the introduction of UAC and the advent of non-administrator accounts by default. A user could download a game that was actually a Trojan, and the game could set some malware to run on startup for all users, all without requiring the UAC prompt. Therefore, Windows doesn't allow you to set the program to run on startup without administrator rights.
There are some tricks you can use to get around requiring the user to run your whole program as an administrator, though. My first idea is to have a second program whose sole job is to set the main program to run on startup, and to start it with option ProcessStartInfo.Verb = "runas" (assuming that you're using System.Diagnostics.Process to start the new process) so that the helper program runs as an administrator, but your overall application can be started without the UAC prompt.
EDIT: In response to your comment
Yes, if you only care about starting the program on startup for a single user, you have a lot more options. As this O'Reilly article describes, one option is to write to HKCU\Software\Microsoft\Windows\CurrentVersion\Run in order to set your program to run at startup for the current user.

Programmatically change the Windows Shell

I'm working on a project that will be "embedded" into a Windows 7 system, this is going to be achieved by disabling task manager and changing the windows shell to the application, as well as other things.
What I'm looking to do here is programmatically change the Windows shell between the application and explorer.exe, I would like to know if there's any way to do this in C#.
Currently I have a few lines of code that attempt to change the registry entry for the Windows Shell, but nothing appears to happen after refreshing the Registry Editor, the code looks like this:
regKey = Registry.LocalMachine.OpenSubKey("SOFTWARE", true).OpenSubKey("Microsoft", true).OpenSubKey("Windows NT", true).OpenSubKey("CurrentVersion", true).OpenSubKey("Winlogon", true);
regKey.DeleteValue("Shell");
regKey.SetValue("Shell", shell);
regKey.Close();
I've tried restarting windows to see if that allows the shell change to complete, but to no avail.
I'd greatly appreciate it if someone can tell me if it's even possible to do it programmatically, and where I'm going wrong with it.
Also, I'd be grateful to know if there's a way to code the program so that it's always running with admin privileges so that registry editing will work.
Many Thanks,
Richard
After much searching of other locations on the net, I have finally got the Shell to change to the executable file of the application that is being built.
The "Embedding" process is a three step process, in the case of the software I'm working on, we start by disabling Task Manager, We then set the shell executable in the Local Machine registry and then repeat the process in the Current User registry.
Below is the code that achieves this:
public void embedSoftware()
{
try
{
// Disable Task Manager
regKey = Registry.CurrentUser.OpenSubKey(subKey, true).CreateSubKey("System");
regKey.SetValue("DisableTaskMgr", 1);
regKey.Close();
// Change the Local Machine shell executable
regKey = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", true);
regKey.SetValue("Shell", shell, RegistryValueKind.String);
regKey.Close();
// Create the Shell executable Registry entry for Current User
regKey = Registry.CurrentUser.OpenSubKey(#"Software\Microsoft\Windows NT\CurrentVersion\Winlogon", true);
regKey.SetValue("Shell", shell);
regKey.Close();
MessageBox.Show("Embedding Complete");
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
In this example the variable "shell" is a string containing the path of the executable to use as the new Windows Shell.
Further to this there's a method to "un-embed" the software, this method simply deletes the "DisableTaskMgr" and "Shell" values from the Current User registries, it also resets the "Shell" value in the Local Machine registry to "explorer.exe".
I hope this helps others out there who're having trouble changing Windows Shells programmatically.
Regards,
Richard

Get current user name when starting with UAC

Our setup has an embedded manifest that triggers the UAC before the application starts. (The applications runs as an admin user). However, if the setup needs to install the .NET Framework, we have to continue the setup after a reboot. For this reason, we have to create a registry key in the current user's RunOnce.
Unfortunatly, HKEY_CURRENT_USER points to the Administrator's registry. We need to find out the user that is currently logged in and started the installation. (Th normal USER clicked the setup.exe, an ADMIN entered his details in the UAC prompt. We need to find out who the USER was)
I've tried all the usual methods (Environment.UserName, WindowsIdentity.GetCurrent())
Thanks!
You can use the LsaEnumerateLogonSessions function to retreive what you need. However, it is a winapi C function call. If you need a managed version of it, I belive you can look at the source code for Cassia, which uses this function in its terminal services API. The call should be the same. You can also look here.
Also you can use the NetWkstaUserEnum WINAPI function. You can find a managed wrapper for it here
With Cassia library this code works fine:
ITerminalServicesManager manager = new TerminalServicesManager();
ITerminalServicesSession session = manager.CurrentSession;
string userInfo = session.DomainName + "\\" + session.UserName;
NTAccount account = session.UserAccount;
Run your initial setup.exe as a small executable that puts up a splash screen while invoking your real setup program as a child process. The small EXE is not run as admin and can pass the logged in user name to the child process. The child process invokes UAC and runs in the admin context but already has the logged in username as a command line parameter.
It is not possible to retrieve the original user if your application is ran as Administrator:
If a user launches Setup by right-clicking its EXE file and selecting
"Run as administrator", then this flag, unfortunately, will have no
effect, because Setup has no opportunity to run any code with the
original user credentials. The same is true if Setup is launched from
an already-elevated process. Note, however, that this is not an Inno
Setup-specific limitation; Windows Installer-based installers cannot
return to the original user credentials either in such cases.
Source : InnoSetup Help
As said by Matthew in comments, you should not run your application as Administrator but only trigger UAC when needed in your code.
This returns the name of the logged in Windows User by stripping out the domain:
using System.Security.Principal; // here is the security namespace you need
...
string userName = WindowsIdentity.GetCurrent().Name.Replace("\\", "|");
string[] split = userName.Split(new Char[] { '|' });
lblDebug.Text = (split.Count() > 1) ? split[1] : userName;

Categories

Resources