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

 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.