Как завершить работу с C #, Process.Start («выключение») не работает в Windows XP - PullRequest
3 голосов
/ 16 сентября 2010

После некоторого поиска того, как перезагрузить мой компьютер или выключить его из C #, я нашел объяснение, как это сделать:

ManagementBaseObject outParameters = null;
ManagementClass sysOS = new ManagementClass("Win32_OperatingSystem");
sysOS.Get();

// Enables required security privilege.
sysOS.Scope.Options.EnablePrivileges = true;

// Get our in parameters
ManagementBaseObject inParameters = sysOS.GetMethodParameters("Win32Shutdown");

// Pass the flag of 0 = System Shutdown
inParameters["Flags"] = "1"; //shut down.
inParameters["Reserved"] = "0";
foreach (ManagementObject manObj in sysOS.GetInstances())
{
    outParameters = manObj.InvokeMethod("Win32Shutdown", inParameters, null);
}

Это работало в Windows 7, но не на Windows XP, на которой я его пробовал. Итак, я решил, что давайте перейдем к более простому решению:

Process.Start("shutdown", "/s /t 00");

Увы, похоже, что он работает и на моем Windows 7, но не на Windows XP. Я пробовал его только на одном компьютере с Windows XP, но он вспыхивает, как командная строка, моя программа, которая работает, сворачивается в системный трей, а затем ничего не происходит .. так как она хочет что-то сделать, но в конечном итоге ничего не происходит. (У меня есть код, который преднамеренно помещает мою программу в системный трей, когда закрывается X, и пользователь должен намеренно выйти из нее ...) Есть ли проблема с этим? Мой код FormClosing такой:

private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
    if (!canExit)
    {
        e.Cancel = true;
        this.WindowState = FormWindowState.Minimized;
    }
    else
    {
        // Write out the logs.
        List<String> logs = LogUtil.getLog(); // mic.getLog();

        // Create a writer and open the file
        TextWriter tw = new StreamWriter(userAppData + "\\logTMC.txt", true);

        // Write a line of text to the file
        tw.WriteLine("----- " + DateTime.Now + " ------");
        foreach (String log in logs)
        {
            tw.WriteLine(log);
        }

        // Close the stream
        tw.Close();
    }
}

Я не уверен, почему я могу выполнить сброс и выключить компьютер с C # в Windows 7, но не в Windows XP ... может быть, я что-то пропустил? Лишняя команда? Лучший способ закрыть файл журнала, который я открываю, когда форма закрывается? Какой-то способ принудительно завершить работу или выполнить сброс, несмотря ни на что, в используемом мной окне Windows XP действительно работает сервер SVN в качестве службы Windows, но я не уверен, имеет ли это значение или нет.

Так что я не совсем уверен, где исследовать мою проблему. Есть ли у Process.Start() способ увидеть возврат или пробный улов, чтобы увидеть, из-за чего он мог не закрыться, или это сделка типа «огонь и забыл»?

Ответы [ 3 ]

3 голосов
/ 16 сентября 2010

Вы можете использовать API ExitWindowsEx через pinvoke.net.

См. ExitWindowsEx , ExitWindows-Enum и ShutdownReason-Enum на pinvoke.net для получения дополнительной информации. Обратите внимание, что ваш процесс должен иметь привилегию SE_SHUTDOWN_NAME (например, через AdjustTokenPrivileges API).

Ответы на этот вопрос о стековом потоке содержат некоторые "полные" примеры (хотя в большинстве из них отсутствуют проверка ошибок и очистка ресурсов - последние могут не иметь значения при успешном завершении работы, YMMV).

Наконец, обратите внимание, что использование Process.Start(), как вы показали, без полного имени для shutdown.exe также проблематично с точки зрения безопасности. Кто-то может поместить вредоносный EXE-файл с именем shutdown в вашу переменную PATH. Поскольку вам, вероятно, нужно запускать с правами администратора, чтобы иметь возможность выполнять «настоящий» shutdown.exe, это может вызвать некоторые проблемы. Если вы укажете что-то вроде Process.Start(Environment.ExpandEnvironmentVariables("%windir%\system32\shutdown.exe")), вы можете, по крайней мере, предположить, что настоящий shutdown.exe защищен от злонамеренной замены правами файловой системы (если злоумышленник сам является администратором, вы все равно в основном взломаны).

1 голос
/ 16 сентября 2010

Я пока не могу добавлять комментарии, поэтому должен опубликовать его в качестве ответа.

На этом сайте есть статья, показывающая несколько способов выключения компьютера: Как отключитьвниз по компьютеру с C #

С первого взгляда я заметил в приведенной выше ссылке, для XP, Pop Catalin использует Process.Start("shutdown","/s /t 0");.Я не уверен, что использование 1 0 будет иметь какое-либо значение.

0 голосов
/ 22 сентября 2010

Я верю, что это правильно.Вам просто нужно изменить команду на:

shutdown.exe -s -t 00

Она работает на моем компьютере с Windows (из cmd).

...