我需要使用管理员权限静默安装不同的设置。 我必须硬编码权限,因为用户不知道用户名和密码来安装他们自己的设置。
我尝试了两种不同的方法。
用户模拟
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool LogonUser(...);
在两种情况下windowsPrincipal.IsInRole(WindowsBuiltInRole.Administrator)
都返回false
由于权利不足,我的设置无法运行。
奇怪的行为:即使使用无效的凭据,LogonUser也始终返回true。
以下是模拟课程:
namespace BlackBlade.Utilities
{
/// <summary>
/// Quelle: http://www.blackbladeinc.com/en-us/community/blogs/archive/2009/08/10/runas-in-c.aspx
/// </summary>
public class SecurityUtilities
{
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool LogonUser(string lpszUserName, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken);
public delegate void RunAsDelegate();
public static void RunAs(RunAsDelegate methodToRunAs, string username, string password)
{
string userName;
string domain;
if (username.IndexOf('\\') > 0)
{
//a domain name was supplied
string[] usernameArray = username.Split('\\');
userName = usernameArray[1];
domain = usernameArray[0];
}
else
{
//there was no domain name supplied
userName = username;
domain = ".";
}
RunAs(methodToRunAs, userName, password, domain);
}
public static void RunAs(RunAsDelegate methodToRunAs, string username, string password, string domain)
{
IntPtr userToken;
WindowsIdentity adminIdentity = null;
WindowsImpersonationContext adminImpersonationContext = null;
try
{
if (LogonUser(username, string.IsNullOrEmpty(domain) ? "." : domain, password, 9, 0, out userToken))
{
//the impersonation suceeded
adminIdentity = new WindowsIdentity(userToken);
adminImpersonationContext = adminIdentity.Impersonate();
// todo: Entfernen.
WindowsPrincipal p = new WindowsPrincipal(adminIdentity);
MessageBox.Show(p.IsInRole(WindowsBuiltInRole.Administrator).ToString());
//run the delegate method
//methodToRunAs();
}
else
throw new Exception(string.Format("Could not impersonate user {0} in domain {1} with the specified password.", username, domain));
}
catch (Exception se)
{
int ret = Marshal.GetLastWin32Error();
if (adminImpersonationContext != null)
adminImpersonationContext.Undo();
throw new Exception("Error code: " + ret.ToString(), se);
}
finally
{
//revert to self
if (adminImpersonationContext != null)
adminImpersonationContext.Undo();
}
}
}
}
答案 0 :(得分:2)
Add a manifest到您开始使用RunAs请求提升的流程。
编辑:首先,使用已知的管理员凭据启动流程,使用LogonUser / CreateProcessAsUser或使用CreateProcessWithLogon。然后检查是否有真正的管理员权限(可能是UAC已关闭),如有必要,请让此进程(以非提升管理员身份运行)使用ShellExecuteEx using the runas verb启动自身的另一个副本。这是the only way。 UAC明确设计为在没有用户确认的情况下禁止提升。
除非关闭UAC,否则用户必须确认提升。为了获得更好的用户体验(不太可怕的消息框),请获取代码签名证书并签署此可执行文件。
答案 1 :(得分:0)
使用组策略推出MSI或EXE安装程序。
或者使用任务计划程序将安装程序作为本地系统帐户运行。
答案 2 :(得分:0)
您是否尝试过将dwLogonType设置为2而不是9?
http://msdn.microsoft.com/en-us/library/windows/desktop/bb540756(v=vs.85).aspx
这是一个适合我的代码示例:
public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;
WindowsImpersonationContext impersonationContext;
[DllImport("advapi32.dll")]
public static extern int LogonUserA(String lpszUserName,
String lpszDomain,
String lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int DuplicateToken(IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool RevertToSelf();
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);
WindowsIdentity tempWindowsIdentity;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
if (RevertToSelf())
{
if (LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, ref token) != 0)
{
if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();
if (impersonationContext != null)
{
CloseHandle(token);
CloseHandle(tokenDuplicate);
return true;
}
}
}
}
if (token != IntPtr.Zero)
CloseHandle(token);
if (tokenDuplicate != IntPtr.Zero)
CloseHandle(tokenDuplicate);