Die Community zu .NET und Classic VB.
Menü

VB 5/6-Tipp 0418: Windows in allen Versionen herunterfahren

 von 

Beschreibung 

Dieser Tipp bietet entgegen Tipp 20 eine umfassende Lösung für alle Windows-Systeme um den Rechner herunterzufahren, zu rebooten und in den Login-Modus zu versetzen. Bei NT-Systemen müssen nämlich zu Beginn eines solchen Vorgangs zuerst, wie hier gezeigt, die nötigen Rechte zum Beenden des Explorers gesetzt werden.

Schwierigkeitsgrad:

Schwierigkeitsgrad 3

Verwendete API-Aufrufe:

AdjustTokenPrivileges, ExitWindowsEx, GetCurrentProcess, LookupPrivilegeValueA (LookupPrivilegeValue), OpenProcessToken

Download:

Download des Beispielprojektes [4,25 KB]

'Dieser Quellcode stammt von http://www.activevb.de
'und kann frei verwendet werden. Für eventuelle Schäden
'wird nicht gehaftet.

'Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum.
'Ansonsten viel Spaß und Erfolg mit diesem Source!

'----------- Anfang Projektdatei prjshutdown.vbp  -----------
'-------- Anfang Formular "Form1" alias frmMain.frm  --------
' Steuerelement: Kontrollkästchen-Steuerelement "Check2"
' Steuerelement: Kontrollkästchen-Steuerelement "Check1"
' Steuerelement: Kombinationsliste "Combo1"
' Steuerelement: Schaltfläche "cmdNTbased"

Option Explicit

Private Const EWX_LOGOFF As Long = 0
Private Const EWX_SHUTDOWN As Long = 1
Private Const EWX_REBOOT As Long = 2
Private Const EWX_POWEROFF As Long = 8

Private Const EWX_FORCE As Long = 4
Private Const EWX_FORCEIFHUNG As Long = 16

Private Sub cmdNTbased_Click()
    If Combo1.ListIndex = -1 Then Exit Sub
    
    Dim ShutdownManager As New clsShutdown
    Dim param As Long
    Dim boxres As VbMsgBoxResult
    
    ' Die eventuellen Zusatzparameter berücksichtigen
    If Check1.Value = 1 Then
        param = param Or EWX_FORCE
    End If
    
    If Check2.Value = 1 Then
        ' Funktioniert erst ab Windows 2000
        param = param Or EWX_FORCEIFHUNG
    End If
    
    param = param Or Combo1.ItemData(Combo1.ListIndex)
    
    
    If (param And EWX_SHUTDOWN) > 0 Or _
       (param And EWX_POWEROFF) > 0 Or _
       (param And EWX_REBOOT) > 0 Then
        
        ' Hier muss berücksichtigt werden, ob es sich
        ' um ein NT-basierendes OS handelt
        boxres = MsgBox("Verwenden Sie ein NT-basierendes Betriebsystem?", _
                        vbYesNoCancel, App.Title)
        
        If boxres = vbYes Then
            ShutdownManager.ShutDownNTbasedWindows param
            Exit Sub
        End If
    End If
    
    ShutdownManager.ShutDownDOSbasedWindows param
End Sub

Private Sub Form_Initialize()
    Combo1.AddItem "Benutzer abmelden"
    Combo1.ItemData(Combo1.NewIndex) = EWX_LOGOFF
    
    Combo1.AddItem "System herunterfahren"
    Combo1.ItemData(Combo1.NewIndex) = EWX_SHUTDOWN
    
    Combo1.AddItem "System neustarten"
    Combo1.ItemData(Combo1.NewIndex) = EWX_REBOOT
    
    Combo1.AddItem "System herunterfahren und ausschalten"
    Combo1.ItemData(Combo1.NewIndex) = EWX_POWEROFF
    
    Combo1.ListIndex = 0
    
    Check1.Caption = "Alle Anwendungen ohne Rückfrage sofort beenden. (Holzhammermethode)"
    Check2.Caption = "Sollte eine Anwendung nicht reagieren, dann diese ohne Rückfrage " & _
        "beenden. (sanfter Holzhammer)(erst ab Windows 2000 verfügbar)"
End Sub
'--------- Ende Formular "Form1" alias frmMain.frm  ---------
'---- Anfang Klasse "clsShutdown" alias clsShutdown.cls  ----

Option Explicit

Private Const TOKEN_ADJUST_PRIVILEGES As Long = &H20
Private Const SE_SHUTDOWN_NAME As String = "SeShutdownPrivilege"
Private Const SE_PRIVILEGE_ENABLED As Long = &H2

Private Const EWX_LOGOFF As Long = 0&
Private Const EWX_SHUTDOWN As Long = 1&
Private Const EWX_REBOOT As Long = 2&
Private Const EWX_FORCE As Long = 4&
Private Const EWX_POWEROFF As Long = 8&
Private Const EWX_FORCEIFHUNG As Long = 16&

Private Type LUID
    lowpart As Long
    highpart As Long
End Type

Private Type LUID_AND_ATTRIBUTES
    pLuid As LUID
    Attributes As Long
End Type

Private Type TOKEN_PRIVILEGES
    PrivilegeCount As Long
    Privileges As LUID_AND_ATTRIBUTES
End Type

Private Declare Function AdjustTokenPrivileges Lib "advapi32.dll" ( _
     ByVal TokenHandle As Long, ByVal DisableAllPrivileges As Long, _
     NewState As TOKEN_PRIVILEGES, BufferLength As Any, _
     PreviousState As Any, ReturnLength As Any) As Long

Private Declare Function ExitWindowsEx Lib "user32.dll" ( _
     ByVal uFlags As Long, ByVal dwReserved As Long) As Long

Private Declare Function OpenProcessToken Lib "advapi32.dll" ( _
     ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, _
     TokenHandle As Long) As Long
     
Private Declare Function GetCurrentProcess Lib "kernel32.dll" () As Long

Private Declare Function LookupPrivilegeValue Lib "advapi32.dll" Alias "LookupPrivilegeValueA" ( _
     ByVal lpSystemName As String, ByVal lpName As String, _
     lpLuid As LUID) As Long

Public Function ShutDownDOSbasedWindows(ByVal ShutDownMode As Long) As Boolean
    Dim retval As Long
    retval = ExitWindowsEx(ShutDownMode, 0&)
    
    If retval = 0 Then
        Call MsgBox("Das System kann aufgrund eines Fehlers nicht heruntergefahren werden.", _
                    vbExclamation + vbOKOnly, App.Title)
                    
        Exit Function
    End If
    
    ShutDownDOSbasedWindows = True
End Function

Public Function ShutDownNTbasedWindows(ByVal ShutDownMode As Long) As Boolean
    Dim retval As Long
    
    If (ShutDownMode And EWX_SHUTDOWN) > 0 Or _
       (ShutDownMode And EWX_POWEROFF) > 0 Or _
       (ShutDownMode And EWX_REBOOT) > 0 Then
       
            If Not AdjustPrivilege2ShutdownOrRestart(True) Then
                Call MsgBox("Das Privileg zum Herunterfahren/Neustarten des Systems " & _
                            "konnte nicht aktiviert werden.", _
                            vbExclamation + vbOKOnly, App.Title)
                            
                Exit Function
            End If
    End If
    
    ShutDownNTbasedWindows = ShutDownDOSbasedWindows(ShutDownMode)
    
    If (ShutDownMode And EWX_SHUTDOWN) > 0 Or _
       (ShutDownMode And EWX_POWEROFF) > 0 Or _
       (ShutDownMode And EWX_REBOOT) > 0 Then
       
            If Not AdjustPrivilege2ShutdownOrRestart(False) Then
                ' Meckere nicht, denn für den Anwender spielt es im Prinzip keine Rolle
            End If
    End If
End Function

Private Function AdjustPrivilege2ShutdownOrRestart(ByVal EnablePrivilege As Boolean) As Boolean
    Dim retval As Long, hToken As Long
    
    'Zunächst ein Handle für den Accesstoken des aktuellen Prozesses ermitteln
    retval = OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES, hToken)
    If retval = 0 Then
        Call MsgBox("Das Handle für den Accesstoken des aktuellen Prozesses konnte " & _
                    "nicht erlangt werden.", vbExclamation + vbOKOnly, App.Title)
                    
        Exit Function
    End If
    
    ' Nun den aktuellen LUID für das SE_SHUTDOWN-Privileg ermitteln
    Dim SE_SHUTDOWN_LI As LUID
    
    retval = LookupPrivilegeValue(vbNullString, SE_SHUTDOWN_NAME, SE_SHUTDOWN_LI)
    If retval = 0 Then
        Call MsgBox("Der aktuelle LUID für das SE_SHUTDOWN-Privileg " & _
                     "konnte nicht ermittelt werden konnte.", _
                     vbExclamation + vbOKOnly, App.Title)
                     
        Exit Function
    End If
     
    'Das SE_SHUTDOWN-Privileg aktivieren
    Dim tokenpriv As TOKEN_PRIVILEGES
    
    'durch den angepassten UDT immer 1
    tokenpriv.PrivilegeCount = 1
    If EnablePrivilege Then
        'Privileg aktivieren
        tokenpriv.Privileges.Attributes = SE_PRIVILEGE_ENABLED
    Else
        'Privileg deaktivieren
        tokenpriv.Privileges.Attributes = 0
    End If
    
    'LUID zuweisen
    tokenpriv.Privileges.pLuid.highpart = SE_SHUTDOWN_LI.highpart
    tokenpriv.Privileges.pLuid.lowpart = SE_SHUTDOWN_LI.lowpart
    
    'Anpassung durchführen
    retval = AdjustTokenPrivileges(hToken, 0, tokenpriv, _
                ByVal CLng(0), ByVal CLng(0), ByVal CLng(0))
                
    If retval = 0 Then
        Call MsgBox("Das Privileg zum Herunterfahren des Systems " & _
                     "konnte aus unbekanntem Grund nicht modifiziert werden.", _
                     vbExclamation + vbOKOnly, App.Title)
                     
        Exit Function
    End If
    
    AdjustPrivilege2ShutdownOrRestart = True
End Function
'----- Ende Klasse "clsShutdown" alias clsShutdown.cls  -----
'------------ Ende Projektdatei prjshutdown.vbp  ------------

Tipp-Kompatibilität:

Windows/VB-VersionWin32sWin95Win98WinMEWinNT4Win2000WinXP
VB4
VB5
VB6

Hat dieser Tipp auf Ihrem Betriebsystem und mit Ihrer VB-Version funktioniert?

Ja, funktioniert!

Nein, funktioniert nicht bei mir!

VB-Version:

Windows-Version:

Ihre Meinung  

Falls Sie Fragen zu diesem Artikel haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.

Archivierte Nutzerkommentare 

Klicken Sie diesen Text an, wenn Sie die 36 archivierten Kommentare ansehen möchten.
Diese stammen noch von der Zeit, als es noch keine direkte Forenunterstützung für Fragen und Kommentare zu einzelnen Artikeln gab.
Aus Gründen der Vollständigkeit können Sie sich die ausgeblendeten Kommentare zu diesem Artikel aber gerne weiterhin ansehen.

Kommentar von Fred am 09.11.2009 um 07:56

Hallo Hairichi

Klar, der Shell funktioniert auch unter XP / VB6 SP6 einwandfrei. Get so ja auch unter Windows START, Run... shutdown.exe -h (z.B. für Help)

Nur: Standby und Hibernate ist damit nicht möglich. Das geht nich ohne API

- IsPwrHibernateAllowed
- SetSystemPowerState

Gruss
Fred

Kommentar von Hairichi am 07.11.2009 um 15:01

Hi
das ist zu viel Code
einfacher gehts so:
[code]Shell("shutdown.exe -s") 'herunterfahren
Shell("shutdown.exe -l") 'ausloggen
Shell("shutdown.exe -r") 'neustarten[code]

//Edit : Getestet in Visual Basic 2008
// Bitte testet es in VB6 und sagt mir obs geht

Gruß
Hairichi

Kommentar von Rainer Kornisch am 08.06.2009 um 09:12

einfach genial !
Für VB-Fans gibt es nichts besseres als ActiveVb

Kommentar von Fred am 15.05.2009 um 22:47

<< Von Seb am 15.05.2009 um 14:44
wofür wird ein 10kB ordner eigentlich gezipt?? >>

Weil ein zip File ein Container ist, ein in sich geschlossenes Objekt und als physischer File beliebig transportierbar und austauschbar.

Ein Ordner (engl: Folder, technisch: Directory) wird nur innerhalb Windows konsistent als Objekt erkannt. In Wirklichkeit ist er eben 'nur' eine logische Verzeichnisstruktur, welche die enthaltenen Objekte auflistet. Also: Nie Ordner herumschicken, sondern Zip-Container. Das Zip-Format ist längst ein weltweiter Defacto-Standard für den Datenaustausch. Etwa so, wie Schuhschachteln oder Zigarettenpackungen... ;)

Kommentar von Seb am 15.05.2009 um 14:44

wofür wird ein 10kB ordner eigentlich gezipt??

Kommentar von FisHFooD am 20.09.2008 um 14:05

Mit dem Standby Modus macht sichs jeder viel zu schwer....

einfach in VB:

shell "rundll32.exe PowrProf.dll, SetSuspendState"

fertig...

Kommentar von FisHFooD am 20.09.2008 um 14:05

Mit dem Standby Modus macht sichs jeder viel zu schwer....

einfach in VB:

shell "rundll32.exe PowrProf.dll, SetSuspendState"

fertig...

Kommentar von Timon am 31.01.2008 um 23:16

Für Stand-by und Hibernate(Ruhezustannd) http://www.microsoft.com/germany/msdn/library/visualtools/vb6/WindowsindenRuhezustandversetzen.mspx?mfr=true

Kommentar von rtzuj am 18.10.2007 um 20:02

wie funzt das?

Kommentar von DominikFe am 10.05.2007 um 17:54

Hier ein Link zu der Online MSDN. Dort könnt ihr sehen, wie man den Computer in den Ruhezustand und in den Stand-By-Zustand versetzt.

http://www.microsoft.com/germany/msdn/library/visualtools/vb6/WindowsindenRuhezustandversetzen.mspx?mfr=true

MFG
Dominik

Kommentar von Franz am 08.05.2007 um 14:47

Hat funktioniert!
Frage:
Wie kann ich Windows in den Ruhezustand schicken?

Kommentar von Diana am 07.05.2007 um 11:31

Hallo,

wie kann ich auch Windows Server 2003, ohne die Abfrage nach dem Grund, herunterfahren ?

Kommentar von Café-dot-neT am 15.10.2005 um 13:27

Seas aus Salzburg!

Ich wollte auch mal Fragen wie des is mit dem "InitiateSystemShutdown" Funktioniert! Ich bzw Wir haben 2 mal im Monat eine "große" (15 PCs) Lan-Party und da bin ich immer der Verwalter. Da da oft auch fremde leute kommen können müssen mir immer neue bestrafungen einfallen. und PC's runterfahren ist doch a supa Idee! allerdings habe ich keine ahnung wie das geht! habe mich schon mal gespielt aber nix is gegangen!

Wenn ihr mir den code vielleicht als email schickt, hat auch nicht jeder einsicht dafür! und das problem mit Trojanern... ist auch gelöst!
Ich für meinen Teil werde das Programm nur für den obigen Zweck benutzen! (klingt scheinheilig, is aber ernst gemeint)

GreeZ Sebi

Kommentar von Alfred Hellmüller am 10.02.2005 um 23:49

Mir fehlt hier die Hibernate-Funktion; EWX_HYBERNATE suche ich seit längerem vergeblich im API-Tschungel. Wäre ein Segen für Schnell-Booter, wird aber nicht von allen Motherboards unterstützt.
Freue mich auf einen Update des Tipps 0418...

Kommentar von E.Karus Kohl am 27.01.2005 um 19:57


Hallo habe Probleme kann meinen Computer nicht ausschalten
bzw runterfahren,bitte aber so erklären das ich es auch
verstehen kann. Bin Neuling was Computer anbelangt.
Hoffentlich kann mir jemand Helfen ?

Kommentar von @MessageBox am 30.12.2004 um 07:56

Bestimmt nich, du willst doch nur einen Trojaner coden, das kannste dir abschminken, keiner wird dir den Source geben!

Kommentar von MessageBox am 27.08.2004 um 12:41

frage:
kann mir jemand den source geben womit man fremde systeme über die ip herunterfährt?

Kommentar von Peyman am 12.07.2004 um 13:04

Hallo Hotte_K,

Wenn du auf einem alten Rechner xp installiert hast dann gehe mal in die Systemsteuerung zu Energieoptionen.
Unter dem Punkt "APM" musst Du den Haken wieder reinnehmen- XP scheint den bei manchen Rechnern nicht automatisch zu setzen.
Dann sollte der Rechner sich wieder abschalten.

Hoffe es hilft!

Kommentar von Peyman am 12.07.2004 um 11:51

Eine Neue Verknüfung auf dem Desktop erstellen mit dem folgendem Inhalt. Je nachdem was man machen möchte.

Workstation schlißen:
%windir%\system32\rundll32.exe\ user32.dll, LockWorkStation

PC Runterfahren:
%windir%\system32\shutdown -s -t 00 -f

PC Neustarten:
%windir%\system32\shutdown -r -t 00 -f


XP Windir=C:\Windows
W2K Windir=C:\Winnt


Es funtioniert unter XP und W2K

Kommentar von Hotte_K. am 22.06.2004 um 21:52

Hi miteinander!

Ich hab nun schon seit Tagen versucht, das Problem bei WIN XP PROF zu lösen, dass der Rechner einfach von selbst ganz herunter fährt.
Nach vielen Versuchen mit BIOS oder diversen Einstellungsänderungen geht es immer noch nicht. Es kommt immer noch die üble Mitteilung:"Sie können den Computer nun ausschalten" und dann muss ich noch 4 sec. auf den Ausknopf drücken, damit er sich ehrlich abschaltet.
Der Script hier sieht ja toll aus, doch wie baue ich so einen Script überhaupt ein? Hab NULL - Ahnung! Bitte um Hiiiilllllfffffeeeeee bitte, bitte.... will endlich, dass die Kiste normal runter fährt, sonst dreh ich durch ... uaaahhhhhhhh !

Kommentar von Thammi am 14.06.2004 um 14:51

@Rick:
Wie wäre es wenn du einen Timer mit dem Interval der Zeit bis zum gewünschten Shutdown machst, wenn du nen Zeitpunkt haben willst kannst du den Intervall ja über die Systemzeit beim Programmstart berechnen.

Kommentar von David Rosier am 13.05.2004 um 12:50

Das ist ja schon ein ganz tolles script.
ich selber bin leider total unbewandert mit vb.
mache eigentlich nur as.
ich habe aber ein problem was warscheinlich nur mit vb am elegantesten zu lösen ist.
ich möchte das per knopfdruck der pc neu startet und beim neutstart eine dosanwendung unter dos aufruft und nach dem beenden der anwendung wieder ins windows hochfährt.
symantec hat diese funktion bei norton ghost.
ich hab leider keine ahnung wie ich das lösen soll.

das eigentliche problem ist das ich bei einem bekannten einen e-prom programm in dos benutzen will. jedoch unter windows lässt er mich nicht auf den printerport zugreifen.
wenn natürlich jemand weiss wie ich das hinbekomme wäre das problem auch gelöst. es ist egal welchen port ich nehme 278 oder 378 irq und dma konflikte gibt es nicht.
vielleicht aber die möglichkeit diese ports irgenwohin zu mappen. os ist win2000
vielen dank im voraus für etwaige antworten ! :-)

Kommentar von Rick am 20.04.2004 um 00:48

Hi,

ich würde gerne wissen, wie ich diesen Tip umsetzen kann, dass WinXP zu einer bestimmten Zeit heruntergefahren wird, ohne dass das System bzw. andere Programme vor dieser Zeit ausgebremst werden.

Gruß Rick

Kommentar von Thomas Wittig am 27.01.2004 um 23:47

Hallo,
mein XP rechner schaltet beim herunterfahren auch nicht aus. Kann ich das Problem mit dem obigen Script lösen und wie muss ich das mnachen, habe keine Erfahrung ím Umgang mit Scripts.

Danke

Thomas

Kommentar von am 14.01.2004 um 14:04

Das der Pc kann aus geht und die Sach mit Standby sind nicht selbstverständlich , geht mal in die Systemsteuerung zu eurem Netzteil , dort kann man was ändern an modi und einstellungen

Kommentar von ralf am 13.05.2003 um 13:36

Leider wurde ich auch ein bißchen von dem Begriff Standby getäuscht. Ich suche händeringend nach einer Möglichkeit, um Windows 2000 per Progi oder Link in den Standbymodus zu versetzen.
Vielleicht weiß ja jemand Rat.
Danke

Kommentar von Eckhart Wörner am 06.04.2003 um 15:51

An alle, die möchten, dass sich ihr PC gleich ausschaltet und nicht die Meldung "Sie können den Computer jetzt ausschalten" anzeigt:
HKEY_LOCAL_MACHINE\Software\Microsoft\WindowsNT\Current Version\Winlogon muss auf 1 gesetzt werden!

Kommentar von Uwe am 20.03.2003 um 11:55

Leider habe ich auch das Problem, das sich der Computer ganz ausschalten sollte, und nicht mit dem Text "Sie können Ihren Computer jetzt ausschalten" stehen bleibt. Kann mir jemand helfen????
Danke

Kommentar von Christian Dresing am 02.12.2002 um 15:04

Frage: wie funktioniert der Shutdown von WinXP in vb.net?

Wäre über eine Antwort auch an meine Email-Adresse (c.dresing@simeonsbetriebe.de)sehr erfreut.

Danke schonmal im Voraus
MfG Chris

Kommentar von c:r:e:a:m2k2 am 12.06.2002 um 23:27

oh mann ! WIN XP herunterfahren.. das is ja so´n thema.. ich jedenfalls hatte zunächst kein problem, meiner ist sogar nach knopfdruck auf den ausschalter komplett heruntergefahren..alles super. doch ich hatte ärger mit meiner besonderen soundkarte, die nicht so recht mit acpi wollte. also hab ich es deaktiviert auf "standard-pc" modus. doch jetzt fährt er nur runter mit der elenden message "sie können den scheiss jetzt abschalten" ... ich seh kein standby button, kein apm, HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon funzt nicht....... nix klappt....wer hat ne idee...

Kommentar von Horst am 14.04.2002 um 13:42

Hatte unter WinXP
das Problem, dass ich
3 X !!!!!runterfahren
musste, bis die Kiste abschaltete.
Hiermit gehts
mit einem Mal.
Fehler sind nicht feststellbar.
Gratulation!!!!!

Kommentar von Ruru am 05.04.2002 um 16:55

mit InitiateSystemShutdownlassen sich auch andere Rechner herunterfahren ;)

Kommentar von Steffen Alexander am 02.04.2002 um 11:17

Danke für den Tipp,
ich habe mir das Prog. modifiziert damit immmer PowerOff gemacht wird und keine Form gezeigt wird. Unter NT mit angemeldeten User geht alles prima (auch über geplanten Vorgang).
Wenn ich mein prog über einen geplanten Vorgang starte und kein User angemeldet ist schaltet NT den Rechner nicht aus sondern bleibt im Dialog "Sie können den Rechner jetzt abschalten" stehen.
Wer kennt das Problem und weiß eine Lösung.
Danke Steffen

Kommentar von M. Zimmerbeutel am 05.02.2002 um 10:33

Der Tip funktioniert spitzenmässig, solange ich kein WinME verwende ... dann bleibt das System mit blinkendem Cursor stehen bei den PowerOff und Shutdown Optionen. Vieleicht hat ja jemand einen Tip für mich.
Gruss
Martin

Kommentar von Kurt am 10.12.2001 um 10:34

Geht der Tipp auch für Windows XP?

Kommentar von Roadrunner am 23.08.2001 um 22:29

Danke für diesen tollen Tipp ! Hat mir einiges an Arbeit erspart...