This is a creation in Article, where the information may have evolved or changed.
Why do you write this program?
has been concerned about the Golang, from the April 2011 configuration environment wrote a Hello world! (Http://weibo.com/1409046677/wr4n3vdYFV), and then did not write Golang code, just focus on golang information/information. Last year to a little more serious to see some Golang basic grammar, and then a few days ago, the desktop computer was turned on for a bit, it may be the BIOS battery is not power, it always need to reset the time after the boot. So it is better to use Golang write a Windows service automatically update the system time, so that the Golang applet today.
Another person might say that using Windows Time synchronization is OK, no need to bother. Here my main purpose is to make a sudden interest to use Golang practiced hand, followed by Windows comes with the time synchronization feature may not work because of the wall, anyway, I have not succeeded in manual synchronization,
Find time Synchronization API
When searching for information, I learned that the network time Protocol (NTP) (http://baike.baidu.com/view/60648.htm) can be very accurate synchronization, I do not want to be so high requirements, just get the latest time, update time on the line, So you have to find a usable online can get the latest time API, began to worry about the wall, looking for domestic, Baidu has a http://open.baidu.com/special/time/, but a page, not what I want, and finally determine the use of foreign HTTP// www.earthtools.org/timezone-1.1/35.86166/104.195397
Writing a synchronization program
Quite simple a small program, the idea is to get the API data, take the time, and then set to the system time, because is not familiar with the Golang API, do not know how to use Golang to update the system time, and then use Golang call DOS command to update.
When writing code, it is clear that in Golang, the case of the public and private, but in the definition of timezone structure, the variables used in lowercase, resulting in always get the correct data, tossing a lot of time. In addition, it took some time to find information for iso-8859-1 coding.
Encapsulated as a Windows service
About writing Windows service, start searching for data http://sanatgersappa.blogspot.com/2013/07/windows-service-with-go-easy-way.html (need to flip the wall ), feel NSSM (http://nssm.cc/) is very convenient, consider using NSSM program, using NSSM to register EXE program as a Windows service, command:
NSSM Install MyService D:\MyService.exe
(where D:\MyService.exe is the full path to the EXE file).
I wrote 2 batch programs Createservice.bat:
NSSM Install Syncsystemtimeservice%cd%\syncsystemtim.exe
Deleteservice.bat:
SC Delete Syncsystemtimeservice
Windows Service registration is successful, after starting the Syncsystemtimeservice service, my program does not seem to take effect, I suspect that either must use the full path (cannot use the%cd% variable), or may use%~dp0 instead of%cd% (reference: http:/ /stackoverflow.com/questions/16255184/ How-do-i-find-the-current-directory-of-a-batch-file-and-then-use-it-for-the-pat), and then I did not continue to investigate the reason, Found on the Internet a service program written using Golang: Http://bitbucket.org/kardianos/service, pull the code down, adjust it to meet the requirements I want.
Enclose the complete code:
Config.txt:
10s
Syncsystemtime.go
package mainimport ( "Bitbucket.org/kardianos/service" "bitbucket.org/ Kardianos/osext " " Encoding/xml " " errors " " FMT " " io " " io /ioutil " " net/http " " OS " " os/exec " " Time "var log Service. Loggerfunc main () { var name = "Syncsystemtimeservice" var displayName = "Sync system time service" var desc = " Synchronize Update window Time service (get latest time over network) " var s, err = service. NewService (NAME,&NBSP;DISPLAYNAME,&NBSP;DESC) log = s if err != nil { fmt. Printf ("%s unable to start: %s", displayname, err) return } if len (OS. Args) > 1 { var err error verb := os. args[1] switch verb { case "Install": err = s.install () if err != nil { fmt. Printf ("failed to install: %s\n", err) return } fmt. Printf ("service \"%s\ " installed.\n", displayname) case "Remove": err = s.remove () if err != nil { fmt. Printf ("failed to remove: %s\n", err) return } fmt. Printf ("service \"%s\ " removed.\n", displayname) case " Run ": dowork () case " Start ": err = s.start () if err != nil { fmt. Printf ("failed to start: %s\n", err) return } Fmt. Printf ("service \"%s\ " started.\n", displayname) case " Stop ": err&nbsP;= s.stop () if err != nil { fmt. Printf ("failed to stop: %s\n", err) return } Fmt. Printf ("service \"%s\ " stopped.\n", displayname) } return } err = s.run (func () error { go dowork () return nil }, func () error { stopwork () return nil }) if err != nil { s.error (Err. Error ()) }}func dowork () { log. Info ("I ' m running!") const defaultschedulingtime = "30m" // minutes schedulingTime := defaultSchedulingTime configFile := "Config.txt" configpath, err := osext. Executablefolder () if err != nil { log. Warning (Err. Error ()) } else { configFile = configPath + Configfile } log. Info (configfile) timeconfig, err := ioutil. ReadFile (configfile) if err == nil { schedulingtime = string (Timeconfig) } else { log. Warning (Err. Error ()) } timeduration, err := time. Parseduration (Schedulingtime) if err != nil { log. Warning (Err. Error ()) timeduration, err = time. ParseduratiOn (Defaultschedulingtime) } go () timer := time. Newticker (timeduration) for { select { case <-timer. C: go () } } select {}} Func stopwork () { log. Info ("I ' m stopping!")} Func go () { networktime := getnetworktime () setsystemtime ( Networktime)}/**1.035.86166104.1953978h21 apr 2014 23:08:092014-04-21 23:08:09 + 08002014-04-21 15:08:09unknown*/type timezone struct { localtime string ' xml: "localtime" ' IsoTime string ' xml: "Isotime" ' utctime string ' xml: "Utctime" '}func charsetreader (Charset string, r io. Reader) (IO. Reader, error) { if charset == "iso-8859-1 " | | charset == "Iso-8859-1" &NBSP;{&NBSP;&NBSP;&NBSP;&NBSP;RETURN&NBSP;R,&NBSP;NIL&NBSP;&NBSP;} return nil, errors. New ("unsupported character set encoding: " + charset)}func GetNetworkTime () string { const web_service_url = "HTTP://WWW.EARTHTOOLS.ORG/TIMEZONE-1.1/ 35.86166/104.195397 " result, err1 := http. Get (Web_service_url) if err1 != nil { log. Warning (ERR1. Error ()) return "" } defer result. Body.close () var timezone timezone data := xml. Newdecoder (result. Body) data. Charsetreader = charsetreader if err := data. Decode (&timezone); err != nil { return "" &NBSP;&NBSP;} // fmt. Println (timezone.Utctime) return timezone. Utctime}func setsystemtime (datetime string) { if dateTime == "" { return } currenttime := time. Now (). Format ("2006-01-02 15:04:05") logcontent := currenttime converttime, err1 := time. Parse ("2006-01-02 15:04:05", datetime) if err1 != nil { log. Warning (ERR1. Error ()) return } converttime = converttime.add (8 * time. Hour) logContent = logContent + " --> " + Converttime.format ("2006-01-02 15:04:05") comparevalue := converttime.format (" 2006-01-02 15:04:05 ") // if the time (month and day) is the same, the if currenttime[0:len is not updated ( currenttime) -3] == comparevalue[0:len (comparevalue)-3] { log. Info ("same time, not to update: " + currentTime + " | " + comparevalue) return } _, err2 := Exec. Command ("CMD", "/C", "DATE", converttime.format ("2006-01-02")). Output () if err2 != nil { log. Error (ERR2. Error ()) } _, err2 = exec. Command ("CMD", "/C", "Time", converttime.format ("15:04:05")). Output () if err2 != nil { log. Error (ERR2. Error ()) } currenttime = time. Now (). Format ("2006-01-02 15:04:05") logContent = logContent + " --> " + currenttime log. Info (logcontent) // writelogfile (logcontent)}/*func writelogfile (logContent string) & nbsp;error { filename := "Log.txt" file, err := os. OpenFile (Filename, os. O_rdwr|os. O_create|os. o_append, 0666) if err != nil { log. Fatal ("Error opening file: %v", err) return err } defer file. Close () log. Setoutput (file) log. Println (logcontent) return nil}*/
BTW: Because log print logs can be seen in the Windows Event Viewer, I commented out the Writelogfile function.
Small programs, small features, please tap, welcome criticism.