worker321 发表于 2017-5-8 07:42:58

安装程序时间同步小工具(Python + Windows Service + NSIS) 安装程序

  时光紧张,先记一笔,后续优化与完善。
  家里有台很多年前买的电脑,CMOS电池残废了,经常碰到开机后系统时光被重置的情况,老妈向我反应用起来很不便利。于是身为一个程序员的我想到写个小具工来帮老妈排难解纷。话不多说,小具工需求如下:
功能需求 -- 电脑开机后动自执行时光同步
非功能需求 -- 安装执行单简,无需安装额定境环

一、码代实现
  基于以上需求,思绪如下:拜访络网取获北京时光,然后调用命令行来设置系统时光。程序写成Windows Service,并设置为开机动自行运。恰好前段时光在学习Python,所以算打用Python来写这个具工。体具码代如下:

取获络网时光
1 def getBeijinTime():
2   """
3    取获北京时光
4   """
5   try:
6         conn = httplib.HTTPConnection("www.beijing-time.org")
7         conn.request("GET", "/time.asp")
8         response = conn.getresponse()
9         print response.status, response.reason
10         if response.status == 200:
11             #剖析应响的消息
12             result = response.read()
13             logging.debug(result)
14             data = result.split("\r\n")
15             year = data"nyear")+1 : len(data)-1]
16             month = data"nmonth")+1 : len(data)-1]
17             day = data"nday")+1 : len(data)-1]
18             #wday = data)-1]
19             hrs = data"nhrs")+1 : len(data)-1]
20             minute = data"nmin")+1 : len(data)-1]
21             sec = data"nsec")+1 : len(data)-1]
22            
23             beijinTimeStr = "%s/%s/%s %s:%s:%s" % (year, month, day, hrs, minute, sec)
24             beijinTime = time.strptime(beijinTimeStr, "%Y/%m/%d %X")
25             return beijinTime
26   except:
27         logging.exception("getBeijinTime except")
28         return None




同步地本系统时光
1 def syncLocalTime():
2   """
3     同步地本时光
4   """
5   logging.info("current local time is: %d-%d-%d %d:%d:%d" % time.localtime()[:6])
6   
7   beijinTime = getBeijinTime()
8   if beijinTime is None:
9         logging.info("get beijinTime is None, will try again in 30 seconds...")
10         timer = threading.Timer(30.0, syncLocalTime)
11       timer.start();
12   else:
13         logging.info("get beijinTime is: %d-%d-%d %d:%d:%d" % beijinTime[:6])
14            
15         tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec = beijinTime[:6]
16         import os
17         os.system("date %d-%d-%d" % (tm_year, tm_mon, tm_mday))   #设置日期
18         os.system("time %d:%d:%d.0" % (tm_hour, tm_min, tm_sec))    #设置时光
19         logging.info("syncLocalTime complete, current local time: %d-%d-%d %d:%d:%d \n" % time.localtime()[:6])




二、署部安装
  为了让Python程序能以Windows务服的式方行运,要需用到py2exe(用来把Python程序编译成exe)和Python Win32 Extensions 。(py2exe把Python码代编译成Winodws务服时依附此件组)载下并安装这两个件组。安装毕完后,在Python的安装目录下找到py2exe的Windows Service示例({PythonRoot}\Lib\site-packages\py2exe\samples\advanced\MyService.py)。然后照仿这个示例将上面的码代完善一下。

Windows务服示例
1 import win32serviceutil
2 import win32service
3 import win32event
4 import win32evtlogutil
5
6 class SynctimeService(win32serviceutil.ServiceFramework):
7   _svc_name_ = "Synctime"
8   _svc_display_name_ = "Synctime"
9   _svc_description_ = "Synchronize local system time with beijin time"
10   _svc_deps_ = ["EventLog"]
11   
12   def __init__(self, args):
13         win32serviceutil.ServiceFramework.__init__(self, args)
14         self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
15
16   def SvcStop(self):
17       self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
18       win32event.SetEvent(self.hWaitStop)
19
20   def SvcDoRun(self):
21         import servicemanager
22         
23         # Write a 'started' event to the event log...
24       win32evtlogutil.ReportEvent(self._svc_name_,
25                                     servicemanager.PYS_SERVICE_STARTED,
26                                     0, # category
27                                     servicemanager.EVENTLOG_INFORMATION_TYPE,
28                                     (self._svc_name_, ''))
29
30         # wait for beeing stopped...
31       win32event.WaitForSingleObject(self.hWaitStop, win32event.INFINITE)
32
33         # and write a 'stopped' event to the event log.
34       win32evtlogutil.ReportEvent(self._svc_name_,
35                                     servicemanager.PYS_SERVICE_STOPPED,
36                                     0, # category
37                                     servicemanager.EVENTLOG_INFORMATION_TYPE,
38                                     (self._svc_name_, ''))   
39
40 if __name__ == '__main__':
41   # Note that this code will not be run in the 'frozen' exe-file!!!
42   win32serviceutil.HandleCommandLine(SynctimeService)



  后之,再编写一个steup.py文件用来生成安装文件。

Setup.py
1 from distutils.core import setup
2 import py2exe
3
4 setup(
5   # The first three parameters are not required, if at least a
6   # 'version' is given, then a versioninfo resource is built from
7   # them and added to the executables.
8   version = "0.0.1",
9   description = "Synchroniz local system time with beijin time",
10   name = "sysctime",
11
12   # targets to build
13   # console = ["synctime.py"],
14   service=["synctime"]
15 )



  编译生成windows程序,如下图:


  然后在控制台中行运:setup.py py2exe ,一切顺利的话会在当前目录下生成build和dist目录。


  控制台目录切换到dist目录,找到synctime.exe,在命令行中行运:
  synctime.exe –install (-remove)  安装或移除时光同步务服。
  现在可以行运services.msc查看务服行运情况


  可以看到务服并没有启动,而且启动式方为手动。在这里可以右击务服选择属性手动把务服启动起来,并且设置为务服动自启动。
  好吧,我承认。这样操作跟上面的需求有点出入了,略显麻烦。为了解决这个问题,自然想到的是用批处理来做。在dist目录下分别建两个批处理文件:

installservice.bat
1 @echo off
2
3 :: 安装windows务服
4 echo 正在安装务服,请稍候...
5 synctime.exe -install
6
7 :: 设置务服动自启动
8 echo 正在启动务服...
9 sc config Synctime start= AUTO
10
11 :: 启动务服
12 sc start Synctime
13
14 echo 务服启动成功, 按任意键继续...
15 pause




removeserivce.bat
1 @echo off
2
3 :: 停止务服
4 echo 正在停止务服,请稍候...
5 sc stop Synctime
6
7 echo 正在卸载务服...
8 :: 删除windows务服
9 synctime.exe -remove
10
11 echo 务服卸载完成,请按任意键继续剩余卸载...
12 pause



  
好了,现在可以把dist打个包发给老妈用了。但是,这样发个一个压缩包,看起来也太不专业了。解决的办法是打一个安装包,把bat脚本打到安装包里,在安装程序时由安装包调用。这里我用的是NISI(使用HM VNISEdit打包向导来生成打包脚本非常便利)。

三、最终安装效果图









四、结尾
  遗留的问题:
  1、从上面的截图可以看到,安装程序在调用批处理时会显示出控制台窗口。这个问题我在网上查找资料,NSIS有相关的插件可以隐藏控制台窗口调用bat文件。
  2、我源码代中有写日志文件的操作,但是以Windows务服的式方行运后,日志文件不能写了,不知道有没有好的解决办法。
  3、360 ...真是要人命啊....Orz..
  最后附上源码代及时光同步具工安装包
  版权说明:本文章版权归本人及博客园共同所有,未经允许请勿用于任何商业用途。转载请标明原文出处:
  http://www.cnblogs.com/talywy/archive/2013/03/07/SynctimeTool.html
  文章结束给大家分享下程序员的一些笑话语录: 看新闻说中国输入法全球第一!领先了又如何?西方文字根本不需要输入法。一点可比性都没有。
页: [1]
查看完整版本: 安装程序时间同步小工具(Python + Windows Service + NSIS) 安装程序