I posted a version of this script 3-4 weeks ago. This one is better.
If you wanted to fully automate the time syncing, the old version had to
be scheduled which is less than ideal for a dial-up connection. This
version is written to be started with a shortcut in the startup folder,
or can run as a service using srvany.exe.
The old version only worked on systems using a mm/dd/yy date format.
Not good. This version should work for any locale. But unless I missed
something in the docs, it's not as easy doing this in jscript as it is
in VBScript. Am I doing it the hard way? I think DateValue(Now) is all
you need with vbscript to get something that can be used with the date
command.
The old version used xmlhttp to test for being online, mainly because
ping wasn't working on my system when I tried it. I later discovered
that 'http.open("OPTIONS"," http://www.*-*-*.com/ ",false);' works better
than the 'http.open("GET"," http://www.*-*-*.com/ ;,false);' I used
before, but it's still about 1/10th second slower than a first ping
(~.6s vs .5s with my connection). Using ping makes it easier to try 2 or
3 sites too, so now that ping is working on my system again I use it in
the new version. [Torgeir: still can't ping www.hydro.com though.]
This version has other improvements too, like waiting for RAS inactivity
before doing a sync thereby increasing accuracy.
I'm hoping someone using XP will try it out and let me know if it works.
I'm "sure" there's no bugs ;-) but if there are I'd appreciate hearing
about those too.
--
Jim Taylor
/*
Tested on Windows 2000. May or may not work with XP.
Set the time server using the command NET TIME /SETSNTP:time.nist.gov
Command line arguments (optional):
arg0
0: (or not present) Do a time sync if possible and exit. (No RAS activity check.)
1: Remain loaded until there's one good sync, then exit.
2: Remain loaded and sync once per x hours or days.
arg1
0: (or not present) Allow all popups appropriate for the arg0 value.
1: Block most popups.
Set shortcut target to: wscript "<path>\jsync.js" arg0 arg1.
*/
var title = "jsync.js";
var logfile = "jsync.log"; //If a path is added remember to use \\ for a backslash.
var PingSites = new Array ("time.nist.gov", "www.yahoo.com", "www.zdnet.com");
var MaxChange = 50; //Warn user if a time correction exceeds this limit in seconds. Not blocked by arg1.
var QuietTime = 20; //if arg0>0, number of seconds that RAS must have no activity before doing a time sync.
var delay = 0; //if arg0>0, number of seconds to display the warning popup before syncing. 0=no warning.
var fso = new ActiveXObject("Scripting.FileSystemObject");
var oSh = WScript.CreateObject("WScript.Shell");
var oEnv = oSh.Environment("PROCESS");
var tempfile = oEnv("TEMP") + "\\$jsync$.tmp" ;
var oArgs = WScript.Arguments;
var arg0 = (oArgs.length > 0)? oArgs(0) : 0;
var arg1 = (oArgs.length > 1)? oArgs(1) : 0;
var pop1, LockedOut, oLogfile, GoodSync, answer, TimeError, NewTime, TimeWas;
var minute=60*1000, hour=60*minute, ForReading=1, ForAppending=8;
while (true){
answer = GoodSync = false;
do{
pop1 = LockedOut = false;
if (arg0) WaitForQuietRAS(QuietTime);
try{
oLogfile = fso.OpenTextFile(logfile, ForAppending, true);
}
catch(e){
LockedOut = true;
}
if (!LockedOut){
if (ping()){
if (!answer) answer = NotifyUser();
switch (answer){
case -1 : WaitForQuietRAS(QuietTime); //timed out - do checks again because of the delay.
if (ping()) GoodSync = SyncTime(); break;
case 2 : GoodSync = true; break; //Cansel button was pushed.
default : GoodSync = SyncTime(); //OK button was pushed or the popup wasn't opened.
}
}
else if (!arg0) pop1 = new Array("Unable to access the Internet.",4,64);
oLogfile.close();
if (pop1){
oSh.popup(pop1[0], pop1[1], title, pop1[2]);
if (!arg1 && GoodSync) pop2();
}
}
if (!arg0 || arg0==1 && GoodSync)
WScript.quit();
WScript.sleep(4*minute);
}
while (!GoodSync);
WScript.sleep(12*hour);
Quote:
}
function NotifyUser()
{
if (arg0 && !arg1 && delay > 0){
var d = (delay + QuietTime) * 1000;
var when = new Date(new Date().getTime() + d).toLocaleString();
when = when.substr(when.indexOf(":")-2);
var s = "The clock will be synchronized to a time server at " + when + ".\n"
+ "(Any RAS activity in the " + QuietTime + " seconds preceding the sync will cause a delay.)\n\n"
+ "Click on OK to synchronize the clock immediately, click on Cancel to cancel the event.";
var BtnCode = oSh.Popup(s, delay, title, 65);
return BtnCode; //-1=timeout, 1=OK, 2=Cansel
}
return 0;
Quote:
}
function pop2()
{
var d = Math.round( (TimeWas - new Date())/1000 );
var s = "This window will close when the PC's date/time has reached its\n"
+ "previous maximum value, " + TimeWas.toLocaleString() + ".";
if (d > 5 && d/60/60 < 10) oSh.popup(s, d, title, 64);
Quote:
}
function SyncTime()
{
var i, f, index, result;
NewTime = 0;
TimeWas = new Date();
do{
if (NewTime) MoveTime(TimeError + 200);
oSh.run("%comspec% /c w32tm.exe -once > " + tempfile, 0, true);
f = fso.OpenTextFile(tempfile, ForReading);
w32tm = f.ReadAll();
f.close();
fso.DeleteFile(tempfile);
var failed = new Array();
failed[0] = new Array("connect failed", "w32tm reports: Unable to connect to server.");
failed[1] = new Array("send failed", "w32tm reports: Received no response from server.");
failed[2] = new Array("source failed", "w32tm reports: Time source failed to produce usable timestamp.");
failed[3] = new Array("Cannot synchronize", "w32tm reports: Cannot synchronize.\n\nHas a time server been set?");
failed[4] = new Array("not get delay", "w32tm reports: Erratic round trip delays, so time was not set.");
for (i in failed){
if (w32tm.indexOf(failed[i][0]) != -1){
if (!arg0) pop1 = new Array(failed[i][1],0,48);
return false;
}
}
if (!NewTime){
index = w32tm.indexOf("ClockError");
TimeError = parseInt(w32tm.substring(index+12, w32tm.indexOf("\n",index)-1));
}
index = w32tm.indexOf("BEGIN:SetTimeNow")+18;
result = w32tm.substring(index+12, w32tm.indexOf("\n",index)-1);
switch (true){
case result.substr(0,3) == "END" : NewTime = "Not changed"; break;
case result.substr(3,7) == "Skewing" : NewTime = 1; break;
case result.substr(3,4) == "Time" : NewTime = GetLocalDT(result.substr(8,result.length-1)); break;
default :
if (!arg0) pop1 = new Array("Script Error " + NewTime,0,16);
return false;
}
}
while (NewTime==1);
ShowAndLog();
return true;
Quote:
}
function ShowAndLog()
{
var day=1000*60*60*24;
if (Math.abs(TimeWas - NewTime) > 24*day) //Fix for "ClockError" in the w32tm output being a signed
TimeError = Math.round((TimeWas - NewTime)/1000)*1000; //32-bit value that overflows if error > 24.86 days.
var server = oSh.RegRead("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\W32Time\\Parameters\\ntpserver");
var TimeIs = new Date(TimeWas.getTime() - TimeError);
var tail = (NewTime == "Not changed")? "not corrected" : "corrected";
var SlowOrFast = (TimeError > 0)? " fast" : " slow";
var strPopUp = "SNTP time server:\t" + server + "\n\n";
var strLog = GetLogTime() + " ";
if (TimeError == 0){
strPopUp += "Time difference:\tCorrect to the millisecond.\n";
strLog += " no time error.";
}
else{
strPopUp += "Time difference:\t" + GetText(TimeError) + SlowOrFast + ". (" + tail + ")\n";
strLog += SlowOrFast + ", " + GetText(TimeError) + ", " + tail + ".";
}
oLogfile.Write(strLog + "\r\n");
if (Math.abs(TimeError) > 1000)
strPopUp += "\nLocal time was:\t" + TimeWas.toLocaleString();
strPopUp += "\nLocal time is:\t" + TimeIs.toLocaleString();
if (Math.abs(TimeError)/1000 > MaxChange){
strPopUp += "\n\n**This change exceeded the " + MaxChange + " second warning level set in the script**";
pop1 = new Array(strPopUp,0,48);
}
else if (!arg1)
pop1 = new Array(strPopUp,0,64);
Quote:
}
function GetLogTime()
{
var p = (GetParts(new Date()));
return p[0] + "." + p[1] + "." + p[2] + " " + p[3] + ":" + p[4];
Quote:
}
function GetLocalDT(UTCtime) //input format (from w32tm output): "8/20/2002 18:22:17:465"
{
var s = UTCtime.split(/ |\/|:/);
var offset = new Date().getTimezoneOffset();
return new Date(s[2], s[0]-1, s[1], s[3], s[4]-offset, s[5]);
Quote:
}
function MoveTime(milliseconds) //positive number moves time back
{
var WillBeDate = new Date(new Date().getTime() - milliseconds);
var p = GetParts(WillBeDate);
oSh.run("%comspec% /c time " + p[3] + ":" + p[4] + ":" + p[5], 0, true);
oSh.run("%comspec% /c date " + GetShortDateFormat(WillBeDate), 0, true);
Quote:
}
function GetShortDateFormat(d) //arranges month, day, year in short date order
{
var i, j, s="", f, sf;
var a = new Array();
a[0] = new Array("y", d.getFullYear() );
a[1] = new Array("M", d.getMonth()+1 );
a[2] = new Array("d", d.getDate() );
f = oSh.RegRead("HKEY_CURRENT_USER\\Control Panel\\International\\sShortDate");
sf = f.split(/\.|\/|-/);
for (i in sf)
for (j in a)
if (sf[i].substr(0,1) == a[j][0])
s += a[j][1] + "-";
return s.replace(/-$/, "");
Quote:
}
function GetParts(d)
{
function pad(n)
{
return(n = (n < 10)? "0" + n : n);
}
var parts = new Array();
parts.push(d.getFullYear()); //parts[0]
parts.push(pad(d.getMonth() + 1)); //parts[1]
parts.push(pad(d.getDate())); //parts[2]
parts.push(pad(d.getHours())); //parts[3]
parts.push(pad(d.getMinutes())); //parts[4]
parts.push(pad(d.getSeconds())); //parts[5]
return parts;
Quote:
}
function GetText(n)
{
var seconds, minutes, hours, days, s="";
var minute=60*1000, hour=60*minute, day=24*hour;
var n = (n < 0)? -n : n;
switch (true){
case n >= day : days = Math.floor(n/day); n -= day * days;
case n >= hour : hours = Math.floor(n/hour); n -= hour * hours;
case n >= minute :
... read more »