1

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

如果用户登录到主机 PC 并且我浏览到它并关闭它,应用程序将退出并按照我的预期关闭 PC - 使用 ExitWindowsEx() (启用关闭权限)。

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

我也尝试过 InitiateSystemShutdown() ,它奇怪地失败并返回错误 2!(该系统找不到指定的文件)。

我使用什么帐户来启动应用程序似乎并不重要。

任何帮助将不胜感激!

谢谢。

4

4 回答 4

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,无论是否登录,它都会重新启动运行该服务的机器。如果我的(vista)机器没有登录,关机确实需要一段时间,但它最终会起作用(在说“关机”的 30-40 秒之后)。我的服务在 LocalSystem 下执行。GrabPrivilege 与我之前发布的代码相同。

因此,您可以从您尝试做的事情可能的这一事实中振作起来。我看到您正在使用管理员帐户来运行您的服务。您是否尝试过在 LocalSystem 下运行服务以进行关机测试?也许您的管理员的权限与 LocalSystem 的权限不太匹配...

于 2009-05-15T16:28:41.120 回答
0

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

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

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

由于目前手头没有 Windows 2003 Server,因此我无法对其进行测试,但也许它会有所帮助。

于 2011-11-18T17:28:02.633 回答
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(或服务-specific API)从第一个服务(或者可能来自应用程序)触发第二个服务。

于 2009-05-14T15:12:36.337 回答
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;
}
于 2009-05-14T15:29:34.187 回答