Thursday, April 5, 2012

InstallShield : Check running process or get process list (InstallScript)

InstallShield does not provide any native function for checking processes, which led users to use Win32 API or WMI provider if they want to check a process or get process list. I found a 'List and Shut Down Running Applications' code in http://www.installsite.org but the code was not working in Windows 7 64bit machine. I didn't want to spend too much time on it, so moved on and tried WMI approach which worked for me.

Check to see if specific process is running.
IsAppRunning() function checks to see if a specified process is currently running on the machine. Basically the code finds a process in Win32_Process WMI class.

function BOOL IsAppRunning(appName)      
 OBJECT wmi, procs;      
begin         
  try
    set wmi = CoGetObject( "winmgmts://./root/cimv2", "" ); 
    if ( !IsObject(wmi) ) then   
        return FALSE;
    endif;
    set procs = wmi.ExecQuery ("Select * from Win32_Process Where Name = '" + appName + "'" ); 
    if (!IsObject(procs)) then    
 return FALSE;
    endif;          
                
    if (procs.Count > 0) then
       return TRUE;
    endif;
  catch  
  endcatch;
  return FALSE;
end;

Get running processes
Another similar code is about getting all processes currently running on the machine. This task also can be done by referring to Win32_Process class but it requires to enumerate all data from the result. This looping task is tricky and cannot be done by simply using for loop. Again, http://www.installsite.org site provides 'Get Object and ForEach in InstallScript' code and it worked great for me.

(1)Download GetObject.zip from installsite.org

(2)Unzip it and copy IsGetObj.dll to InstallShield (2010/mine) - Behavior and Login - Support Files / Billboards - Language Independent. This will copy the DLL file to SUPPORTDIR directory which is only available during installation. SUPPORTDIR is temp folder typically created under current user folder.

(3) Add prototype at the top of the script
   prototype ISGetObj.ForEachStart(byref OBJECT, byref VARIANT);
   prototype ISGetObj.ForEachGetNextItem(byref VARIANT, byref OBJECT);
(4) Use ForEachStart and ForEachGetNextItem function to iterate item from WMI query resultset.

function STRING GetProcesses()      
  OBJECT wmi, procs, procItem;      
  VARIANT __varEnumHolder;  
  STRING procList;
begin         
  try
   set wmi = CoGetObject( "winmgmts://./root/cimv2", "" ); 
   if ( !IsObject(wmi) ) then   
      return "";
   endif;
   set procs = wmi.ExecQuery("Select * from Win32_Process"); 
   if (!IsObject(procs)) then    
      return "";
   endif;          
                
   UseDLL(SUPPORTDIR ^ "IsGetObj.dll");   
   ForEachStart(procs, __varEnumHolder);    
   while(0 == ForEachGetNextItem(__varEnumHolder, procItem))  
     procList = procList + "\n" + procItem.Name;
   endwhile;       
   
   set __varEnumHolder = NOTHING;
   UnUseDLL("IsGetObj.dll");
  catch  
  endcatch;
  return procList;
end;   

The example above returns all running process names separated by CR.

3 comments: