Delphi - Indy TIdHTTP方式创建程序外壳 - 实现可执行程序的自动升级
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 #
#############################################################
#url2=http://192.1.1.0/exe/Test/Test.exe
#url3=http://192.19.1.0/exe/Test/version.inf
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方式创建程序外壳 - 实现可执行程序的自动升级的更多相关文章
- DevExpress XtraReports 入门六 控件以程序方式创建一个 交叉表 报表
原文:DevExpress XtraReports 入门六 控件以程序方式创建一个 交叉表 报表 本文只是为了帮助初次接触或是需要DevExpress XtraReports报表的人群使用的,为了帮助 ...
- [delphi]indy idhttp post方法
网易 博客 LOFTCam-用心创造滤镜 LOFTER-最美图片社交APP 送20张免费照片冲印 > 注册登录 加关注 techiepc的博客 万事如意 首页 日志 LOFTER 相册 音乐 ...
- Delphi中DLL的创建和使用
参考:http://blog.csdn.net/ninetowns2008/article/details/6311663 结合这篇博客:http://www.cnblogs.com/xumenger ...
- Delphi XE5教程2:程序组织
内容源自Delphi XE5 UPDATE 2官方帮助<Delphi Reference>,本人水平有限,欢迎各位高人修正相关错误! 也欢迎各位加入到Delphi学习资料汉化中来,有兴趣者 ...
- 有谁知道Delphi中"窗口"的创建过程?
求助:有谁知道Delphi中窗口的创建过程,此“窗口”不仅仅指 TForm 类型, 还包括一般的窗口控件,如TButton,TEdit等等,希望有能够十分详细的运作 过程,比如说CreatPara ...
- 零基础逆向工程39_Win32_13_进程创建_句柄表_挂起方式创建进程
1 进程的创建过程 打开系统 --> 双击要运行的程序 --> EXE开始执行 步骤一: 当系统启动后,创建一个进程:Explorer.exe(也就是桌面进程) 步骤二: 当用户双击某一个 ...
- Delphi中DLL的创建和使用(转)
Delphi中DLL的创建和使用 1.DLL简介: 2.调用DLL: 3.创建DLL: 4.两个技巧: 5.初始化: 6.例外处理. 1.DLL简介 ...
- [转]C#创建服务及使用程序自动安装服务,.NET创建一个即是可执行程序又是Windows服务的exe
写在前面 原文地址:C#创建服务及使用程序自动安装服务,.NET创建一个即是可执行程序又是Windows服务的exe 这篇文章躺在我的收藏夹中有很长一段时间了,今天闲着没事,就自己动手实践了一下.感觉 ...
- Spring工厂方式创建Bean实例
创建Bean实例的方式: 1) 通过构造器(有参或无参) 方式: <bean id="" class=""/> 2) 通过静态工厂方法 方式: &l ...
随机推荐
- ALLOT流控设备SSG
Allot AC 系列产品EOL的通知如下. 该产品于2021年3月31日EOL. 替代的产品系列为SG/SSG系列. Allot Secure Service Gateway(SSG)应用程序和用户 ...
- datatables editor fields type
其实editor fields type 默认支持的输入类型就是w3c输入框类型. text number password textarea select checkbox ...
- java 第二章
变量:变量就是代表程序运行时存放数据的地方 数据存放在:磁盘,内存卡,U盘,光盘,内存条,固态硬盘,机械硬盘等 字节:8个二进制位构成1个"字节(Byte)",它是存储空间的基本计 ...
- IntelliJ IDEA 2019.2最新解读:性能更好,体验更优,细节处理更完美!
idea 2019.2 准备 idea 2019.2正式版是在2019年7月24号发布的,本篇文章,我将根据官方博客以及自己的理解来进行说明,总体就是:性能更好,体验更优,细节处理更完美! 支持jdk ...
- TestNG中group的用法
TestNG中的组可以从多个类中筛选组属性相同的方法执行. 比如有两个类A和B,A中有1个方法a属于组1,B中有1个方法b也属于组1,那么我们可以通过配置TestNG文件实现把这两个类中都属于1组的方 ...
- Chrome 跨域 disable-web-security 关闭安全策略
谷歌浏览器暂时关闭跨域. 当遇到以下情况,则可以简单的使用 关闭Chrome 安全策略跨域 开发时跨域,上线后,部署在一个域名下没有跨域问题 开发时,临时解决跨域问题 只有开发时用这个,其他时候,就不 ...
- 戴尔PowerEdge T110 Ⅱ服务器U盘安装Windows Server 2019 DataCenter
一. 下载准备 准备工作——下载Microsoft Windows Server 2019 官方简体中文激活版 (MSDN)原版iso镜像 准备工作——安装刻录软件UltraISO,单文件绿色版就够用 ...
- Linux基础文件类型
一.文件时间 ls -l 文件名 仅看的是文件的修改时间 [root@linux ~]# ls -l /etc/passwd -rw-r--r-- root root 5月 : /etc/passwd ...
- 记录一下我做Udacity 的Data Scientist Nano Degree Project
做项目的时候看了别人的blog,决定自己也随手记录下在做项目中遇到的好的小知识点. 最近在做Udacity的Data Scientist Nano Degree Project的Customer_Se ...
- Android 虹软人脸识别SDK-人脸对比
准备 : 登录官方网站,获取SDK,进行个人验证后新建项目,获取APP_ID,和SDK_KEY: https://ai.arcsoft.com.cn/ucenter/resource/build/in ...