我知道这个问题已经被问到了多种变体,但我目前正处于我的智慧和谷歌搜索能力的尽头。我编写了一个控制台应用程序来重新启动远程机器上的服务。
我们域中的其他用户也需要能够为此目的使用此应用程序,即使他们的凭据不足以重新启动该服务。不过,他们确实拥有对该机器的正常用户访问(读取)权限。因此,我正在使用模拟。不幸的是,该应用程序仅对某些用户有效,而对其他人无效。
所有这些用户都属于同一个 AD 组,都拥有他们正在操作的计算机的本地管理员权限,并激活了 UAC。
这是代码:
public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int DuplicateToken(IntPtr hToken, int impersonationLevel,
ref IntPtr hNewToken);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public extern static bool CloseHandle(IntPtr handle);
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
static void Main(string[] args)
{
SafeTokenHandle safeTokenHandle;
try
{
const int LOGON32_PROVIDER_DEFAULT = 0;
const int LOGON32_LOGON_INTERACTIVE = 2;
const int LOGON32_LOGON_SERVICE = 5;
// Call LogonUser to obtain a handle to an access token.
bool returnValue = LogonUser(user, domain, password,
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
out safeTokenHandle);
// Use the token handle returned by LogonUser.
using (WindowsIdentity newId = new WindowsIdentity(safeTokenHandle.DangerousGetHandle()))
{
//Duplicate token to set Impersonation Level to Delegate (3)
IntPtr tokenDuplicate = IntPtr.Zero;
DuplicateToken(newId.Token, 3, ref tokenDuplicate);
using (WindowsIdentity newId2 = new WindowsIdentity(tokenDuplicate))
{
using (WindowsImpersonationContext impersonatedUser = newId2.Impersonate())
{
var token = newId2.ImpersonationLevel;
Console.WriteLine("Running as: " + WindowsIdentity.GetCurrent().Name);
Console.WriteLine("Impersonation level: " + token.ToString());
var sc = new ServiceController
{
MachineName = remote,
ServiceName = myService
};
if (sc.Status.Equals(ServiceControllerStatus.Running))
{
sc.Stop();
while (!sc.Status.Equals(ServiceControllerStatus.Stopped))
{
sc.Refresh();
System.Threading.Thread.Sleep(100);
}
}
sc.Refresh();
if (sc.Status.Equals(ServiceControllerStatus.Stopped))
{
sc.Start();
while (!sc.Status.Equals(ServiceControllerStatus.Running))
{
sc.Refresh();
System.Threading.Thread.Sleep(100);
}
}
}
}
}
}
}
public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
{
private SafeTokenHandle()
: base(true)
{
}
[DllImport("kernel32.dll")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr handle);
protected override bool ReleaseHandle()
{
return CloseHandle(handle);
}
}
我使用了 DuplicateToken,因为没有它,ImpersonationLevel 是“无”,所以我认为这可能是原因。唉,这并没有改变任何事情。
模拟上下文中使用的用户凭据在远程计算机上具有本地管理员权限,并且可以重新启动服务。在使用此应用程序的六个用户中,其中 4 个用户的服务正常重新启动,而另外 2 个用户则失败了
无法在 [remote] 上启动服务控制管理器。您可能没有足够的权限...
运行应用程序时的控制台输出适用于所有用户:
运行为:[正确用户]
模拟级别:委派
以管理员身份运行应用程序也不会改变任何内容。它是一个普通的独立控制台应用程序,而不是 WCF 服务或任何依赖 IIS 的东西。
所有用户都在域内运行 Windows 7 Professional,直接连接到网络,而不是通过 VPN。
知道这可能是什么原因吗?我错过了什么吗?失败的用户会不会遗漏一些东西?框架版本?可再发行产品?任何事物?