有时候卸载installshield安装的程序,卸载完会提示是否重启电脑以完成所有卸载,产生这个提示的常见原因有如下几种:
1. 卸载时,程序正处于运行状态
2. 卸载时,程序文件夹处于打开状态
3. 卸载时,有文件被别的进程调用,或者在进程中,常见情况如dll在进程中
一般来说解决办法是针对第三种情况的,解决办法是卸载时强制杀进程,比如在OnMaintUIBefore或者OnUninstall里写上强制杀进程的代码。对于第一种情况和第二种情况,如果是可交互的普通GUI程序,一般不予理会,因为这些行为是不能禁止的合理行为。
--------------------------------------------------------------------------------------------------------------
Installshield停止操作系统进程的代码 --IS6及以上版本适用
setup.rul的代码
Code
////////////////////////////////////////////////////////////////////////////////
//
// IIIIIII SSSSSS
// II SS InstallShield (R)
// II SSSSSS (c) 1996-2000, InstallShield Software Corporation
// II SS (c) 1990-1996, InstallShield Corporation
// IIIIIII SSSSSS All Rights Reserved.
//
//
// This code is generated as a starting setup template. You should
// modify it to provide all necessary steps for your setup.
//
//
// File Name: Setup.rul
//
// Description: InstallShield script
//
// Comments: This template script performs a basic setup. With minor
// modifications, this template can be adapted to create
// new, customized setups.
//
////////////////////////////////////////////////////////////////////////////////
// Include header files
#include "ifx.h" //DO NOT REMOVE
////////////////////// string defines ////////////////////////////
//////////////////// installation declarations ///////////////////
// ----- DLL function prototypes -----
// your DLL function prototypes
#include "ShutDownRunningApp.rul"
// ---- script function prototypes -----
// your script function prototypes
// your global variables
//////////////////////////////////////////////////////////////////////////////
//
// FUNCTION: OnFirstUIBefore
//
// EVENT: FirstUIBefore event is sent when installation is run for the first
// time on given machine. In the handler installation usually displays
// UI allowing end user to specify installation parameters. After this
// function returns, ComponentTransferData is called to perform file
// transfer.
//
///////////////////////////////////////////////////////////////////////////////
function OnFirstUIBefore()
NUMBER nResult,nSetupType;
STRING szTitle, szMsg;
begin
if ProcessRunning("notepad") then
MessageBox("Application is running.", INFORMATION);
ProcessEnd("notepad");
Delay(2); // Delay to allow process list to refresh
if ProcessRunning("notepad") then
MessageBox("Application is running.", INFORMATION);
else
MessageBox("Application is not running.", INFORMATION);
endif;
else
MessageBox("Application is not running.", INFORMATION);
endif;
abort;
// TO DO: if you want to enable background, window title, and caption bar title
// SetTitle( @TITLE_MAIN, 24, WHITE );
// SetTitle( @TITLE_CAPTIONBAR, 0, BACKGROUNDCAPTION );
// Enable( FULLWINDOWMODE );
// Enable( BACKGROUND );
// SetColor(BACKGROUND,RGB (0, 128, 128));
TARGETDIR = PROGRAMFILES ^@COMPANY_NAME ^@PRODUCT_NAME;
Dlg_Start:
// beginning of dialogs label
Dlg_ObjDialogs:
nResult = ShowObjWizardPages(nResult);
if (nResult = BACK) goto Dlg_Start;
// setup default status
SetStatusWindow(0, "");
Enable(STATUSEX);
StatusUpdate(ON, 100);
return 0;
end;
//////////////////////////////////////////////////////////////////////////////
//
// FUNCTION: OnFirstUIAfter
//
// EVENT: FirstUIAfter event is sent after file transfer, when installation
// is run for the first time on given machine. In this event handler
// installation usually displays UI that will inform end user that
// installation has been completed successfully.
//
///////////////////////////////////////////////////////////////////////////////
function OnFirstUIAfter()
begin
Disable(STATUSEX);
ShowObjWizardPages(NEXT);
end;
///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION: OnMaintUIAfter
//
// EVENT: MaintUIAfter event is sent after file transfer, when end user runs
// installation that has already been installed on the machine. Usually
// this happens through Add/Remove Programs applet.
// In the handler installation usually displays UI that will inform
// end user that maintenance/uninstallation has been completed successfully.
//
///////////////////////////////////////////////////////////////////////////////
function OnMaintUIAfter()
begin
Disable(STATUSEX);
ShowObjWizardPages(NEXT);
end;
///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION: OnMoving
//
// EVENT: Moving event is sent when file transfer is started as a result of
// ComponentTransferData call, before any file transfer operations
// are performed.
//
///////////////////////////////////////////////////////////////////////////////
function OnMoving()
STRING szAppPath;
begin
// Set LOGO Compliance Application Path
// TO DO : if your application .exe is in a subfolder of TARGETDIR then add subfolder
szAppPath = TARGETDIR;
RegDBSetItem(REGDB_APPPATH, szAppPath);
RegDBSetItem(REGDB_APPPATH_DEFAULT, szAppPath ^ @PRODUCT_KEY);
end;
// --- include script file section ---
////////////////////////////////////////////////////////////////////////////////
//
// IIIIIII SSSSSS
// II SS InstallShield (R)
// II SSSSSS (c) 1996-2000, InstallShield Software Corporation
// II SS (c) 1990-1996, InstallShield Corporation
// IIIIIII SSSSSS All Rights Reserved.
//
//
// This code is generated as a starting setup template. You should
// modify it to provide all necessary steps for your setup.
//
//
// File Name: Setup.rul
//
// Description: InstallShield script
//
// Comments: This template script performs a basic setup. With minor
// modifications, this template can be adapted to create
// new, customized setups.
//
////////////////////////////////////////////////////////////////////////////////
// Include header files
#include "ifx.h" //DO NOT REMOVE
////////////////////// string defines ////////////////////////////
//////////////////// installation declarations ///////////////////
// ----- DLL function prototypes -----
// your DLL function prototypes
#include "ShutDownRunningApp.rul"
// ---- script function prototypes -----
// your script function prototypes
// your global variables
//////////////////////////////////////////////////////////////////////////////
//
// FUNCTION: OnFirstUIBefore
//
// EVENT: FirstUIBefore event is sent when installation is run for the first
// time on given machine. In the handler installation usually displays
// UI allowing end user to specify installation parameters. After this
// function returns, ComponentTransferData is called to perform file
// transfer.
//
///////////////////////////////////////////////////////////////////////////////
function OnFirstUIBefore()
NUMBER nResult,nSetupType;
STRING szTitle, szMsg;
begin
if ProcessRunning("notepad") then
MessageBox("Application is running.", INFORMATION);
ProcessEnd("notepad");
Delay(2); // Delay to allow process list to refresh
if ProcessRunning("notepad") then
MessageBox("Application is running.", INFORMATION);
else
MessageBox("Application is not running.", INFORMATION);
endif;
else
MessageBox("Application is not running.", INFORMATION);
endif;
abort;
// TO DO: if you want to enable background, window title, and caption bar title
// SetTitle( @TITLE_MAIN, 24, WHITE );
// SetTitle( @TITLE_CAPTIONBAR, 0, BACKGROUNDCAPTION );
// Enable( FULLWINDOWMODE );
// Enable( BACKGROUND );
// SetColor(BACKGROUND,RGB (0, 128, 128));
TARGETDIR = PROGRAMFILES ^@COMPANY_NAME ^@PRODUCT_NAME;
Dlg_Start:
// beginning of dialogs label
Dlg_ObjDialogs:
nResult = ShowObjWizardPages(nResult);
if (nResult = BACK) goto Dlg_Start;
// setup default status
SetStatusWindow(0, "");
Enable(STATUSEX);
StatusUpdate(ON, 100);
return 0;
end;
//////////////////////////////////////////////////////////////////////////////
//
// FUNCTION: OnFirstUIAfter
//
// EVENT: FirstUIAfter event is sent after file transfer, when installation
// is run for the first time on given machine. In this event handler
// installation usually displays UI that will inform end user that
// installation has been completed successfully.
//
///////////////////////////////////////////////////////////////////////////////
function OnFirstUIAfter()
begin
Disable(STATUSEX);
ShowObjWizardPages(NEXT);
end;
///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION: OnMaintUIAfter
//
// EVENT: MaintUIAfter event is sent after file transfer, when end user runs
// installation that has already been installed on the machine. Usually
// this happens through Add/Remove Programs applet.
// In the handler installation usually displays UI that will inform
// end user that maintenance/uninstallation has been completed successfully.
//
///////////////////////////////////////////////////////////////////////////////
function OnMaintUIAfter()
begin
Disable(STATUSEX);
ShowObjWizardPages(NEXT);
end;
///////////////////////////////////////////////////////////////////////////////
//
// FUNCTION: OnMoving
//
// EVENT: Moving event is sent when file transfer is started as a result of
// ComponentTransferData call, before any file transfer operations
// are performed.
//
///////////////////////////////////////////////////////////////////////////////
function OnMoving()
STRING szAppPath;
begin
// Set LOGO Compliance Application Path
// TO DO : if your application .exe is in a subfolder of TARGETDIR then add subfolder
szAppPath = TARGETDIR;
RegDBSetItem(REGDB_APPPATH, szAppPath);
RegDBSetItem(REGDB_APPPATH_DEFAULT, szAppPath ^ @PRODUCT_KEY);
end;
// --- include script file section ---
ShutDownRunningApp.rul的代码
Code
//////////////////////////////////////////////////////////////////////////////
//
// Description: Windows NT process control functions.
//
// The process code is adapted from code posted by William F.
// Snodgrass to www.installsite.org. The original code header
// is appended below. The array code is adapted from code posted
// by Rajesh Ramachandran to the installshield.is6.installscript
// newsgroup.
//
// Submitted by Richard Iwasa (riwasa@email.com).
//
// Usage example:
//
// if ProcessRunning("notepad") then
// MessageBox("Application is running.", INFORMATION);
//
// ProcessEnd("notepad");
//
// Delay(2); // Delay to allow process list to refresh
//
// if ProcessRunning("notepad") then
// MessageBox("Application is running.", INFORMATION);
// else
// MessageBox("Application is not running.", INFORMATION);
// endif;
// else
// MessageBox("Application is not running.", INFORMATION);
// endif;
//
// Original code header appended below:
//
// GetRunningApp();
// ShutDownApp();
//
// These script created functions will look for any running application
// based on the file name, then display an error message within the Setup.
// You can optionally halt the install or just continue on.
//
// You can use the ShutDownApp() function for shutting down that process
// or others as well. This is useful for processes that run in the
// background but have no Windows associated with them. May not work with
// Services.
//
// This script calls functions in PSAPI.DLL that are not supported on
// Windows 95 or 98.
//
// ***Instructions***
// Place these script peices into the Setup.rul file.
//
// Modify the script to include the applications you would like to get or
// shutdown.
//
// Submitted by William F. Snodgrass
// Contact info: bsnodgrass@geographix.com
//
// Created by Theron Welch, 3/3/99
// Minor modifications by Stefan Krueger, 11/03/99
//
// Copyright (c) 1999-2000 GeoGraphix, Inc.
//
//////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////
// Function prototypes.
/////////////////////////////////////////////////
prototype POINTER ArrayToPointer(BYREF VARIANT);
prototype NUMBER ProcessEnd(STRING);
prototype BOOL ProcessRunning(STRING);
// Kernel functions.
prototype NUMBER Kernel32.OpenProcess(NUMBER, BOOL, NUMBER);
prototype NUMBER Kernel32.TerminateProcess(NUMBER, NUMBER);
// Process information functions.
prototype NUMBER PSAPI.EnumProcesses(POINTER, NUMBER, BYREF NUMBER);
prototype NUMBER PSAPI.EnumProcessModules(NUMBER, BYREF NUMBER, NUMBER,
BYREF NUMBER);
prototype NUMBER PSAPI.GetModuleFileNameExA(NUMBER, NUMBER, BYREF STRING,
NUMBER);
/////////////////////////////////////////////////
// Structures.
/////////////////////////////////////////////////
// Structure to mirror the C/C++ SAFEARRAY data structure.
typedef _SAFEARRAY
begin
SHORT cDims;
SHORT fFeatures;
LONG cbElements;
LONG cLocks;
POINTER pvData;
// rgsaBound omitted
end;
// Structure to mirror the C/C++ VARIANT data structure.
typedef _VARIANT
begin
SHORT vt;
SHORT wReserver1;
SHORT wReserved2;
SHORT wReserved3;
NUMBER nData;
end;
/////////////////////////////////////////////////
// Constants.
/////////////////////////////////////////////////
#define PSAPI_FILE "psapi.dll" // Windows NT process DLL
#define PROCESSID_LENGTH 4 // 4 bytes (DWORD) for a process ID
// Process information constants.
#define PROCESS_QUERY_INFORMATION 0x400
#define PROCESS_ALL_ACCESS 0x1f0fff
#define PROCESS_VM_READ 0x10
//////////////////////////////////////////////////////////////////////////////
//
// Function: ArrayToPointer
//
// Description: Converts an InstallShield array into a C array.
//
// When an array is created in InstallScript, a VARIANT variable
// is created which holds an OLEAutomation SAFEARRAY. To pass
// such an array to a DLL function expecting a C-style array,
// this function explicitly typecasts the pointer to the array
// to a _VARIANT pointer so that the _SAFEARRAY pointer can be
// extracted. The pointer to the actual data is then extracted
// from the _SAFEARRAY pointer.
//
// Parameters: structArray - Array variable.
//
// Returns: POINTER - Pointer to array.
//
//////////////////////////////////////////////////////////////////////////////
function POINTER ArrayToPointer(structArray)
_SAFEARRAY POINTER pstructArray; // _SAFEARRAY array pointer
_VARIANT POINTER pstructVariant; // _VARIANT array pointer
begin
// Typecast the pointer to the array to a _VARIANT pointer.
pstructVariant = &structArray;
// Extract the _SAFEARRAY pointer from the _VARIANT.
pstructArray = pstructVariant->nData;
// Return the pointer to the actual data from the _SAFEARRAY.
return pstructArray->pvData;
end;
//////////////////////////////////////////////////////////////////////////////
//
// Function: _Process_End
//
// Description: Terminates running processes for the specified application.
//
// Parameters: szAppName - Name of the application to terminate.
//
// Returns: >= 0 - Number of processes terminated.
// -1 - Failure.
//
//////////////////////////////////////////////////////////////////////////////
function NUMBER ProcessEnd(szAppName)
NUMBER nvReturn; // Number of processes terminated
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 -1;
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. The OpenProcess function
// must have full (all) access to be able to terminate
// processes.
nvProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION |
PROCESS_ALL_ACCESS, 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.
ParsePath(svFileName, svModuleName, FILENAME_ONLY);
if StrCompare(svFileName, szAppName) = 0 then
// The process module matches the application
// name passed to the function.
if TerminateProcess(nvProcessHandle, 0) > 0 then
nvReturn++;
endif;
endif;
endif;
endif;
endif;
endfor;
if UnUseDLL(PSAPI_FILE) < 0 then
MessageBox("ERROR: Could not unload [" + WINSYSDIR ^ PSAPI_FILE +
"].", SEVERE);
return -1;
endif;
return nvReturn;
end;
//////////////////////////////////////////////////////////////////////////////
//
// Function: _Process_Running
//
// Description: Determines if the specified process is running in memory.
//
// Parameters: szAppName - Name of the application to check.
//
// Returns: TRUE - The process is running.
// FALSE - The process is not running.
//
//////////////////////////////////////////////////////////////////////////////
function BOOL ProcessRunning(szAppName)
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.
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;
//////////////////////////////////////////////////////////////////////////////
//
// Description: Windows NT process control functions.
//
// The process code is adapted from code posted by William F.
// Snodgrass to www.installsite.org. The original code header
// is appended below. The array code is adapted from code posted
// by Rajesh Ramachandran to the installshield.is6.installscript
// newsgroup.
//
// Submitted by Richard Iwasa (riwasa@email.com).
//
// Usage example:
//
// if ProcessRunning("notepad") then
// MessageBox("Application is running.", INFORMATION);
//
// ProcessEnd("notepad");
//
// Delay(2); // Delay to allow process list to refresh
//
// if ProcessRunning("notepad") then
// MessageBox("Application is running.", INFORMATION);
// else
// MessageBox("Application is not running.", INFORMATION);
// endif;
// else
// MessageBox("Application is not running.", INFORMATION);
// endif;
//
// Original code header appended below:
//
// GetRunningApp();
// ShutDownApp();
//
// These script created functions will look for any running application
// based on the file name, then display an error message within the Setup.
// You can optionally halt the install or just continue on.
//
// You can use the ShutDownApp() function for shutting down that process
// or others as well. This is useful for processes that run in the
// background but have no Windows associated with them. May not work with
// Services.
//
// This script calls functions in PSAPI.DLL that are not supported on
// Windows 95 or 98.
//
// ***Instructions***
// Place these script peices into the Setup.rul file.
//
// Modify the script to include the applications you would like to get or
// shutdown.
//
// Submitted by William F. Snodgrass
// Contact info: bsnodgrass@geographix.com
//
// Created by Theron Welch, 3/3/99
// Minor modifications by Stefan Krueger, 11/03/99
//
// Copyright (c) 1999-2000 GeoGraphix, Inc.
//
//////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////
// Function prototypes.
/////////////////////////////////////////////////
prototype POINTER ArrayToPointer(BYREF VARIANT);
prototype NUMBER ProcessEnd(STRING);
prototype BOOL ProcessRunning(STRING);
// Kernel functions.
prototype NUMBER Kernel32.OpenProcess(NUMBER, BOOL, NUMBER);
prototype NUMBER Kernel32.TerminateProcess(NUMBER, NUMBER);
// Process information functions.
prototype NUMBER PSAPI.EnumProcesses(POINTER, NUMBER, BYREF NUMBER);
prototype NUMBER PSAPI.EnumProcessModules(NUMBER, BYREF NUMBER, NUMBER,
BYREF NUMBER);
prototype NUMBER PSAPI.GetModuleFileNameExA(NUMBER, NUMBER, BYREF STRING,
NUMBER);
/////////////////////////////////////////////////
// Structures.
/////////////////////////////////////////////////
// Structure to mirror the C/C++ SAFEARRAY data structure.
typedef _SAFEARRAY
begin
SHORT cDims;
SHORT fFeatures;
LONG cbElements;
LONG cLocks;
POINTER pvData;
// rgsaBound omitted
end;
// Structure to mirror the C/C++ VARIANT data structure.
typedef _VARIANT
begin
SHORT vt;
SHORT wReserver1;
SHORT wReserved2;
SHORT wReserved3;
NUMBER nData;
end;
/////////////////////////////////////////////////
// Constants.
/////////////////////////////////////////////////
#define PSAPI_FILE "psapi.dll" // Windows NT process DLL
#define PROCESSID_LENGTH 4 // 4 bytes (DWORD) for a process ID
// Process information constants.
#define PROCESS_QUERY_INFORMATION 0x400
#define PROCESS_ALL_ACCESS 0x1f0fff
#define PROCESS_VM_READ 0x10
//////////////////////////////////////////////////////////////////////////////
//
// Function: ArrayToPointer
//
// Description: Converts an InstallShield array into a C array.
//
// When an array is created in InstallScript, a VARIANT variable
// is created which holds an OLEAutomation SAFEARRAY. To pass
// such an array to a DLL function expecting a C-style array,
// this function explicitly typecasts the pointer to the array
// to a _VARIANT pointer so that the _SAFEARRAY pointer can be
// extracted. The pointer to the actual data is then extracted
// from the _SAFEARRAY pointer.
//
// Parameters: structArray - Array variable.
//
// Returns: POINTER - Pointer to array.
//
//////////////////////////////////////////////////////////////////////////////
function POINTER ArrayToPointer(structArray)
_SAFEARRAY POINTER pstructArray; // _SAFEARRAY array pointer
_VARIANT POINTER pstructVariant; // _VARIANT array pointer
begin
// Typecast the pointer to the array to a _VARIANT pointer.
pstructVariant = &structArray;
// Extract the _SAFEARRAY pointer from the _VARIANT.
pstructArray = pstructVariant->nData;
// Return the pointer to the actual data from the _SAFEARRAY.
return pstructArray->pvData;
end;
//////////////////////////////////////////////////////////////////////////////
//
// Function: _Process_End
//
// Description: Terminates running processes for the specified application.
//
// Parameters: szAppName - Name of the application to terminate.
//
// Returns: >= 0 - Number of processes terminated.
// -1 - Failure.
//
//////////////////////////////////////////////////////////////////////////////
function NUMBER ProcessEnd(szAppName)
NUMBER nvReturn; // Number of processes terminated
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 -1;
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. The OpenProcess function
// must have full (all) access to be able to terminate
// processes.
nvProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION |
PROCESS_ALL_ACCESS, 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.
ParsePath(svFileName, svModuleName, FILENAME_ONLY);
if StrCompare(svFileName, szAppName) = 0 then
// The process module matches the application
// name passed to the function.
if TerminateProcess(nvProcessHandle, 0) > 0 then
nvReturn++;
endif;
endif;
endif;
endif;
endif;
endfor;
if UnUseDLL(PSAPI_FILE) < 0 then
MessageBox("ERROR: Could not unload [" + WINSYSDIR ^ PSAPI_FILE +
"].", SEVERE);
return -1;
endif;
return nvReturn;
end;
//////////////////////////////////////////////////////////////////////////////
//
// Function: _Process_Running
//
// Description: Determines if the specified process is running in memory.
//
// Parameters: szAppName - Name of the application to check.
//
// Returns: TRUE - The process is running.
// FALSE - The process is not running.
//
//////////////////////////////////////////////////////////////////////////////
function BOOL ProcessRunning(szAppName)
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.
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;
----------------------------------------------------------------------------------------------
Installshield停止操作系统进程的代码--IS5版本适用
出处:http://www.installsite.org/pages/en/isp_ext.htm
这个地址上有不少好东西,有空要好好研究下
里面的“List and Shut Down Running Applications”就是演示了Installshield如何停止操作系统进程
这个地址上有不少好东西,有空要好好研究下
里面的“List and Shut Down Running Applications”就是演示了Installshield如何停止操作系统进程
Code
/**********************************************************************************
/* GetRunningApp();
/* ShutDownApp();
/*
/* These script created functions will look for any running application based on
/* the file name, then display an error message within the Setup. You can optionally
/* halt the install or just continue on.
/*
/* You can use the ShutDownApp() function for shutting down that process or others
/* as well. This is useful for processes that run in the background but have no Windows
/* associated with them. May not work with Services.
/*
/* This script calls functions in PSAPI.DLL that are not supported on Windows 95 or 98.
/*
/* ***Instructions***
/* Place these script peices into the Setup.rul file.
/*
/* Modify the script to include the applications you would like to get or shutdown.
/*
/* Submitted by William F. Snodgrass
/* Contact info: bsnodgrass@geographix.com
/*
/* Created by Theron Welch, 3/3/99
/* Minor modifications by Stefan Krueger, 11/03/99
/*
/* Copyright (c) 1999-2000 GeoGraphix, Inc.
**********************************************************************************/
//////////////////// installation declarations ///////////////////
// ----- DLL function prototypes -----
// your DLL function prototypes
// Custom function for shutting down MyApp process
prototype ShutDownApp();
// Custom function for shutting down any running application
prototype GetRunningApp( BYREF STRING );
///////////////////////////////////////////////////////////////////////////////////
// Dll function calls needed
// Kernel functions
prototype LONG Kernel32.OpenProcess( LONG, BOOL, LONG ); // 1ST Param = 2035711 for PROCESS_ALL_ACCESS (It pays to know hex!!), 2nd = Doesn't matter, 3rd = Process ID
prototype BOOL Kernel32.TerminateProcess( LONG, INT ); // 1st Param = Process ID, 2nd = Doesn't matter - "0"
// Process info functions
prototype LONG Psapi.EnumProcesses( POINTER, LONG, BYREF LONG ); // 1st Param = By ref, Process ID, 2nd = number of bytes in param 1 = "4", 3rd = cb needed - might as well be "4"
prototype LONG Psapi.GetModuleFileNameExA( LONG, LONG, POINTER, LONG );// 1st Param = ProcessID, 2nd= Module ID, 3rd = pointer to a string, 4th = length of string
prototype LONG Psapi.EnumProcessModules( LONG, BYREF LONG, LONG, BYREF LONG ); // 1st Param = Process Handle, 2nd = Module Handle, 3rd = bytes passed ("4"), 4th = bytes needed ("4")
///////////////////////////////////////////////////////////////////////////////////
// your global variables
STRING svApp
program
if ( 1 == GetRunningApp ( svApp ) ) then
MessageBox ( "The installation has detected that " + svApp + " is running. " +
"Please close " + svApp + " then restart the installation process.", SEVERE );
abort;
endif;
if ( 0 == ShutDownProjectManager() ) goto end_install; // This statement is within the Program block and jumps to the
"end_install:" switch if the function fails. -WFS
endprogram
///////////////////////////////////////////////////////////////////////////////////
//
// Function: GetRunningApp
//
// Purpose: This function returns "1" if an app is running. Otherwise "0".
// If "1" is returned, the "appName" parameter will contain the name of the
// application running.
//
// Theron Welch 3/3/99
//
///////////////////////////////////////////////////////////////////////////////////
function GetRunningApp( appName )
HWND hWnd;
LONG ProcessIDs[ 512 ]; // An array that's hopefully big enough to hold all process IDs
LONG cbNeeded;
LONG cb;
LONG numItems;
LONG ProcessHandle;
LONG ModuleHandle;
LONG Count;
LONG Ret;
LONG Ret2;
POINTER pArray; // This pointer will point at the array of process IDs
STRING ModuleName[ 128 ];
STRING FileName[ 64 ];
POINTER pModuleName;
begin
UseDLL ( WINSYSDIR ^ "Psapi.dll" ); // Load the helper dll - PsApi.dll
cbNeeded = 96;
cb = 8;
pArray = &ProcessIDs; // Point at the array
while ( cb <= cbNeeded )
cb = cb * 2;
EnumProcesses ( pArray, cb, cbNeeded ); // Get the currently running process IDs
endwhile;
numItems = cbNeeded / 4; // Calculate number of process IDs - 4 is the size in bytes of a Process ID (DWORD)
for Count = 1 to numItems // For each process id
ProcessHandle = OpenProcess ( 2035711, 1, ProcessIDs[ Count ] ); // Get a handle to the process
if ( 0 != ProcessHandle ) then
Ret = EnumProcessModules ( ProcessHandle, ModuleHandle, 4, cb ); // Get the module handle - first one is EXE, the one I care about!
if ( 0 != Ret ) then
pModuleName = &ModuleName; // Point at the array
Ret = GetModuleFileNameExA ( ProcessHandle, ModuleHandle, pModuleName, 128 ); // Get the exe name
if ( 0 != Ret ) then
ParsePath ( FileName, ModuleName, FILENAME_ONLY ); // Convert the full path to a filename
//////////////////////////////Outlook/////////////////////////////////////////
// Copy the next 5 lines and customize for each app
Ret = StrCompare ( FileName, "Outlook" );
if ( 0 == Ret ) then // If there's a match
FileName = "Microsoft Outlook"; // Change to a name that makes sense
appName = FileName; // Copy the filename to the passed in parameter (by ref)
return 1; // Return "Found"
endif;
///////////////////////////////////////////////////////////////////////////////
//////////////////////////////Navwnt/////////////////////////////////////////
Ret = StrCompare ( FileName, "Navwnt" );
if ( 0 == Ret ) then // If there's a match
FileName = "Norton Anti-Virus"; // Change to a name that makes sense
appName = FileName; // Copy the filename to the passed in parameter (by ref)
return 1; // Return "Found"
endif;
///////////////////////////////////////////////////////////////////////////////
endif;
endif;
endif;
endfor;
return 0; // "Well, uh, apparently, no application is running"
end;
///////////////////////////////////////////////////////////////////////////////////
//
// Function: ShutDownApp
//
// Purpose: This function attempts to shut down the app you decide on. It returns
// "1" if successful or if app is not running.
// Otherwise "0" if it could not be shut down. Install should terminate
// if "0" is returned.
//
// Theron Welch 3/3/99
//
///////////////////////////////////////////////////////////////////////////////////
function ShutDownApp()
HWND hWnd;
LONG ProcessIDs[ 512 ]; // An array that's hopefully big enough to hold all process IDs
LONG cbNeeded;
LONG cb;
LONG numItems;
LONG ProcessHandle;
LONG ModuleHandle;
LONG Count;
LONG Ret;
LONG Ret2;
POINTER pArray; // This pointer will point at the array of process IDs
STRING ModuleName[ 128 ];
STRING FileName[ 64 ];
POINTER pModuleName;
begin
UseDLL ( WINSYSDIR ^ "Psapi.dll" ); // Load the helper dll - PsApi.dll
cbNeeded = 96;
cb = 8;
pArray = &ProcessIDs; // Point at the array
while ( cb <= cbNeeded )
cb = cb * 2;
EnumProcesses ( pArray, cb, cbNeeded ); // Get the currently running process IDs
endwhile;
numItems = cbNeeded / 4; // Calculate number of process IDs - 4 is the size in bytes of a Process ID (DWORD)
for Count = 1 to numItems // For each process id
ProcessHandle = OpenProcess ( 2035711, 1, ProcessIDs[ Count ] ); // Get a handle to the process
if ( 0 != ProcessHandle ) then
Ret = EnumProcessModules ( ProcessHandle, ModuleHandle, 4, cb ); // Get the module handle - first one is EXE, the one I care about!
if ( 0 != Ret ) then
pModuleName = &ModuleName; // Point at the array
Ret = GetModuleFileNameExA ( ProcessHandle, ModuleHandle, pModuleName, 128 ); // Get the exe name
if ( 0 != Ret ) then
ParsePath ( FileName, ModuleName, FILENAME ); // Convert the full path to a filename
// MessageBox( FileName, INFORMATION );
Ret = StrCompare ( FileName, "MYAPP~1.EXE" ); // Compare filenames (used for short file names. -WFS)
Ret2 = StrCompare ( FileName, "MYAPP.exe" ); // Compare filenames
if ( 0 == Ret || 0 == Ret2 ) then // If it's the filename I'm looking for
Ret = TerminateProcess( ProcessHandle, 0 ); // Terminate the process
if ( 0 == Ret ) then
goto Error;
endif;
goto Quit;
endif;
endif;
endif;
endif;
endfor;
Quit:
UnUseDLL ( "Psapi.dll" ); // Unload the helper dll - PsApi.dll
return 1; // Happy
Error:
UnUseDLL ( "Psapi.dll" ); // Unload the helper dll - PsApi.dll
return 0; // Sad
end;
/**********************************************************************************
/* GetRunningApp();
/* ShutDownApp();
/*
/* These script created functions will look for any running application based on
/* the file name, then display an error message within the Setup. You can optionally
/* halt the install or just continue on.
/*
/* You can use the ShutDownApp() function for shutting down that process or others
/* as well. This is useful for processes that run in the background but have no Windows
/* associated with them. May not work with Services.
/*
/* This script calls functions in PSAPI.DLL that are not supported on Windows 95 or 98.
/*
/* ***Instructions***
/* Place these script peices into the Setup.rul file.
/*
/* Modify the script to include the applications you would like to get or shutdown.
/*
/* Submitted by William F. Snodgrass
/* Contact info: bsnodgrass@geographix.com
/*
/* Created by Theron Welch, 3/3/99
/* Minor modifications by Stefan Krueger, 11/03/99
/*
/* Copyright (c) 1999-2000 GeoGraphix, Inc.
**********************************************************************************/
//////////////////// installation declarations ///////////////////
// ----- DLL function prototypes -----
// your DLL function prototypes
// Custom function for shutting down MyApp process
prototype ShutDownApp();
// Custom function for shutting down any running application
prototype GetRunningApp( BYREF STRING );
///////////////////////////////////////////////////////////////////////////////////
// Dll function calls needed
// Kernel functions
prototype LONG Kernel32.OpenProcess( LONG, BOOL, LONG ); // 1ST Param = 2035711 for PROCESS_ALL_ACCESS (It pays to know hex!!), 2nd = Doesn't matter, 3rd = Process ID
prototype BOOL Kernel32.TerminateProcess( LONG, INT ); // 1st Param = Process ID, 2nd = Doesn't matter - "0"
// Process info functions
prototype LONG Psapi.EnumProcesses( POINTER, LONG, BYREF LONG ); // 1st Param = By ref, Process ID, 2nd = number of bytes in param 1 = "4", 3rd = cb needed - might as well be "4"
prototype LONG Psapi.GetModuleFileNameExA( LONG, LONG, POINTER, LONG );// 1st Param = ProcessID, 2nd= Module ID, 3rd = pointer to a string, 4th = length of string
prototype LONG Psapi.EnumProcessModules( LONG, BYREF LONG, LONG, BYREF LONG ); // 1st Param = Process Handle, 2nd = Module Handle, 3rd = bytes passed ("4"), 4th = bytes needed ("4")
///////////////////////////////////////////////////////////////////////////////////
// your global variables
STRING svApp
program
if ( 1 == GetRunningApp ( svApp ) ) then
MessageBox ( "The installation has detected that " + svApp + " is running. " +
"Please close " + svApp + " then restart the installation process.", SEVERE );
abort;
endif;
if ( 0 == ShutDownProjectManager() ) goto end_install; // This statement is within the Program block and jumps to the
"end_install:" switch if the function fails. -WFS
endprogram
///////////////////////////////////////////////////////////////////////////////////
//
// Function: GetRunningApp
//
// Purpose: This function returns "1" if an app is running. Otherwise "0".
// If "1" is returned, the "appName" parameter will contain the name of the
// application running.
//
// Theron Welch 3/3/99
//
///////////////////////////////////////////////////////////////////////////////////
function GetRunningApp( appName )
HWND hWnd;
LONG ProcessIDs[ 512 ]; // An array that's hopefully big enough to hold all process IDs
LONG cbNeeded;
LONG cb;
LONG numItems;
LONG ProcessHandle;
LONG ModuleHandle;
LONG Count;
LONG Ret;
LONG Ret2;
POINTER pArray; // This pointer will point at the array of process IDs
STRING ModuleName[ 128 ];
STRING FileName[ 64 ];
POINTER pModuleName;
begin
UseDLL ( WINSYSDIR ^ "Psapi.dll" ); // Load the helper dll - PsApi.dll
cbNeeded = 96;
cb = 8;
pArray = &ProcessIDs; // Point at the array
while ( cb <= cbNeeded )
cb = cb * 2;
EnumProcesses ( pArray, cb, cbNeeded ); // Get the currently running process IDs
endwhile;
numItems = cbNeeded / 4; // Calculate number of process IDs - 4 is the size in bytes of a Process ID (DWORD)
for Count = 1 to numItems // For each process id
ProcessHandle = OpenProcess ( 2035711, 1, ProcessIDs[ Count ] ); // Get a handle to the process
if ( 0 != ProcessHandle ) then
Ret = EnumProcessModules ( ProcessHandle, ModuleHandle, 4, cb ); // Get the module handle - first one is EXE, the one I care about!
if ( 0 != Ret ) then
pModuleName = &ModuleName; // Point at the array
Ret = GetModuleFileNameExA ( ProcessHandle, ModuleHandle, pModuleName, 128 ); // Get the exe name
if ( 0 != Ret ) then
ParsePath ( FileName, ModuleName, FILENAME_ONLY ); // Convert the full path to a filename
//////////////////////////////Outlook/////////////////////////////////////////
// Copy the next 5 lines and customize for each app
Ret = StrCompare ( FileName, "Outlook" );
if ( 0 == Ret ) then // If there's a match
FileName = "Microsoft Outlook"; // Change to a name that makes sense
appName = FileName; // Copy the filename to the passed in parameter (by ref)
return 1; // Return "Found"
endif;
///////////////////////////////////////////////////////////////////////////////
//////////////////////////////Navwnt/////////////////////////////////////////
Ret = StrCompare ( FileName, "Navwnt" );
if ( 0 == Ret ) then // If there's a match
FileName = "Norton Anti-Virus"; // Change to a name that makes sense
appName = FileName; // Copy the filename to the passed in parameter (by ref)
return 1; // Return "Found"
endif;
///////////////////////////////////////////////////////////////////////////////
endif;
endif;
endif;
endfor;
return 0; // "Well, uh, apparently, no application is running"
end;
///////////////////////////////////////////////////////////////////////////////////
//
// Function: ShutDownApp
//
// Purpose: This function attempts to shut down the app you decide on. It returns
// "1" if successful or if app is not running.
// Otherwise "0" if it could not be shut down. Install should terminate
// if "0" is returned.
//
// Theron Welch 3/3/99
//
///////////////////////////////////////////////////////////////////////////////////
function ShutDownApp()
HWND hWnd;
LONG ProcessIDs[ 512 ]; // An array that's hopefully big enough to hold all process IDs
LONG cbNeeded;
LONG cb;
LONG numItems;
LONG ProcessHandle;
LONG ModuleHandle;
LONG Count;
LONG Ret;
LONG Ret2;
POINTER pArray; // This pointer will point at the array of process IDs
STRING ModuleName[ 128 ];
STRING FileName[ 64 ];
POINTER pModuleName;
begin
UseDLL ( WINSYSDIR ^ "Psapi.dll" ); // Load the helper dll - PsApi.dll
cbNeeded = 96;
cb = 8;
pArray = &ProcessIDs; // Point at the array
while ( cb <= cbNeeded )
cb = cb * 2;
EnumProcesses ( pArray, cb, cbNeeded ); // Get the currently running process IDs
endwhile;
numItems = cbNeeded / 4; // Calculate number of process IDs - 4 is the size in bytes of a Process ID (DWORD)
for Count = 1 to numItems // For each process id
ProcessHandle = OpenProcess ( 2035711, 1, ProcessIDs[ Count ] ); // Get a handle to the process
if ( 0 != ProcessHandle ) then
Ret = EnumProcessModules ( ProcessHandle, ModuleHandle, 4, cb ); // Get the module handle - first one is EXE, the one I care about!
if ( 0 != Ret ) then
pModuleName = &ModuleName; // Point at the array
Ret = GetModuleFileNameExA ( ProcessHandle, ModuleHandle, pModuleName, 128 ); // Get the exe name
if ( 0 != Ret ) then
ParsePath ( FileName, ModuleName, FILENAME ); // Convert the full path to a filename
// MessageBox( FileName, INFORMATION );
Ret = StrCompare ( FileName, "MYAPP~1.EXE" ); // Compare filenames (used for short file names. -WFS)
Ret2 = StrCompare ( FileName, "MYAPP.exe" ); // Compare filenames
if ( 0 == Ret || 0 == Ret2 ) then // If it's the filename I'm looking for
Ret = TerminateProcess( ProcessHandle, 0 ); // Terminate the process
if ( 0 == Ret ) then
goto Error;
endif;
goto Quit;
endif;
endif;
endif;
endif;
endfor;
Quit:
UnUseDLL ( "Psapi.dll" ); // Unload the helper dll - PsApi.dll
return 1; // Happy
Error:
UnUseDLL ( "Psapi.dll" ); // Unload the helper dll - PsApi.dll
return 0; // Sad
end;