网站首页 > 编程文章 正文
1.软件打包安装程序
利用setupfactory软件进行客户端软件打包,形成一个setup安装程序。
2. 建立FTP服务器
利用quickeasyftpserver在远程服务器中建立FTP服务器,放置2个文件,一个setup安装文件,一个是ver.txt文件,里面写上软件的版本号12位,例如20200917V001。
3. 客户端程序开发
在客户端程序中点击升级按钮后
(1) 程序首先删除本地的上一次的版本和升级文件,然后从ftp服务器上下载ver.txt,然后判断服务器的setup版本和当前软版本是否一致,不一致,就提示用户升级。
(2) 如果用户同意升级,就在ftp上下载setup安装文件。
(3) 下载完成后,再开一个线程执行setup程序,然后把当前的程序关闭,安装程序会覆盖当前的程序。
问题:
这种方法比较简单,主要问题是不知道ftp文件的下载进度,会有一直卡死的现象。这个原因是进度条的定时器程序刷新UI和FTP下载程序在一个线程中,造成拥塞了。下载时就不能定时中断,刷新UI了
解决方案:
(1) 对于ftp下载采用异步方式,下载完后发送信号给主线程。
(2) 主线程点击升级按钮,绑定子线程和对应的回调函数。然后启动ftp子线程。
(3) 在回调函数中,执行此程序就是下载结束了,这时可以在主线程中启动,进度条满格,然后执行分线程执行安装程序,并在主程序中把自己结束
代码如下:
from update import Ui_MainWindow
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QMessageBox
import sys
import os
from ftplib import FTP # 引入ftp模块
import win32process
from PyQt5.QtCore import QBasicTimer, QThread, pyqtSignal
import time
mycurrent_ver = '20200916V001' # 当前软件版本号
mynew_ver = ''
#异步线程
class MyCal(QThread):
#自定义一个信号名
cal_signal = pyqtSignal(int) #定义信号返回的数值类型
#构造函数
def __init__(self, mypath, filename,parent=None): #
super(MyCal, self).__init__(parent)
self.mypath = mypath
self.filename=filename
print("分线程:",self.mypath,self.filename)
#析构函数
def __del__(self):
self.wait()
#该线程主程序
def run(self):
##ftp下载程序版本程序
ftp = MyFtp('127.0.0.1)
ftp.login('admin', '123456')
ftp.downloadFile(self.mypath, '/down/', self.filename)
ftp.close()
print("分线程下载结束:", self.mypath+self.filename)
self.cal_signal.emit(1) #发射信号,传参数
class MyFtp:
ftp = FTP()
def __init__(self, host, port=21):
self.ftp.connect(host, port)
def login(self, username, pwd):
self.ftp.set_debuglevel(2) # 打开调试级别2,显示详细信息
self.ftp.login(username, pwd)
print(self.ftp.welcome)
def downloadFile(self, localpath, remotepath, filename):
os.chdir(localpath) # 切换工作路径到下载目录
self.ftp.cwd(remotepath) # 要登录的ftp目录
self.ftp.nlst() # 获取目录下的文件
file_handle = open(filename, "wb").write # 以写模式在本地打开文件
self.ftp.retrbinary('RETR %s' % os.path.basename(filename), file_handle, blocksize=1024) # 下载ftp文件
# ftp.delete(filename) # 删除ftp服务器上的文件
def close(self):
self.ftp.set_debuglevel(0) # 关闭调试
self.ftp.quit()
# 主窗体
class MainForm(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
super(MainForm, self).__init__()
self.setupUi(self)
self.timer = QBasicTimer()
self.step = 0
# self.myupdate_bt()
# 进度条控制定时器
def timerEvent(self, event):
if self.step >= 100:
self.timer.stop()
self.pushButton_2.setText('开始进度条')
self.step = 0
self.progressBar.setValue(self.step)
return
self.step = self.step + 1
if self.step>=99:
self.step=99
self.progressBar.setValue(self.step)
# 进度条控制
def myprocessbar_bt(self):
pass
if self.timer.isActive():
self.timer.stop()
self.pushButton_2.setText('开始进度条')
else:
self.timer.start(100, self)
self.pushButton_2.setText('停止进度条')
def myupdate_bt(self):
pass
myhomedir = os.getcwd()
mypath = os.getcwd() + '\\down\\'
myfilepath1 = mypath + "ver.txt"
myfilepath2 = mypath + "setup.exe"
# 删除文件
x1 = os.path.exists(myfilepath1) # True/False
if x1 == True:
print("删除文件:" + myfilepath1)
os.remove(myfilepath1)
x1 = os.path.exists(myfilepath2) # True/False
if x1 == True:
print("删除文件:" + myfilepath2)
os.remove(myfilepath2)
##ftp下载程序版本程序
ftp = MyFtp('127.0.0.1)
ftp.login('admin', '123456')
ftp.downloadFile(mypath, '/down/', 'ver.txt')
ftp.close()
print("下载结束:", myfilepath1)
# 判断版本
with open(myfilepath1, 'rt') as f1:
mynew_ver = f1.readline()[0:12]
self.label_4.setText(mynew_ver)
self.label_2.setText(mycurrent_ver)
if mynew_ver != mycurrent_ver:
x1 = QMessageBox.information(self, "确认信息", "有新版本,确认是否升级", QMessageBox.Yes | QMessageBox.No)
if x1 == QMessageBox.No:
os.chdir(myhomedir)
return
print("开始升级")
QMessageBox.information(self, "确认信息", "开始下载程序!!")
self.myprocessbar_bt()#显示进度条
# self.timer.start(100, self)
##拥塞ftp下载程序
# ftp = MyFtp('127.0.0.1')
# ftp.login('admin', '123456')
# ftp.downloadFile(mypath, '/down/', 'setup.exe')
# ftp.close()
# print("下载结束:", myfilepath2)
# QMessageBox.information(self, "确认信息", "下载程序结束!!")
####异步FTP下载
self.cal = MyCal(mypath, 'setup.exe') # 点击按钮后新建计算的线程
self.cal.cal_signal.connect(self.cal_callback) # 连接计算线程的信号
self.cal.start() # 开始运行线程
else:
QMessageBox.information(self, "确认信息", "已经是最新版本,不用升级")
os.chdir(myhomedir)
return
# 省略 使用接收到线程返回的参数
###执行第三方程序,新线程
#win32process.CreateProcess(myfilepath2, '', None, None, 0, win32process.CREATE_NO_WINDOW, None, None,win32process.STARTUPINFO())
os.chdir(myhomedir)
print("主程序退出")
#sys.exit()
def cal_callback(self): # 接收到计算线程信号后的回掉函数
pass
print('异步ftp下载结束')
self.step=100
self.progressBar.setValue(self.step)
#self.myprocessbar_bt()#显示进度条
myhomedir = os.getcwd()
mypath = myhomedir
myfilepath1 = mypath + "\\ver.txt"
myfilepath2 = mypath + "\\setup.exe"
QMessageBox.information(self, "确认信息", "下载结束,开始升级")
print(myfilepath2)
win32process.CreateProcess(myfilepath2, '', None, None, 0, win32process.CREATE_NO_WINDOW, None, None,win32process.STARTUPINFO())
sys.exit()
# 主程序入口
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
win_main = MainForm()
win_main.show()
sys.exit(app.exec_())
界面如下
猜你喜欢
- 2024-09-11 Qt开发-文本编辑器中的数据存取(qt文本编辑器代码)
- 2024-09-11 Qt数据库应用15-通用数据库同步(qt的数据库操作)
- 2024-09-11 开源|一个基于QT设计串口调试工具
- 2024-09-11 第23天 | 28天学会PyQt5,多行文本框
- 2024-09-11 PyQt: QAbstractButton开关按钮与互斥的用法
- 2024-09-11 第6篇 基础(六)实现Qt文本编辑功能
- 2024-09-11 实战PyQt5: 003-PyQt的信号和槽机制简介
- 2024-09-11 Qt开发经验小技巧181-185(qt软件开发)
- 2024-09-11 Qt开发经验总结之武林秘籍(qt开发程序)
- 2024-09-11 Qt状态机框架介绍(二)(状态机编程实例及适用范围)
你 发表评论:
欢迎- 05-142014年最流行前端开发框架对比评测
- 05-14七爪源码:如何使用 Next.js 构建 Shopify 店面
- 05-14Web 前端怎样入门?
- 05-14我为什么不建议你使用框架
- 05-14推荐几个好用的React UI 框架
- 05-14PDFsharp:强大的 .NET 跨平台 PDF 处理库
- 05-14一组开源免费的Web动画图标,荐给需要的设计师和程序员
- 05-14salesforce 零基础学习(二十九)Record Types简单介绍
- 最近发表
- 标签列表
-
- spire.doc (59)
- system.data.oracleclient (61)
- 按键小精灵源码提取 (66)
- pyqt5designer教程 (65)
- 联想刷bios工具 (66)
- c#源码 (64)
- graphics.h头文件 (62)
- mysqldump下载 (66)
- sqljdbc4.jar下载 (56)
- libmp3lame (60)
- maven3.3.9 (63)
- 二调符号库 (57)
- 苹果ios字体下载 (56)
- git.exe下载 (68)
- diskgenius_winpe (72)
- pythoncrc16 (57)
- solidworks宏文件下载 (59)
- qt帮助文档中文版 (73)
- satacontroller (66)
- hgcad (64)
- bootimg.exe (69)
- android-gif-drawable (62)
- axure9元件库免费下载 (57)
- libmysqlclient.so.18 (58)
- springbootdemo (64)
本文暂时没有评论,来添加一个吧(●'◡'●)