Windows не будет отключаться программно при выходе - PullRequest
1 голос
/ 14 мая 2009

У меня есть приложение, которое запускается из службы с использованием учетной записи локального администратора. Это приложение доступно через веб-браузер, и хост-компьютер можно отключить через этот интерфейс.

Если пользователь вошел в систему на главном ПК, и я зашел на него и закрыл его, приложение завершает работу и выключает ПК, как я и ожидал, - используя ExitWindowsEx () (с включенной привилегией выключения).

Если, однако, компьютер вышел из системы, я просматриваю его - приложение все еще работает в службе и пытается завершить работу с помощью ExitWindowsEx (), оно возвращается успешно, и кажется, что нет проблем, но компьютер никогда не выключается вниз.

Я также пробовал InitiateSystemShutdown (), которая неожиданно завершается с ошибкой и возвращает ошибку 2! (Система не может найти указанный файл).

Кажется, не имеет значения, с какой учетной записи я использую для запуска приложения.

Любая помощь будет принята с благодарностью!

Спасибо.

Ответы [ 4 ]

1 голос
/ 15 мая 2009

К сожалению, не могу воспроизвести. У меня есть уже существующий сервис, который предоставляет почтовый ящик, поэтому я добавил код:

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 ...

0 голосов
/ 18 ноября 2011

Вы пытались использовать инструмент shutdown.exe ? О какой ошибке он сообщает?

Я столкнулся с той же проблемой с Windows XP x64, но делал это удаленно через WMI, но утилита выключения выдала мне ту же ошибку (21). С этой информацией я наткнулся на это исправление:

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

Я не смог протестировать его, так как в данный момент у меня нет под рукой Windows 2003 Server, но, возможно, это поможет.

0 голосов
/ 14 мая 2009

Попробуйте этот код и скажите нам, что он делает:

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;
}
0 голосов
/ 14 мая 2009

Если я http://www.google.ca/search?hl=en&q=exitwindowsex+service, то первое, что я нахожу, например, http://www.eggheadcafe.com/software/aspnet/29901267/lockworkstation-and-exitw.aspx, что говорит о том, что есть проблема, если в вашей службе включен флаг «взаимодействовать с рабочим столом» (который устарел). 1005 *

Затем люди предлагают исправления в различных сообщениях, отвечающих указанной выше теме, например http://www.eggheadcafe.com/conversation.aspx?messageid=29901274&threadid=29901267 ... что-то подобное может помочь вам.

Альтернативой, которая, безусловно, является кладжем, но которая избегает использования предложенной магии, может быть запуск второго сервиса, который не взаимодействует с рабочим столом: второй сервис должен вызывать ExitWindowsEx ... и использовать любой IPC ( или специфичный для службы API) для запуска второй службы из первой службы (или, возможно, из приложения).

...