InstallShield安装新版本时卸载老版本

InstallShield安装新的打包程序时,默认会提示下面的对话框,大意是说已经安装了产品的另一个版本,要用户手动去卸载老版本,不是很友好。

下面是对InstallShield在安装新版本时自动卸载老版本的一些尝试,主要是Install Script程序的编写。

1.首先要将Installation Designer–》Upgrades–》Prepare Setup For Upgrade Scenarios–》Upgrade Windows Installer Setup–》common下的Small/Minor Upgrade Settings选择为Don’t prompt user,just install the upgrade。这样不会出现上面的提示框,继续下面的卸载和安装。

2.下一步是要对OnResumeUI事件进行响应,主要是OnResumeUIBefore和OnResumeUIAfter。

3.在OnResumeUIBefore中完成老版本的卸载,脚本如下:

//---------------------------------------------------------------------------
// OnResumeUIBefore
//
// The OnResumeUIBefore event is called when end user runs installation that
// is performing a resumed install. Usually this happens by specifying
// a property like REINSTALL or ADDLOCAL at the command line when the
// product is already installed. After this function returns,
// ComponentTransferData is called to perform file transfer.
//---------------------------------------------------------------------------
function OnResumeUIBefore()
string szfilename, szmsg1, szmsg2;
int nresult;
STRING szDir, szIcon;
begin

nresult = MessageBox("新版本安装之前将卸载旧版本,是否继续?", MB_YESNO);
if(nresult = IDNO)then
abort;
endif;

szfilename = UNINSTALL_STRING +" /UNINSTALL /hide_progress";
nresult = StrFind(szfilename,".exe");
if nresult >=0 then
StrSub(szmsg1,szfilename,0,nresult + 4);
StrSub(szmsg2,szfilename,nresult + 4,200);
LongPathToQuote(szmsg1, FALSE );
LongPathToQuote(szmsg2, FALSE );
//szfilename = "\"" + szmsg1 + "\"" +szmsg2;
endif;

if(LaunchAppAndWait(szmsg1, szmsg2, LAAW_OPTION_WAIT_INCL_CHILD | LAAW_OPTION_WAIT) < 0 )then
MessageBox("旧版本卸载失败", MB_OK);
abort;
else
WaitForApplication(LAAW_PROCESS_INFORMATION.hProcess, LAAW_PROCESS_INFORMATION.dwProcessId, INFINITE, LAAW_OPTION_WAIT_INCL_CHILD | LAAW_OPTION_WAIT);
endif;

szIcon = DesktopFolder;
DeleteFolderIcon(szIcon, "AliProbe");

szDir = INSTALLDIR + "AliProbe V1.1";
DeleteDir(szDir, ALLCONTENTS);
end;

需要注意的地方是,在调用LaunchAppAndWait方法等待老版本卸载完成的时候,一定要加上LAAW_OPTION_WAIT_INCL_CHILD ,主要是因为卸载的过程是Windows Install启动卸载程序,所以一定要等待Windows Install的子进程结束,否则将不能等待。

4.在OnResumeUIAfter中完成新版本的安装,脚本如下:

//---------------------------------------------------------------------------
// OnResumeUIAfter
//
// The OnResumeUIBefore event is called when end user runs installation that is
// performing a resumed install. Usually this happens by specifying a property
// like REINSTALL or ADDLOCAL at the command line when the product is already
// installed. In the handler, installation usually displays UI that will
// inform end user that Reinstallation has been completed successfully.
//---------------------------------------------------------------------------
function OnResumeUIAfter()
STRING noUse;
NUMBER szProcessId;
NUMBER nvProcessHandle; // Handle to a process
NUMBER nvModuleHandle; // Handle to a process module
STRING szModuleName; // Module filename
NUMBER nvBytesRequired;

begin

szProcessId = GetCurrentProcessId();
if szProcessId != 0 then
if ProcessRunning(noUse, szProcessId, szModuleName) = TRUE then
LaunchApp(szModuleName, "/hide_progress");
else
MessageBox("自动安装新版本遇到问题,请再次运行安装文件完成安装。", MB_OK);
endif;
else
MessageBox("自动安装新版本遇到问题,请再次运行安装文件完成安装。", MB_OK);
endif;
end;

这里是通过GetCurrentProcessId得到当前进程的Id,并调用ProcessRunning获取当前进程模块的完整路径。

5.ProcessRunning的脚本如下:

//
//
// Function: _Process_Running
//
// Description: Determines if the specified process is running in memory.
//
// Parameters: szAppName - Name of the application to check.
// nvFindProcessId - ID of the process to find.
// szFindModName - Name of the Module of the found process
//
// Returns: TRUE - The process is running.
// FALSE - The process is not running.
//
//

function BOOL ProcessRunning(szAppName, nvFindProcessId, szFindModName)
BOOL bvRunning; // Process is running
NUMBER nvProcessIDs(512); // Array of process IDs
NUMBER nvBytesReturned; // Number of bytes returned in process ID array
NUMBER nvProcesses; // Number of processes running
NUMBER nvIndex; // Loop index
NUMBER nvProcessHandle; // Handle to a process
NUMBER nvModuleHandle; // Handle to a process module
NUMBER nvBytesRequired; // Number of bytes required to store values
POINTER pvProcessIDs; // Pointer to process ID array
STRING svModuleName; // Module name
STRING svFileName; // Module filename
begin
// The psapi.dll reads the Windows NT performance database. The DLL
// is part of the Win32 SDK.

if UseDLL(WINSYSDIR ^ PSAPI_FILE) < 0 then
// Could not load psapi.dll.

MessageBox("ERROR: Could not load [" + WINSYSDIR ^ PSAPI_FILE +
"].", SEVERE);

return FALSE;
endif;

// Get the PIDs of all currently running processes.

pvProcessIDs = ArrayToPointer(nvProcessIDs);

EnumProcesses(pvProcessIDs, 512, nvBytesReturned);

// Determine the number of process IDs retrieved. Each process ID
// is PROCESSID_LENGTH bytes.

nvProcesses = nvBytesReturned / PROCESSID_LENGTH;

// Get the executable associated with each process, and check if
// its filename matches the one passed to the function.

for nvIndex = 1 to nvProcesses
// Get a handle to the process.

nvProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ, 0, nvProcessIDs(nvIndex));

if nvProcessHandle != 0 then
// Get a handle to the first module in the process, which
// should be the executable.

if EnumProcessModules(nvProcessHandle, nvModuleHandle,
PROCESSID_LENGTH, nvBytesRequired) != 0 then
// Get the path of the module.

if GetModuleFileNameExA(nvProcessHandle, nvModuleHandle,
svModuleName, SizeOf(svModuleName)) != 0 then
// Extract the filename (without an extension) from
// the path.

//Add by QianShi at 2010.6.23
//Get module name by process id.
if nvProcessIDs(nvIndex) = nvFindProcessId then
szFindModName = svModuleName;
bvRunning = TRUE;
goto ProcessRunningEnd;
endif;

ParsePath(svFileName, svModuleName, FILENAME_ONLY);

if StrCompare(svFileName, szAppName) = 0 then
// The process module matches the application
// name passed to the function.

bvRunning = TRUE;

goto ProcessRunningEnd;
endif;
endif;
endif;
endif;
endfor;

ProcessRunningEnd:

if UnUseDLL(PSAPI_FILE) < 0 then
MessageBox("ERROR: Could not unload [" + WINSYSDIR ^ PSAPI_FILE +
"].", SEVERE);

return FALSE;
endif;

return bvRunning;
end;

程序的功能主要是枚举当前的进程Id,并通过Id匹配来得到Id对应的Module name,本函数同样可以判断某个name的进程是否正在运行。

以上就是本人对用IS脚本完成安装新版本前卸载老版本的方法, 如果大家有其他好的方法,请多多指教。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值