Testing if SysCAD is open in VBA (COM Automation)

From SysCAD Documentation
Jump to navigation Jump to search

Navigation: User Guide ➔ COM Automation ➔ Testing if SysCAD is Open in VBA

Command Scripts COM Automation Python Automation VBA Automation C++ Automation Testing if SysCAD is open

Generally a COM Automation macro is written to start SysCAD, load a project, perform some actions, close SysCAD. For this to work correctly and reliably, SysCAD should NOT be open when executing the Macro. Using "Set App = New ScdApplication" to try hook into an already open copy of SysCAD (especially if it has a project open or if more than one copy of SysCAD is open) is likely to lead to unpredictable results.

A few lines of code at the start of the Macro can test if SysCAD is already open. If it is open then give a message and exit the Macro. See VBA Automation example for an example of how this could be included. Code segment to test for open copies of SysCAD:

 Sub ProBalExample()
  If SysCADProcessesRunning <> 0 Then
    MsgBox "SysCAD is open!  Please close all copies of SysCAD (and/or SysCAD processes)."
    Exit Sub
  End If
  'do stuff... 
  '== Start SysCAD..
  Set App = New ScdApplication
 End Sub

The code for the function SysCADProcessesRunning is shown below. It is recommended that a separate Module is added to the VBA project and the code below pasted into this module.

VBA Code to check for Open SysCAD application or Process

Recommendation: Place this into a separate VBA Module so that the main VBA code isn't cluttered with this helper function.

 Option Explicit
 'Const TH32CS_INHERIT = &H80000000
 Const MAX_PATH As Integer = 260
 Private Type PROCESSENTRY32
  dwSize As Long
  cntUsage As Long
  th32ProcessID As Long
  th32DefaultHeapID As Long
  th32ModuleID As Long
  cntThreads As Long
  th32ParentProcessID As Long
  pcPriClassBase As Long
  dwFlags As Long
  szExeFile As String * MAX_PATH
 End Type
 Private Declare Function CreateToolhelp32Snapshot Lib "kernel32" (ByVal lFlags As Long, ByVal lProcessID As Long) As Long
 Private Declare Sub CloseHandle Lib "kernel32" (ByVal hPass As Long)
 ' API Functions to get the processes
 Private Declare Function Process32First Lib "kernel32" (ByVal hSnapShot As Long, uProcess As PROCESSENTRY32) As Long
 Private Declare Function Process32Next Lib "kernel32" (ByVal hSnapShot As Long, uProcess As PROCESSENTRY32) As Long
 Function ProcessesRunning(SearchName As String)
  Dim hSnapShot As Long '* Handle
  Dim uProcess As PROCESSENTRY32 '* Process
  Dim lRet '* Return Val
  Dim processName As String
  'On Error Resume Next
  'Takes a snapshot of the running processes and the heaps, modules, and threads used by the processes
  hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0&)
  uProcess.dwSize = Len(uProcess)
  ProcessesRunning = 0
  'Retrieve information about the first process encountered in our system Snapshot
  lRet = Process32First(hSnapShot, uProcess)
  Do While lRet
    lRet = Process32Next(hSnapShot, uProcess)
    ' Trim the unwanted characters at the end of process
    processName = Left$(uProcess.szExeFile, IIf(InStr(1, uProcess.szExeFile, Chr$(0)) > 0, InStr(1, uProcess.szExeFile, Chr$(0)) - 1, 0))
    If InStr(processName, SearchName) Then
      ProcessesRunning = ProcessesRunning + 1
    End If
  CloseHandle hSnapShot
 End Function
 Function SysCADProcessesRunning()
  SysCADProcessesRunning = ProcessesRunning("SysCAD93.exe")
 End Function

Python Version

In python, use the psutil module. http://code.google.com/p/psutil/

 from psutil import *
 def SysCADProcessesRunning():
  ''' list of PID numbers associated with SysCAD processes'''
   return [i for i in get_pid_list() if Process(i).name=="SysCAD93.exe"]

To kill a load of zombies:

 def killSysCADZombies():
   for iPID in SysCADProcessesRunning(): terminate(iPID)

There are a lot of other useful functions in this module for querying CPU usage, thread usage, memory etc.