Delphi 实现自动更新
Delphi 通用程序自动更新升级:http://www.delphitop.com/html/wangluo/2968.html
https://www.cnblogs.com/hnxxcxg/p/4105337.html
delphi 让程序自己更新本程序:http://www.delphitop.com/html/chengxu/1270.html
1)服务端IIS网站上创建新的虚拟路径,给新创建的虚拟路径增加MIME类型:.bpl、.ini等。
2)设置update.ini文件版本号配置文件
[ver]
config.ini=1
bplCommon.bpl=1
bplGoods.bpl=1
bplPower.bpl=1
bplPurchasing.bpl=1
prjMain.exe=2
3)客户端
untAutoUpdate.dfm文件:
object frmAutoUpdate: TfrmAutoUpdate
Left = 0
Top = 0
Caption = #33258#21160#21319#32423#31243#24207
ClientHeight = 140
ClientWidth = 573
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
Position = poScreenCenter
OnClose = FormClose
OnCreate = FormCreate
OnDestroy = FormDestroy
OnShow = FormShow
PixelsPerInch = 96
TextHeight = 13
object btnDownload: TButton
Left = 199
Top = 24
Width = 138
Height = 41
Caption = #26816#26597#26356#26032
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -24
Font.Name = 'Tahoma'
Font.Style = []
ParentFont = False
TabOrder = 0
OnClick = btnDownloadClick
end
object bar: TProgressBar
Left = 24
Top = 88
Width = 529
Height = 17
TabOrder = 1
end
object cdsLocal: TClientDataSet
Aggregates = <>
IndexFieldNames = 'filename'
Params = <>
Left = 48
Top = 8
object cdsLocalfilename: TStringField
FieldName = 'filename'
Size = 100
end
object cdsLocalver: TIntegerField
FieldName = 'ver'
end
end
object cdsServer: TClientDataSet
Aggregates = <>
IndexFieldNames = 'filename'
Params = <>
Left = 120
Top = 8
object cdsServerfilename: TStringField
FieldName = 'filename'
Size = 100
end
object cdsServerver: TIntegerField
FieldName = 'ver'
end
end
end
untAutoUpdate.pas文件:
{ *******************************************************
单元功用:自动升级
单元设计:陈新光
设计日期:2014-11-17
单元修改:
修改日期:
******************************************************* }
unit untAutoUpdate;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Winapi.UrlMon, Vcl.StdCtrls,
System.IniFiles, Data.DB, Datasnap.DBClient,
Vcl.ComCtrls, Wininet;
type
TfrmAutoUpdate = class(TForm)
btnDownload: TButton;
cdsLocal: TClientDataSet;
cdsServer: TClientDataSet;
cdsLocalfilename: TStringField;
cdsLocalver: TIntegerField;
cdsServerfilename: TStringField;
cdsServerver: TIntegerField;
bar: TProgressBar;
procedure btnDownloadClick(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
appPath: string;
urlPath: string;
FList: TStringList;
function DownloadFile(Source, Dest: string): Boolean;
procedure InitCdsLocal;
procedure InitCdsServer;
procedure CreateLocalVer;
procedure CreateServerVer;
public
{ Public declarations }
end;
var
frmAutoUpdate: TfrmAutoUpdate;
implementation
{$R *.dfm}
{ TForm1 }
procedure TfrmAutoUpdate.btnDownloadClick(Sender: TObject);
var
Source, Dest: string;
errCount: Integer;
procedure _down;
begin
Source := urlPath + cdsServer.FieldByName('filename').Text;
Dest := appPath + cdsServer.FieldByName('filename').Text;
if not DownloadFile(Source, Dest) then
begin
Inc(errCount);
ShowMessage(cdsServer.FieldByName('filename').Text + '下载失败');
end;
end;
begin
errCount := 0;
// 下载服务端的update.ini
Source := urlPath + 'update.ini';
Dest := appPath + 'update2.ini';
if DownloadFile(Source, Dest) then // 下载update.ini 成功
begin
// 生成服务端文件版本情况列表
CreateServerVer;
if FileExists(appPath + 'update.ini') then // 本地有update.ini
begin
// 生成本地文件版本情况列表
CreateLocalVer;
// 比对文件版本号决定哪些需要下载
bar.Max := cdsServer.RecordCount;
cdsServer.First;
while not cdsServer.Eof do
begin
if not cdsLocal.FindKey([cdsServer.FieldByName('filename').Text]) then
// 新文件要下载
begin
_down;
end
else
begin
if cdsServer.FieldByName('ver').AsInteger > // 版本号低的旧文件要下载
cdsLocal.FieldByName('ver').AsInteger then
begin
_down;
end;
end;
cdsServer.Next;
bar.Position := bar.Position +1;
bar.Update;
end;
end
else
begin // 本地无update.ini 下载所有文件
bar.Max := cdsServer.RecordCount;
cdsServer.First;
while not cdsServer.Eof do
begin
_down;
cdsServer.Next;
bar.Position := bar.Position +1;
bar.Update;
end;
end;
// 更新本地update.ini
CopyFile(PChar(appPath + 'update2.ini'),
PChar(appPath + 'update.ini'), False);
DeleteFile(appPath + 'update2.ini');
end
else
begin // 从服务器下载update.ini 失败
ShowMessage('下载update.ini失败');
Exit;
end;
if errCount = 0 then begin
ShowMessage('更新程序成功');
end else
ShowMessage('更新程序程序失败');
end;
procedure TfrmAutoUpdate.CreateLocalVer;
var
ini: TIniFile;
i: integer;
begin
ini := TIniFile.Create(appPath + 'update.ini');
try
FList.Clear;
ini.ReadSectionValues('ver', FList);
for i := 0 to FList.Count - 1 do
begin
cdsLocal.Append;
cdsLocal.FieldByName('filename').Text :=
Copy(FList[i], 1, pos('=', FList[i]) - 1);
cdsLocal.FieldByName('ver').Text :=
Copy(FList[i], pos('=', FList[i]) + 1,
length(FList[i]));
cdsLocal.Post;
end;
finally
ini.Free;
end;
end;
procedure TfrmAutoUpdate.CreateServerVer;
var
ini: TIniFile;
i: integer;
begin
ini := TIniFile.Create(appPath + 'update2.ini');
try
FList.Clear;
ini.ReadSectionValues('ver', FList);
for i := 0 to FList.Count-1 do
begin
cdsServer.Append;
cdsServer.FieldByName('filename').Text :=
Copy(FList[i], 1, pos('=', FList[i]) - 1);
cdsServer.FieldByName('ver').Text :=
Copy(FList[i], pos('=', FList[i]) + 1,
length(FList[i]));
cdsServer.Post;
end;
finally
ini.Free;
end;
end;
function TfrmAutoUpdate.DownloadFile(Source, Dest: string): Boolean;
begin
try
DeleteUrlCacheEntry(PChar(Source)); // 先要清空缓存
Result := UrlDownloadToFile(nil, PChar(Source), PChar(Dest), 0, nil) = 0;
except
Result := False;
end;
end;
procedure TfrmAutoUpdate.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
frmAutoUpdate:=nil;
end;
procedure TfrmAutoUpdate.FormCreate(Sender: TObject);
begin
FList :=TStringList.Create;
end;
procedure TfrmAutoUpdate.FormDestroy(Sender: TObject);
begin
FreeAndNil(FList);
end;
procedure TfrmAutoUpdate.FormShow(Sender: TObject);
var
ini: TIniFile;
begin
appPath := ExtractFilePath(Application.ExeName);
// 升级文件的url path
ini := TIniFile.Create(appPath + 'config.ini');
try
urlPath := ini.ReadString('appServer', 'update', '');
finally
ini.Free;
end;
InitCdsLocal;
InitCdsServer;
end;
procedure TfrmAutoUpdate.InitCdsLocal;
begin
if not cdsLocal.Active then
cdsLocal.CreateDataSet
else
cdsLocal.EmptyDataSet;
end;
procedure TfrmAutoUpdate.InitCdsServer;
begin
if not cdsServer.Active then
cdsServer.CreateDataSet
else
cdsServer.EmptyDataSet;
end;
end.
Delphi 实现自动更新的更多相关文章
- delphi 的插件机制与自动更新
delphi 的插件机制与自动更新 : 1.https://download.csdn.net/download/cxp_2008/2226978 参考 2.https://download.cs ...
- 解析大型.NET ERP系统 自动更新
C/S架构的应用程序需要支持自动更新功能,当新版本程序发布后,正在运行的客户端能检测到新版本的程序,通知用户是否下载更新.工作以来参与过几个自动更新模块的设计与维护,撰文总结自动更新模块设计与实现. ...
- QML 从无到有 3 (自动更新)
新的需求出来啦,需要自动更新功能,不怕程序升级了. 自动更新,QML不好写,需要c++来辅助,这里就涉及QML中调用c++功能(这里就不写了,百度一下,很多). 思路:获取版本>下载程序> ...
- 扩展BindingList,防止增加、删除项时自动更新界面而不出现“跨线程操作界面控件 corss thread operation”异常
在做界面程序时,常常需要一些数据类,界面元素通过绑定等方式显示出数据,然而由于UI线程不是线程安全的,一般都需要通过Invoke等方式来调用界面控件.但对于数据绑定bindingList而言,没法响应 ...
- 分析nuget源码,用nuget + nuget.server实现winform程序的自动更新
源起 (个人理解)包管理最开始应该是从java平台下的maven开始吧,因为java的开发大多数是基于开源组件开发的,一个开源包在使用时很可能要去依赖其他的开源包,而且必须是特定的版本才可以.以往在找 ...
- ClickOnce部署(2):自动更新
上次我们说了如何用最基本的方式用ClickOnce技术部署应用程序项目,本篇我们来认识一下如何让应用程序具备自动更新的功能. 我们依然通过实例来学习. 第一步,随便建一个应用程序项目,至于是控制台.W ...
- Android接入百度自动更新SDK
一:前言 公司的app,上传到百度应用市场,然后说必须要接入百度的自动更新sdk才能上架,于是从百度官网上去下载jar包,下载的时候必须要带上数据统计,如果使用自动的jar包,还需要带上广告联盟,坑爹 ...
- C#之tcp自动更新程序
.NETTCP自动更新程序有如下几步骤: 第一步:服务端开启监听 ServiceHost host; private void button1_Click(object sender, EventAr ...
- 使用 SVN Hook 实现服务器端代码自动更新
之前的做法是客户端提交代码之后,再去服务器端项目中 svn up 一下来更新代码,让服务器端的项目更新到最新版本.可以编写一个 post-commit 钩子脚本来实现服务器端代码的自动更新,它在 SV ...
随机推荐
- jenkins 构建
自动触发构建 远程构建 本地默认情况下是能够自动构建的,因为浏览器已经登录 了jenkins,如果从别的地方调用的话需要加上用户名和密码做认证,方法如下 curl -u a:a http://Jenk ...
- hostnamectl 修改 CentOS7 主机名
hostnamectl 控制主机名 # 显示状态 hostnamectl Static hostname: centos Icon name: computer-vm Chassis: vm Mach ...
- 4、JPA-EntityManager.merge()
EntityManager#merge merge() 用于处理 Entity 的同步.即数据库的插入和更新操作 merge的几种情况 1. 若传入的是一个临时对象 package jpa.test; ...
- ruby-----render讲解
Ruby rails页面跳转代码如下: 1.render(:text => string) 2.render(:inline => string, [:type => "r ...
- SpringBoot集成原生redis
redis的使用之一是Spring-data-redis,前面有介绍. 本篇介绍原生redis也就是jedis.这个效率更高 1.maven引入依赖 <!--springBoot-->&l ...
- mysql:insert插入数据过慢如何解决,设置innodb_flush_log_at_trx_commit为0就能解决
问题: 最近在做性能测试,造数据,发现insert好慢,只有几十条每秒,很奇怪,最后再网上找到了原因. 网文如下: MY SQL insert 速度过慢 最近在用MySQL做存储,测试中发现插入数据太 ...
- 【1】[leetcode-124] 二叉树中的最大路径和
(没做出来,典型题目重要) 二叉树中的最大路径和(hard) 给定一个非空二叉树,返回其最大路径和. 本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列.该路径至少包含一个节点,且不一定经 ...
- HDU - 4027 Can you answer these queries?(线段树区间修改)
https://cn.vjudge.net/problem/HDU-4027 题意 给一个有初始值的数组,存在两种操作,T=0时将[L,R]的值求平方根,T=1时查询[L,R]的和. 分析 显然不符合 ...
- 细说shiro之二:组件架构
官网:https://shiro.apache.org/ Shiro主要组件包括:Subject,SecurityManager,Authenticator,Authorizer,SessionMan ...
- Dictionary与SortedDictionary
Dictionary是无序的,如果想排序,需要使用SortDictionary. 下面是一个用法示例 //按照某个字段排序 public void SortByCardItem(string item ...