这是我的Windows / .NET安全堆栈:
在我的默认VS2008 DEV环境中,我有这个方法,可以从ASP.NET应用程序调用,该方法工作正常:
private static void StopStartReminderService() {
ServiceController svcController = new ServiceController("eTimeSheetReminderService");
if (svcController != null) {
try {
svcController.Stop();
svcController.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(10));
svcController.Start();
} catch (Exception ex) {
General.ErrorHandling.LogError(ex);
}
}
}
当我在生产服务器上运行它时,我从ServiceController中收到以下错误:
来源:System.ServiceProcess - > System.ServiceProcess.ServiceController - > IntPtr的 GetServiceHandle(Int32) - > System.InvalidOperationException消息: 无法在计算机上打开eTimeSheetReminderService服务'。'。
为什么会发生这种情况,我该如何解决?
修改
答案如下,主要是在评论中,但澄清一下:
MS KB article和this, just to get a better understanding
注意:我没有通过web.config模仿,我在代码中执行此操作。请参阅上面的MS KB文章。
答案 0 :(得分:13)
授予IIS启动/停止特定服务的权限:
subinacl /service {yourServiceName} /grant=IIS_WPG=F
这将为该特定服务授予对内置IIS_WPG组的完整服务控制权限。 (这适用于IIS6 / Win2k3。)YMMV适用于较新版本的IIS。)
答案 1 :(得分:6)
尝试将此添加到您的Web.Config。
<identity impersonate="true"/>
答案 2 :(得分:1)
这是一个很好的问题,也引起了我的兴趣...
以下是我为解决这个问题所做的工作:
步骤3:使用模拟模拟步骤1中创建的用途以启动和停止服务
public const int LOGON32_PROVIDER_DEFAULT = 0;
WindowsImpersonationContext _impersonationContext;
[DllImport("advapi32.dll")]
// ReSharper disable once MemberCanBePrivate.Global
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)]
// ReSharper disable once MemberCanBePrivate.Global
public static extern int DuplicateToken(IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
// ReSharper disable once MemberCanBePrivate.Global
public static extern bool RevertToSelf();
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
// ReSharper disable once MemberCanBePrivate.Global
public static extern bool CloseHandle(IntPtr handle);
private bool _impersonate;
public bool ImpersonateValidUser(String userName, String domain, String password)
{
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)
{
var tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
_impersonationContext = tempWindowsIdentity.Impersonate();
if (_impersonationContext != null)
{
CloseHandle(token);
CloseHandle(tokenDuplicate);
_impersonate = true;
return true;
}
}
}
}
if (token != IntPtr.Zero)
CloseHandle(token);
if (tokenDuplicate != IntPtr.Zero)
CloseHandle(tokenDuplicate);
_impersonate = false;
return false;
}
#region Implementation of IDisposable
#endregion
#region Implementation of IDisposable
private void Dispose(bool dispose)
{
if (dispose)
{
if (_impersonate)
_impersonationContext.Undo();
_impersonationContext.Dispose();
}
}
public void Dispose()
{
Dispose(true);
}
#endregion
public static void StartStopService(bool startService, string serviceName)
{
using (var impersonateClass = new Impersonation())
{
impersonateClass.ImpersonateValidUser(Settings.Default.LocalUsername, Settings.Default.Domain, Settings.Default.Password);
using (var sc = new ServiceController(serviceName))
{
if (startService)
sc.Start();
else if (sc.CanStop)
sc.Stop();
}
}
}
答案 3 :(得分:1)
IIS 8的更新(可能还有一些稍早的版本)
用户组 IIS_WPG 不再存在。它已更改为 IIS_IUSRS 。
此外,要开始停止服务,不必提供完全权限(F)。启动,停止和暂停服务(TOP)的权限应该足够了。因此命令应该是:
subinacl / service {yourServiceName} / grant = IIS_IUSRS = TOP
请注意,在运行此命令之前,您需要将命令提示符(最好提升为以管理员身份运行)指向C:\Windows\System32
文件夹。
如果出现错误,还要确保已将subinacl.exe文件从安装目录复制到C:\Windows\System32
。
答案 4 :(得分:0)
只是预感,但我觉得错误不一定与安全有关。您是否在生产服务器上为该服务提供了相同的名称?
答案 5 :(得分:0)
如果您的Web应用程序具有数据库且Windows服务可以访问它,您只需使用DB中的标志即可重新启动该服务。在服务中,您可以读取此标志,如果不忙则重新启动等。仅在您可以修改服务代码的情况下。 如果是第三方服务,您可以创建自己的Windows服务并使用数据库配置来控制(重新启动)服务。它是安全的方式,为您提供更多的灵活性和安全性。