We have an application suite that we update via a homegrown "Auto Update" application. This application basically connects to our "Updates server" and downloads files to overwrite, update, or even add new features/applications to our application suite. However, this does not work well with UAC. Our Auto Update application is a command line .NET application that is launched via HKLM\Software\Microsoft\Windows\CurrentVersion\Run registry key.
The problem that we have is when UAC is turned on our appl开发者_如何学运维ication doesn't run. Nor does it prompt users to allow the program to run. What are my options to work around this or solve the problem?
The following are not options:
1. Turn UAC off - Company Policy 2. Use ClickOnce - Doesn't support our needs (thats why we went homegrown)Many thanks.
You can request UAC elevation in the application manifest. If you specify requireAdministrator, it will invoke UAC, unless machine policy prevents UAC prompts.
You're ahead of the game because your updater is a separate exe. In addtion to putting a manifest on it as suggested by @Martin, ideally you would also change the UI of the main app. Either enable a button/menu item that said "apply updates" or pop up some modal UI that says "mandatory updates are ready, click OK to continue". Then on the button or menu item or the OK of the modal UI, decorate with a shield. This reminds the users they will be getting a UAC prompt.
Your code will work fine without this, but they will be startled. They're using the app, monitoring the nuclear reactor or approving expense accounts or whatever and suddenly - blam! - the screen goes black and they get a prompt - it has an exe name on it but nobody reads it and it might not explain much anyway.
There's a good chance this unsolicited UAC prompt will not get consent from the user. So changing your UI to explain it to them is a better way.
Ideally you would use MSI as your installer/updater - it knows if/how to elevate.
Your other solution is to ShellExecute
your updater with administrative privelages:
RunAsAsAdmin("C:\Users\Adam\AppData\Temp\ISW-1864.exe");
Where RunAsAdmin
is code that knows how to execute a process and elevate in the process:
function RunAsAdmin(hWnd: HWND; filename: string; Parameters: string): Boolean;
{
See Step 3: Redesign for UAC Compatibility (UAC)
http://msdn.microsoft.com/en-us/library/bb756922.aspx
}
var
sei: TShellExecuteInfo;
begin
ZeroMemory(@sei, SizeOf(sei));
sei.cbSize := SizeOf(TShellExecuteInfo);
sei.Wnd := hwnd;
sei.fMask := SEE_MASK_FLAG_DDEWAIT or SEE_MASK_FLAG_NO_UI;
sei.lpVerb := PChar('runas');
sei.lpFile := PChar(Filename); // PAnsiChar;
if parameters <> '' then
sei.lpParameters := PChar(parameters); // PAnsiChar;
sei.nShow := SW_SHOWNORMAL; //Integer;
Result := ShellExecuteEx(@sei);
end;
精彩评论