Diskuze: C# - Vypnutí Počítače jiným způsobem než shutdown.exe, shutdown příkaz v cmd
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.

Člen

Zobrazeno 6 zpráv z 6.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
Lze přímo zavolat příslušné funkce Windows API
ExitWindowsEx
https://msdn.microsoft.com/…=vs.85).aspx
InitiateSystemShutdown
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 SeShutdownPrivilege (SE_SHUTDOWN_NAME), jinak jediným efektem může být odhlášení uživatele.
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?
A jde případně zastavit tento shutdown?
InitiateSystemShutdwon zastavit jde (AbortSystemShutdown, 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, LookupPrivilegeValue, AdjustTokenPrivileges, 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.
Já bych chtěl kód který Vynuceně vypne počítač a jde složitě Zrušit
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á.
Zobrazeno 6 zpráv z 6.