Delphi 实现可执行程序的自动升级

准备工作:

1:Delphi调用TIdHTTP方式开发程序,生成程序打包外壳

说明:程序工程命名为ERP_Update

界面布局如下:

代码实现如下:

 unit Unit1;

 interface

 uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls,
IdTCPConnection, SHELLAPI, ComCtrls, jpeg, IdHTTP,
IdTCPClient, IdBaseComponent, IdComponent, Registry; type
TFrm_FTP = class(TForm)
Label4: TLabel;
IdHTTP1: TIdHTTP;
Image1: TImage;
ProgressBar1: TProgressBar;
Label1: TLabel;
procedure RUN_START;
procedure FormCreate(Sender: TObject);
procedure IdHTTP1Work(Sender: TObject; AWorkMode: TWorkMode;
const AWorkCount: Integer);
procedure IdHTTP1WorkBegin(Sender: TObject; AWorkMode: TWorkMode;
const AWorkCountMax: Integer);
procedure IdHTTP1WorkEnd(Sender: TObject; AWorkMode: TWorkMode);
function HttpDownLoad(aURL, aFile: string): Boolean;
function GetURLFileName(aURL: string): string;
function GET_CODE(V_s: TstringS; V_CODE: string): string;
function GET_SubStr(V_s: string; V_CODE1, V_CODE2: string): string;
procedure DelFile(V_Name: string);
function GET_Ora_Home(): string;
private
{ Private declarations } public
{ Public declarations }
end; var
Frm_FTP: TFrm_FTP;
ss: Tstrings;
V_Err: Boolean;
BytesToTransfer: LongWord; implementation {$R *.dfm} function TFrm_FTP.GET_Ora_Home(): string;
var
v_Result: string;
begin
v_Result := '';
with TRegistry.Create do
try
RootKey := HKEY_LOCAL_MACHINE;
if OpenKey('\Software\ORACLE', false) then
begin
v_Result := ReadString('ORACLE_HOME');
if v_Result <> '' then
v_Result := v_Result + '\network\admin\tnsnames.ora';
CloseKey;
end;
finally
Free;
end;
Result := v_Result;
end; procedure TFrm_FTP.RUN_start;
var
V_LiveUpdate, V_version, C_ServerIP, C_ServerVer, C_ExeVer, c_ExeName, C_ExePath: string;
i: Integer;
begin
V_Err := False;
C_ExePath := ExtractFilePath(Application.ExeName); //可执行程序的路径[D:\CDERP\长电包装生产管理系统\]
//获取本地的版本信息等数据
ss := Tstringlist.create;
ss.loadfromfile(C_ExePath + 'LiveUpdate.ini');
V_version := GET_SubStr(ss.Strings[], 'url=', ''); //服务器地址
V_LiveUpdate := stringreplace(UpperCase(V_version), 'VERSION.INF', 'LIVEUPDATE.INI', [rfReplaceAll]); //服务器地址
C_ExeVer := GET_SubStr(ss.Strings[], 'version=', ''); //本地程序的版本
C_ExeName := GET_SubStr(ss.Strings[], 'exe=', ''); //本地程序的名称
//获取服务器的版本
if HttpDownLoad(V_version, C_ExePath + GetURLFileName(V_version)) then
begin
ss.loadfromfile(C_ExePath + 'version.inf');
C_ServerVer := get_code(ss, '#version=');
end
else
C_ServerVer := C_ExeVer; //如果升级服务器异常就不升级
if (trim(ParamStr()) = '') or (trim(ParamStr()) = '/afterupgrade0') then
begin
//程序在本地第一次执行,如果需要升级将下载cderp.exe到本地update.exe并执行
//比较版本信息
if C_ServerVer > C_ExeVer then
begin
C_ExeVer := C_ServerVer;
DelFile(C_ExePath + 'update.exe');
HttpDownLoad(GET_SubStr(V_version, '', '/exe/') + '/exe/ERP_Update.exe', C_ExePath + 'update.exe');
ShellExecute(handle, 'open', pchar(C_ExePath + 'ERP_Update.exe'), pchar('"' + C_ExePath + '" "' + C_ExeVer + '"'), nil, SW_ShowNormal);
end
else
ShellExecute(handle, 'open', pchar(C_ExePath + C_ExeName), nil, nil, SW_ShowNormal);
application.Terminate;
end
else
begin
Frm_FTP.WindowState := wsNormal;
Frm_FTP.Visible := true;
Frm_FTP.Refresh;
V_Err := False;
//防止可执行程序没有完全关闭, 等待一会
ProgressBar1.max := ;
for i := to do
begin
Label4.Caption := '升级准备...';
ProgressBar1.Position := i;
Application.ProcessMessages;
Sleep();
end;
for i := to do
begin
C_ServerIP := get_code(ss, '#url' + trim(IntToStr(i)) + '=');
if C_ServerIP = '' then
begin
Break;
end;
HttpDownLoad(C_ServerIP, C_ExePath + GetURLFileName(C_ServerIP));
end;
HttpDownLoad(V_LiveUpdate, C_ExePath + GetURLFileName(V_LiveUpdate));
if not V_Err then
begin
ss.loadfromfile(C_ExePath + GetURLFileName(V_LiveUpdate));
ss.delete();
ss.delete();
ss.Add('version=' + C_ServerVer);
ss.Add('exe=' + C_ExeName);
ss.savetofile(C_ExePath + GetURLFileName(V_LiveUpdate));
ss.free;
Application.MessageBox('程序已经升级完成!', '升级完成', MB_ICONINFORMATION + MB_OK);
ShellExecute(handle, 'open', pchar(C_ExePath + C_ExeName), nil, nil, SW_ShowNormal);
end;
application.Terminate;
end;
end; procedure TFrm_FTP.FormCreate(Sender: TObject);
begin
RUN_start;
end; function TFrm_FTP.GET_CODE(V_s: TstringS; V_CODE: string): string;
var
i, j, l: integer;
v_Result: string;
begin
j := V_s.Count - ;
l := length(v_code);
i := ;
while i <= j do
begin
if copy(trim(UpperCase(V_s.Strings[i])), , l) = UpperCase(V_CODE) then
begin
v_Result := copy(trim(V_s.Strings[i]), l + , );
j := ;
end;
i := i + ;
end;
Result := v_Result;
end; function TFrm_FTP.GET_SubStr(V_s: string; V_CODE1, V_CODE2: string): string;
var
j, k: integer;
v_str: string;
begin
//Label4.Caption := GET_SubStr('url=http://192.1.1.0/exe/ERP_Update/version.inf', '://', '/exe');
//数据解析,找到字符串中的子串
v_str := UpperCase(V_s);
k := pos(UpperCase(v_code1), v_str);
if v_code1 = '' then
begin
k := ;
end;
if k > then
begin
v_str := copy(v_str, k + length(v_code1), );
if v_code2 = '' then
k :=
else
k := pos(UpperCase(v_code2), v_str);
if k > then
begin
v_str := copy(v_str, , k - );
end
else
begin
v_str := '';
end;
end
else
begin
v_str := '';
end;
Result := v_str;
end; procedure TFrm_FTP.DelFile(V_Name: string);
var
i: integer;
begin
i := ;
while FileExists(V_Name) do
begin
DeleteFile(V_Name);
Application.ProcessMessages;
i := i + ;
if i > then
begin
if MessageDlg('系统不能执行删除操作[' + V_Name + '],是否重试?', mtConfirmation, [mbYes, mbNo], ) = mrNO then
begin
i := ;
Abort;
end;
end;
end;
end; procedure TFrm_FTP.IdHTTP1Work(Sender: TObject; AWorkMode: TWorkMode;
const AWorkCount: Integer);
begin
ProgressBar1.Position := AWorkCount;
end; procedure TFrm_FTP.IdHTTP1WorkBegin(Sender: TObject; AWorkMode: TWorkMode;
const AWorkCountMax: Integer);
begin
if AWorkCountMax > then
ProgressBar1.max := AWorkCountMax
else
ProgressBar1.Max := BytesToTransfer; end; procedure TFrm_FTP.IdHTTP1WorkEnd(Sender: TObject; AWorkMode: TWorkMode);
begin
BytesToTransfer := ; end;
//http方式下载 function TFrm_FTP.HttpDownLoad(aURL, aFile: string): Boolean;
var
MyStream: TMemoryStream; //如果文件不存在
F_Str: string;
begin
if V_Err then exit;
try
label4.Caption := '正在升级...' + GetURLFileName(aURL);
label4.Refresh;
MyStream := TMemoryStream.Create;
IdHTTP1.Request.ContentRangeStart := ;
try
IdHTTP1.Get(stringreplace(UpperCase(aURL), '192.1.1.0/EXE/', '192.1.1.0/EXE/', [rfReplaceAll]), MyStream); //开始下载
MyStream.SaveToFile(aFile);
if pos('.REG', UpperCase(aFile)) > then
WinExec(pchar('regedit.exe /s "' + aFile + '"'), SW_HIDE); if pos('TNSNAMES.ORA', UpperCase(aFile)) > then
begin
F_Str := GET_Ora_Home;
if F_Str <> '' then MyStream.SaveToFile(F_Str);
end; label4.Caption := '升级完成';
finally
MyStream.Free;
end;
Result := True;
except
on E: Exception do
begin
Application.MessageBox(PChar('升级[' + GetURLFileName(aURL) + ']过程中出现错误了,错误信息如下:' + # + # + E.Message), PChar('系统提示'), Mb_OK + MB_ICONERROR);
V_Err := True;
Result := False;
end;
end;
end; function TFrm_FTP.GetURLFileName(aURL: string): string;
var
i: integer;
s: string;
begin
s := aURL;
i := Pos('/', s);
while i <> do //去掉"/"前面的内容剩下的就是文件名了
begin
Delete(s, , i);
i := Pos('/', s);
end;
Result := s;
end; end.

2:FTP服务器搭建,FTP用户创建

举例说明如下:

在192.1.1.0上创建FTP账户Test 密码Test,路径 \exe\;

案例:将Test.exe系统做出一个可以自动升级的系统

文件准备:

1:Test.exe (目标系统);

2:ERP_Update.exe (自动升级外壳程序);

3:创建配置文件 (LiveUpdate.ini、Version.inf);

建立一个记事本文件,命名为LiveUpdate.ini,内容输入

[LiveUpdate]
url=http://192.1.1.0/exe/Test/version.inf
version=0
exe=Test.EXE

建立一个记事本文件,命名为version.inf,内容输入

#############################################################
#   Generated by AutoUpgrader Pro at: 2019-8-29 20:50:39    #
#############################################################
#message={}
#url1=http://192.1.1.0/exe/ERP_Update.exe
#url2=http://192.1.1.0/exe/Test/Test.exe
#url3=http://192.19.1.0/exe/Test/version.inf
#method=0 (self-upgrade)
#version=0

4:FTP操作(文件替换、配置文件更新);

将Test.exe (目标系统)、ERP_Update.exe (自动升级外壳程序)、创建配置文件 (LiveUpdate.ini、Version.inf)文件同时放到192.1.1.0FTP服务器\exe\Test\文件夹下。

并手工修改LiveUpdate中的Version,同理Version中也需要这么改。

至此在本地打开ERP_Udapate即可实现自动升级。

作者:Jeremy.Wu
  出处:https://www.cnblogs.com/jeremywucnblog/

  本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

Delphi - Indy TIdHTTP方式创建程序外壳 - 实现可执行程序的自动升级的更多相关文章

  1. DevExpress XtraReports 入门六 控件以程序方式创建一个 交叉表 报表

    原文:DevExpress XtraReports 入门六 控件以程序方式创建一个 交叉表 报表 本文只是为了帮助初次接触或是需要DevExpress XtraReports报表的人群使用的,为了帮助 ...

  2. [delphi]indy idhttp post方法

    网易 博客 LOFTCam-用心创造滤镜 LOFTER-最美图片社交APP 送20张免费照片冲印 > 注册登录  加关注 techiepc的博客 万事如意 首页 日志 LOFTER 相册 音乐 ...

  3. Delphi中DLL的创建和使用

    参考:http://blog.csdn.net/ninetowns2008/article/details/6311663 结合这篇博客:http://www.cnblogs.com/xumenger ...

  4. Delphi XE5教程2:程序组织

    内容源自Delphi XE5 UPDATE 2官方帮助<Delphi Reference>,本人水平有限,欢迎各位高人修正相关错误! 也欢迎各位加入到Delphi学习资料汉化中来,有兴趣者 ...

  5. 有谁知道Delphi中"窗口"的创建过程?

      求助:有谁知道Delphi中窗口的创建过程,此“窗口”不仅仅指 TForm 类型, 还包括一般的窗口控件,如TButton,TEdit等等,希望有能够十分详细的运作 过程,比如说CreatPara ...

  6. 零基础逆向工程39_Win32_13_进程创建_句柄表_挂起方式创建进程

    1 进程的创建过程 打开系统 --> 双击要运行的程序 --> EXE开始执行 步骤一: 当系统启动后,创建一个进程:Explorer.exe(也就是桌面进程) 步骤二: 当用户双击某一个 ...

  7. Delphi中DLL的创建和使用(转)

    Delphi中DLL的创建和使用     1.DLL简介:   2.调用DLL:   3.创建DLL:   4.两个技巧:   5.初始化:   6.例外处理.            1.DLL简介  ...

  8. [转]C#创建服务及使用程序自动安装服务,.NET创建一个即是可执行程序又是Windows服务的exe

    写在前面 原文地址:C#创建服务及使用程序自动安装服务,.NET创建一个即是可执行程序又是Windows服务的exe 这篇文章躺在我的收藏夹中有很长一段时间了,今天闲着没事,就自己动手实践了一下.感觉 ...

  9. Spring工厂方式创建Bean实例

    创建Bean实例的方式: 1) 通过构造器(有参或无参) 方式: <bean id="" class=""/> 2) 通过静态工厂方法 方式: &l ...

随机推荐

  1. ALLOT流控设备SSG

    Allot AC 系列产品EOL的通知如下. 该产品于2021年3月31日EOL. 替代的产品系列为SG/SSG系列. Allot Secure Service Gateway(SSG)应用程序和用户 ...

  2. datatables editor fields type

    其实editor fields type 默认支持的输入类型就是w3c输入框类型. text   number   password   textarea   select   checkbox   ...

  3. java 第二章

    变量:变量就是代表程序运行时存放数据的地方 数据存放在:磁盘,内存卡,U盘,光盘,内存条,固态硬盘,机械硬盘等 字节:8个二进制位构成1个"字节(Byte)",它是存储空间的基本计 ...

  4. IntelliJ IDEA 2019.2最新解读:性能更好,体验更优,细节处理更完美!

    idea 2019.2 准备 idea 2019.2正式版是在2019年7月24号发布的,本篇文章,我将根据官方博客以及自己的理解来进行说明,总体就是:性能更好,体验更优,细节处理更完美! 支持jdk ...

  5. TestNG中group的用法

    TestNG中的组可以从多个类中筛选组属性相同的方法执行. 比如有两个类A和B,A中有1个方法a属于组1,B中有1个方法b也属于组1,那么我们可以通过配置TestNG文件实现把这两个类中都属于1组的方 ...

  6. Chrome 跨域 disable-web-security 关闭安全策略

    谷歌浏览器暂时关闭跨域. 当遇到以下情况,则可以简单的使用 关闭Chrome 安全策略跨域 开发时跨域,上线后,部署在一个域名下没有跨域问题 开发时,临时解决跨域问题 只有开发时用这个,其他时候,就不 ...

  7. 戴尔PowerEdge T110 Ⅱ服务器U盘安装Windows Server 2019 DataCenter

    一. 下载准备 准备工作——下载Microsoft Windows Server 2019 官方简体中文激活版 (MSDN)原版iso镜像 准备工作——安装刻录软件UltraISO,单文件绿色版就够用 ...

  8. Linux基础文件类型

    一.文件时间 ls -l 文件名 仅看的是文件的修改时间 [root@linux ~]# ls -l /etc/passwd -rw-r--r-- root root 5月 : /etc/passwd ...

  9. 记录一下我做Udacity 的Data Scientist Nano Degree Project

    做项目的时候看了别人的blog,决定自己也随手记录下在做项目中遇到的好的小知识点. 最近在做Udacity的Data Scientist Nano Degree Project的Customer_Se ...

  10. Android 虹软人脸识别SDK-人脸对比

    准备 : 登录官方网站,获取SDK,进行个人验证后新建项目,获取APP_ID,和SDK_KEY: https://ai.arcsoft.com.cn/ucenter/resource/build/in ...