Laden...

Rechner runterfahren [==> Code-Snippets für den Shutdown]

Erstellt von TotoKoenig vor 19 Jahren Letzter Beitrag vor 16 Jahren 21.966 Views
T
TotoKoenig Themenstarter:in
6 Beiträge seit 2005
vor 19 Jahren
Rechner runterfahren [==> Code-Snippets für den Shutdown]

Hallo Zusammen!

Nach erfolglosem googlen brauche ich mal einen Gedankenanstoß!
Ich möchte durch einen Button in einer Form meinen Rechner runterfahren können.
Kann mir jmd da auf die Sprünge helfen? Wäre echt nett!

LG Toto

95 Beiträge seit 2005
vor 19 Jahren

Hi,

unter mentalis.org findest du eine fertige Klasse genannt WindowsController. Damit kannst du ohne problem den Rechner Runtefahren / Neu starten usw.

Gruß

LordK

Programmieren in C# hält die grauen Zellen am Leben.
Es schärft alle fünf Sinne: den Schwachsinn, den Blödsinn, den Wahnsinn, den Unsinn und den Stumpfsinn.

T
TotoKoenig Themenstarter:in
6 Beiträge seit 2005
vor 19 Jahren

Suppi,

werde es mir direkt mal anschauen. Danke!

Gruß Toto

C
1.215 Beiträge seit 2004
vor 19 Jahren

ansonsten gehts per ExitWindowsEx API oder per WMI "Win32_OperatingSystem.Win32ShutDown" bzw. "Win32_OperatingSystem.ShutDown".
für beide vorgänge benötigt der user das SE_SHUTDOWN_NAME privilege (standardmässig gewährt)...

grtz
chief

N
4.644 Beiträge seit 2004
vor 19 Jahren

Beispiel aus dem C# Codebook:

public static void ShutdownSystem(string hostName, string remoteAuthUser, string remoteAuthPassword, bool reboot)
{
	// Den Hostnamen auf localhost setzen, wenn keiner übergeben wurde
	if (hostName == null || hostName == "")
		hostName = "localhost";
	// ManagementScope-Objekt erzeugen, damit die EnablePrivileges-Eigenschaft
	// gesetzt und die Authentifizierungs-Informationen übergeben werden können
	ManagementScope scope = new ManagementScope(@"\\" + hostName + "\\root\\cimv2");
	scope.Options.EnablePrivileges = true;
	scope.Options.Username = remoteAuthUser;
	scope.Options.Password = remoteAuthPassword;
	// Win32_OperatingSystem-Instanz für das aktive Betriebssystem ermitteln
	ManagementClass mc = new ManagementClass(scope, new ManagementPath("Win32_OperatingSystem"), new ObjectGetOptions());
	ManagementObjectCollection moc = mc.GetInstances();
	ManagementObjectCollection.ManagementObjectEnumerator mocEnumerator = moc.GetEnumerator();
	mocEnumerator.MoveNext();
	ManagementObject mo = (ManagementObject)mocEnumerator.Current;
	// Rechner über die Win32Shutdown-Methode neu starten oder herunterfahren
	if (reboot)
		mo.InvokeMethod("Reboot", null);
	else
		mo.InvokeMethod("Shutdown", null);
	// WMI-Objekte freigeben um den Speicher möglichst schnell zu entlasten
	mo.Dispose();
	moc.Dispose();
	mc.Dispose();
}
95 Beiträge seit 2005
vor 19 Jahren

ansonsten gehts per ExitWindowsEx API oder per WMI "Win32_OperatingSystem.Win32ShutDown" bzw. "Win32_OperatingSystem.ShutDown".

Im endeffekt macht die Klasse von Mentalis.org nichts anderes als dir den Zugriff auf die ExitWindowsEx API zu vereinfachen.

Programmieren in C# hält die grauen Zellen am Leben.
Es schärft alle fünf Sinne: den Schwachsinn, den Blödsinn, den Wahnsinn, den Unsinn und den Stumpfsinn.

49.485 Beiträge seit 2005
vor 19 Jahren

Hallo LordK,

zu ExitWindowEx etwas Code für Win NT/Win2k/WinXP:

   //==========================================================================
   [StructLayout (LayoutKind.Sequential, Pack=1)]
   public struct TOKEN_PRIVILEGES // tp
   {
      public int  PrivilegeCount;
      // Statt des zweite Elements:
      // LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY];
      // setze ich die Definition der Struktur LUID_AND_ATTRIBUTES direkt ein,
      // da ANYSIZE_ARRAY = 1
      public long  Luid;
      public int   Attributes;
   }

   //==========================================================================
   [DllImport ("user32.dll", CharSet=CharSet.Ansi, ExactSpelling=true,
   SetLastError=true, CallingConvention=CallingConvention.Winapi)]
   private static extern bool ExitWindowsEx (
      int ulFlags,
      int dwReserved
   );

   //==========================================================================
   [DllImport ("kernel32.dll", CharSet=CharSet.Ansi, ExactSpelling=true,
   SetLastError=false, CallingConvention=CallingConvention.Winapi)]
   private static extern IntPtr GetCurrentProcess (
   );

   //==========================================================================
   [DllImport ("advapi32.dll", CharSet=CharSet.Ansi, ExactSpelling=false,
   SetLastError=true, CallingConvention=CallingConvention.Winapi)]
   private static extern bool LookupPrivilegeValue (
      string   lpSystemName, // address of string specifying the system
      string   lpName,       // address of string specifying the privilege
      ref long lpLuid        // address of locally unique identifier
   );

   //==========================================================================
   [DllImport ("advapi32.dll", CharSet=CharSet.Ansi, ExactSpelling=true,
   SetLastError=true, CallingConvention=CallingConvention.Winapi)]
   private static extern bool OpenProcessToken (
      IntPtr      hProcess,     // handle of process
      int         dwAccessMask, // desired access to process
      ref IntPtr  phToken       // address of handle of open access token
   );

   //==========================================================================
   [DllImport ("advapi32.dll", CharSet=CharSet.Ansi, ExactSpelling=true,
   SetLastError=true, CallingConvention=CallingConvention.Winapi)]
   private static extern bool AdjustTokenPrivileges (
      IntPtr  hTokenHandle,                // handle of token that contains privileges
      bool    fDisableAllPrivileges,       // flag for disabling all privileges
      ref TOKEN_PRIVILEGES  NewState,      // address of new privilege information
      int     dwBufferLength,              // size of previous information buffer
      // Eigentlich kommt jetzt
      // ref TOKEN_PRIVILEGES  PreviousState, // address of previous information
      // ref int pdwReturnLength              // address of required buffer size
      // Aber das wir fr beides null bergeben wollen, schreiben wir stattdessen
      IntPtr PreviousState,                // address of previous information
      IntPtr pdwReturnLength               // address of required buffer size
   );

   //==========================================================================
   public const int EWX_LOGOFF   = 0x00;
   public const int EWX_SHUTDOWN = 0x01;
   public const int EWX_REBOOT   = 0x02;
   public const int EWX_FORCE    = 0x04;
   public const int EWX_POWEROFF = 0x08;

   private const int SE_PRIVILEGE_ENABLED    = 0x00000002;

   private const int TOKEN_QUERY             = 0x0008;
   private const int TOKEN_ADJUST_PRIVILEGES = 0x0020;
   private const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";

   //==========================================================================
   public bool Shutdown (int iFlags)
   {

      bool             fOK;
      TOKEN_PRIVILEGES tp;
      long             luid;
      IntPtr           hToken;
      int dwErrNo;

      //-----------------------------------------------------------------------
      // Vorgepl„nkel
      //-----------------------------------------------------------------------
      luid = 0;
      fOK = LookupPrivilegeValue (null, SE_SHUTDOWN_NAME, ref luid);
      if (!fOK) {
         dwErrNo = Marshal.GetLastWin32Error ();
         return false;
      }

      hToken = IntPtr.Zero;
      fOK = OpenProcessToken (GetCurrentProcess (),
                              TOKEN_ADJUST_PRIVILEGES,
                              ref hToken);
      if (!fOK) {
         dwErrNo = Marshal.GetLastWin32Error ();
         return false;
      }

      tp.PrivilegeCount = 1;
      tp./*Privileges [0].*/Luid = luid;
      tp./*Privileges [0].*/Attributes = SE_PRIVILEGE_ENABLED;

      fOK = AdjustTokenPrivileges (hToken, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
      if (!fOK) {
         dwErrNo = Marshal.GetLastWin32Error ();
         return false;
      }

      //-----------------------------------------------------------------------
      // Jetzt wird's ernst
      //-----------------------------------------------------------------------
      fOK = ExitWindowsEx (iFlags, 0);
      if (!fOK) {
         dwErrNo = Marshal.GetLastWin32Error ();
         return false;
      }

      return true;
   }
}

herbivore

Suchhilfe: 1000 Worte

1
310 Beiträge seit 2006
vor 16 Jahren

Hallo Herbivore,

hab Deinen Code in mein Projekt eingebunden und rufe ihn so auf

if (cb_shutdown.Checked) { bool b = Shutdown(1); }

Der Rechner fährt herunter und zeigt mir dann in VGA-Auflösung, dass ich den Rechner jetzt ausschalten könnte (Win2000). Drücken des Netzschalters bringt aber nichts, erst 4 Sekunden drücken.

Das will ich aber alles nicht, der Rechner soll einfach ausgehen. Dies ist auch möglich, wird Win über das Startmenü beendet, geht er auch aus.

Was muss ich ändern und was macht eigentlich der integer Parameter im Aufruf?

Gruß 11.08.2006

R
206 Beiträge seit 2007
vor 16 Jahren

Versuch mal

Process.Start("cmd.exe shutdown -s");

oder so...

1
310 Beiträge seit 2006
vor 16 Jahren

Klingt gut!

Wie kann ich auf die Cmd.exe zugreifen? So gehts nicht:
Process.Start("c:\WINNT\System32\cmd.exe shutdown -s");

In Deiner Version findet er es auch nicht.

4.221 Beiträge seit 2005
vor 16 Jahren

EWX_POWEROFF ist Dein Freund ... also herbivore's Shutdown mit 8 statt mit 1 aufrufen...

Code kopieren ist das eine.... ihn zu verstehen was anderes...

Edit: Nachtrag

The flag passed to the ExitWindowsEx function determines whether the function performs a forced or normal log off, shutdown, or a restart. You can pass the following flags to this function:

EWX_FORCE - Forcibly terminates processes that do not respond to a shut down command.

NOTE: Using this flag can cause data loss because Windows does not send the messages WM_QUERYENDSESSION and WM_ENDSESSION to applications currently running in the computer. Use this flag only in cases where data loss is not critical.

EWX_LOGOFF - terminates all processes and then logs off the computer.

EWX_POWEROFF - shuts down the computer and turns off the power in systems with a power-off feature. Under Windows NT and Windows 2000, the process that calls the ExitWindowsEx function with this flag must have the SE_SHUTDOWN_NAME privilege. Windows 95, Windows 98, and Windows Me do not support or require this privilege.

EWX_REBOOT [ASCII 150] shuts down and then restarts the computer. Under Windows NT and Windows 2000, the process that calls the ExitWindowsEx function with this flag must have the SE_SHUTDOWN_NAME privilege. Windows 95, Windows 98, and Windows Me do not support or require this privilege.

EWX_SHUTDOWN - shuts down the computer to a point that is safe to turn off the power. All file buffers have been flushed to disk, and all running processes have stopped. Under Windows NT and Windows 2000, the process that calls the ExitWindowsEx function with this flag must have the SE_SHUTDOWN_NAME privilege. Windows 95, Windows 98, and Windows Me do not support or require this privilege.

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

R
206 Beiträge seit 2007
vor 16 Jahren

Process.Start("c:\WINNT\System32\cmd.exe" , " shutdown -s");

so?

Kanns jetzt nicht testen....

1
310 Beiträge seit 2006
vor 16 Jahren

Das Ganze soll natürlicha uch funktionieren, wenn der Rechner gesperrt ist. Meine Anwendung rechnte sehr lange und soll den Rechner runtefahren, wenn es fertig ist. Der Rechner sperrt sich nach 15 Minuten und das kann ich nicht aufheben. Die Variante mit if (cb_shutdown.Checked) { bool b = Shutdown(8); } funktioniert so leider nicht.

Auch das hier mag er nicht: Process.Start("c:\WINNT\System32\cmd.exe" , " shutdown -s");

Er ruft es zwar auf, aber er fährt nicht runter. Logge ich mich wieder ein, ist die Eingabeaufforderung noch offen.

1
310 Beiträge seit 2006
vor 16 Jahren

Ok - Teilerfolg. Mit dem Tool DShutdown.exe kann man auch gesperrte Rechner runterfahren. Mir ist nur noch nicht klar, wie ich die Datei mit den entsprechenden Paramtern aufrufen soll:


string Pfad = Application.StartupPath.ToString() + "\\DShutdown.exe /NOW /FORCE";
            Process.Start(Pfad);

So soll man aufrufen:

DShutdown.EXE [/Hn] [/Mn] [/DAYn] [/MONTH-n1-n2...] [IP:pcname] [/type] [OPTIONS] [/Fashions]

Mn: n = Minutes
Hn: n = Hour
DAYn: n = Day of the week (Mon-Sat) or of the month (1-31)
MONTHn: n = Month (Jan-Dec | All)
IP:pcname: pcname = name (or IP address) of remote computer
TYPE: LOGOFF
SHUTDOWN
REBOOT
FORCE
POWEROFF
FORCEIFHUNG
HIBERNATE
STANDBY
FORCEAFTERWAIT
HANGUP
DISABLELAN
CANCELIFUSERISLOGGED
STARTPROGRAM "ProgramPath | FilePath"
WRITELOG
SOUNDADVISE
EXITPROGRAM
WAKEONLAN: "Mac-Address"
WAKEUP
OPTIONS: SAVEONEXIT
SOUNDSTART
MODE: SHUTDOWNAFTER|SHUTDOWNAT|SHUTDOWNON
NOW
HIDDEN
SERVERMODE
NOCOUNTDOWN
INTERCEPTSHUTDOWN

Den Parameter /FORCE muss ich benutzen, so wie ich es angegeben habe, klappts aber nicht, er erkennt nicht, dass ich Parameter angebe.

Aber wenn das Tool das kann, dann sollte es eigentlich auch direkt aus C# gehen...

4.221 Beiträge seit 2005
vor 16 Jahren

Ruf mal herbivore's code mit 12 auf (8+4)

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

242 Beiträge seit 2006
vor 16 Jahren

Auch das hier mag er nicht: Process.Start("c:\WINNT\System32\cmd.exe" , " shutdown -s");

entweder


Process.Start("shutdown.exe" , "-s");

oder


Process.Start("cmd.exe" , "/c shutdown -s");

oder noch besser, nimm einafch eine von den klassen die dir angeboten wurden =)

mfG b3nJ

-edit-

Ok - Teilerfolg. Mit dem Tool DShutdown.exe kann man auch gesperrte Rechner runterfahren. Mir ist nur noch nicht klar, wie ich die Datei mit den entsprechenden Paramtern aufrufen soll:

  
string Pfad = Application.StartupPath.ToString() + "\\DShutdown.exe /NOW /FORCE";  
            Process.Start(Pfad);  

[...]

Den Parameter /FORCE muss ich benutzen, so wie ich es angegeben habe, klappts aber nicht, er erkennt nicht, dass ich Parameter angebe.

so sollte es gehen:


Process.Start(pplication.StartupPath.ToString() + "\\DShutdown.exe", "/NOW /FORCE");

mfG b3nJ

1
310 Beiträge seit 2006
vor 16 Jahren

Danke, mit dem Parameter "12" von Herbivores Code klappt es wie gewünscht, d.h. der Rechner fäht auch gesperrt runter.

Mich würde alledings einmal die Bedeutung aller möglichen Parameter interessieren.

49.485 Beiträge seit 2005
vor 16 Jahren

Hallo 11.08.2006,

die Bedeutung der Parameter hat Programmierhans oben gepostet.

herbivore

55 Beiträge seit 2006
vor 16 Jahren

Wenn du den shutdown Befehl von Windows benutzen willst musst das so machen:


Process.Start("shutdown -s -t 0")

-s steht für Herunterfahren und -t 0 steht für die Zeit, in diesem Fall 0 Sekunden.
Und man muss auch nicht vorher cmd.exe angeben

92 Beiträge seit 2006
vor 16 Jahren

wie ich hier sehe gibs auch den command "WAKEONLAN" sowie "WAKEUP" auf der Shutdown.exe

Verfolge zurzeit auch die Idee den PC (oder die PC's) automatisch herunterfahren zu lassen, aber möchte auch das diese wieder automatisch hochkommen. Ist es mit obigen Befehlen also theoretisch möglich, wenn mind. 1 PC läuft, von diesem die anderen PC's zu "Wecken" ?? wäre natürlich sehr sehr geil 🙂

664 Beiträge seit 2005
vor 16 Jahren

Hi

du kannst das auch direkt über C# realisieren.
--> http://dotnet-snippets.de/dns/wake-on-lan-SID608.aspx

92 Beiträge seit 2006
vor 16 Jahren

DANKE!