Visualizzazione dei risultati da 1 a 10 su 10
  1. #1

    [C#] Problema con ExitWindowsEx

    Salve, ho un problema con la funzione da DLL ExitWindowsEx.

    Dovrei spegnere il pc al termine di un'applicazione, ho fatto un test semplice, ovvero na form con un bottone Spegni, ma non funziona, ecco il primo tentativo:

    codice:
    [DllImport("user32.dll", SetLastError = true)]
            [return: MarshalAs(UnmanagedType.Bool)]
            static extern bool ExitWindowsEx(uint uFlags, uint dwReason);
    
            [Flags]
            public enum ExitWindows : uint
            {
                // ONE of the following five:
                LogOff = 0x00,
                ShutDown = 0x01,
                Reboot = 0x02,
                PowerOff = 0x08,
                RestartApps = 0x40,
                // plus AT MOST ONE of the following two:
                Force = 0x04,
                ForceIfHung = 0x10,
            }
    
            [Flags]
            enum ShutdownReason : uint
            {
                MajorApplication = 0x00040000,
                MajorHardware = 0x00010000,
                MajorLegacyApi = 0x00070000,
                MajorOperatingSystem = 0x00020000,
                MajorOther = 0x00000000,
                MajorPower = 0x00060000,
                MajorSoftware = 0x00030000,
                MajorSystem = 0x00050000,
    
                MinorBlueScreen = 0x0000000F,
                MinorCordUnplugged = 0x0000000b,
                MinorDisk = 0x00000007,
                MinorEnvironment = 0x0000000c,
                MinorHardwareDriver = 0x0000000d,
                MinorHotfix = 0x00000011,
                MinorHung = 0x00000005,
                MinorInstallation = 0x00000002,
                MinorMaintenance = 0x00000001,
                MinorMMC = 0x00000019,
                MinorNetworkConnectivity = 0x00000014,
                MinorNetworkCard = 0x00000009,
                MinorOther = 0x00000000,
                MinorOtherDriver = 0x0000000e,
                MinorPowerSupply = 0x0000000a,
                MinorProcessor = 0x00000008,
                MinorReconfig = 0x00000004,
                MinorSecurity = 0x00000013,
                MinorSecurityFix = 0x00000012,
                MinorSecurityFixUninstall = 0x00000018,
                MinorServicePack = 0x00000010,
                MinorServicePackUninstall = 0x00000016,
                MinorTermSrv = 0x00000020,
                MinorUnstable = 0x00000006,
                MinorUpgrade = 0x00000003,
                MinorWMI = 0x00000015,
    
                FlagUserDefined = 0x40000000,
                FlagPlanned = 0x80000000
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                ExitWindowsEx((uint)ExitWindows.ShutDown, (uint)ShutdownReason.MajorOther & (uint)ShutdownReason.MinorOther);
            }
    Dopo un tentativo in debug mi sono accorto che ExitWindowsEx tornava False, allora ho provato così:

    codice:
            private void button1_Click(object sender, EventArgs e)
            {
                ExitWindowsEx((uint)ExitWindows.ShutDown & (uint)ExitWindows.Force, (uint)ShutdownReason.MajorOther & (uint)ShutdownReason.MinorOther);
            }
    Ora funziona, ma invece di spegnere il pc ha eseguito il logoff.

    Oh provato allora con

    codice:
            private void button1_Click(object sender, EventArgs e)
            {
                ExitWindowsEx((uint)ExitWindows.PowerOff & (uint)ExitWindows.Force, (uint)ShutdownReason.MajorOther & (uint)ShutdownReason.MinorOther);
            }
    Ma anche questo esegue il solo logoff.

    Il sistema operativo su cui lo sto testando è Windows 7, forse la causa potrebbe essere questo?

    Saluti

  2. #2
    Come dice la documentazione,
    To shut down or restart the system, the calling process must use the AdjustTokenPrivileges function to enable the SE_SHUTDOWN_NAME privilege. For more information, see Running with Special Privileges.

    Examples
    For an example, see How to Shut Down the System.
    Amaro C++, il gusto pieno dell'undefined behavior.

  3. #3
    Utente di HTML.it
    Registrato dal
    Apr 2009
    Messaggi
    970
    Scusate l'intervento ma usando shutdown con i relativi parametri? Ora io uso windows 7 ma come Administrator ( ) ed è perfetto.
    Sbagliare è umano, perseverare è diabolico.

  4. #4
    Intendi usando Process.Start?
    È considerata pessima pratica di programmazione richiamare eseguibili esterni per compiere un'azione per la quale basta richiamare una API, dal momento che non hai la certezza che l'eseguibile in questione effettivamente ci sia, che accetti effettivamente quei parametri (che succede se in una prossima versione di Windows cambia sintassi?), non sai se l'operazione è andata a buon fine (i return code delle utility di Windows di rado sono documentati), ed è uno spreco di risorse lanciare un processo a parte per compiere un'azione così banale.
    Amaro C++, il gusto pieno dell'undefined behavior.

  5. #5
    Utente di HTML.it
    Registrato dal
    Apr 2009
    Messaggi
    970
    Perchè scusa l'API interessata non potrebbe cambiare sintassi in versioni successive di Windows ?
    Sbagliare è umano, perseverare è diabolico.

  6. #6
    No. Microsoft garantisce che le API siano retrocompatibili (a meno che non sia indicato il contrario sulla pagina della API specifica); se vengono aggiunte nuove funzionalità o effettuate modifiche, lo si fa sempre in modo da non rompere la compatibilità e binaria e a livello di sorgenti.

    Allo stesso modo, se anche un'API viene dichiarata deprecata viene comunque mantenuta; è il motivo per cui, a distanza di quindici anni da Windows 95 sono ancora disponibili (per quanto marcate come ultra-deprecate) API come WinExec.
    Amaro C++, il gusto pieno dell'undefined behavior.

  7. #7
    Utente di HTML.it
    Registrato dal
    Apr 2009
    Messaggi
    970
    ok grazie.
    Domanda ma non è che shutdown.exe chiama tali API?
    Sbagliare è umano, perseverare è diabolico.

  8. #8
    Originariamente inviato da Pirelli72
    Domanda ma non è che shutdown.exe chiama tali API?
    Sicuramente; il punto non è il chiamare la ExitWindowsEx, che è perfettamente lecito (a patto di farlo correttamente, altrimenti non funziona ), l'errore è andare a richiamare eseguibili esterni (con tutti i potenziali problemi che ho citato prima) quando si possono usare direttamente le API, che non hanno di questi problemi.
    Amaro C++, il gusto pieno dell'undefined behavior.

  9. #9
    Allora, innanzitutto tnx a MItaly, seguendo il suo link e googlando ho trovato la soluzione pronta pronta C#:

    codice:
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.InteropServices;
    
    namespace Spegnimento
    {
        class Shutdown
        {
            [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 static 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);
            }
    
            public void avvia()
            {
                //Console.WriteLine("Sto per spegnere il computer...");
                //Modificare EWX_SHUTDOWN con EWX_LOGOFF, EWX_REBOOT, ecc, ecc...
                DoExitWin(EWX_POWEROFF | EWX_FORCEIFHUNG);
            }
        }
    }
    Ricreando un oggetto ShutDown si può richiamare il metodo avvia che spegne il pc.

    Funziona anche su W7

  10. #10
    Ottimo ; per fare le per bene però dovresti controllare il valore di ok man mano, ed eventualmente sollevare una Win32Exception qualora qualcosa vada male.
    Amaro C++, il gusto pieno dell'undefined behavior.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.