Timer + autom. Aufwecken des PCs, wenn im Ruhezustand ?
Verfasst: 10.03.2011 15:46
Im englischen Forum scheint mir leider keiner helfen zu können/wollen (http://www.purebasic.fr/english/viewtop ... 13&t=45691), deswegen stelle ich nun mal hier meine Frage.
Ich will einen Timer starten, wenn der Computer in den Ruhezustand geht und dann nach 30 Sekunden wieder aufwecken.
Blöderweise funktionieren ein paar Sachen noch nicht:
- Computer nach 30 aufwecken (siehe Logfile)
- #WM_POWERBROADCAST abfangen, wenn der Ruhezustand durch das Programm eingeleitet wurde (anstelle von Standby-Buttons des Systems etc.)
- ...
Hier ist der aktuelle Code:
Hier ist eine Logfile, die mit Windows Vista erstellt wurde. Standby wurde hierbei durch den "Standby-Modus"-Button gestartet:
Momentan denke ich, dass es mehrere Probleme geben könnte: DateToFiletime() erstellt aus welchen Gründen auch immer eine Zeit in der Vergangenheit, SleepEx_() wird benötigt, Sicherheitsgründe (Privilegien benötigt?), mein PC unterstützt diese Art von Standby nicht und/oder Konflikte mit dem Message-Handling von PureBasic...
Bitte probiert mal den Code und postet welche Ergebnisse ihr bekommt, damit ich eventuell herausfinden kann, warum es nicht funktioniert. Danke.
Ich will einen Timer starten, wenn der Computer in den Ruhezustand geht und dann nach 30 Sekunden wieder aufwecken.
Blöderweise funktionieren ein paar Sachen noch nicht:
- Computer nach 30 aufwecken (siehe Logfile)
- #WM_POWERBROADCAST abfangen, wenn der Ruhezustand durch das Programm eingeleitet wurde (anstelle von Standby-Buttons des Systems etc.)
- ...
Hier ist der aktuelle Code:
Code: Alles auswählen
EnableExplicit
#Title = "TimerTest"
Enumeration
#Window
#Text
#ButtonSuspend
#ButtonHibernate
#FileLog
EndEnumeration
#PBT_APMRESUMESUSPEND = $0007
#PBT_APMSUSPEND = $0004
Structure LogListItem
Text.s
Time.l
Level.l
EndStructure
Global NewList LogList.LogListItem()
Define Logfile.s
Logfile.s = GetPathPart(ProgramFilename()) + #Title + "_LOG.txt"
Procedure LogListAdd(Text.s, Level=0)
If AddElement(LogList())
With LogList()
\Text = Text
\Time = Date()
\Level = Level
EndWith
EndIf
EndProcedure
Procedure LogListAddError(Text.s, Level=2, Info=#True)
Protected Error, ErrorInfo.s
If Info = #True
Error = GetLastError_()
ErrorInfo = Space(#MAX_PATH)
FormatMessage_(#FORMAT_MESSAGE_FROM_SYSTEM, 0, Error, 0, @ErrorInfo, Len(ErrorInfo), 0)
ErrorInfo = " -> (" + RSet(Hex(Error, #PB_Long), 8, "0") + ") " + #DQUOTE$ + ErrorInfo + #DQUOTE$
EndIf
LogListAdd(Text + ErrorInfo, Level)
EndProcedure
Procedure LogListSave(Filename.s)
Protected FileNr
Protected Result = #False
FileNr = CreateFile(#PB_Any, Filename)
If FileNr
ForEach LogList()
WriteStringN(FileNr, FormatDate("%hh:%ii:%ss", LogList()\Time) + #TAB$ + LogList()\Text)
Next
Result = #True
CloseFile(FileNr)
EndIf
ProcedureReturn Result
EndProcedure
Procedure DateToFiletime(Date, *ft.FILETIME)
Protected st.SYSTEMTIME
With st
\wYear = Year(Date)
\wMonth = Month(Date)
\wDay = Day(Date)
\wDayOfWeek = DayOfWeek(Date)
\wHour = Hour(Date)
\wMinute = Minute(Date)
\wSecond = Second(Date)
\wMilliseconds = 0
EndWith
SystemTimeToFileTime_(@st, *ft)
LocalFileTimeToFileTime_(@*ft, *ft)
EndProcedure
Procedure TimerCallback(*ArgToCompletionRoutine, TimerLowValue.l, TimerHighValue.l)
LogListAdd("Timer: Beendet")
EndProcedure
Procedure TimerStart()
Protected hTimer
Protected ft.FILETIME
hTimer = CreateWaitableTimer_(#Null, #False, #Title)
If hTimer
LogListAdd("Timer: Erstellt")
DateToFiletime(Date() + 30, @ft) ; Wait 30 seconds until "waking up"
If SetWaitableTimer_(hTimer, @ft, 0, @TimerCallback(), 0, #True)
If GetLastError_() <> #ERROR_NOT_SUPPORTED
LogListAdd("Timer: Gestartet")
;SleepEx_(#INFINITE, #True)
Else
LogListAddError("Timer: Gestartet aber Aufwecken wird nicht unterstützt! (Meldung folgt nun sofort)")
EndIf
Else
LogListAddError("Timer: Nicht gestartet!")
EndIf
CloseHandle_(hTimer)
Else
LogListAddError("Timer: Nicht erstellt!")
EndIf
EndProcedure
Procedure WindowCallback(hWnd, uMsg, wParam, lParam)
Select uMsg
Case #WM_POWERBROADCAST
Select wParam
Case #PBT_APMSUSPEND
LogListAdd("Standby: Aktiviert")
TimerStart()
Case #PBT_APMRESUMESUSPEND
LogListAdd("Standby: Beendet")
EndSelect
EndSelect
ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
Procedure Suspend(Hibernate, ForceCritical=#False, DisableWakeEvent=#False)
Protected LibraryID
Protected Result = #False
LibraryID = OpenLibrary(#PB_Any, "powrprof.dll")
If LibraryID
Result = CallFunction(LibraryID, "SetSuspendState", Hibernate, ForceCritical, DisableWakeEvent)
CloseLibrary(LibraryID)
EndIf
ProcedureReturn Result
EndProcedure
Procedure SuspendAllowed()
Protected LibraryID
Protected Result = #False
LibraryID = OpenLibrary(#PB_Any, "powrprof.dll")
If LibraryID
Result = CallFunction(LibraryID, "IsPwrSuspendAllowed")
CloseLibrary(LibraryID)
EndIf
ProcedureReturn Result
EndProcedure
Procedure HibernateAllowed()
Protected LibraryID
Protected Result = #False
LibraryID = OpenLibrary(#PB_Any, "powrprof.dll")
If LibraryID
Result = CallFunction(LibraryID, "IsPwrHibernateAllowed")
CloseLibrary(LibraryID)
EndIf
ProcedureReturn Result
EndProcedure
If OpenWindow(#Window, #PB_Ignore, #PB_Ignore, 300, 170, #Title, #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_Invisible)
TextGadget(#Text, 10, 10, 280, 70, "Der Timer sollte automatisch starten (für 30 Sec.), wenn auf einen dieser Buttons oder im Startmenü entsprechendes geklickt wird." + #CRLF$ + #CRLF$ + "Hinweis: Die Buttons sollten funktionieren!")
ButtonGadget(#ButtonSuspend, 10, 90, 280, 30, "Standby-Modus")
ButtonGadget(#ButtonHibernate, 10, 130, 280, 30, "Ruhezustand")
If SuspendAllowed() = #False : DisableGadget(#ButtonSuspend, #True) : EndIf
If HibernateAllowed() = #False : DisableGadget(#ButtonHibernate, #True) : EndIf
SetWindowCallback(@WindowCallback())
HideWindow(#Window, #False)
LogListAdd("Programm: Gestartet")
Repeat
Select WaitWindowEvent()
Case #PB_Event_Gadget
Select EventGadget()
Case #ButtonSuspend
LogListAdd("Standby: Starte Standby-Modus")
TimerStart() ; <-- Warum wird #WM_POWERBROADCAST nicht abgefangen um das hier zu machen? (siehe WindowCallback())
Suspend(#False)
Case #ButtonHibernate
LogListAdd("Standby: Starte Ruhezustand")
TimerStart() ;
Suspend(#True)
EndSelect
Case #PB_Event_CloseWindow
LogListAdd("Programm: Beendet")
LogListSave(Logfile) ;: RunProgram(Logfile)
Break
EndSelect
ForEver
EndIf
Code: Alles auswählen
15:25:14 Programm: Gestartet
15:25:20 Standby: Starte Standby-Modus
15:25:20 Timer: Erstellt
15:25:20 Timer: Gestartet
15:25:20 Timer: Beendet <-- Wo sind die 30 Sec.?
15:26:37 Standby: Beendet
15:26:45 Programm: Beendet
Momentan denke ich, dass es mehrere Probleme geben könnte: DateToFiletime() erstellt aus welchen Gründen auch immer eine Zeit in der Vergangenheit, SleepEx_() wird benötigt, Sicherheitsgründe (Privilegien benötigt?), mein PC unterstützt diese Art von Standby nicht und/oder Konflikte mit dem Message-Handling von PureBasic...
Bitte probiert mal den Code und postet welche Ergebnisse ihr bekommt, damit ich eventuell herausfinden kann, warum es nicht funktioniert. Danke.