时间同步小工具(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[1][len("nyear")+1 : len(data[1])-1]
16             month = data[2][len("nmonth")+1 : len(data[2])-1]
17             day = data[3][len("nday")+1 : len(data[3])-1]
18             #wday = data[4][len("nwday")+1 : len(data[4])-1]
19             hrs = data[5][len("nhrs")+1 : len(data[5])-1]
20             minute = data[6][len("nmin")+1 : len(data[6])-1]
21             sec = data[7][len("nsec")+1 : len(data[7])-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

转载于:https://www.cnblogs.com/talywy/archive/2013/03/07/SynctimeTool.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: duilib 是一个用于创建 Windows 安装程序的开源库,它基于 NSIS(Nullsoft Scriptable Install System)。NSIS 是一个脚本驱动的安装程序创建工具,它可以帮助软件开发者快速、高效地创建 Windows 安装程序。 duilib 是基于 NSIS 的一个图形用户界面(GUI)扩展库,可以为 NSIS 脚本提供一套丰富的用户界面元素和交互功能。它提供了一系列的 UI 控件,如按钮、编辑框、静态文本等,可以用于创建自定义的安装程序界面。同时,duilib 还提供了模板和皮肤机制,使开发者能够自定义和美化安装程序界面,从而使其更符合应用程序的风格和品牌。 使用 duilib 可以帮助开发者简化和加速安装程序的开发过程。它提供了丰富的功能和示例代码,使得创建自定义的安装界面变得相对容易。而且,duilib 的使用方式与 NSIS 脚本非常相似,开发者可以利用已经熟悉的 NSIS 脚本知识快速上手。 总结来说,duilib 是一个基于 NSIS 的图形用户界面扩展库,可以帮助开发者更方便、更快速地创建自定义的 Windows 安装程序界面。它提供了丰富的 UI 控件和皮肤机制,使得安装界面可以更加美观和符合应用程序的风格。使用 duilib 可以简化和加速安装程序的开发过程,为用户提供更好的安装体验。 ### 回答2: NSIS 是 Nullsoft 脚本式安装系统(Nullsoft Scriptable Install System)的缩写。它是一种免费的、开源的脚本式安装系统,用于在 Windows 操作系统上创建安装程序。 NSIS 是一种具有很高灵活性和强大功能的安装系统,可以用来创建各种不同类型的安装程序。使用 NSIS,开发者可以通过编写脚本来定义每个安装程序的行为和外观。它支持自定义界面、图标、卸载程序、启动器等功能。此外,NSIS 还支持压缩和加密功能,可以有效地减小安装程序的体积,并添加保护措施。 NSIS 的脚本语言简单易学,使用简洁的命令和语法,可以轻松地完成各种任务,包括文件复制、注册表操作、创建快捷方式、运行脚本等。同时,它还提供了很多插件和扩展,开发者可以根据需要选择和使用。 NSIS 的性能非常优秀,它创建的安装程序小巧快速,用户安装时无需依赖其他额外的运行环境,可以直接在 Windows 操作系统上运行。 总而言之,NSIS 是一种功能强大、灵活易用的安装系统,适用于开发者创建并分发各种软件的安装程序。通过使用 NSIS,开发者可以轻松地定制和创建自己的安装程序,为用户提供良好的安装体验。 ### 回答3: duilib 是一个开源的界面开发库,主要用于开发Windows平台下基于NSIS(Nullsoft Scriptable Install System)的安装程序。 NSIS 是一个受欢迎的跨平台的安装程序制作工具,用于创建Windows平台下的安装程序。但是,NSIS自身的界面开发功能相对较弱,所以开发者通常利用duilib这个界面库来增强NSIS的界面开发能力。 duilib 提供了一系列的界面控件和布局管理功能,使得开发者可以很方便地创建自定义的安装程序界面。它支持包括按钮、标签、输入框、进度条等常见的界面控件,开发者可以根据需求进行自定义的样式和布局设计。 duilib 还提供了丰富的事件处理机制,使得开发者可以通过编写事件处理函数来实现与界面控件的交互。开发者可以根据自己的需求,对控件的各种事件进行处理,比如按钮点击、鼠标移动等。 使用duilib对NSIS进行界面开发的优势在于它的灵活性和易用性。开发者可以通过在duilib的基础上进行二次开发,轻松实现各种复杂的界面效果,并满足特定的需求。同时,duilib还提供了丰富的文档和示例代码,方便开发者学习和参考。 总之,duilib 是一个功能强大的界面开发库,能够极大地提升NSIS安装程序的界面用户体验,使得开发者可以更加自由地进行界面设计和交互功能实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值