c # Windows Странность процесса выключения

2

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

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

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

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

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

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

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

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

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

}

другой: от: Как выключить компьютер с С#

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 );
}
  • 0
    Так какой APi вы используете? где твой код? Вы устанавливаете свою программу как запуск, чтобы автоматически запускаться при входе в Windows?
  • 0
    обновил пост
Теги:
wpf
wcf

1 ответ

2

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

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

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

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

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

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

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

"Перезапустить любое зарегистрированное приложение" <- это то, что заставляет его щелкнуть... lol.

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

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

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

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню