C#:以“启动流程”;“真正的”;具有硬编码权限的管理员
我需要以管理员权限静默安装不同的设置。 我必须硬编码特权,因为用户不知道自己安装设置的用户名和密码 我尝试了两种不同的方法C#:以“启动流程”;“真正的”;具有硬编码权限的管理员,c#,.net,impersonation,runas,C#,.net,Impersonation,Runas,我需要以管理员权限静默安装不同的设置。 我必须硬编码特权,因为用户不知道自己安装设置的用户名和密码 我尝试了两种不同的方法 ProcessStartInfo,用户名、密码和UseShellExecute=false 使用 [DllImport("advapi32.dll", SetLastError = true)] private static extern bool LogonUser(...); 在这两种情况下windowsPrincipal.IsInRole(WindowsBuilt
[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();
}
}
}
}
namespace BlackBlade.Utilities
{
///
///奎尔:http://www.blackbladeinc.com/en-us/community/blogs/archive/2009/08/10/runas-in-c.aspx
///
公共类安全实用程序
{
[DllImport(“advapi32.dll”,SetLastError=true)]
私有静态外部bool LogonUser(字符串lpszUserName、字符串lpszDomain、字符串lpszPassword、int-dwLogonType、int-dwLogonProvider、out-IntPtr phToken);
公共委托void RunAsDelegate();
公共静态无效RunAs(RunAsDelegate methodToRunAs、字符串用户名、字符串密码)
{
字符串用户名;
字符串域;
if(username.IndexOf('\\')>0)
{
//提供了一个域名
字符串[]usernameArray=username.Split('\\');
userName=usernameArray[1];
domain=usernameArray[0];
}
其他的
{
//没有提供域名
用户名=用户名;
domain=“.”;
}
RunAs(methodToRunAs、用户名、密码、域);
}
公共静态无效RunAs(RunAsDelegate methodToRunAs、字符串用户名、字符串密码、字符串域)
{
IntPtr用户令牌;
WindowsIdentity adminIdentity=null;
WindowsImpersonationContext adminImpersonationContext=null;
尝试
{
if(LogonUser(用户名,字符串。IsNullOrEmpty(域)?“:域,密码,9,0,out userToken))
{
//模仿成功了
adminIdentity=新的WindowsIdentity(userToken);
adminImpersonationContext=adminIdentity.Impersonate();
//托多:恩特弗宁。
WindowsPrincipal p=新的WindowsPrincipal(adminIdentity);
Show(p.IsInRole(WindowsBuiltInRole.Administrator.ToString());
//运行委托方法
//methodorunas();
}
其他的
抛出新异常(string.Format(“无法使用指定的密码模拟域{1}中的用户{0}。”,用户名,域));
}
捕获(异常se)
{
int-ret=Marshal.GetLastWin32Error();
if(adminImpersonationContext!=null)
adminImpersonationContext.Undo();
抛出新异常(“错误代码:+ret.ToString(),se);
}
最后
{
//回归自我
if(adminImpersonationContext!=null)
adminImpersonationContext.Undo();
}
}
}
}
使用组策略推出MSI或EXE安装程序
或者,使用任务计划程序以本地系统帐户的身份运行安装程序。是否尝试将dwLogonType设置为2而不是9 下面是一个适用于我的代码示例:
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);
以运行方式启动的进程请求提升
编辑:首先,使用已知的管理员凭据启动进程,可以使用LogonUser/CreateProcessAsUser或CreateProcessWithLogon。然后检查真正的管理员权限(可能UAC已关闭),如有必要,让此进程(以非提升管理员身份运行)使用启动自身的另一个副本。这是。UAC被明确设计为在未经用户确认的情况下禁止提升
用户必须确认标高,除非UAC关闭。要获得更好的用户体验(减少可怕的消息框),请获取代码签名证书并签署此可执行文件。请为您的问题提供一个更有意义的标题!感谢您提供了一个更好的位置:)LogonUser返回true是正确的,即使凭据无效,因为使用新的\u凭据登录类型,它实际上不会登录提供的用户!它只是将凭证存储在呼叫用户令牌的副本中,以便在网络操作中使用(想想
net use/U
)。如果您想将用户登录到本地计算机上,请使用rdkleine建议的交互式登录类型。根据您的评论,我必须对这个问题投反对票。你没有向用户详细解释情况。但是我描述了我想要什么,但似乎没有人关心,并且描述了其他方式。我知道安全问题,但这是实际的设置。不可能。这些设备是无域的。第二条建议也是不可能的。我们将发送一个U盘给我们的用户,它应该像“单击我们的setup.exe”一样简单。那么谁有管理员登录?用户?你呢?用户的系统管理员?正确的答案是将你的设置标记为需要管理员权限,然后让用户的系统管理员处理。换句话说:不要这样做。您基本上是要求用户关闭安全性。thumb驱动器的任何收件人都将获得其机器的管理员密码。是的,安全是一种痛苦。我无法改变这一点。情况如上所述。“保存它的代码将被模糊化”:对。。。像那样永远有效。如果奖品是值得的,一个人就可以破获它