I have an issue with my software installation / first time run on Vista / 7 in relation to the VirtualStore.
My software is written in C#. Installer: NSIS.
My application is installed using NSIS. It runs as administrator
After installation is finished, the user can immediately start the software from the installer.
This results in the first run of the program to be executed as admin.
During the first run, a wizard has to be completed. This wizard will import data from an older version of the software, that is already on the computer (C:\Program Files\OldProgram\Data)
However, on 7/Vista, this data is in the VirtualStore of the user. When I'm admin, I don't "see" this data and I can't convert it.
Questions:
Can I know which user is currently logged in?
Is there a generic way to access the Virtual Store of this user? Taking into account that the "Program Files" folder is named different is some countries and on 64-bits my app sits in "Program Files (x86)".
UserInfo::GetName will give you the username, use UserMgr if you need more control
Windows does not really provide a way to access another users special folders without their token, but this helper macro works in most cases. The name/location of the virtual store is not documented AFAIK so you have to get the closest special folder with GetUserShellFolderFromRegistry and then hardcode the VirtualStore part of the path...
If you want to launch a program as the user and not the administrator performing the install, use the UAC plugin (Or just remove the run checkbox on the finish page and let the user start the program normally)
Related
I am creating a service that access a folder path:
string localAppDataFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
Unfortunately, the folder returned is not:
C:\Users\mainuser\AppData\Local
... but:
C:\Windows\system32\config\systemprofile\AppData\Local
...instead.
mainuser is the user that is currently logged in. Is it possible for service to launch a program that is placed in current users AppData\Local? I am aware that you can go to Services-> Right click Properties-> Log on and type in password and account name, but I am looking for a programmatic solution, ideally using sc create command.
Alternatively, I can move all folders in interest to C:\ProgramData and completely avoid current user. Is there a way to keep the files in users AppData\Local and use programmatic solution without password?
In short, Services don't (and shouldn't) launch programs for users or access user information in general (unless they run as the specified user). They are agnostic of users and their profiles, their use-case is to run as part of the system
If you want to run an application when a user logs on, either use a group policy, or add it to the user settings to run on startup. If need be, set this up in the installer
This is the way every service works, and the norm for windows for a long time (with the exception of drivers)
I wrote a .NET console application that needs to be scheduled trough Windows scheduler. Such console performs some network and database activities and write a logfile. The application work if run on Desktop/Command prompt but if I try to run it trough the scheduler it refuse to start. Another issue I faced is the write access to the app folder. Even if I set permissions to the folder containing application binaries to be wrote by 'Everyone' the app seems unable to create the log file and/or append data to it. The problem fixes if I run the application with Administrator priviledges (on desktop) but if I define the Activity in the scheduler to Run with higher privildegs this will not fix it anyway.
Best course of action is to create a Service account with admin privileges and schedule the task under such account and select the option to run whether the user is logged on or off.
This approach is even more relevant where Active Directory is in place.
Hope this helps,
Apex
I found the issue... http://support.microsoft.com/kb/2452723
It seems that the "Start In" parameter of the Action should not contain quotes.
Of course the folder should be 'writetable' for the user assigned to the task.
Background
I've written a small C#/.NET 4.0 application that syncs various settings from a game installed in Program Files to and from other copies of the same game on different machines (think Chrome bookmark sync, but for this game). The sync itself is a relatively simple affair, dealing with files stored inside the game's Program Files folder.
On my machine, this works fine without having to elevate my application through UAC. Windows 7 makes the game use Program Files virtualisation and my application works fine with that.
However, on a lot of tester's machines, I'm getting reports that the application either can't work with the files and in come cases can't even see the game's folder! Having the user right-click and "Run as Administrator" solves the problem in every case.
So, we just set the application's manifest to require admin privileges, right? That's fine (although not ideal) for when the user manually invokes the application or the sync process because they'll be interacting with the application and ready to accept a UAC request.
However, one of the features of my application is a "Sync Automatically" option, which allows the user to "set and forget" the application. With this set, the application puts itself into the registry at HKCU\Software\Microsoft\Windows\CurrentVersion\Run to be run at startup and sits in the system tray syncing the settings in the background as needed.
Obviously, I need to be smarter here. Presenting a UAC prompt as soon as the user logs in to their account or at random intervals afterwards isn't the way forwards.
So, my question!
What's the best way to approach a situation where I'd need to run an application at startup that needs administrator privileges? Is there a way to have the user authorise an installation that causes the system to automatically run the application with the correct privileges without a prompt at startup/login?
Update Just to be clear, this must be achievable in code.
You should consider making your Sync functionality exist within a Windows Service.
This is the preferred method for running 'background' functionality on Windows.
The Service can either run under the user's account (assuming they have permissions to modify the files), or you can use another account which does. Worst case, you can run as SYSTEM (although, this isn't best practice).
If you've already got your background process functionality working, then this should be a simple process to convert over to a Service.
There's a sample project here that will set you on the right path: http://www.codeproject.com/KB/dotnet/simplewindowsservice.aspx
Since you mentioned running at startup, why not use a scheduled task instead of what you're doing with the registry? You can set them up from code - there's a project on CodePlex that is basically a managed wrapper to save you having to do the PInvokes yourself. You run your little "set up the startup task" app elevated, and it specifies that the app should launch elevated, and the user won't even be prompted. I believe that's the answer to the question in your last paragraph.
I would use Security namespace and check inline for the user roles.
using System.Threading;
using System.Security.Principal;
namespace StackOverflow_Demo
{
class Program
{
static void Main(string[] args)
{
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
WindowsPrincipal currentPrincipal = (WindowsPrincipal) Thread.CurrentPrincipal;
if (currentPrincipal.IsInRole("Administrators"))
{
// continue programm
}
else
{
// throw exception/show errorMessage - exit programm
}
}
}
}
The currentUser may start your application and will get an info message if he is not member of admininistrator role!
Hope this may help!
In c#, on a windows 7 machine, how can I programmatically access every file on the file system as though I was a "Master Administrator".
The main priority here, is that after my c# program is installed, that it won't run into any file/folder access permission problems. My program runs as a windows service, and it must allow a user to backup any files on the file system.
I would have thought that it would work if you just make sure that the service runs under an account in the Backup Operator group. I thought that group had access to all files no matter what permissions there are.
Quote from MS Support page:
SID: S-1-5-32-551
Name: Backup Operators
Description: A built-in group. By default, the group has no members. Backup Operators can back up and restore all files on a computer, regardless of the permissions that protect those files. Backup Operators also can log on to the computer and shut it down.
Though that page is for earlier versions of Windows so I'm not 100% certain that it's not been changed.
There is the Win32 backup API which is most likely what you want, maybe in combination with the Volume Shadow Service. And your application has to have the SeBackupPrivilege privilege. Note, though, that files encrypted with EFS can be read, but only in their encrypted form.
Links which may also be interesting for you:
http://mutable.net/blog/archive/2006/11/21/an-intelligent-backup-system-for-windows-part-3.aspx
http://msdn.microsoft.com/en-us/library/aa362520(v=VS.85).aspx
You will have to configure the service to run under an account with sufficient privileges.
AFAIK the standard 'Local System' already has rather high privileges. But no matter what, you won't be able to access files that are reserved to the System account, or files that are in use exclusively. Your program will always have to be able to handle Access related exceptions.
Background: I am by no means a windows security / user permissions expert. I have an application (written in C#), that has to be able to write / delete files & folders in its root directory, write / delete files elsewhere on the disk, write/modify values in System Registry (Local Machine) and start & stop other applications and services. I figure that I need administrator privileges for at least some of those actions.
I tried running this and on computers with UAC turned off it works great without any additional settings. However on computers with UAC turned on (any level above 'never notify' in Windows 7) it will crash. I need it to work on all computers.
Up to now I would just manually check the "run this program as administrator" checkbox and everything would be fine. However now we have decided that we will allow customers to install this software on their own, and it needs to run "out of the box".
I have a deployment project in Visual Studio 2008 that installs everything and writes the necessary start up data in registry. What I need to do now is to set the "Run this program as Administrator" flag. I am guessing this isn't quite as simple as I'd like it to be.
So What is the proper way of doing this? This program is started on startup, and it would be irritating for our customers if UAC would pop up (and possibly dim the screen) every time they restart their computer.
Thank you for your help.
EDIT: Thank you for your replies. I realise that working around UAC would be frowned upon, and I can see that Microsoft does not support "white lists" so it would ask for permission only once. That's fine I can respect that, however I do have some follow up questions:
Can you provide me with a link that will show me how to properly elevate the program to correct elevated state? Is there any literature on what are the options, etc... Basicly I'd love a UAC 101 guide.
Is there a way to elevate the security status when I need the extra privileges (and only then prompt with UAC). Basicly this applications runs in the background, doing mostly nothing for most of the time. Every now and again it will check some files (at this point I will require to be able to write to disk and read the registry (read only is fine at this point), however since it's a temporary folder it wouldn't matter where I'd put it. If there is a location where the application can write without any privileges that would be perfect.)
However at some point I will need to preform all the rest of the tasks (user needs to confirm this action anyway) so if UAC would prompt at this point that would be no problem. Is there a way to elevate it just at this point, and then return it to default permissions?
Will such a solution work with older versions of Windows, including Vista and Xp (and perhaps older?) What would it take to make it work?
The proper way is to elevate when the program starts, with the UAC prompt (which you can set via the program's manifest) - attempting to be clever and bypass it is frowned upon.
Think about it - if you could install something which would elevate automatically without the UAC prompt ... what would be the point of UAC?
To add a UAC manifest to a program you simply add the manifest in a project and edit it. A sample manifest for UAC is here. If you want to elevate at the last possible moment then you need a spawn separate process - you cannot elevate an existing process. So separate that bit out and then start it using
Process.StartInfo.UseShellExecute = true;
Process.StartInfo.Verb = "runas";
You need to rethink how your application works. You're quite correct that it would be annoying to display an elevation prompt on login. So don't do it. On the other hand, you may well have tasks which you need to perform using administrative access.
So you have two choices:
Change your tasks so that they no longer require administrative elevation (e.g., write your files elsewhere).
Break your application into a Windows service component and a user interface component. The service component can run under an elevated account (hopefully the least-elevated account necessary to perform the tasks you need to do). The user interface component can talk to the service (via named pipes or similar) when necessary.
You can split your program into two components:
a user application running without elevation
a Windows service that is responsible for the tasks that require elevation
Since you're using .NET, communication between the components is probably easiest done using WCF.
And as a side note: Programmatically modifying files under C:\Program Files is not considered good practice and might lead to a number of other problems. Windows has dedicated places for storing configuration settings and other program data.