应用程序改造
对应用程序进行静默安装和静默卸载改造。改造后,工业软件可通过ISCDesk实现一键下载、安装和卸载。
针对工业软件在ISCDesk中安装/卸载异常的场景,提出以下几点建议:
- 建议工业软件的安装脚本支持覆盖安装,即在出现安装中断之后,可以继续安装或者全新安装。
- 建议工业软件的卸载脚本支持继续卸载,即在出现任何卸载异常之后,可以继续卸载。
- 建议将安装/卸载异常原因补充到进度文件。
- 不建议采取先清空进度文件再写进度文件的机制,避免ISCDesk读取不到进度。
静默安装改造
- 本地新建“InstallApp.vbs”文件,并复制以下代码至新建文件中,用于调用安装程序的静默安装命令。
' 获取命令行参数 Set objArgs = WScript.Arguments ' 获取文件夹路径 folderPath = objArgs(0) ' 移除路径末尾的斜杠 If Right(folderPath, 1) = "\" Then folderPath = Left(folderPath, Len(folderPath) - 1) End If ' 构建命令 Set fso = CreateObject("Scripting.FileSystemObject") ' 获取当前脚本所在目录的路径 scriptFolder = fso.GetParentFolderName(WScript.ScriptFullName) ProgressPath = folderPath & "\installProgress.log" ' 若progress文件已存在,则删除 If fso.fileExists(ProgressPath) Then fso.DeleteFile(ProgressPath) End If ' 构建cmd命令 ' ①假设此vbs文件在D:\test中,安装程序文件名称为install.exe,目标安装目录(传进来的folderPath,无需改动)为D:\installpath。 ' 假如您的安装程序需要接受到的静默安装命令格式为: ' "D:\test\install.exe" D:\installpath ' installPath,parameters改为如下所示: ' installPath = fso.BuildPath(scriptFolder, "install.exe") ' parameters = folderPath ' ②假设此vbs文件在D:\test中,安装程序文件名称为setup.exe,目标安装目录(传进来的folderPath,无需改动)为D:\installpath。 ' 假如您的安装程序需要接受到的静默安装命令格式为: ' "D:\test\setup.exe" "D:\installpath" ' 则installPath,parameters改为如下所示: ' installPath = fso.BuildPath(scriptFolder, "setup.exe") ' parameters ="""" & folderPath & """" ' ③假设此vbs文件在D:\test中,安装程序文件名称为安装.exe,目标安装目录(传进来的folderPath,无需改动)为D:\installpath。 ' 假如您的安装程序需要接受到的静默安装命令格式为: ' "D:\test\安装.exe" /quiet InstallPath="D:\installpath" /isinstall ' installPath,parameters改为如下所示: ' installPath = fso.BuildPath(scriptFolder, "安装.exe") ' parameters =" /quiet" & " InstallPath=" & """" & folderPath & """" & " /isinstall" ' ◆◆◆◆◆具体什么参数应根据您的安装程序而决定,请根据您所接受的指令格式对下面installPath,parameters进行修改。◆◆◆◆◆ installPath = fso.BuildPath(scriptFolder, "setup.exe") parameters = folderPath ' 创建 Shell 对象执行 Set shell = CreateObject("wscript.shell") command = installPath & parameters & " 1" shell.run command ' 赋值uninstall.vbs中的folderPath Dim filePath filePath = scriptFolder & "\uninstall.vbs" ' 读取文件内容 Dim objStream Set objStream = CreateObject("ADODB.Stream") objStream.Charset = "GB2312" objStream.Open objStream.LoadFromFile filePath Dim content content = objStream.ReadText objStream.Close ' 替换第一行代码 Dim newCode newCode = "folderPath=" & """" & folderPath & """" content = Replace(content, Split(content, vbCrLf)(0), newCode) ' 使用GB2312编码写入文件 Set objStream = CreateObject("ADODB.Stream") objStream.Charset = "GB2312" objStream.Open objStream.WriteText content objStream.SaveToFile filePath, 2 objStream.Close ' 将uninstall.vbs卸载脚本拷贝至卸载程序的同级目录下 ' 假设卸载程序位置在安装目录下 ' 卸载路径 = folderPath ' 假设卸载程序位置在安装目录下的program文件夹内 ' 卸载路径 = folderPath & "\program" fso.CopyFile scriptFolder & "\uninstall.vbs", folderPath & "\uninstall.vbs"
- 应用安装时需要生成“install.json”文件,记录安装进度。文件格式如下:
{"status":1,"progress":100,"errorMsg":""}
“status”表示安装是否完成,“1”代表安装完成,“0”代表安装未完成;“progress”代表应用安装进度从“0~100”;“errorMsg”代表安装过程中的错误信息,如果没有出错则填空值即可。
本文提供一种“install.json”文件生成方法作为参考:
本方法中使用的软件安装程序通过innosetup安装包制作软件制作,因此安装进度获取依赖Inno Setup Compiler。
- 在安装打包程序“.iss”文件的[Code]代码段增加如下代码,在安装时可实时记录安装进度。
var lastPercent: Integer; procedure InitializeWizard; begin lastPercent := -1; end; procedure WriteLog(logContent: String; fileName: String); var bExist:Boolean; myFileName:String; svArray:TArrayOfString; MyFile: TFileStream; begin myFileName := ExpandConstant('{app}') + '\' + fileName; SetLength(svArray, 1); svArray[0] := logContent; SaveStringsToFile(myFileName, svArray, true); end; procedure CurInstallProgressChanged(CurProgress, MaxProgress: Integer); var percent: Integer; begin percent := CurProgress * 100 / MaxProgress; if lastPercent >= percent then else begin WriteLog(Format('Installing...:%d', [percent]), 'installProgress.log'); lastPercent := percent; end end;
- 在“InstallApp.vbs”文件增加如下代码,生成“install.json”文件。
Set objFSO = CreateObject("Scripting.FileSystemObject") ' 目标文件夹路径 strFolderPath = folderPath ' 创建JSON文件函数 Sub CreateJsonFile(progress) Dim objJson, jsonObj, outFile Set objJson = CreateObject("Scripting.Dictionary") Set jsonObj = CreateObject("Scripting.Dictionary") ' 设置JSON对象的属性 If CInt(progress) >= 100 Then jsonObj.Add "status", 1 Else jsonObj.Add "status", 0 End If jsonObj.Add "progress", CInt(progress) '将进度值转换为整数类型 jsonObj.Add "errorMsg", """""" ' 将JSON对象添加到顶级对象 objJson.Add "", jsonObj ' 打开输出文件 Set outFile = objFSO.CreateTextFile(strFolderPath & "\install.json", True) ' 创建JSON字符串 Dim jsonString jsonString = "{" For Each key In jsonObj.Keys jsonString = jsonString & """" & key & """:" & jsonObj(key) & "," Next jsonString = Left(jsonString, Len(jsonString) - 1) ' 移除最后一个逗号 jsonString = jsonString & "}" ' 将JSON数据写入文件 outFile.Write jsonString ' 关闭文件 outFile.Close End Sub ' 获取当前进度函数 Function GetProgress() Dim Progress Progress = 0 If fso.fileExists(ProgressPath) Then Dim content Dim pos Set file = fso.OpenTextFile(ProgressPath, 1) Do Until file.AtEndOfStream content = file.ReadLine If Len(content) = 0 Then Exit Do End If pos = InStr(content, "Installing...:") If pos > 0 Then Progress = CInt(Mid(content, pos + 14)) End If Loop file.Close End If GetProgress = Progress End Function Function FindSetupProcess() Dim bExist,WMI,Objs,Process,processPath bExist = 0 Set WMI=GetObject("WinMgmts:") Set Objs=WMI.InstancesOf("Win32_Process") Process="" For Each Obj In Objs Process = Obj.Description processPath = Obj.ExecutablePath If Process = "NotePad--_setup.exe" And processPath = installPath Then bExist = 1 End If Next FindSetupProcess = bExist End Function ' 主循环 Do While True Dim bExist bExist = FindSetupProcess() ' 获取安装进度,安装程序退出时进度置为100 If bExist = 1 Then progress = GetProgress() Else progress = 100 End If ' 创建JSON文件 CreateJsonFile(progress) If bExist = 1 Then ' ◆◆◆◆◆等待1秒,读取安装进度◆◆◆◆◆ WScript.Sleep 1000 Else fso.DeleteFile(ProgressPath) Exit Do End If Loop
- 在安装打包程序“.iss”文件的[Code]代码段增加如下代码,在安装时可实时记录安装进度。
- 修改“InstallApp.vbs”参数。
- 鼠标右键打开编辑“InstallApp.vbs”。
- 参考静默安装命令示例①、②、③,修改“installPath”和“parameters”。
图1 修改参数
- 将“InstallApp.vbs”复制至安装程序同级目录。
图2 复制粘贴InstallApp.vbs
静默卸载改造
- 本地新建“uninstall.vbs”文件,并复制以下代码至新建文件中,用于调用卸载程序的静默卸载命令。
folderPath="D:\123" ' folderPath无需关注与修改,会自动由install.vbs在安装过程中赋值 ' 构建命令 Set fso = CreateObject("Scripting.FileSystemObject") ' 获取当前脚本所在目录的路径 scriptFolder = fso.GetParentFolderName(WScript.ScriptFullName) ProgressPath = folderPath & "\uninstallProgress.log" ' 如果progress文件已存在,则删除 If fso.fileExists(ProgressPath) Then fso.DeleteFile(ProgressPath) End If ' ①假如您的卸载程序所接受到的静默卸载命令格式为: ' "D:\installpath\uninstall.exe" ' installPath,parameters改为如下所示 ' installPath = fso.BuildPath(scriptFolder, "uninstallApp.exe") ' parameters ="" ' ②假如您的卸载程序所接受到的静默卸载命令格式为: ' "D:\installpath\uninstall.exe" /uninstall /quiet ' installPath,parameters改为如下所示 ' installPath = fso.BuildPath(scriptFolder, "uninstallApp.exe") ' parameters =" /uninstall" & " /quiet" ' ◆◆◆◆◆具体什么参数应根据您的卸载程序而决定,请根据您所接受的指令格式对下面uninstallPath,parameters进行修改。◆◆◆◆◆ uninstallPath = fso.BuildPath(scriptFolder, "uninstallApp.exe") parameters =" /uninstall" & " /quiet" Set shell = CreateObject("wscript.shell") command = """" & uninstallPath & """" & parameters shell.run command
- 应用卸载时需要生成“uninstall.json”文件,记录卸载进度,文件格式如下:
{"status":1,"progress":100,"errorMsg":""}
“status”表示卸载是否完成,“1”代表卸载完成,“0”代表卸载未完成;“progress”代表应用卸载进度从0~100;“errorMsg”代表卸载过程中的错误信息,如果没有出错则填空值即可。
本文提供一种“uninstall.json”文件生成方法作为参考:
本方法中使用的软件安装程序通过innosetup安装包制作软件制作,因此卸载进度获取依赖Inno Setup Compiler。
- 在安装打包程序“.iss”文件的[Code]代码段下增加如下代码,在卸载时可实时记录卸载进度。
procedure WriteLog(logContent: String; fileName: String); var bExist:Boolean; myFileName:String; svArray:TArrayOfString; MyFile: TFileStream; begin myFileName := ExpandConstant('{app}') + '\' + fileName; SetLength(svArray, 1); svArray[0] := logContent; SaveStringsToFile(myFileName, svArray, true); end; procedure TimerProc(h: LongWord; AMsg: LongWord; IdEvent: LongWord; dwTime: LongWord); begin WriteLog(Format('Uninstalling...:%d',[UninstallProgressForm.ProgressBar.Position * 100 /UninstallProgressForm.ProgressBar.Max]), 'uninstallProgress.log'); end; function SetTimer(hWnd: LongWord; nIDEvent, uElapse: LongWord; lpTimerFunc: LongWord): LongWord; external 'SetTimer@user32.dll stdcall'; procedure InitializeUninstallProgressForm(); begin SetTimer(0, 0, 100, CreateCallback(@TimerProc)); { every 100 ms } end; procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep); var Progress: Integer; begin case CurUninstallStep of usUninstall: begin WriteLog('Uninstalling...:0', 'uninstallProgress.log'); end; usPostUninstall: begin WriteLog('Uninstalling...:100', 'uninstallProgress.log'); end; end; end;
- 在“uninstallApp.vbs”中增加如下代码,生成“uninstall.json”文件。
' 目标文件夹路径 strFolderPath = folderPath ' 创建JSON文件函数 Sub CreateJsonFile(progress) Dim objJson, jsonObj, outFile Set objJson = CreateObject("Scripting.Dictionary") Set jsonObj = CreateObject("Scripting.Dictionary") ' 设置JSON对象的属性 If progress >= 100 Then jsonObj.Add "status", 1 Else jsonObj.Add "status", 0 End If jsonObj.Add "progress", CInt(progress) '将进度值转换为整数类型 jsonObj.Add "errorMsg", """""" ' 将JSON对象添加到顶级对象 objJson.Add "", jsonObj ' 打开输出文件 Set outFile = fso.CreateTextFile(strFolderPath & "\uninstall.json", True) ' 创建JSON字符串 Dim jsonString jsonString = "{" For Each key In jsonObj.Keys jsonString = jsonString & """" & key & """:" & jsonObj(key) & "," Next jsonString = Left(jsonString, Len(jsonString) - 1) ' 移除最后一个逗号 jsonString = jsonString & "}" ' 将JSON数据写入文件 outFile.Write jsonString ' 关闭文件 outFile.Close End Sub ' 获取当前进度函数 Function GetProgress() Dim Progress Progress = 0 If fso.fileExists(ProgressPath) Then Dim content Dim pos Set file = fso.OpenTextFile(ProgressPath, 1) Do Until file.AtEndOfStream content = file.ReadLine If Len(content) = 0 Then Exit Do End If pos = InStr(content, "Uninstalling...:") If pos > 0 Then Progress = CInt(Mid(content, pos + 16)) End If Loop file.Close End If GetProgress = Progress End Function Function FindUnSetupProcess() Dim bExist,WMI,Objs,Process,processPath bExist = 0 Set WMI=GetObject("WinMgmts:") Set Objs=WMI.InstancesOf("Win32_Process") Process="" For Each Obj In Objs Process = Obj.Description processPath = Obj.ExecutablePath If Process = "unins000.exe" And processPath = uninstallPath Then bExist = 1 End If Next FindUnSetupProcess = bExist End Function Dim count, lastProgress count = 0 lastProgress = 0 ' 主循环 Do While True Dim bExist bExist = FindUnSetupProcess() ' 获取安装进度,安装程序退出时进度置为100 If bExist = 1 Then progress = GetProgress() Else progress = 100 End If ' 创建JSON文件 CreateJsonFile(progress) If bExist = 1 Then ' ◆◆◆◆◆等待1秒,读取安装进度◆◆◆◆◆ WScript.Sleep 1000 Else fso.DeleteFile(ProgressPath) 'MsgBox(bExist) Exit Do End If Loop
- 在安装打包程序“.iss”文件的[Code]代码段下增加如下代码,在卸载时可实时记录卸载进度。
- 修改“uninstall.vbs”参数。
- 鼠标右键打开编辑“uninstall.vbs”。
- 参考静默卸载命令示例,修改“uninstallPath”和“parameters”。
图3 修改参数
- 将“uninstall.vbs”复制至安装程序同级目录。
图4 复制uninstall.vbs
打包安装程序
将安装程序、InstallApp.vbs和uninstall.vbs打包压缩为一个压缩包。