c # Windows Странность процесса выключения - PullRequest
0 голосов
/ 19 сентября 2018

Мне нужна помощь по простой, но странной проблеме.Проблема с выключением и перезапуском окон из моего приложения.Я знаю, это просто, и есть много примеров в Интернете, но вот сделка.Завершение работы / перезапуск, выполняемый этими методами, такими как process.start () или win api или managmentobject, не похож на тот, который выполняется при нажатии кнопки выключения или перезапуска Windows.Как?

Хорошо, я создал клиентское приложение для школьной лаборатории, которое помогает учителям отслеживать активность учащихся на рабочем столе с помощью захвата экрана и других вещей, таких как выключение, перезагрузка, блокировка и т. Д. Если я выключаю / перезагружаю ПК сМое приложение - экран запуска Windows для ПК ученика не будет отображаться на компьютере учителя до тех пор, пока ученик не войдет в систему. Но если я выполню выключение или перезапуск из меню Windows на машине ученика, то на машине учителя появится экран запуска машины ученика.

Я знаю, что выключение / перезапуск, инициированный моим приложением, выполняет чистое выключение / перезапуск компьютера ученика, в то время как выключение / перезапуск Windows делает что-то гибридного типа, где пользовательский сеанс каким-то образом сохраняется.и перешел к следующему запуску.

Я хочу знать, как написать код, который может копировать это поведение для выключения или перезапуска. («что-то вроде гибридного типа, где пользовательский сеанс каким-то образом сохраняется. иперешел на следующий запуск ").Также / hybrid не работает.

Клиентское приложение - это приложение wpf, которое запускается с повышенными привилегиями из планировщика задач с запуском и входом в систему.Приложение wpf сворачивает в системный трей и размещает службу wcf с tcp сервером.

код для выключения:

var psi = new ProcessStartInfo("shutdown", "/s /t 5");
            psi.CreateNoWindow = true;
            psi.UseShellExecute = false;
            Process.Start(psi);

другой код для выключения: // с: Каквыключите компьютер из C #

void Shutdown()
{
ManagementBaseObject mboShutdown = null;
ManagementClass mcWin32 = new ManagementClass("Win32_OperatingSystem");
mcWin32.Get();

// You can't shutdown without security privileges
mcWin32.Scope.Options.EnablePrivileges = true;
ManagementBaseObject mboShutdownParams =
         mcWin32.GetMethodParameters("Win32Shutdown");

 // Flag 1 means we want to shut down the system. Use "2" to reboot.
mboShutdownParams["Flags"] = "1";
mboShutdownParams["Reserved"] = "0";
foreach (ManagementObject manObj in mcWin32.GetInstances())
{
    mboShutdown = manObj.InvokeMethod("Win32Shutdown", 
                                   mboShutdownParams, null);
}

}

еще один: из: Как выключить компьютер из C #

using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential, Pack=1)]
internal struct TokPriv1Luid
{
public int Count;
public long Luid;
public int Attr;
}

[DllImport("kernel32.dll", ExactSpelling=true) ]
internal static extern IntPtr GetCurrentProcess();

[DllImport("advapi32.dll", ExactSpelling=true, SetLastError=true) ]
internal static extern bool OpenProcessToken( IntPtr h, int acc, ref IntPtr
phtok );

[DllImport("advapi32.dll", SetLastError=true) ]
internal static extern bool LookupPrivilegeValue( string host, string name,
ref long pluid );

[DllImport("advapi32.dll", ExactSpelling=true, SetLastError=true) ]
internal static extern bool AdjustTokenPrivileges( IntPtr htok, bool disall,
ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen );

[DllImport("user32.dll", ExactSpelling=true, SetLastError=true) ]
internal static extern bool ExitWindowsEx( int flg, int rea );

internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
internal const int TOKEN_QUERY = 0x00000008;
internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
internal const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
internal const int EWX_LOGOFF = 0x00000000;
internal const int EWX_SHUTDOWN = 0x00000001;
internal const int EWX_REBOOT = 0x00000002;
internal const int EWX_FORCE = 0x00000004;
internal const int EWX_POWEROFF = 0x00000008;
internal const int EWX_FORCEIFHUNG = 0x00000010;

private void DoExitWin( int flg )
 {
bool ok;
TokPriv1Luid tp;
IntPtr hproc = GetCurrentProcess();
IntPtr htok = IntPtr.Zero;
ok = OpenProcessToken( hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref 
htok );
tp.Count = 1;
tp.Luid = 0;
tp.Attr = SE_PRIVILEGE_ENABLED;
ok = LookupPrivilegeValue( null, SE_SHUTDOWN_NAME, ref tp.Luid );
ok = AdjustTokenPrivileges( htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero 
);
ok = ExitWindowsEx( flg, 0 );
}

1 Ответ

0 голосов
/ 20 сентября 2018

Окей, люди .... наконец-то решили.Если кому-то когда-нибудь понадобится это, вот оно.

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

Я использовал различные методы выключения, упомянутые на stackoverflow и других сайтах, они работали, но не так, как работают кнопки выключения и перезагрузки Windows.

Вот метод, который копирует это поведение

Если вы посмотрите на параметры, которые команда shutdown принимает в командной строке, она упоминает:

/ g: полное выключение и перезагрузка компьютера.После перезагрузки системы перезапустите все зарегистрированные приложения.

/ sg: выключите компьютер.При следующей загрузке перезапустите все зарегистрированные приложения.

«Перезапустите любое зарегистрированное приложение» <- вот что заставляет его щелкать ... lol. </p>

Поэтому я использовал этот код:

Для выключения:

var psi = new ProcessStartInfo("shutdown", "/sg /t 0");
        psi.CreateNoWindow = true;
        psi.UseShellExecute = false;
        Process.Start(psi);

Для перезагрузки:

var psi = new ProcessStartInfo("shutdown", "/g /t 0");
        psi.CreateNoWindow = true;
        psi.UseShellExecute = false;
        Process.Start(psi);

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

PS: Команды выключения / sg и / g поддерживаются только в последних версиях Windows.Я могу подтвердить, что его нет в Windows 7 и ниже.Работает на Windows 10. Не знаю о Windows 8 и 8.1.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...