I've inherited maintenance of an application that, when it runs, occasionally causes the UAC admin elevation (Do-you-wish-to-allow-this?) dialog to appear. To me, the obvious first thing to try is "switch on UAC logging", re-run the application to make the dialog appear, then find the entry in the log that says, for example, "2013-11-23-19:10:03 [MyApplication] attempted to write registry entry [MyRegistryKey]. Requires admin authorization", then take steps to resolve things so the dialog doesn't surface when the application is being used.
However, some people posted questions about UAC logging in 2008/09, in relation to Vista, and the answer was something like "UAC doesn't log, but that would be a great feature for a future release". Was UAC logging ever implemented, either in Windows 7 or as a patch release? If not, is there an alternative technique that is commonly used?
I resolved the problem eventually. Here is what happened.
1) I tried Ben's suggestion of using the sysinternals tools. The tools that seemed useful were
DependencyWalker
ProcessExplorer
ProcessMonitor
They each provide a lot of information about what is going on, and I can see that these will need to be the first port of call for many, if not most, Windows problems. However, in my case I double clicked the app and got the UAC userid/password dialog but then found that not much information had been written by the tools up to the point the dialog was surfaced.
It also looked like it would be useful to digest the contents of the Microsoft Press Windows Internals books when attempting to troubleshoot problems with UAC.
2) I tried using the Application Compatibility Toolkit, but it showed no issues with the program either on XP (where it worked) or Windows 7 (both with standard user, which surfaced the UAC dialog and admin user, which worked)
3) I then tried painstakingly recreating the app from scratch, starting with an empty project and then copying in files and settings bit by bit. At each stage, I checked whether the app would launch without surfacing the UAC dialog.
Eventually I applied a change and this caused the UAC dialog to surface. This was a VB6 app and I changed the "application title" and the "product name" in the dialog Project, Properties, Make. The previous (failing) value of each field was "ApplicationName Update". To make the app work without UAC elevation, what I had to do was remove the word "Update".
As Ian suggested above, it looks like the UAC heuristics were being applied, and to values within the exe. I see that the Windows Internals book does talk about scanning for byte sequences in the exe when deciding whether to elevate.
4) So in summary, the approach that worked for me was to reassemble the app bit by bit and see at what stage the UAC dialog is triggered. Once this happens, knowledge of the four reasons given by Ian in the previous answer become important.
5) I should point out that I have fixed the problem by removing the thing that was being flagged in the heuristics, but didn't consider the alternative suggested by Ian: "asInvoker". It could be that this is the best thing to try rather than spending time inside the (legacy) app fixing problems.
find the entry in the log that says, for example, "2013-11-23-19:10:03 [MyApplication] attempted to write registry entry [MyRegistryKey]. Requires admin authorization"
UAC does not work like that. Windows does not watch an application, and based on the activity decide that it should run elevated next time.
Windows 7 mostly behaves the same as Windows XP in this regard. If your app is running as a standard user, tries to write to:
HKLM\Software\Cotoso\Litware
your application will get an Access Denied error message.
Unless File and Registry Virtualization is enabled for buggy apps
Unfortunately, most applications are poorly written. Most applications, when run as a standard user on Windows 2000 or Windows XP, crash horribly. Since 1999, as part of the Windows Logo Requirements, Microsoft has required developers to test their applications while running as a standard user. Almost nobody ever does.
That is why, starting with Windows Vista, Microsoft added a feature that lets your buggy application think it successfully wrote to HKLM, or Program Files. If a write fails, which would have succeeded if the user was an administrator, Windows will reissue the write operation, except this time redirect it someplace that will succeed. For example:
writes to
HKLM\Software
are redirected to
HKCU\<User SID>_Classes\VirtualStore\Machine\Software
writes to
C:\Program Files
are redirected to
C:\Users\Westwell\AppData\Local\VirtualStore\Program Files
Neither of these redirection mechanisms will cause your application to be elevated on next launch. Both of these features are temporary compatibility hacks. You can inform Windows that you wrote your application correctly, opt-out of file and registry virtualzation, by adding a requestedExecutionLevel of asInvoker to your application's assembly manifest:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity version="1.0.0.0" processorArchitecture="X86" name="client" type="win32"/>
<description>Westwell Contoso</description>
<!-- Disable file and registry virtualization -->
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
Now only eliminates the side-discussion of why sometimes writes can succeed, even when the user is a standard user.
When does UAC Elevation happen
There are five reasons why an application might prompt to elevate on launch:
You manifested that your application needs to be run as an administrator.
If you app needs to be run as an administrator, and cannot perform any useful functionality without being an administrator, then you can manifest your application as requireAdministrator (rather than asInvoker):
<description>Westwell Contoso</description>
<!-- Disable file and registry virtualization -->
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
If this were the case, then the application would always run as an administrator. So that's not it.
You manifested that your application be run as administrator only if the user actually is an administrator.
Applications like RegEdit can run fine as a standard user, they do not require elevation. But if the user is actually an Administrator RegEdit can prompt to elevate to the user's full admin privelages. This done by marking your application as highestAvailable (rather than asInvoker or requireAdministrator):
<description>Westwell Contoso</description>
<!-- Disable file and registry virtualization -->
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
If this were the case, your app would prompt for elevation for admins, but not prompt for standard users. This cannot be the cause because your application has no manifest.
Compatibilty option marked the application as Run as administrator.
The user can choose to mark an application so that it should prompt for elevation:
The state of this checkbox (and the other checkboxes) is stored in the registry:
HKCU\Software\Microsoft\WindowsNT\CurrentVersion\AppCompatFlags\Layers
and for "all users" under:
HKLM\Software\Microsoft\WindowsNT\CurrentVersion\AppCompatFlags\Layers
This option can be per-user, or per-machine. So it's possible some users will see an elevation prompt, and others will not. This could be a source of your problem.
Installer detection heuristics.
By default, Windows will attempt to recognize that an application is probably an installer (e.g. setup.exe, install.exe, update.exe) and prompt the user to elevate. This feature can be disabled through group policy, the policy name is User Account Control: Detect application installations and prompt for elevation.
The Easy Fix
The easy fix is to simply mark your application asInvoker. That will disable heuristics.
After that, it must be a compability setting on the machine (AppCompatFlags in HKCU or HKLM).
Bonus Reading
Registry Virtualization
User Account Control Data Redirection
Related
Applications must be run with administrator privileges. How to ask the user is? How to verify that he agreed to? How do I know whether already running application as an administrator?
Made as described here by the user ChrisW67. The result is not received. If possible, give an example of "Hello world" project.
P.S Windows 7. Am writing in Qt Creator. Qt5.2
Disclaimer: Why does your application require admin rights? A modern application should in most cases be able to avoid this. One could use a service for the elevated actions.
I realize that you are using Qt. I don't have access to this tool at the moment, but here are a few general options. Essentially you need to modify the manifest that gets embedded into the binary on compilation:
.NET:
How do I force my .NET application to run as administrator? (as stated above; you modify the manifest that gets embedded in your application executable). More here.
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
Remember to verify admin rights in case the UAC is disabled - in that case the user is not prompted for admin rights on application launch.
C++: In C++ you can set a flag in the project properties: How to run application with Admin privileges using Manifest file in Visual Studio 2005?
Shortcut: You can set up the launching shortcut to require admin rights. The user will then be prompted on launch. "Run this program as an Administrator".
Firstly I want to emphasize that I'm not trying to do anything "nasty" or "hackerish", nor am I trying to hide anything from user here.
During installations (using InstallShield LE) of my application user is prompted by Windows UAC to allow it to run in Administrator mode; If user accepts it - installation continues (standard behavior) and user again can check the option to add this program to autorun list (by adding a registry key to HKLM/../Run). All is fine and normal. But after every Windows restart, when this application starts, UAC kicks in and asks for user permission. Question is, how to avoid it, since it's a bit annoying (yet my app needs Administrator privileges to run)?
I mean user already granted such permissions on installation, so I cannot see a reason why it needs to be prompted on every startup? Moreover, I believe most antivirus software and such, also require elevated permissions to operate, but UAC doesn't prompt for it at Windows Startup.
Thank you for any advises, information, comments or solutions.
Does your application really need to start elevated? Or will it need to elevated access later when the user uses it to perform an action? If you can, drop the later admin task into a separate exe, allowing the main exe to start with no elevation - when you shellexecute the worker process later it will UAC on demand.
At install time, as you have noted, you have elevated the installer. If you want to run elevated code on subsequent runs, automatically, this is the point to install a service - which is what all those other apps you mentioned do.
You can't get around UAC for a process started in an interactive session. You could use a service running as a privileged user but you would be far better off finding a way to do whatever you do without requiring admin rights.
It's not possible for a program to run elevated without prompting. What you want to do is factor those portions of your application that need elevation into a windows service that runs as system. Then your autostarting application can make remoting calls to the service to delgate those activities that the user can't do without elevating.
Not done it but I found this article Selectively disable UAC for your trusted Vista applications that says use 'Application Compatibility Toolkit' from microsoft.
The Compatibility Administrator allows you to create a database of
compatibility fixes that will allow you to run certain applications
without an accompanying UAC.
Run the Compatibility Administrator as admin
select a new database template
Click the Fix button on the toolbar. When you see the Create New Application Fix wizard ... enter details about your app
Select a Compatibility Level
Select RunAsInvoker as the fix
It seems that the last one
Selecting the RunAsInvoker option will allow the application to launch
without requiring the UAC prompt.
Should do what you want provided that the invoker is admin and I think you can do this at start up using the scheduler : Create Administrator Mode Shortcuts Without UAC Prompts in Windows 7 or Vista
As you can see it runs your app in the compatibility mode which may or may not be acceptable for you.
I have a set of NetTCP services configured that run under a Windows service for production but I use a console app to spin them up for debugging purposes. With Windows Vista I disabled UAC outright because it was annoying, however I'm trying to leave it enabled with 7 because it does everything I want while being very quiet and not naggy.
The issue I ran into is when running VS in "standard" mode (i.e. not using run as administrator) the services won't spin up because it says this:
"The service endpoint failed to listen on the URI 'net.tcp://localhost:60000/[ServiceName]' because access was denied. Verify that the current user is granted access in the appropriate allowedAccounts section of SMSvcHost.exe.config."
After a bit of research I was able to find this file and modify it with the SID for my user account. The config looks like this:
<?xml version="1.0" encoding="utf-8"?><configuration>
<runtime>
<gcConcurrent enabled="false" />
<generatePublisherEvidence enabled="false" />
</runtime>
<system.serviceModel.activation>
<net.tcp listenBacklog="10" maxPendingConnections="100" maxPendingAccepts="2" receiveTimeout="00:00:10" teredoEnabled="false">
<allowAccounts>
<add securityIdentifier="S-1-5-21-XXXXXXX"/>
</allowAccounts>
</net.tcp>
<net.pipe maxPendingConnections="100" maxPendingAccepts="2" receiveTimeout="00:00:10">
<allowAccounts>
<add securityIdentifier="S-1-5-21-XXXXXXX"/>
</allowAccounts>
</net.pipe>
<diagnostics performanceCountersEnabled="true" />
</system.serviceModel.activation></configuration>
The SID came from the tool packaged in the Sysinternals suite and was validated against ADSI Edit so I know it's correct. After a reboot the services still won't spin up though and I'm trying to avoid forcing it to run in administrative mode because then you can't double-click on solution or project files anymore which is rather irritating.
Anyone have any ideas? The SMSvcHost.exe.config file came from "C:\Windows\Microsoft.NET\Framework\v3.0\Windows Communication Foundation" and even though I'm running x64 the app is compiled in x86 mode. I'm not sure if that is where my trouble lies?
To find "right" configuration file location do the following:
Locate NetTcpPortSharing in serivce tab in Task Manager.
Click Go to process in context menu.
Click Open file location.
ps.
on my Windows 2008 R2 x64 with .NET 4 location is C:\Windows\Microsoft.NET\Framework64\v4.0.30319
I'm marking this as a community wiki because I'm not really looking for one complete answer. So if you feel like posting one or two things that will activate the UAC prompt instead of a comprehensive list then go ahead.
What actions in Windows will activate UAC? I'd like to avoid it as much as possible because my application doesn't need admin privileges. And I'm sure many other people want to avoid it.
Specifically, I would like to know if reading from the registry would activate it. Or writing to it?
You don't need to address the above question, just anything that will activate it is fair game.
It's really hard to Google anything about UAC because you get bombarded with articles about how to disable it. And I'd rather not have my application make the assumption UAC is disabled.
Nothing "activates" UAC.
If your application would fail to run as a standard user under Windows XP it will fail to run under Windows Vista or Windows 7 as a standard user.
What you are really asking is: what actions can a standard user not perform under Windows?
The things a standard user cannot do are pretty well known (they've been the same since Windows 2000). The main ones are:
modify anything in HKEY_LOCAL_MACHINE
modify anything in the Windows directory
modify anything in the Program Files folder
If you try to do any of those they will fail on:
Windows 2000
Windows XP
Windows Vista
Windows 7
Nobody should have been running as an administrator for day-to-day computer use. If your application did any of those bad things in Windows XP it would fail. The user would have to:
logon (or fast user switch) to an administrator
perform the administrative task
switch back to their real account
UAC is a convience mechanism, allowing you to easily temporarily switch to an administrator. Nothing you do will "trigger" it; you have to make it happen.
If you know your code needs to modify a file in C:\Program Files\My App\Data, then you should add a button on your form that will trigger the elevation.
You then need to launch an (elevated) copy of your program, do the thing, and close.
I created a launch4j installer (an exe-wrapper for java programs) and named it "MyApp.exe". It doesn't need any admin authentication. It just runs fine without any UAC prompt.
BUT: If I rename this installer to "install.exe" or "setup.exe", the UAC icon appears and I get a UAC promp when starting the installer.
Seems as if there are some "reserved words" in filenames that cause windows to start a program with elevated rights (UAC).
Starting with Windows Vista, Microsoft added a class of compatibility shims that will allow an application that assumes it has administrative file and registry access to continue to function.
In other words: An application that failed on Windows XP would run on Windows Vista.
These OS provided bug-fixes can be disabled by adding a section to the application manifest, declaring the application should run asInvoker:
<!-- Disable Windows Vista standard user compatability heuristics -->
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker"/>
</requestedPrivileges>
</security>
</trustInfo>
Ideally, a developer would test their application to ensure that it doesn't (needlessly) require administrative privelages. In order for me to test this, i would need to manifest it asInvoker.
But when it comes down to it, i'm not going to release the application to the customer manifested asInvoker. If i did miss something, i don't want the user to be impacted. i want Microsoft's operating system to fix my mistakes. Problem with this solution is:
i have to modify the manfiest before release
i'll never know about the things i missed, becuase they're just work on Windows Vista.
A similar conundrum comes up with Windows 7's supportedOS manifiest entires. You can add a manifest to the application indicating which version of Windows you were designed and tested for:
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!--The ID below indicates application support for Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!--The ID below indicates application support for Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
</application>
</compatibility>
In the case of the supportedOS items, the operating system knows up front which OS you were designed for. This will place your application in the context of Windows Vista if you do not say that you support Windows 7:
(source: msdn.com)
This action is similar to running an application in some Compatibility Mode, e.g.:
Windows Server 2008 (Service Pack 1)
Windows Vista (Service Pack 2)
Windows Vista (Service Pack 1)
Windows Vista
Windows Server 2003 (Service Pack 1)
Windows XP (Service Pack 2)
Windows 2000
Windows NT 4.0 (Service Pack 5)
Windows 98 / Windows Me
Windows 95
where you will get a schmorgasboard of compatibilty shims applied, and Windows will emulate old undocumented behaviour in order to help your app from crashing when it depended on that undocumented behaviour.
An example of compatibility shims that Windows 7 will provide for an application running in the Windows Vista context:
RPC will use the old private thread pool, rather than the OS thread pool
you will be able to Lock the primary video desktop display buffer
you will be able to Blit to the primary desktop video buffer without specifying a clipping window
you will be vulnerable to a GetOverlappedResult race condition (if you depended on it)
you will continue to get Program Compatibilty Assistant (PCA) mitigation
And once again, in order to test my application properly under Windows 7, i have to add the supportsOS manifest entry. But, again, i'm not going to ship the application with that flag, because i don't want to lose the benefit of these shims (e.g. PCA). And, again, if an app has problems that were fixed because it was running in the Vista context: i'll never know about it from our customers - because the app is just working.
Thoughts? Guidance? Best practices?
i'm not going to release the application to the customer manifested asInvoker. If i did miss something, i don't want the user to be impacted.
I think this is a bad approach. My advice is to manifest correctly from the start and test what you deploy.
Microsoft is not going to bend over backwards for everyone's compatibility. They're going to target the most common, high-impact mistakes made by the biggest vendors. If you miss some small issue, the chance of them providing a shim in the future is small.
Every time Microsoft adds a compatibility shim, we all pay a price. There are APIs that don't work the way they should because they had to handle some case in a brain dead way to achieve compatibility with somebody else's bug. This means long, painful debugging sessions, it means wading through longer (or less complete) documentation, and it means little inefficiencies in the OS for everyone. It also means Windows developers are wasting time fixing other people's mistakes instead of improving the OS.
Sometimes these compatibility changes are big hammers that penalize developers who do it right. Many applications don't handle high DPI correctly, so--in the name of compatibility--Vista assumes that no applications handle it correctly (unless they explicitly claim otherwise). Vista applies UI scaling. Applications that didn't handle high-DPI get improved (but suboptimal) results. Applications that did handle high_DPI get degraded results. (And customers who used the good apps see them get worse when they upgrade to Vista and blame Microsoft.) The developers who didn't pay their taxes get help from Microsoft, the rest of us (including Microsoft) get penalized. The only way to avoid this is for everyone to pay their taxes.
In general, Microsoft is getting better at making these compatibility shims more targeted (though Vista was pretty blunt). Nevertheless, there's a little cost to each one.
Follow the best practice during development. Test what you plan to deploy. If it breaks big, Microsoft might fix it for you. Otherwise, you might have to release an update. That's better than everyone suffering a penalty because some developers didn't do the right thing.
AsInvoker is the correct way to distribute your application!!!
All that says, is run with the user's credentials. It doesn't say 'do something sneaky' or 'use admin rights'.
Without that manifest, you're branding your application as "I'm not aware of UAC, so please provide me whatever hacks you need to make me still maybe function on any system that has UAC"
But if your application doesn't try to do admin-only things - and you can easily test that by simply being logged in as a standard user & then running your app and watching for failures - then AsInvoker is absolutely correct.
This might help you get a handle on it: A Programmer's Exploration of Vista's User Account Control
As I understand it, instead of supplying a manifest file with your distribution it can also be linked directly into your EXE file by adding the following command to your application's resource file: [1,2].
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "YourApp.exe.manifest"
A separate manifest file in the directory containing the EXE file could override this linked-in manifest, but that is up to the customer. You wouldn't supply it.
Now, the "RC" resource compiler from Microsoft accepts preprocessor directives such as #ifdef [3]. Which means, you could instruct your Visual Studio to have two separate build targets defining different preprocessor definitions such as TESTING and DEPLOYMENT.
Then, it is just a matter of using #ifdef directives to use two different manifest files for your testing and deployment build targets, and you can edit the manifest files as you wish. Would this solve your problem?
[1] http://msdn.microsoft.com/en-us/library/ms997646.aspx
[2] http://doc.ddart.net/xmlsdk/htm/sdk_dependencies_5wvi.htm
[3] http://msdn.microsoft.com/en-us/library/aa381033%28VS.85%29.aspx