制作windows服务

大家都遇到过把自己开发的项目打包成相应的服务。在windows中快速部署。针对这个问题,我整理了一个思路,不管是html和python代码都是可以实现打包来封装部署的。这样做的好处是能够把自己开发的东西做成windows可以运行的exe文件,并且能够做成可以起停的系统服务。方便我们管理。

作者:lizhonglin
github: https://github.com/Leezhonglin/
blog: https://leezhonglin.github.io/

具体制作步骤如下:

1.准备好需要的文件
li-boss-service.exe
li-boss-service-def.xml
li-boss-service.exe.xml

这是注册服务的必须的三个有了它最终才呢个实现该服务的注册。

2.修该配置文件

li-boss-service-def.xml需要我们进行修改,修改成我们需要的信息。具体修改如下

<?xml version="1.0" encoding="UTF-8"?>
<service>
  <id>LiBoss</id>  <!--服务id-->
  <name>LiBoss</name> <!--服务名称-->
  <description>LiBoss Service</description> <!--服务描述信息-->
  <logpath>%BASE_PATH%\logs</logpath> <!--服务日志信息保存路径-->
  <log mode="roll-by-size">
    <sizeThreshold>10240</sizeThreshold>
    <keepFiles>8</keepFiles>
  </log>
  <executable>%BASE_PATH%\run.exe</executable> <!--执行文件的绝对路径-->
  <startarguments>-p %BASE_PATH%</startarguments>
  <stopexecutable>%BASE_PATH%</stopexecutable> 
  <stoparguments>-p %BASE_PATH% -s stop</stoparguments>
</service>

我们需要替换%BASE_PATH% 的内容为自己要启动的服务的路径即可。

注意:如果自己知道执行文件的路径就可以手动修改配置文件li-boss-service-def.xml里面的内容为自己的实际内容。然后保存为一个新的文件名称为li-boss-service.xml才能使用。

---------------------------分割线------------------------------------------------------------------

实际实现的案例
1.步骤一

我想注册一个服务名称叫LiBoss的服务在系统中。这个LiBoss服务是python的一个简单flask项目打包后的服务。

flask项目代码如下:

#!/usr/bin/python
# -*- coding: UTF-8 -*
"""
@author:li-boss
@file_name: start_app.py
@create date: 2019/11/15 23:00 
@blog https://leezhonglin.github.io
@csdn 
@file_description:简单的flask应用
"""


from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello_world():
   return '<h1>Hello Li-boss!!!</h1>'

if __name__ == '__main__':
   app.run()

使用python的pyinstaller来打包exe.

pyinstaller -F start_app.py

项目打包成功后有如下文件:

python windows开发 linux 发布 python程序发布windows_python

这样项目的内容就打包成exe的执行文件了。

我们可以进入dist目录执行start_app.exe来启动项目。

执行结果如下:

python windows开发 linux 发布 python程序发布windows_配置文件_02

这样我们就可以通过浏览器来访问我们的项目

python windows开发 linux 发布 python程序发布windows_xml_03

看到上面的就过我们的打包基础工作就已经成功。这样就有新的问题产生了,我们要运行项目的话每次都需要手动来点击这个start_app.exe文件。而且还有一个小黑框出现。就达不到方便使用的效果。为此我们要正式进入主题。制作服务,我么最终的目的就是把这个项目通过windows打包工具封装成一个安装完成后可以根据系统的启动自动启动服务 我么能非常方便的停止服务。向windows自带的服务一样。由于我们安装的最终路径都不能确定所以我们需要完成安装完成后自动修改服务的配置文件。因此我通过python代码来实现自动修改配置文件。

2.步骤二

修改配置文件的python代码

#!/usr/bin/python
# -*- coding: UTF-8 -*
"""
@author:li-boss
@file_name: in_service.py
@create date: 2019/11/23 10:43 
@blog https://leezhonglin.github.io
@file_description:修改服务配置文件
"""

import os


def create_new_file(file_name, new_file_name, old_str, new_str):
    """
    修改修改python配置文件
    :param file_name: 被打开的文件的路径
    :param new_file_name: 修改后生成的新文件的路径
    :param old_str: 旧的字符串
    :param new_str: 新字符串
    :return:
    """
    # encoding根据具体的系统来确定 如果是windows创建的记事本请用gbk
    fo = open(file_name, 'r+')
    results = []
    link = fo.readlines()
    for fileLine in link:
        str = fileLine.replace(old_str, new_str)
        results.append(str)
        # print('>>', fileLine.strip())
    fo.close()

    # 获取的新数据写入新文件中
    # encoding根据具体的系统来确定 如果是windows创建的记事本请用gbk
    new_fo = open(new_file_name, 'w+')
    for str in results:
        new_fo.write(str)
    new_fo.close()
    # print('修改完成')


if __name__ == "__main__":
    # 当前的工作目录
    # path = os.getcwd()
    # 打包用的路径修改路径
    path = os.path.abspath('..') + r"\dist"

    # VHost_CONF配置路径
    csips_server_conf = path + r"\li-boss-service-def.xml"
    # 定义旧的字符串
    old_str = "%BASE_PATH%"

    new_server_file = path + "\li-boss-service.xml"

    # 生成vhost配置文件
    create_new_file(csips_server_conf, new_server_file, old_str, path)

代码完成后一样我们需要通过pyinstaller来打包。打包完后如下:

python windows开发 linux 发布 python程序发布windows_xml_04

3.步骤三

把步骤二的和步骤一的结果放一起。结果如下:

python windows开发 linux 发布 python程序发布windows_配置文件_05

4.步骤四

把服务需要的那个三个文件拷贝到dist目录下面如下图:

python windows开发 linux 发布 python程序发布windows_python_06

5.步骤五

添加安装/卸载bat文件

安装

@ echo off
%1 %2
ver|find "5.">nul&&goto :Admin
mshta vbscript:createobject("shell.application").shellexecute("%~s0","goto :Admin","","runas",1)(window.close)&goto :eof
:Admin


:: 切换目录
cd "%~dp0/dist/"  
:: 执行in_service.exe
"in_service.exe"
@echo ------------------install  start-------------------------!

:: 停止服务
net stop LiBoss
:: 删除服务
sc delete LiBoss
:: 注册服务
"%~dp0/dist/li-boss-service.exe"  install
:: 启动服务
net start LiBoss

@echo ------------------install  ok----------------------------!

卸载

@echo ------------------uninstall  start-------------------------!
net stop LiBoss
sc delete LiBoss
 
@echo ------------------uninstall  ok----------------------------!

del %0
6.步骤六

添加软件的license.txt

内容

版权归li-boss所有
未经授权不得使用.
7.步骤七

制作windows封装exe的脚本,我这里使用nsis v2.51为例.具体打包过程见文章《NSIS打包electron生成的文件为exe安装包》。

这里不做过多的说明。

; 该脚本使用 HM VNISEdit 脚本编辑器向导产生

; 安装程序初始定义常量
!define PRODUCT_NAME "Li-Boss Service"
!define PRODUCT_VERSION "1b32dc1 v1.0"
!define PRODUCT_PUBLISHER "Li-boss, Inc."
!define PRODUCT_WEB_SITE "https://leezhonglin.github.io"
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
!define PRODUCT_UNINST_ROOT_KEY "HKLM"

SetCompressor lzma

; ------ MUI 现代界面定义 (1.67 版本以上兼容) ------
!include "MUI.nsh"

!include "Library.nsh"
!include "x64.nsh"

;自动识别系统是32位还是64位
!define LIBRARY_X64
!ifdef LIBRARY_X64
!define PROGRAMFILES_MAP  $PROGRAMFILES64
!else
!define PROGRAMFILES_MAP  $PROGRAMFILES
!endif

; MUI 预定义常量
!define MUI_ABORTWARNING
!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install.ico"
!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico"

; 欢迎页面
!insertmacro MUI_PAGE_WELCOME
; 许可协议页面
!insertmacro MUI_PAGE_LICENSE "C:\Users\li-boss\Desktop\li-boss\Licence.txt"
; 安装目录选择页面
!insertmacro MUI_PAGE_DIRECTORY
; 安装过程页面
!insertmacro MUI_PAGE_INSTFILES
; 安装完成页面
!insertmacro MUI_PAGE_FINISH

; 安装卸载过程页面
!insertmacro MUI_UNPAGE_INSTFILES

; 安装界面包含的语言设置
!insertmacro MUI_LANGUAGE "SimpChinese"

; 安装预释放文件
!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS
; ------ MUI 现代界面定义结束 ------

Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
OutFile "li-boss-service.exe"
InstallDir "$PROGRAMFILES\Li-Boss Service"
ShowInstDetails show
ShowUnInstDetails show

Section "MainSection" SEC01
  SetOutPath "$INSTDIR"
  SetOverwrite ifnewer
  File /r "C:\Users\li-boss\Desktop\li-boss\*.*"
SectionEnd

Section -AdditionalIcons
  WriteIniStr "$INSTDIR\${PRODUCT_NAME}.url" "InternetShortcut" "URL" "${PRODUCT_WEB_SITE}"
  CreateDirectory "$SMPROGRAMS\Li-Boss Service"
  CreateShortCut "$SMPROGRAMS\Li-Boss Service\Website.lnk" "$INSTDIR\${PRODUCT_NAME}.url"
  CreateShortCut "$SMPROGRAMS\Li-Boss Service\Uninstall.lnk" "$INSTDIR\uninst.exe"
SectionEnd

Section -Post
  WriteUninstaller "$INSTDIR\uninst.exe"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
SectionEnd

/******************************
 *  以下是安装程序的卸载部分  *
 ******************************/

Section Uninstall
  # 卸载的时候先执行删除服务
  nsExec::Exec '$INSTDIR\unInstall.bat'
  Delete "$INSTDIR\${PRODUCT_NAME}.url"
  Delete "$INSTDIR\uninst.exe"

  Delete "$SMPROGRAMS\Li-Boss Service\Uninstall.lnk"
  Delete "$SMPROGRAMS\Li-Boss Service\Website.lnk"
  Delete "$INSTDIR\*.*"

  RMDir "$SMPROGRAMS\Li-Boss Service"

  RMDir /r "$INSTDIR\dist"
  RMDir /r "$INSTDIR\build"

  RMDir "$INSTDIR"

  DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
  SetAutoClose true
SectionEnd

#-- 根据 NSIS 脚本编辑规则,所有 Function 区段必须放置在 Section 区段之后编写,以避免安装程序出现未可预知的问题。--#



Function .onInstSuccess
  # 安装完成自动执行服务注册
	nsExec::Exec '$INSTDIR/Install.bat'
  Abort

FunctionEnd

Function un.onInit
  MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "您确实要完全移除 $(^Name) ,及其所有的组件?" IDYES +2
  Abort
FunctionEnd

Function un.onUninstSuccess
  HideWindow
  MessageBox MB_ICONINFORMATION|MB_OK "$(^Name) 已成功地从您的计算机移除。"
FunctionEnd

打包完成后:

在这里插入图片描述
运行完之后,查看系统服务就有一个名称为LiBoss的服务。

python windows开发 linux 发布 python程序发布windows_python_07

到这里制作的服务已经完成。

注意:上面的三个文件的后缀为xml的在windows中需要注意编码,一定是ANSI