Diskuze: C# - Vypnutí Počítače jiným způsobem než shutdown.exe, shutdown příkaz v cmd

C# .NET .NET (C# a Visual Basic) C# - Vypnutí Počítače jiným způsobem než shutdown.exe, shutdown příkaz v cmd American English version English version

Aktivity (3)
Avatar
Adam Black
Člen
Avatar
Adam Black:17. března 18:12

Ahoj,
Jak vypnout počítač jiným způsobem než shutdown.exe / shutdown příkaz v cmd?

 
Odpovědět 17. března 18:12
Avatar
Martin Dráb
Redaktor
Avatar
Odpovídá na Adam Black
Martin Dráb:17. března 18:30

Lze přímo zavolat příslušné funkce Windows API

ExitWindowsEx
https://msdn.microsoft.com/…=vs.85).aspx

InitiateSystem­Shutdown
https://msdn.microsoft.com/…=vs.85).aspx

Pak tu ještě existuje oficiálně nedokumentovaná NtShutdownSystem, která počítač vypne do pár vteřin, ale moc ji nedoporučuju používat ,neb o takovým vypnutí se dozví jen jádro systému, ne aplikace.

Ideální je ale povolit pro svoji aplikaci privilegium SeShutdownPri­vilege (SE_SHUTDOWN_NAME), jinak jediným efektem může být odhlášení uživatele.

Nahoru Odpovědět 17. března 18:30
2 + 2 = 5 for extremely large values of 2
Avatar
Adam Black
Člen
Avatar
Odpovídá na Martin Dráb
Adam Black:17. března 18:40
using System.Runtime.InteropServices;

void Shutdown2()
{
    const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
    const short SE_PRIVILEGE_ENABLED = 2;
    const uint EWX_SHUTDOWN = 1;
    const short TOKEN_ADJUST_PRIVILEGES = 32;
    const short TOKEN_QUERY = 8;
    IntPtr hToken;
    TOKEN_PRIVILEGES tkp;

    // Get shutdown privileges...
    OpenProcessToken(Process.GetCurrentProcess().Handle,
          TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out hToken);
    tkp.PrivilegeCount = 1;
    tkp.Privileges.Attributes = SE_PRIVILEGE_ENABLED;
    LookupPrivilegeValue("", SE_SHUTDOWN_NAME, out tkp.Privileges.pLuid);
    AdjustTokenPrivileges(hToken, false, ref tkp, 0U, IntPtr.Zero,
          IntPtr.Zero);

    // Now we have the privileges, shutdown Windows
    ExitWindowsEx(EWX_SHUTDOWN, 0);
}

// Structures needed for the API calls
private struct LUID
{
    public int LowPart;
    public int HighPart;
}
private struct LUID_AND_ATTRIBUTES
{
    public LUID pLuid;
    public int Attributes;
}
private struct TOKEN_PRIVILEGES
{
    public int PrivilegeCount;
    public LUID_AND_ATTRIBUTES Privileges;
}

[DllImport("advapi32.dll")]
static extern int OpenProcessToken(IntPtr ProcessHandle,
                     int DesiredAccess, out IntPtr TokenHandle);

[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool AdjustTokenPrivileges(IntPtr TokenHandle,
    [MarshalAs(UnmanagedType.Bool)]bool DisableAllPrivileges,
    ref TOKEN_PRIVILEGES NewState,
    UInt32 BufferLength,
    IntPtr PreviousState,
    IntPtr ReturnLength);

[DllImport("advapi32.dll")]
static extern int LookupPrivilegeValue(string lpSystemName,
                       string lpName, out LUID lpLuid);

[DllImport("user32.dll", SetLastError = true)]
static extern int ExitWindowsEx(uint uFlags, uint dwReason);

Bude tento kód fungovat?
A jde případně zastavit tento shutdown?

 
Nahoru Odpovědět 17. března 18:40
Avatar
Martin Dráb
Redaktor
Avatar
Odpovídá na Adam Black
Martin Dráb:17. března 19:49

A jde případně zastavit tento shutdown?

InitiateSystem­Shutdwon zastavit jde (AbortSystemShut­down, možná bude fungovat i na ExitWindowsEx). U ExitWIndowsEx lze specifikovat, že shutdown je vynucený, pak bude se zastavením problém.

NtShutdownSystem myslím zastavit vůbec nejde, to je prostě konečná.

Bude tento kód fungovat?

Od pohledu fungovat bude. Jen bys měl, jakmile jej již nepotřebuješ, zavřít handle k tokenu (hToken) pomocí CloseHandle. Také se hodí testovat, zda funkce OpenProcessToken, LookupPrivile­geValue, AdjustTokenPri­vileges, popř. i ExitWindowsEx (či jiné, tohle platí obecně) skončily úspěchem, nebo chybou (a jakou), protože si tím ušetříš spoustu práce při zjišťování, proč to nefunguje.

Nahoru Odpovědět 17. března 19:49
2 + 2 = 5 for extremely large values of 2
Avatar
Adam Black
Člen
Avatar
Odpovídá na Martin Dráb
Adam Black:17. března 20:48

Já bych chtěl kód který Vynuceně vypne počítač a jde složitě Zrušit

 
Nahoru Odpovědět 17. března 20:48
Avatar
Martin Dráb
Redaktor
Avatar
Odpovídá na Adam Black
Martin Dráb:17. března 21:04

Pokud chceš opravdu vynucený a tvrdý shutdown (což znamená, že běžící aplikace se o něm nedozví a nemají možnost si uložit stav/soubory na disk), tak NtShutdownSystem.

Je stále potřeba privilegium SE_SHUTDOWN_NAME.

V C jsou potřebné definice následující:

typedef enum _SHUTDOWN_ACTION {
ShutdownNoReboot = 0,
ShutdownReboot = 1,
ShutdownPowerOff = 2,
} SHUTDOWN_ACTION;

long WINAPI NtShutdownSystem(SHUTDOWN_ACTION Action);

Pro tebe bude hodnota parametru 2 asi jako dělaná.

Nahoru Odpovědět 17. března 21:04
2 + 2 = 5 for extremely large values of 2
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 6 zpráv z 6.