注销后,Windows不会以编程方式关闭

时间:2009-05-14 14:52:49

标签: windows windows-services shutdown

我有一个使用本地管理员帐户从服务中启动的应用程序。该应用程序可通过Web浏览器访问,主机PC可通过此界面关闭。

如果用户登录到主机PC并浏览并关闭它,应用程序将退出并关闭PC,如我所料 - 使用ExitWindowsEx()(启用了shutdown特权)。

但是,如果PC已注销,我浏览到它 - 应用程序仍然在服务中运行,并尝试使用ExitWindowsEx()关闭,它返回成功,似乎没有问题,但PC从未关闭下来。

我也尝试过InitiateSystemShutdown(),这种情况很糟糕,并返回错误2! (该系统找不到指定的文件)。

用于启动应用程序的帐户似乎并不重要。

非常感谢任何帮助!

感谢。

4 个答案:

答案 0 :(得分:1)

可悲的是,无法复制。我有一个预先存在的服务,它公开了一个邮件槽,所以我添加了代码:

void RebootThisMachine ()
{
   if (GrabPrivilege (SE_SHUTDOWN_NAME))
   {
      if (!InitiateSystemShutdown (NULL,NULL,0,TRUE,TRUE))
      {
         wsprintf (g_szDebug, TEXT("RebootMachine - ISS failed, error %d"),
                   GetLastError()) ;
         DebugMessage (DEBUG_ERROR, g_szDebug) ;
      }
   }
   else
   {
      wsprintf (g_szDebug, TEXT("RebootMachine - cannot grab priv, error %d"),
                GetLastError()) ;
      DebugMessage (DEBUG_ERROR, g_szDebug) ;
   }
}

当我从我写的一个小命令行实用程序收到邮件消息时调用它。 InitiateSystemShutdown是服务的正确API,无论是否已登录,它都会重新启动运行该服务的计算机。如果我的(远景)机器没有登录,关机确实需要一段时间,但它最终会起作用(在30-40s之后说“关闭”)。我的服务在LocalSystem下执行。 GrabPrivilege与我之前发布的代码相同。

所以你可以从你想要做的事情 这一事实中获益。我发现您使用的是管理员帐户来运行您的服务。您是否尝试在LocalSystem下运行服务以进行关机测试?也许管理员的权限与LocalSystem的权限不匹配......

答案 1 :(得分:0)

如果我http://www.google.ca/search?hl=en&q=exitwindowsex+service那么我发现的第一件事就是http://www.eggheadcafe.com/software/aspnet/29901267/lockworkstation-and-exitw.aspx,这表明如果您的服务启用了“与桌面交互”标志(已弃用),则会出现问题。

然后人们会在回复上述主题的各种消息中提出修正建议,例如http://www.eggheadcafe.com/conversation.aspx?messageid=29901274&threadid=29901267 ......这样的事情可能会对您有所帮助。

另一种选择,肯定是一种kludge,但它避免使用建议的魔法,可能是运行第二个服务而不与桌面交互:让第二个服务调用ExitWindowsEx ...并使用任何IPC(或者特定于服务的API)从第一个服务(或者可能来自应用程序)触发第二个服务。

答案 2 :(得分:0)

试试这段代码并告诉我们它的作用:

GrabPrivilege (SE_SHUTDOWN_NAME);
ExitWindowsEx (EWX_REBOOT|EWX_FORCE, 0); // or whatever EWX flags you want

辅助功能:

BOOL  GrabPrivilege (LPCTSTR lpctPrivName) 
{
   TOKEN_PRIVILEGES newtkp;
   HANDLE hToken;
   BOOL   bRetVal = FALSE;

   if (OpenProcessToken (GetCurrentProcess(), 
                         TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, 
                         &hToken)) 
   {
      LookupPrivilegeValue (NULL, 
                            lpctPrivName, 
                            &newtkp.Privileges[0].Luid); 
      newtkp.PrivilegeCount = 1;  // one privilege to set
      newtkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 

      if (AdjustTokenPrivileges (hToken, 
                                 FALSE, 
                                 &newtkp, 
                                 0, 
                                 (PTOKEN_PRIVILEGES) NULL, 
                                 0))
      {
         DWORD dwRet = GetLastError();
         if (dwRet == ERROR_SUCCESS) bRetVal = TRUE;
      }
   }
   CloseHandle (hToken);
   return bRetVal;
}

答案 3 :(得分:0)

您是否尝试过使用 shutdown.exe 工具?它报告了什么错误?

我遇到了与Windows XP x64相同的问题,但我是通过WMI远程进行的,但是关机工具给了我同样的错误(21)。有了这些信息,我遇到了这个修补程序:

http://support.microsoft.com/kb/834100

我无法测试它,因为我目前没有Windows 2003 Server,但也许它会有所帮助。