Run C# Application on Windows Start up - c#

I'm trying to start a few applications for the current user only when Windows starts up.
I can accomplish this with the following:
RegistryKey oKey = Registry.CurrentUser.OpenSubKey("Software", true);
oKey = oKey.OpenSubKey("Microsoft", true);
oKey = oKey.OpenSubKey("Windows", true);
oKey = oKey.OpenSubKey("CurrentVersion", true);
oKey = oKey.OpenSubKey("Run", true);
oKey.SetValue("Application 1", "C:\\path\\to\\ap1.exe");
oKey.SetValue("Application 2", "C:\\path\\to\\ap2.exe");
But I'm trying to run this as part of a Visual Studio Installer Project. I've added my custom action, the program starts like it should, and the installer works great in XP.
In Windows 7, the installer gets elevated privileges, and does everything but insert the entries into the registry for the current user. How ever, it does insert the registry entries when ran as a standalone application (outside of the installer project) and it does not get elevated privileges.
The only thing I can figure is that with the elevated privileges, it's trying to insert the entries into the Administrators account instead of the current user? or is there something else I'm missing? and is there another way I can achieve my goal here?

Is there a reason to not use the startup folder for the user?
More than likely the problem is the user the installer is executing under. If the user isn't the admin the elevated installer will run under the context of the user who elevated the process.
It would be a safer choice to add your application to the startup folder or to add the registry key on first launch.

If the installer is getting elevated permissions, why write the setting to HKCU? Write it to HKLM instead. It will then take effect for all users.

Related

Can't Add Full Control to Settings File

I have a C# application which stores it's settings in ProgramData subfolder such as
C:\ProgramData\Manufacturer\Product\Version\Settings.xml
I noticed that the application can't save settings changes, getting a permission denied error. My work-around was to manually change security settings and give Everyone full control on the folder tree and file. This works, but I'd like a more robust method.
Using suggestions from SO, I created the following code:
private void set_permissions()
{
try
{
// Create security idenifier for all users (WorldSid)
SecurityIdentifier sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
// get file info and add write, modify permissions
FileInfo fi = new FileInfo(settingsFile);
FileSecurity fs = fi.GetAccessControl();
FileSystemAccessRule fsar =
new FileSystemAccessRule(sid, FileSystemRights.FullControl, InheritanceFlags.None, PropagationFlags.None, AccessControlType.Allow);
fs.AddAccessRule(fsar);
fi.SetAccessControl(fs);
LogIt.LogInfo("Set permissions on Settings file");
}
catch(Exception ex)
{
LogIt.LogError(ex.Message);
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
When I step through the code, I get
Attempted to perform an unauthorized operation exception
when I execute this statement:
fi.SetAccessControl(fs);
If I close Visual Studio 2015 and open it as administrator, then my code will execute properly and the file security now has an entry for Everyone with full control.
So finally, here comes the question:
I'm following suggestion of putting the above code in my application, then in the setup project I add a custom action to run the newly installed application with an Install command-line option. My application, if it sees "Install" argument, will run the above code. Since I'm using a setup project which installs for all users by default, it automatically gives the administrator prompt before install. Does that mean the entire session, including the special action to run the application after install, is running under administrator rights?
If so, this should work, right?
But if the person installing changes it to "This user" then it would not be running with admin rights, and my code will fail. If needed, I could always be the one to do the final install and therefore would always use the administrator prompt, but I hate to depend on that.
Is there a more proper way to do this?
Thanks...
It seems that your program is not running elevated and therefore cannot update files in that location, and I assume that you want your users to not require admin privilege that you could add using an elevation manifest in your program.
So why choose that location to store the data? Why not just use User's Application Data folder?
As for that code, it's probably more robust to add it as an installer class custom action rather than run an executable. In an Everyone install that runs elevated the code will run privileged with the local system account.

Detecting elevated privileges on Windows Server 2008 or higher

I have an C#, .Net 4.6.1 Windows Forms Application running on Windows Server Platforms (2008 or higher) which requires to be "Run as Administrator". Elevated privileges are required because the application changes User Access Rights on various folders (underneath the IIS Default Web Site Root if that matters).
I have no luck in detecting if the application has been "Run as Administrator". If I start the application normally (that is not as Administrator) the following code
var isAdmin = WindowsIdentity.GetCurrent().Owner.IsWellKnown(WellKnownSidType.BuiltinAdministratorsSid);
returns true but the code which changes some User Access Rights on a Directory fails with a Insufficient Privileges Error.
If I run the application as administrator the above check also returns true, but the changing of User Access rights works just fine.
Other attempts I have made without success:
Using the GetTokenInformation method inside the advapi32.dll as suggested here
Adding a manifest file to the application where I set the requestedExecutionLevel to requireAdministrator
Thanks in advance for any help.
The following must work (I hope so; I have a Windows client and it's working with me).
var Identity = WindowsIdentity.GetCurrent();
var Principal = new WindowsPrincipal(Identity);
bool IsAdmin = Principal.IsInRole(WindowsBuiltInRole.Administrator);
Try to change the permissions of a known folder and if there is an exception then you know the program has not been run as administrator.

run wix batch script as elevated/admin

I have written a WIX Installer using wixsharp that wraps a legacy installation procedure that used a batch file.
When running the MSI as an non-admin I do get prompted to elevate (the UAC dialog) however the batch script is run as a non-admin
var project = new Project(string.Format("App");
project.Actions = new[] { new PathFileAction(#"C:\build\build_script.bat", args[1], #"C:\build\", Return.check, When.After, Step.InstallExecute, Condition.NOT_Installed, Sequence.InstallExecuteSequence) };
project.UI = WUI.WixUI_InstallDir;
One way around this is to start a command prompt as Administrator and run the MSI using msiexec - this works but is very clunky.
How can I make my PathFileAction run as Administrator?
I used this answer which is based on pure WIX - you need to add Execute='deferred' Impersonate='no' to the output xml so in wixsharp this is possible via Attributes...
var publishAction = new PathFileAction(#"C:\build\build_script.bat"...
publishAction.Attributes = new Dictionary<string, string>()
{
{"Execute", "deferred"},
{"Impersonate", "no"}
};
UPDATE: this will run the script as NT AUTHORITY\SYSTEM - if you want to run it as yourself (with elevated permissions) it appears this is not possible
I can't see the contents of build_script.bat but I assume it's installing the MSI silently. In this scenario UAC prompts aren't possible so the installer exits out with a no priv failure. You have to run the .bat file elevated or you have to "bless" the MSI by advertising (msiexec /jm) it first so that it'll self elevate in place from the non elevated user process.

Mark MSI so it has to be run as elevated Administrator account

I have a CustomAction as part of an MSI.
It MUST run as a domain account that is also a member of the local Administrators account.
It can't use the NoImpersonate flag to run the custom action as NT Authority\System as it will not then get access to network resources.
On Vista/2008 with UAC enabled if NoImpersonate is off then it will run as the executing user but with the unprivileged token and not get access to local resources such as .installState. See UAC Architecture
Anyone know of a way to either
Force the MSI to run with the elevated token in the same way that running from an elevated command prompt does?
Force the CustomAction to run elevated (requireAdministrator in manifest doesn't appear to work)?
Work out if UAC is enabled and if it hasn't been ran elevated and if so warn or cancel the installation?
Answering my own question for any other poor s0d looking at this.
You can't add a manifest to an MSI. You could add a SETUP.EXE or bootstrapper to shell the MSI and manifest that with requireAdministrator but that defeats some of the point of using an MSI.
Adding a manifest to a CustomAction does not work as it is ran from msiexec.exe
The way I have tackled this is to set the MSIUSEREALADMINDETECTION property to 1 so the Privileged condition actually works and add a Launch Condition for Privileged that gives an error message about running via an elevated command prompt and then quits the installation.
This has the happy side effect - when an msi is ran from an elevated command prompt deferred CustomActions are ran as the current user with a full Administrator token (rather than standard user token) regardless of the NoImpersonate setting.
More details - http://www.microsoft.com/downloads/details.aspx?FamilyID=2cd92e43-6cda-478a-9e3b-4f831e899433
[Edit] - I've put script here that lets you add the MSIUSEREALADMINDETECTION property as VS doesn't have ability to do it and Orca's a pain.
requireAdministrator in the manifest should work.
You can also use a bootloader .exe file which can use ShellExecute with "RUNAS" as the verb (you can use 7-zip to create the bootloader, or there are many other ways).
You can creating a simple sfx archive file for msi file with Winrar and these options:
Setup tab > Run after execution input: your msi file name
Advanced tab > Mark Request Administrative access option checkbox

Uninstall Command Fails Only in Release Mode

I'm able to successfully uninstall a third-party application via the command line and via a custom Inno Setup installer.
Command line Execution:
MSIEXEC.exe /x {14D74337-01C2-4F8F-B44B-67FC613E5B1F} /qn
Inno Setup Command:
[Run]
Filename: msiexec.exe; Flags: runhidden waituntilterminated;
Parameters: "/x {{14D74337-01C2-4F8F-B44B-67FC613E5B1F} /qn";
StatusMsg: "Uninstalling Service...";
I am also able to uninstall the application programmatically when executing the following C# code in debug mode.
C# Code:
string fileName = "MSIEXEC.exe";
string arguments = "/x {14D74337-01C2-4F8F-B44B-67FC613E5B1F} /qn";
ProcessStartInfo psi = new ProcessStartInfo(fileName, arguments)
{
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = true
};
Process process = Process.Start(psi);
string errorMsg = process.StandardOutput.ReadToEnd();
process.WaitForExit();
The same C# code, however, produces the following failure output when run as a compiled, deployed Windows Service:
"This action is only valid for products that are currently installed."
Additional Comments:
The Windows Service which is issuing
the uninstall command is running on
the same machine as the code being
tested in Debug Mode. The Windows
Service is running/logged on as the
Local system account.
I have consulted my application logs
and I have validated that the
executed command arguments are thhe
same in both debug and release mode.
I have consulted the Event Viewer
but it doesn't offer any clues.
Thoughts? Any help would be greatly appreciated. Thanks.
Step 1: Check the MSI error log files
I'm suspicious that your problem is due to running as LocalSystem.
The Local System account is not the same as a normal user account which happens to have admin rights. It has no access to the network, and its interaction with the registry and file system is quite different.
From memory any requests to read/write to your 'home directory' or HKCU under the registry actually go into either the default user profile, or in the case of temp dirs, c:\windows\temp
I've come across similar problems in the past with installation, a customer was using the SYSTEM account to install and this was causing all sorts of permission problems for non-administrative users.
MSI log files aren't really going to help if the application doesn't appear "installed", I'd suggest starting with capturing the output of MSIINV.EXE under the system account, that will get you an "Inventory" of the currently installed programs (or what that user sees installed) http://blogs.msdn.com/brada/archive/2005/06/24/432209.aspx
I think you probably need to go back to the drawing board and see if you really need the windows service to do the uninstall. You'll probably come across all sorts of Vista UAC issues if you haven't already...
Thanks to those offering help. This appears to be a permissions issue. I have updated my service to run under an Administrator account and it was able to successfully uninstall the third-party application. To Orion's point, though the Local System account is a powerful account that has full access to the system -- http://technet.microsoft.com/en-us/library/cc782435.aspx -- it doesn't seem to have the necessary rights to perform the uninstall.
[See additional comments for full story regarding the LocalSystem being able to uninstall application for which it installed.]
This is bizarre. LocalSystem definitely has the privileges to install applications (that's how Windows Update and software deployment in Active Directory work), so it should be able to uninstall as well.
Perhaps the application is initially installed per-user instead of per-machine?
#Paul Lalonde
The app's installer is wrapped within a custom InnoSetup Installer. The InnoSetup installer, in turn, is manually executed by the logged in user. That said, the uninstall is trigged by a service running under the Local System account.
Apparently, you were on to something. I put together a quick test which had the service running under the LocalSystem account install as well as uninstall the application and everything worked flawlessly. You were correct. The LocalSystem account has required uninstall permissions for applications in which it installs. You saved the day. Thanks for the feedback!

Categories

Resources