PC aus Ruhezustand wecken

  • VB.NET

Es gibt 22 Antworten in diesem Thema. Der letzte Beitrag () ist von TimoS.

    PC aus Ruhezustand wecken

    Hallo an alle

    Ich habe ein großes Problem ! ?(
    Ich möchte meinen PC (Windows XP) mit einem VB Programm aus dem Ruhezustand wecken.
    Es besteht nicht die Möglichkeit für WOL, Bios Wecker, oder dem Taskplaner, da das Programm vollautomatisch laufen soll
    und zudem sich die Zeiten des Hochfahrens ändern können.
    In den Ruhezustand versetze ich den Rechner mit:
    'Application.SetSuspendState(PowerState.Hibernate, False, False)

    Aber das Aufwecken will einfach nicht ;(

    Ich habe es mit der Seite support.microsoft.com/kb/q231298/ versucht aber die Funktion
    CreateWaitableTimer() gibt immer den Fehler aus:
    "Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist."

    Ich habe aber leider keine Ahnung was ich dagegen tun kann...

    Bitte, bitte helft mir

    An alle schon mal dank im voraus

    Hubertus23 :thumbup:
    Aus den reinen Ruhezustand unter XP kann man einen Rechner nicht wecken, da er da richtig aus bzw. runter gefahren ist, nur mit dem unterschied das alles was sich gerade im Speicher befand auf die Festplatte geschrieben und beim nächsten hochfahren wieder eingelesen wird.
    Beim Eintreten des Ruhezustands oder des Standby-Modus' weist Windows alle Prozesse (und deren Threads) an, ihre Arbeit zu unterbrechen (und schreibt evtl. den Arbeitsspeicher auf die Platte, je nach Anforderung). Nach diesen Vorbereitungen schickt Windows per ACPI einen entsprechenden Befehl an das BIOS, welches daraufhin die Hardware in entsprechende Modi schaltet (ACPI S3 oder S5, bei schlechten Konfigurationen manchmal auch S1). Für dich ist allerdings nur wichtig, dass Windows die Arbeit der Prozesse unterbricht. Das bedeutet, dass weder im Ruhezustand noch im Standby-Modus Code ausgeführt werden kann. Der Rechner wird letztlich per Hardwaresignal (Power-Knopf, WOL Magic Packet, RTC-Alarm) wieder aufgeweckt. Und das bedeutet wiederum, dass für das Aufwecken eine Aktion von außen erforderlich ist. Ohne Hilfe kann Windows den Rechner nicht aufwecken.
    Gruß
    hal2000
    Danke für deine Anwort,

    Ok dass ist natürlich klar dass im Standby und Im Ruhezustand kein Programm mehr ausgeführt wird.

    Aber ich ziele ja mehr darauf ab die einstellungen zum Aufwecken (also die Uhrzeit) VOR dem
    eigentlichen "Runterfahrbefehl" einzustellen !

    Ich habe auch schon Programme im Web gefunden (Kaufsoftware) die es auch irgendwie hinkriegen
    die Frage ist nur wie ? ?(

    Deshalb war ich ja auch so überglücklich als ich die oben erwähnte Hilfeseite von Windows gefunden habe
    denn die scheint ja nah an der Lösung zu sein nur das da immer dieser Fehler kommt... :wacko:

    Ich habe es auch schon mit dem Taskplaner versucht, mit folgenden Code:
    ...
    Shell("C:\WINDOWS\system32\cmd.exe /C at " & myStartTime & ":00 /interactive update.exe", AppWinStyle.Hide, True, -1)
    Shell("C:\WINDOWS\system32\cmd.exe /C waketask 1 At1", AppWinStyle.Hide, True, -1)
    ...[b]
    [/b]
    Zu Erklärung: Ich rufe damit die Eingabeaufforderung auf und übergebe dem standard Taskplaner "at.exe" meine Variablen (myStartTime)
    danach nochmal das selbe nur diesmal mit waketask.exe der in dem soeben erstellten Task die Flag "Rechner zum Ausführen des Task reaktivieren" setzt.

    Das ganze klappt auch wunderbar aber leider und das auch zu meiner Verwunderung nicht über Nacht, d.h.
    Mein Progi fährt den Rechner um 15:00 Uhr in den Ruhezustand und stellt vorher den Task ein für den nächsten Tag um 7:00 Uhr aber am
    nächsten Morgen passiert nichts
    ABER wenn ich mein Programm so umstelle das es den Rechner um 15:00 Uhr runterfährt und den Task auf 15:15 einstellt funktioniert es und der Rechner fährt hoch :cursing: 8|

    Wer es mal mit der Waketask.exe ausprobieren will: huebert.info/waketask/
    (Und keine Sorge das ist alles Viren frei :) )

    Auch für andere Vorschläge bin ich offen

    Dankbar für jede Anwort
    Hubertus 23 :thumbup:

    [b][/b]
    Nach langer Suche bin ich auf Folgendes gestoßen:
    pcreview.co.uk/forums/thread-3451405.php

    Damit kannst du deinen Rechner per Code nach einer bestimmten Zeitspanne aufwecken. Der Code veranlasst Windows über das API, die Hardwareuhr (RTC) so zu programmieren, dass der Rechner nach der gegebenen Wartezeit aufwacht.

    Es kommt jetzt darauf an, wie lange du schon mit .NET programmierst - für Anfänger ist dieses Beispiel sicherlich nicht geeignet. Noch dazu ist es in C# geschrieben, was allerdings gleichwertig zu VB ist.
    Gruß
    hal2000
    Danke für deine Anwort hal2000 :thumbsup:

    Aber leider bringt die Seite mich auch nicht weiter. Im Prinzip ist es
    das selbe Script wie auf support.microsoft.com/kb/q231298/
    nur eben in C#.
    Der Ansatz davon ist gut nur leider muss das Script in VB programmiert
    sein weil ich den Rest des Programms schon fertig habe. Das wäre ja
    nicht unbedingt schlimm aber leider ist das Programm nicht für
    mich sondern für einen Kunden und ich habe keine Zeit das ganze
    neu zu schreiben...

    Ich habe alle Kollegen und Internetseiten gefragt und eingesehen
    aber neimand konnte mir bis jetzt helfen. ;(

    Wenn es nicht anders geht muss ich mich damit begnügen
    den Rechner laufen zu lassen oder in per Zeitschaltuhr etc.
    immer zur selben Zeit zu wecken. :rolleyes:

    Trotzdem Danke für deine Hilfe... :D

    Falls jemand trotzdem noch Vorschläge hat nur immer her damit.

    Vielen Dank hubertus23
    Hallo !

    Danke für den Link gs93 :thumbsup:

    Sehr interessant nur scheint der Übersetzer mit dem relativ schweren C#
    nicht klar zu kommen. ?(
    Aber trotzdem habe ich versucht das beste draus zu machen. Er hat mir den
    C#-Code übersetzt und dann hab ich ihn in ein Testprojekt (Visual Studio 2008)
    kopiert und da kamen massenhaft Fehler was aber bei den vielen Syntax Fehler
    des Übersetzters nicht verwunderte. :rolleyes:

    Naja nach einem langen hin und her hatte ich dann einen fehlerfreien Code aber
    der hat leider auch nicht funktioniert...

    Vieleicht bin ich auch nur betreibsblind ??? :wacko:


    Wenn jemand so nett wäre und es selber mal versucht..?
    Es kommt nur darauf an einen Code zu haben der keine Fehler ausgibt !

    Trotzdem danke noch mal für den Link kann ich bestimmt noch mal gebrauchen !! :thumbup:

    Hubertus23
    Ich schreibe den zweiten Code des Forums (sich hinter meinem Link verbergend) mal in eine VB-Klasse (auch wenn du die C#-Klasse original übernehmen könntest). Aber da du anscheinend was lernen willst tue ich dir mal den Gefallen.

    EDIT: Projekt angehängt. Jetzt musst du nur noch die DLL importieren und eine Anwendung erstellen, die sie verwendet.
    Dateien
    • wakelib.zip

      (36,72 kB, 459 mal heruntergeladen, zuletzt: )
    Gruß
    hal2000

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „hal2000“ ()

    Hallo an alle
    besonders an hal2000

    DANKE DANKE DANKE DANKE DANKE DANKE
    DANKE DANKE DANKE DANKE DANKE DANKE
    DANKE DANKE DANKE DANKE DANKE DANKE
    DANKE DANKE DANKE DANKE DANKE DANKE
    DANKE DANKE DANKE DANKE DANKE DANKE
    DANKE DANKE DANKE DANKE DANKE DANKE

    Das hat endlich funktioniert !!!!!! :thumbsup:

    ...
    Aber leider, leider habe ich noch eine Frage !? 8|

    Mein Quelltext sieht jetzt so aus:

    VB.NET-Quellcode

    1. Imports Microsoft.Win32.SafeHandles
    2. Imports System.ComponentModel
    3. Imports System.Runtime.InteropServices
    4. Imports System.Threading
    5. Public Class Form1
    6. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    7. Dim my_time As New DateTime(2009, 5, 7, 7, 50, 0) 'Zeit zu der der Rechner aufwachen soll
    8. Wake.SetWaitForWakeupTime(my_time) 'Aufruf der Funktion
    9. Application.SetSuspendState(PowerState.Suspend, True, False) 'In Standbymodus fahren
    10. End Sub
    11. End Class
    12. Public Class Wake
    13. <DllImport("kernel32.dll")> Public Shared Function CreateWaitableTimer( _
    14. ByVal lpTimerAttributes As IntPtr, _
    15. ByVal bManualReset As Boolean, _
    16. ByVal lpTimerName As String) As SafeWaitHandle
    17. End Function
    18. <DllImport("kernel32.dll", SetLastError:=True)> Public Shared Function SetWaitableTimer( _
    19. ByVal hTimer As SafeWaitHandle, _
    20. <[In]()> ByRef pDueTime As Long, _
    21. ByVal lPeriod As Integer, _
    22. ByVal pfnCompletionRoutine As IntPtr, _
    23. ByVal lpArgToCompletionRoutine As IntPtr, _
    24. ByVal fResume As Boolean) As <MarshalAs(UnmanagedType.Bool)> Boolean
    25. End Function
    26. ''' <summary>
    27. ''' Stellt eine UTC-Zeit ein, zu der der Rechner aus dem Stromsparmodus aufwacht.
    28. ''' </summary>
    29. ''' <param name="wakeAt">Die Zeit im UTC-Format, zu der der Rechner aufwachen soll.</param>
    30. Public Shared Sub SetWaitForWakeupTime(ByVal wakeAt As DateTime)
    31. Dim utc As New DateTime(wakeAt.Ticks, DateTimeKind.Utc)
    32. Dim duetime As Int64 = utc.ToFileTime()
    33. Using handle As SafeWaitHandle = CreateWaitableTimer(IntPtr.Zero, True, "MyWaitableTimer")
    34. If SetWaitableTimer(handle, duetime, 0, IntPtr.Zero, IntPtr.Zero, True) Then
    35. Using wh As New EventWaitHandle(False, EventResetMode.AutoReset)
    36. wh.SafeWaitHandle = handle
    37. wh.WaitOne()
    38. End Using
    39. Else
    40. Throw New Win32Exception(Marshal.GetLastWin32Error())
    41. End If
    42. End Using
    43. End Sub
    44. End Class


    (Dies ist nur ein Testprogramm)
    Nur leider scheint die Zeitübergabe nicht richtig zu funktionieren.
    Der Timer (die Funktion SetWaitForWakeupTime()) startet aber das Programm wacht
    nicht zu der übergebenen Zeit wieder auf ????
    Was mache ich noch falsch ??? Bitte hilf mir ein letztes Mal !!!

    Gruß Hubertus23 8-)
    Du musst die Aufwachzeit im UTC-Format eingeben. Siehe dazu:
    weltzeituhr.com/infos/utc.shtml

    und:
    de.wikipedia.org/wiki/Koordinierte_Weltzeit

    Wenn der Rechner also um 11 deutscher Zeit aufwachen soll, musst du 09:00:00 UTC angeben. Wir leben zwar in der Zeitzone UTC + 1, du musst aber noch die Sommerzeit hinzurechnen. Deswegen 9 und nicht 10 Uhr UTC.

    Außerdem könntest du die DLL direkt verwenden: Such' sie dir im Release-Verzeichnis (oder erstelle die Release-Version selbst) der "wakelib". Gehe dann in deiner Anwendung auf "Verweis hinzufügen" (im Kontextmenü des Projektes im Projektmappen-Explorer) und wähle unter "Durchsuchen" die DLL aus. Sie wird automatisch kopiert und geladen. Über den Ausdruck "Public Class Form1" kannst du dann "Imports wakelib" schreiben und die Funktion genauso nutzen wie sonst auch. Nur dass du dazu den Code nicht kopieren musstest. Probiers' doch mal aus XD.
    Gruß
    hal2000

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „hal2000“ ()

    Hallo zusammen, das thema ist zwar schon etwa 2 Monate alt aber es würde mich trotzdem intressieren wie das am ende genau ausgesehen hat es funktioniert.....

    Ich hab die wakelib von hal2000 in mein Programm integriert und dann volgendes aufgerufen:

    VB.NET-Quellcode

    1. Imports wakelib
    2. Public Class Form20
    3. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    4. 'Zeit zu der der Rechner aufwachen soll
    5. Dim my_time As New DateTime(2009, 7, 28, 21, 15, 5)
    6. Wake.SetWaitForWakeupTime(my_time)
    7. Application.SetSuspendState(PowerState.Suspend, True, False)
    8. End Sub


    Hab nun aber fest gestellt wenn ich DateTime in der zukunft eingebe geht gar nichts, d.h. das Programm reagiert nicht mehr ohne Fehlermeldungen.
    Wenn ich ein DateTime in der vergangenheit eingebe dann fährt der PC in den Standby....aber er wird natürlich nicht mehr von selber geweckt:-(
    Wenn ich das Programm von hubertus23 1zu1 übernehme passiert leider das gleiche...

    Hat mir vielleicht einer einen Tipp warum er mir die Zeit nicht übernimmt?

    gruss und danke

    zulu23
    Hallo zulu23,

    Ich habe da tatsächlich etwas vergessen zu sagen: :D

    Das Problem was du hast ist verständlich da, wenn ich die Funktion

    VB.NET-Quellcode

    1. Wake.SetWaitForWakeupTime(my_time)

    aufrufe, das Programm sofort einschläft,
    d.h. es würde erst NACH der angegebenen Zeit aufwachen und den PC in den
    Ruhezustand fahren.

    Deshalb habe ich zu einem kleinen Trick gegriffen: Ich habe den

    VB.NET-Quellcode

    1. Application.SetSuspendState(PowerState.Suspend, True, False)

    Befehl einfach in ein seperates Programm geschrieben verbunden mit einem
    Timer.

    Siehe dazu einfach meinen Quellcode:
    Hauptprogramm (das was den Rechner aufwachen lässt)

    VB.NET-Quellcode

    1. 'Vars für das Datum vom Morgen (zum Aufwachen)
    2. Dim timer_day As Integer = Now.Day + 1
    3. Dim timer_month As Integer = Now.Month
    4. Dim timer_year As Integer = Now.Year
    5. Dim myStartTime As Integer
    6. ... 'meine Verarbeitung der Zeit (unwichtig für dich)
    7. 'Datum für den morgigen Start festlegen
    8. Dim tomorrow As New DateTime(timer_year, timer_month, timer_day, (myStartTime - (Now.Hour - Date.UtcNow.Hour)), 0, 0)
    9. 'Ruhezustand auslösen in 10 Sek. (hibernate.exe)
    10. Shell("C:\Programme\MeinProgramm\hibernate.exe", AppWinStyle.Hide, False, -1)
    11. 'Wake_me_up_Timer stellen
    12. Wake.SetWaitForWakeupTime(tomorrow)


    Und der Code für die "hibernate.exe"

    VB.NET-Quellcode

    1. Dim i As Integer = 0
    2. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load, hibernate_timer.Tick
    3. If i = 10 Then
    4. hibernate_timer.Enabled = False
    5. Application.SetSuspendState(PowerState.Hibernate, True, False)
    6. Me.Close()
    7. End If
    8. i = i + 1
    9. End Sub

    Ganz wichtig : du musst unbedingt die UTC-Zeit beachten, die habe ich gleich
    beim Erstellen der Zeit mit eingebunden !! :D

    So jetzt brauchst du nur noch einen Timer in deiner "hibernate.exe" mit Intervall=1000 und fertig.

    P.S. Es müssen nicht unbedingt 10 Sek. Wartezeit sein.

    Es ist vielleicht nicht die schönste Variante aber es funktioniert und ist für mich völlig
    in Ordnung.

    Wenn du noch Fragen hast einfach posten !! :thumbup:

    Gruß hubertus23
    Hey hubertus23

    Danke vielmals für deine super Erklärung!!! :thumbsup: Hatte erst am weekend zeit zum alles ausfühlich zu testen.
    Mit deiner Variante(mit zusätzlichem Programm) funktioniert alles wunderbar.

    Weisst du ob man mehrere Zeiten angeben kann und er dann immer wieder aufwacht oder wird einfach immer die letzte eingegebene Zeit verwendet zum aufwachen?

    Gruss zulu23
    Hallo Liebes Forum!

    Ich weiß das Thema ist alt aber trotzdem.
    Ich habe dank eurer super Anleitung (Danke auch von mir) es jetzt auch soweit geschaft!

    Jetzt wollte ich die Frage von hal2000 nochmal aufgreifen:

    Kann man gleich mehrere Zeiten Festlegen zu den der PC "geweckt" wird oder muss man jedes mal wenn er hochgefahren ist wieder eine neue Zeit einstellen?

    LG klibene
    Du kannst einen Scheduler schreiben und in dem festlegen, wann der PC geweckt werden soll und intern läuft ein Timer, der prüft ob die Uhrzeit erreicht ist, wenn ja würde ich eine Wake-On-Lan befehl senden, wenn ja läuft der Timer weiter. Natürlich nach Senden des Befehls läuft der Timer weiter.
    Danke für deine Antwort!

    Jetzt hab ich noch eine andere Frage:

    Mein Ziel ist es, dass ich irgendwann einen Zeitpunkt (z.B.: Morgen um 9:00 Uhr) festlege und der PC zu diesem Zeitpunkt startet, ich ihn aber nicht jetzt gleich sondern erst irgendwann am Abend ausschalte.
    Das ist grudsätzlich auch kein Problem mit den Skrips die ihr gepostet hab das einzige ist, dass sobald das Programm die mit dem Befehl "Wake.SetWaitForWakeupTime(my_time)" die Zeit ins Bios schreibt das Programm Einfriert und erst wieder verwendet werden kann wann der Eingestellte Zeitpunkt erreicht ist oder der PC neu gestartet wird!

    Kann man das irgendwie ändern?

    LG Bene