我有一个重启某些Windows服务的Delphi应用程序.
如果执行此应用程序的用户具有管理权限(Administrators组成员),则服务重新启动将成功.
对于普通用户,服务重启将失败.
如果普通用户使用"右键单击"以管理员身份运行,它也会成功.但是,普通用户必须输入管理员用户名和密码.
我想为普通用户解决这个问题.
我的想法是在代码中"冒充用户",显然冒充本地管理员帐户.
但是,它仍然无效.
这是我的代码:
function GetCurrUserName: string;
var
Size : DWORD;
begin
Size := MAX_COMPUTERNAME_LENGTH + 1;
SetLength(Result, Size);
if GetUserName(PChar(Result), Size) then
SetLength(Result, Size)
else
Result := '';
end;
function ConnectAs(const lpszUsername, lpszPassword: string): Boolean;
var
hToken : THandle;
begin
Result := LogonUser(PChar(lpszUsername), nil, PChar(lpszPassword), LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, hToken);
if Result then
Result := ImpersonateLoggedOnUser(hToken)
else
RaiseLastOSError;
end;
Run Code Online (Sandbox Code Playgroud)
我称之为:
try
ConnectAs('Administrator','password');
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
// Restart the Windows service
// Done, back to the user
RevertToSelf;
Run Code Online (Sandbox Code Playgroud)
服务重启将失败.如果用户以管理员身份运行它(右键单击RunAs),它就可以运行.
模仿本身运作良好.我可以通过获取当前用户名来检查它.但是,为什么它仍然不起作用.看起来用户在没有管理员权限的情况下进行模拟.
还有其他任何形象吗?
这是可以预料的.在UAC下,管理员组中的用户会收到筛选的令牌,除非他们通过UAC提升过程.您正在模仿其他用户,但是您没有UAC提升,因此拥有过滤的,降低的权限令牌.
为了执行具有提升权限的代码,在UAC下,您必须通过UAC提升过程.如果你可以避免这样做,那么UAC将毫无意义.
据我所知,你有以下原则选择:
runas
shell动词强制提升,或者确实使用其他一些机制来安排提升.这将引导您完成要避免的UAC对话框.顺便说一句,我注意到你没有检查你的电话中的错误ImpersonateLoggedOnUser
.