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

发布于 2024-07-20 07:41:43 字数 390 浏览 11 评论 0原文

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

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

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

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

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

任何帮助将不胜感激!

谢谢。

I have an application that is launched from within a service using a local administrator account. This application is accessible by a web browser and the host PC can be shut down through this interface.

If a user is logged into the host PC and I browse to it and shut it down, the application exits and shuts down the PC as I would expect - using ExitWindowsEx() (with the shutdown priviledge enabled).

If, however, the PC is logged off, I browse to it - the application still running within the service, and attempt a shutdown using ExitWindowsEx(), it returns successful and the appears to be no problem but the PC never shuts down.

I have also tried InitiateSystemShutdown() which bizzarely fails and returns error 2! (The system cannot find the file specified).

It doesn't seem to matter what account I use to launch the application with.

Any help would be greatly appreciated!

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

九公里浅绿 2024-07-27 07:41:43

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

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 下运行服务以进行关闭测试? 也许您的管理员的权限与本地系统的权限不太匹配......

Sadly, cannot repro. I have a pre-existing service which exposes a mailslot, so I added the code:

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) ;
   }
}

and called it when I received a mailslot message from a little command-line utility I wrote. InitiateSystemShutdown is the right API for a service, and this reboots the machine running the service whether it's logged in or not. The shutdown does take a while if my (vista) machine is not logged in, but it eventually works (after 30-40s of saying "shutting down"). My service executes under LocalSystem. GrabPrivilege is the same code as I posted before.

So you can take heart from the fact that what you're trying to do is possible. I see you are using an administrator account to run your service. Have you tried running your service under LocalSystem for the purposes of a shutdown test? Perhaps the privs of your administrator don't quite match those of LocalSystem...

伴随着你 2024-07-27 07:41:43

如果我 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 ...类似的东西可能会帮助你。

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

If I http://www.google.ca/search?hl=en&q=exitwindowsex+service then the frst thing I find for example is http://www.eggheadcafe.com/software/aspnet/29901267/lockworkstation-and-exitw.aspx which suggests there's a problem if your service has the "interact with desktop" flag (which is deprecated) enabled.

People then suggest fixes in various messages which reply to the above topic, such as http://www.eggheadcafe.com/conversation.aspx?messageid=29901274&threadid=29901267 ... something like that might help you.

An alternative, which is certainly a kludge but which avoids using the suggested magic, might be to have a second service running which doesn't interact with the desktop: have the second service invoke ExitWindowsEx ... and use any IPC (or a service-specific API) to trigger the second service from the first service (or perhaps from the application).

故事和酒 2024-07-27 07:41:43

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

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;
}

Try this code and tell us what it does:

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

Helper function:

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;
}
我们的影子 2024-07-27 07:41:43

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

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

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

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

Have you tried using the shutdown.exe tool? What error does it report?

I ran into the same issue with Windows XP x64, but I was doing it remotely via WMI, but the shutdown tool gave me the same error (21). With that information I came across this hotfix:

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

I wasn't able to test it since I have no Windows 2003 Server handy at the moment, but maybe it helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文