Basically, I have an application that is installed on the users computers.
The users are on Windows 7.
The users are NOT given admin access.
The application, however, needs to be able to save files to its own Program Files directory.
The path I wanted to take was:
Download various binaries (web service).
Write binary to files in temporary folder.
Launch a console app. (Console App waits for the main app to shutdown)
Console App copies the temporary files to the Program Files directory.
Console App relaunches the main app.
Console App shuts down.
The problem is that I know Windows 7 does not allow applications that are not running as administrator to write to the Program Files directory, and I understand why (for security), but since I am writing this app myself, installing it on the machines myself, is there any way to make my app be able to write to whichever directory it resides in (platform independent because it uses relative paths) without having a popup box ask to run the app as admin? Can't the app be signed to ALWAYS run as admin?
In fact, I don't even need the main application to be the one that runs with administrative access. I need the console-app (the one that copies the temporary files) to be able to copy those temporary files as permanent files.
Update: Yes, this is for an auto-updating application. I thought about ClickOnce and the such, but there are additional requirements which lead me to create my own internal updating, mainly because the updates need to be silent and piece by piece. Sometimes (depending on the pieces updated) the application needs to shutdown, move the files in, restart. Other times the application simply needs to move the files in and continue running.
ClickOnce just didn't work for my situation, and our organization was looking for something in-house so it can be customized to fit our future needs.
As the comments already pointed out: ProgramFiles is inaccessible if you have a somewhat recent version of Windows (Vista+), UAC enabled (the default) and non-admin users.
Your updated question says that you need to update (at least parts of) your application and that might need a restart. You created your own way to update the modules.
My suggestion is the following: Don't write to ProgramFiles
Either install your application completely to the user profile or split it up.
I'd try to create an executable that does very litte:
Sets up shadowing so that assemblies are not locked
Look up an assembly in a writable location (ProgramData or in the user profile) and load it
Run the app from there
In case of an update you can overwrite your assemblies (since they are shadowed and stored in a sensible location) and, if necessary, stop the program/ask the user to relaunch/implement a restart mechanism. You shouldn't need administrative privileges for this.
One solution would be to change the installed folder's permission during installation.
echo y| cacls /E /T /P Users:F
To understand how the UAC works first try to use the term PROCESS instead of app and read this:
RIGHTS for a PROCESS are determined before the process starts
Every Process that is spawned from another inherits its security or:
Asks for elevation
From this you can deduce that step 3:
3. Launch a console app. (Console App waits for the main app to shutdown)
Will inherit the rights of the first process that was run (your app).
At some point you will need to ask for elevation. If that is before your app is run or before running asubprocess, is your choice.
The most user friendly way to do this is to modify folder permissions once at first start or installation. That is a way to not bother the user each time. But some UAC will surely pop to the user at some point.
Related
i know that i can run app as admin by adding this line
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
but I want the application to run as normal and Only when I click on a button to do something will the user request access
An Android-like device that doesn't have access at run-time but requests access when you save a file
In Windows, a process cannot elevate after launch. Full stop.
You have five options, roughly ordered from worst to best:
The process runs as administrator all the time, which you've already said you don't want.
You trust the user to know when they'll need administrator privileges and run accordingly.
Enhance your installer to require administrator access in order to minimize needed administrator privileges later. For example, the installer can change the permissions on a shared folder so non-privileged users can access it.
Your application bundles two separate programs, where tasks which require administrator privileges are moved to the second program, and you build a way for the first program to trigger the correct task with the correct arguments in the second program and know when/if the task completes. In other words, you fake it.
Design your application to not need administrator access in the first place. Two examples: One, you should never need write access to the Program Files folder. This is a bad habit left over from the Windows 98 days, and in pretty much every case the Application Data folder should be used instead. Two, instead of a traditional deployment to the Program Files folder (which requires administrator access to do program updates), you can use something like ClickOnce, which can be run as a non-privileged user.
So the problem here is that I'm using ClickOnce to create an internal application that co-workers can install once and I can push updates by publishing. The problem is that ClickOnce doesn't jive with my need for administrator privileges; it won't publish if I have that requirement declared in the app.manifest. The reason that I have that in there is that I need to be able to edit the host file which is in system32/drivers/etc. Most other threads I've read say that the most I can do is run asInvoker so that the app can inherit all of the permissions that I have as a principal user on the domain, but I found this to be a bit inaccurate. You see, my user has permissions to edit the host file, but my principal does not possess the administrator role. So my question is this...
How can my ClickOnce app request/gain permission to edit the host file? As an aside -- the applicaiton will also be doing some minor registry editing. Alternative approaches are welcome.
As jvanrhyn alludes, the official policy is that ClickOnce applications cannot request administrative elevation if User Account Control (UAC) is enabled (as it is by default on Vista and later). Like you've discovered, if the manifest file sets the requestedExecutionLevel attribute to requireAdministrator, the application will fail to install and run.
This is a security precaution. The whole purpose of UAC is to minimize the risk of applications making unauthorized changes to system settings, which could compromise system integrity. The whole point of ClickOnce is to make deployment of applications fast and easy. Clearly these are two contradictory goals.
Again, the official stance is that if your applications requires administrative privileges, you should be deploying it using Windows Installer or some similar utility.
However, since as far as I understand your question you only need to have administrative privileges on first install, there might be a workaround where you can continue to use ClickOnce for deployment. You would keep the application's requestedExecutionLevel at asInvoker so that it would run under normal circumstances with standard (unelevated) privileges and would work with ClickOnce. But you would also have a secondary application that did require elevation. Your primary application would then launch this secondary application on demand (e.g., on first run), causing the secondary application's privilege demands to kick in, and thus prompt the user for elevation. That second application would run elevated, make the changes that it needed to make, and then quit. The primary application would continue to run un-elevated, and could be launched thereafter without requiring administrative privileges.
This is keeping with the spirit of the security precautions, since it minimizes the need for applications to run with administrative privileges. You can include the secondary "helper" application as a delivered resource in the ClickOnce application, and it can then be launched from the ClickOnce private storage area.
I have one major problem with my app. I have an app & updater as a separate exe files. When an update is available, updater does the update, and on process completion it starts my app. The main problem is - app is installed in program files folder, so updater need UAC admin privileges, and that's ok, but when I need to run my app updater needs to run it as a normal user, because if it's run as an administrator drag and drop doesn't work (not an app problem, UAC blocks it). I've tried several different solutions, and even this one:
How to run NOT elevated in Vista (.NET)
It haven't helped me - my app is run as an administrator.
You'd better avoid starting a non-elevated process from an elevated one. It's tricky part and error-prone.
This approach is better:
Your updater initially starts as non-elevated application, and its manifest has asInvoker level.
When it starts, it restarts itself with elevated privileges using runas verb, and passes a command-line parameter to indicate it. This instance performs the update and returns.
Here comes the non-elevated updater again, and starts your application with the same non-elevated user token that started the first instance of updater in step 1.
Pretty simple and robust.
Look at this post on how to Enable Drag and Drop for an Elevated process. Even though it says MFC app you can cll those Windows API in Any app I suppose
https://helgeklein.com/blog/2010/03/how-to-enable-drag-and-drop-for-an-elevated-mfc-application-on-vistawindows-7/
I did create a windows service. Can I add in the OnStart(string[]args] method the Process.Start - used to open another executable. Will it work? I want to create an windows service application that opens an executable file (foor example cmd where i can add my own commands to open a notepad file . Thx
You would have to allow the service to interact with the desktop (under service properties in Services mgr), but is sometimes considered a bad practice. Note, this is made difficult in Windows 2008 and above because of Session 0 isolation.
It works, but the rights the process run, as well as the resources it can see are the same as the wiundow service ( ie Local System Account ) if you don't change the defaults. This could make the difference or not, depends on what the executable do. If the executable has to show some UI you will experience troubles since by default the servcie does not see the user desktop. The same happen if you need to see a mapped network drive. In general it works if the executable is some batch that does not requires th econnected user profile right/resources.
I found this nice snippet of code online:
rkApp = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
Which runs great but alas on windows 7 and vista I suspect, it crashes cause it doesn't have permission to write there.
So then I research (on stackoverflow of course) how to avoid this, quickest method:
rkApp = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
Simple enough! Though there is two issues remaining. One is with both methods (on a XP Box that is), the program thinks its relative path is somewhere in the C:\windows folder now...so I.e. it won't find my path relative help files etc. The second issue is, on windows 7, my program won't startup until I log in. I want it to start up in the background if possible before anyone logs in.
Its a simple .exe that hangs out in the systray when its running. I didn't want to create this monstrosity of an installer to get around these admin and pathing issues.
I Think I would have to create it as a service (no clue how to do that) to get it to start up when the machine reboots before anyone logs in. Secondly to do that I am sure I have to figure out the admin privileges, and since I don't want to have to approve the program to run every time it starts up it sounds like I would have to figure out its admin privileges during install time, but alas no installer.
So just curious what routes I might take to get this to work. I can even suffer it coming up only after when the user logs in, but my current methods that work this way really screw up the pathing of my program since it tries to write stuff out to a new directory (not the one I originally started the EXE from). Etc...and I have no clue how to go about fixing that pathing issue.
It sounds like you need two programs here.
You can't have an application run in the system tray and run prior to login. The system tray doesn't "exist" until the user logs in and has a valid desktop.
The normal way to handle this is to make two programs. First, create a windows service that does the bulk of your work. This will run on startup, and be independent of any user logins.
Then, make a user mode application which uses IPC to communicate with the service. This can run on login, and "talk" to the service remotely, thereby providing your system tray requirements.
If you want your program to start as a service before anyone logs on, then it's going to need to be installed and run as an admin user. There's not getting round this fact.
There's a Microsoft Knowledge Base article on creating a service which should get you started.
There's a project template for a Windows Service installed by default in Visual Studio 2008:
"File > New > Project > Visual C# > Windows > Windows Service"