Also in the following code, which is more efficient?
if (Length(ParamStr(1)) <> 0) then
or
if (ParamStr(1) <> '') then
{$A8,B-,C-,D-,E-,F-,G+,H+,I-,J-,K-,L-,M-,N+,O+,P+,Q-,R-,S-,T-,U-,V-,W-,X+,Y-,Z1}
program LaunchUAC;
uses
Windows, ShellAPI;
{$R 'MANIFEST.RES'}
(*
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- Copyright (c) eyeClaxton Software (www.eyeclaxton.com) -->
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
processorArchitecture="x86"
version="1.0.0.0"
name="eyeClaxton.asInvoker.LaunchUAC" type="win32" />
<description>asInvoker LaunchUAC</description>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
publicKeyToken="6595b64144ccf1df"
language="*"
processorArchitecture="x86"/>
</dependentAssembly>
</dependency>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
</windowsSettings>
</application>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
</requestedPrivileges>
</security>
开发者_运维技巧 </trustInfo>
</assembly>
*)
function IsMinimumVista(): Boolean;
var
OSVerInfo: TOSVersionInfo;
begin
OSVerInfo.dwOSVersionInfoSize := SizeOf(OSVerInfo);
Result := Windows.GetVersionEx(OSVerInfo) and (OSVerInfo.dwMajorVersion > 5);
end;
procedure RunAsAdmin(theHandle: hWnd; theFilename: string;
theParams: string; theShow: Integer; bWaitFor: Boolean = True);
var
ShellExInfo: TShellExecuteInfo;
hHandle: DWORD;
Msg: TMsg;
MsgResult: LongBool;
begin
Windows.ZeroMemory(@ShellExInfo, SizeOf(ShellExInfo));
ShellExInfo.cbSize := SizeOf(TShellExecuteInfo);
ShellExInfo.Wnd := theHandle;
ShellExInfo.fMask := SEE_MASK_FLAG_DDEWAIT;
if bWaitFor then
ShellExInfo.fMask := ShellExInfo.fMask or SEE_MASK_NOCLOSEPROCESS;
if (Launch.IsMinimumVista()) then
ShellExInfo.lpVerb := PChar('runas');
ShellExInfo.lpFile := PChar(theFilename);
if (Length(theParams) <> 0) then
ShellExInfo.lpParameters := PChar(theParams);
ShellExInfo.nShow := theShow;
hHandle := 0;
if ShellAPI.ShellExecuteEx(@ShellExInfo) then
try
hHandle := ShellExInfo.hProcess;
if bWaitFor then
begin
while (Windows.WaitForSingleObject(hHandle, 50) <> WAIT_OBJECT_0) do
repeat
MsgResult := PeekMessage(Msg, ShellExInfo.Wnd, 0, 0, PM_REMOVE);
if MsgResult then
begin
Windows.TranslateMessage(Msg);
Windows.DispatchMessage(Msg);
end;
until (not (MsgResult));
end;
finally
if (hHandle <> 0) then
Windows.CloseHandle(hHandle);
end;
end;
begin
if (Length(ParamStr(1)) <> 0) then
Launch.RunAsAdmin(0, ParamStr(1), ParamStr(2), SW_SHOWNORMAL)
else
Windows.MessageBeep(MB_ICONERROR);
end.
If you're determined to avoid threads, I would suggest using MsgWaitForMultipleObjects but only have your spawned process handle in the array. Once you get a return value of WAIT_OBJECT_0, you can call GetExitCodeProcess.
At a guess,since you're using Pascal strings which have a pre-calculated length, checking the length should be more efficient than doing a compare against an empty string, but it's entirely possible the compiler may convert one into the other anyway, if it's smart enough to spot the compare against ''.
There are few issues with your code. Do you understand what it does or you just copy&paste it?
- If you want to call GetExitCodeProcess - just call it: right before calling CloseHandle in your case.
- You don't need to pump messages, just call WaitForSingleObject for infinite period (possible DDE initialization is handled inside ShellExecute).
- You check that hHandle <> 0 for CloseHandle, but not for WaitForSingleObject. Either do it for both or none.
- Use
ShellExInfo.lpParameters := Pointer(theParams);
instead ofif (Length(theParams) <> 0) then ShellExInfo.lpParameters := PChar(theParams);
. - Use
ShellExInfo.lpVerb := 'runas';
instead ofShellExInfo.lpVerb := PChar('runas');
. - Your parameter passing is wrong: you not only ignore all parameters, except first, but also doesn't enclose param to quotes.
- Unused
theHandle: hWnd
parameter is clear indication that you just grabbed first piece of code, without realizing how it works. - May be something else, but I'm bored already...
Also in the following code, which is more efficient?
"Premature optimization is the root of all evil" - Donald Knuth.
精彩评论