Jump to content

setting system time / dll issues...


Recommended Posts

ok, i'm working on that employee timeclock that Valuater was talking about in another post. i didn't put this with that post because even though it's related, i thought it should have it's own topic... short version: i'm trying to set the system time on windows machine. i know this could be done a few ways, like opening a command prompt and sending it the keys "time{ENTER}" & $NewTime... i'm trying to do everything quietly, so i did some research on changing the system time. i found a function in kernel32.dll named SetSystemTime... this function takes a systemtime object for input... MSDN defines that object as follows:

typedef struct _SYSTEMTIME { 

WORD wYear;

WORD wMonth; 

WORD wDayOfWeek; 

WORD wDay; 

WORD wHour; 

WORD wMinute; 

WORD wSecond; 

WORD wMilliseconds;

} SYSTEMTIME, *PSYSTEMTIME;

so in vb, you could create a systemtime object, and assign values to those properties, then pass it to the function and set the time... i've tried using this to do the same thing...

$blah = dllopen("kernel32.dll")
$arg = DLLCALL($blah,"long","SetSystemTime","WORD",@YEAR,"WORD",@MON,"WORD",@WDAY,"WORD",$hour,"WORD",$min,"WORD",$sec)
dllclose($blah)

I have a msgbox() then outputting the return value of $arg, which is invariably 0, msdn says that 0 is indicative of a failure. Not sure if anyone has worked with this function before, or if there is a way to create a custom data type like this in autoit because i know all variables are variant type normally...

the code to set the time in vb is:

Option Explicit

      Private Type SYSTEMTIME
        wYear As Integer
        wMonth As Integer
        wDayOfWeek As Integer
        wDay As Integer
        wHour As Integer
        wMinute As Integer
        wSecond As Integer
        wMilliseconds As Integer
      End Type

      Private Declare Function SetSystemTime Lib "kernel32" (lpSystemTime _
        As SYSTEMTIME) As Long

      Private Sub Form_Load()
        Dim lReturn As Long
        Dim lpSystemTime As SYSTEMTIME
        lpSystemTime.wYear = 1996
        lpSystemTime.wMonth = 6
        lpSystemTime.wDayOfWeek = 5
        lpSystemTime.wDay = 28
        lpSystemTime.wHour = 9
        lpSystemTime.wMinute = 42
        lpSystemTime.wSecond = 0
        lpSystemTime.wMilliseconds = 0
        lReturn = SetSystemTime(lpSystemTime)
      End Sub

any ideas how to make it work in autoit?

Link to comment
Share on other sites

First off, hour, min, and sec should be '@' (macros) instead of '$' (variables)...i'll test the code in a minute

Just looked on MSDN, their comments about SetSystemTime include:

it needs to be in UTC time

you have to enable the SE_SYSTEMTIME_NAME privilege

Edited by MSLx Fanboy

Writing AutoIt scripts since

_DateAdd("d", -2, _NowCalcDate())
Link to comment
Share on other sites

First off, hour, min, and sec should be '@' (macros) instead of '$' (variables)...i'll test the code in a minute

Just looked on MSDN, their comments about SetSystemTime include:

it needs to be in UTC time

you have to enable the SE_SYSTEMTIME_NAME privilege

<{POST_SNAPBACK}>

i have the hour min and sec variables because i do not want them to reflect system time, but values from a website that i've already parsed. also, the SE_SYSTEMTIME_NAME privilege is automatically changed when you use the function, per MS Platform SDK documentation:

Remarks

The SetSystemTime function enables the SE_SYSTEMTIME_NAME privilege before changing the system time. This privilege is disabled by default. For more information, see Running with Special Privileges.

appreciate the help, just wanted to clear up those things you'd addressed.
Link to comment
Share on other sites

  • Developers

you need to create a structure ... here's an example to set the clock 2 hours back:

$Str  = "ushort;ushort;ushort;ushort;ushort;ushort;ushort;ushort"
$Systime  = DllStructCreate($Str)
$blah = dllopen("kernel32.dll")
$arg = DLLCALL($blah,"long","GetSystemTime","ptr",DllStructGetPtr($Systime))
DllStructSetData($Systime,5,DllStructGetData($Systime,5)-2)
$arg = DLLCALL($blah,"long","SetSystemTime","ptr",DllStructGetPtr($Systime))
dllclose($blah)
DllStructDelete($Systime)
Edited by JdeB

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

you need to create a structure ... here's an example to set the clock 2 hours back:

$Str  = "ushort;ushort;ushort;ushort;ushort;ushort;ushort;ushort"
$Systime  = DllStructCreate($Str)
$blah = dllopen("kernel32.dll")
$arg = DLLCALL($blah,"long","GetSystemTime","ptr",DllStructGetPtr($Systime))
DllStructSetData($Systime,5,DllStructGetData($Systime,5)-2)
$arg = DLLCALL($blah,"long","SetSystemTime","ptr",DllStructGetPtr($Systime))
dllclose($blah)
DllStructDelete($Systime)

<{POST_SNAPBACK}>

Awesome man, that is EXACTLY what i needed. Thank you very much.
Link to comment
Share on other sites

you need to create a structure ... here's an example to set the clock 2 hours back:

$Str  = "ushort;ushort;ushort;ushort;ushort;ushort;ushort;ushort"
$Systime  = DllStructCreate($Str)
$blah = dllopen("kernel32.dll")
$arg = DLLCALL($blah,"long","GetSystemTime","ptr",DllStructGetPtr($Systime))
DllStructSetData($Systime,5,DllStructGetData($Systime,5)-2)
$arg = DLLCALL($blah,"long","SetSystemTime","ptr",DllStructGetPtr($Systime))
dllclose($blah)
DllStructDelete($Systime)

<{POST_SNAPBACK}>

Question, do i have to use the DllStructGetData() in the SetData? I would think not, as it looks like you're just accessing the current value and setting with a decrement in your example (that runs fine). But when i try to give it a variable, nothing happens to the time... i've verified that my variable hasn't lost scope or anything, but there is no change to the time...i'll post the full code below to see if anyone has any ideas, but another thing i noticed and wasn't sure about. Using SciTe, when i watch the status window at the bottom, it takes 30 - 60 seconds after running this script to get the line that says ">AutoIT3.exe ended". I was curious if this delay is because of SciTe or AutoIT.exe. The only reason that it matters is because the systray icon goes away as soon as the last statement is executed, but if the program isn't actually ending at that point, it may be something to submit as a bug. Maybe i'm just reading into it too much and that's the 'unload time' for SciTe, but maybe not you know? Anyway, the original issue, here's my code:

#include <Date.au3>
#region get and parse file
$getlist = inetget("http://tycho.usno.navy.mil/cgi-bin/timer.pl","c:\time")
if $getlist = 0 then msgbox(0,"Error","Inet time not availible, check connection.")
$input = fileopen("C:\time",0)
$infile = ""
While 1
    $infile = $infile & FileRead($input, 1)
    If @error = -1 Then ExitLoop
    Wend
fileclose($input)
$mytime = stringinstr($infile,"PDT")
$thetime = stringmid($infile,$mytime -12,8)
#endregion
;MsgBox(0,"STATUS","FIRST DOWN" & @CRLF & $THETIME)
#region figure times
$hour = StringLeft($thetime,2)
$min = stringmid($thetime,4,2)
$sec = stringright($thetime,2)
#endregion
;MsgBox(0,"STATUS","SECOND DOWN"& @CRLF & $HOUR & @CRLF & $MIN & @CRLF & $SEC)
;if _NowTime() <> $thetime Then
#region - JDEB'S CODE
$Str  = "ushort;ushort;ushort;ushort;ushort;ushort;ushort;ushort"
$Systime  = DllStructCreate($Str)
$blah = dllopen("kernel32.dll")
$arg = DLLCALL($blah,"long","GetSystemTime","ptr",DllStructGetPtr($Systime))
DllStructSetData($Systime,5,$hour)
$arg = DLLCALL($blah,"long","SetSystemTime","ptr",DllStructGetPtr($Systime))
dllclose($blah)
DllStructDelete($Systime) 
#endregion

in addition to just using the variable, i've tried to work with the current value to get the value i want.... using:

DllStructSetData($Systime,5,DllStructGetData($Systime,5) + $hour - DllStructGetData($Systime,5))

when i did that, it did increment the current time by the value stored in my variable, but it does not set it to what i want it to be, it just adds it to the current time.

Link to comment
Share on other sites

  • Developers

Question, do i have to use the DllStructGetData() in the SetData?  I would think not, as it looks like you're just accessing the current value and setting with a decrement in your example (that runs fine).  But when i try to give it a variable, nothing happens to the time...

<{POST_SNAPBACK}>

Correct...

I have no delays but th only delay i can thin of is the retrieval of the website.

You need to take the UTC time since thats what windows uses internally

Here's a version that work fine for me without any delays:

opt("TrayIconDebug",1)
#include <Date.au3>
#region get and parse file
$getlist = inetget("http://tycho.usno.navy.mil/cgi-bin/timer.pl","c:\time")
if $getlist = 0 then msgbox(0,"Error","Inet time not availible, check connection.")
$infile = FileRead("C:\time",FileGetSize("C:\time"))
$mytime = stringinstr($infile,"UTC")
$thetime = stringmid($infile,$mytime -9,8)
#endregion
;MsgBox(0,"STATUS","FIRST DOWN" & @CRLF & $THETIME)
#region figure times
$hour = number(StringLeft($thetime,2))
$min = Number(stringmid($thetime,4,2))
$sec = Number(stringright($thetime,2))
#endregion
;MsgBox(0,"STATUS","SECOND DOWN"& @CRLF & $HOUR & @CRLF & $MIN & @CRLF & $SEC)
;if _NowTime() <> $thetime Then
#region - JDEB'S CODE
$Str  = "ushort;ushort;ushort;ushort;ushort;ushort;ushort;ushort"
$Systime  = DllStructCreate($Str)
$blah = dllopen("kernel32.dll")
$arg = DLLCALL($blah,"long","GetSystemTime","ptr",DllStructGetPtr($Systime))
DllStructSetData($Systime,5,$hour)
DllStructSetData($Systime,6,$Min)
DllStructSetData($Systime,7,$sec)
$arg = DLLCALL($blah,"long","SetSystemTime","ptr",DllStructGetPtr($Systime))
dllclose($blah)
DllStructDelete($Systime) 
#endregion

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

Correct...

I have no delays but th only delay i can thin of is the retrieval of the website.

You need to take the UTC time since thats what windows uses internally

Here's a version that work fine for me without any delays:

opt("TrayIconDebug",1)
#include <Date.au3>
#region get and parse file
$getlist = inetget("http://tycho.usno.navy.mil/cgi-bin/timer.pl","c:\time")
if $getlist = 0 then msgbox(0,"Error","Inet time not availible, check connection.")
$infile = FileRead("C:\time",FileGetSize("C:\time"))
$mytime = stringinstr($infile,"UTC")
$thetime = stringmid($infile,$mytime -9,8)
#endregion
;MsgBox(0,"STATUS","FIRST DOWN" & @CRLF & $THETIME)
#region figure times
$hour = number(StringLeft($thetime,2))
$min = Number(stringmid($thetime,4,2))
$sec = Number(stringright($thetime,2))
#endregion
;MsgBox(0,"STATUS","SECOND DOWN"& @CRLF & $HOUR & @CRLF & $MIN & @CRLF & $SEC)
;if _NowTime() <> $thetime Then
#region - JDEB'S CODE
$Str  = "ushort;ushort;ushort;ushort;ushort;ushort;ushort;ushort"
$Systime  = DllStructCreate($Str)
$blah = dllopen("kernel32.dll")
$arg = DLLCALL($blah,"long","GetSystemTime","ptr",DllStructGetPtr($Systime))
DllStructSetData($Systime,5,$hour)
DllStructSetData($Systime,6,$Min)
DllStructSetData($Systime,7,$sec)
$arg = DLLCALL($blah,"long","SetSystemTime","ptr",DllStructGetPtr($Systime))
dllclose($blah)
DllStructDelete($Systime) 
#endregion

<{POST_SNAPBACK}>

super man, that works perfectly on mine too, i could have sworn that i'd tried it just like that (obviously not in the one i'd posted, but in an earlier attempt.). I was thinking that maybe the delay between the end of the script and the autoit.exe ending may have been tying up the dll or something (i ran a few tests while it was doing that, and i kept getting 65535 as the return value of the call to the dll...) but yes, this works great and i'm going to study this to see where i went wrong.
Link to comment
Share on other sites

super man, that works perfectly on mine too,  i could have sworn that i'd tried it just like that (obviously not in the one i'd posted, but in an earlier attempt.).  I was thinking that maybe the delay between the end of the script and the autoit.exe ending may have been tying up the dll or something (i ran a few tests while it was doing that, and i kept getting 65535 as the return value of the call to the dll...) but yes, this works great and i'm going to study this to see where i went wrong.

<{POST_SNAPBACK}>

found where i was messing up...

$hour = Number(StringLeft($thetime,2))

$min = Number(stringmid($thetime,4,2))

$sec = Number(stringright($thetime,2))

i wasn't doing the explicit typecasting, was just assuming the variant would be used as a number because i forgot that my computer can't read my mind... haven't had to typecast in autoit before, good to know how... thanks again
Link to comment
Share on other sites

  • Developers

found where i was messing up...

i wasn't doing the explicit typecasting, was just assuming the variant would be used as a number because i forgot that my computer can't read my mind... haven't had to typecast in autoit before, good to know how... thanks again

<{POST_SNAPBACK}>

Nah, goofing around with DllCall stuff is exact science again !! :) Edited by JdeB

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...