Solved

Set reference to an open application

Posted on 2001-06-07
13
230 Views
Last Modified: 2008-01-09
I want to determine if a Microsoft application (Excel, Access, Word, etc.) is curently running and set a reference to it. I then need to check all parent windows to see if a child window is a specific file name.

I have tried GetObject and AppActivate, but GetObject just creates a new instance of the application even if one is open. AppActivate does not seem to see the application, perhaps because its window is minimized.

I can use API functions like GetWindow and determine is the applicationis running, and I can use other functions to enumerate windows, child windows, return handles to windows, etc. However, I cannot get VB to set a reference to it.

The Shell function seems to mess up Excel, as I get the Application Title bar but the user window is as previous and I cannot use the Excel menu.

Does anyone have any ideas?
0
Comment
Question by:Renee1031599
  • 4
  • 4
  • 3
  • +2
13 Comments
 
LVL 1

Expert Comment

by:rmariman
ID: 6165684
I don't know what you want to do with the application-reference, but this listing gives you an overview of the running processes (filenames) together with the Process ID (PID). This can be used to end a process (see EndProcess):

Declare Function TerminateProcess Lib "kernel32" (ByVal hProcess As Long, ByVal uExitCode As Long) As Long
Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Declare Function GetCurrentProcess Lib "kernel32" () As Long
Declare Function GetCurrentProcessId Lib "kernel32" () As Long
Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Declare Function Process32First Lib "kernel32" (ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long
Declare Function Process32Next Lib "kernel32" (ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long
Declare Function CloseHandle Lib "Kernel32.dll" (ByVal Handle As Long) As Long
Declare Function EnumProcesses Lib "psapi.dll" (ByRef lpidProcess As Long, ByVal cb As Long, ByRef cbNeeded As Long) As Long
Declare Function GetModuleFileNameExA Lib "psapi.dll" (ByVal hProcess As Long, ByVal hModule As Long, ByVal ModuleName As String, ByVal nSize As Long) As Long
Declare Function EnumProcessModules Lib "psapi.dll" (ByVal hProcess As Long, ByRef lphModule As Long, ByVal cb As Long, ByRef cbNeeded As Long) As Long
Declare Function CreateToolhelp32Snapshot Lib "kernel32" (ByVal dwFlags As Long, ByVal th32ProcessID As Long) As Long
Declare Function GetVersionExA Lib "kernel32" (lpVersionInformation As OSVERSIONINFO) As Integer

Public Type PROCESSENTRY32
   dwSize As Long
   cntUsage As Long
   th32ProcessID As Long           ' This process
   th32DefaultHeapID As Long
   th32ModuleID As Long            ' Associated exe
   cntThreads As Long
   th32ParentProcessID As Long     ' This process's parent process
   pcPriClassBase As Long          ' Base priority of process threads
   dwFlags As Long
   szExeFile As String * 260       ' MAX_PATH
End Type

Public Type OSVERSIONINFO
   dwOSVersionInfoSize As Long
   dwMajorVersion As Long
   dwMinorVersion As Long
   dwBuildNumber As Long
   dwPlatformId As Long           '1 = Windows 95.
                                  '2 = Windows NT

   szCSDVersion As String * 128
End Type

Public Const PROCESS_QUERY_INFORMATION = 1024
Public Const PROCESS_VM_READ = 16
Public Const MAX_PATH = 260
Public Const STANDARD_RIGHTS_REQUIRED = &HF0000
Public Const SYNCHRONIZE = &H100000
'STANDARD_RIGHTS_REQUIRED Or SYNCHRONIZE Or &HFFF
Public Const PROCESS_ALL_ACCESS = &H1F0FFF
Public Const TH32CS_SNAPPROCESS = &H2&
Public Const hNull = 0

Function StrZToStr(s As String) As String
   StrZToStr = Left$(s, Len(s) - 1)
End Function

Public Function getVersion() As Long
   Dim osinfo As OSVERSIONINFO
   Dim retvalue As Integer
   osinfo.dwOSVersionInfoSize = 148
   osinfo.szCSDVersion = Space$(128)
   retvalue = GetVersionExA(osinfo)
   getVersion = osinfo.dwPlatformId
End Function

Sub ListPID()
Select Case getVersion()

Case 1 'Windows 95/98

   Dim f As Long, sname As String
   Dim hSnap As Long, proc As PROCESSENTRY32
   hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
   If hSnap = hNull Then Exit Sub
   proc.dwSize = Len(proc)
   ' Iterate through the processes
   f = Process32First(hSnap, proc)
   Do While f
     sname = StrZToStr(proc.szExeFile)
     Debug.Print sname
     f = Process32Next(hSnap, proc)
   Loop

Case 2 'Windows NT

   Dim cb As Long
   Dim cbNeeded As Long
   Dim NumElements As Long
   Dim ProcessIDs() As Long
   Dim cbNeeded2 As Long
   Dim NumElements2 As Long
   Dim Modules(1 To 200) As Long
   Dim lRet As Long
   Dim ModuleName As String
   Dim nSize As Long
   Dim hProcess As Long
   Dim i As Long
   'Get the array containing the process id's for each process object
   cb = 8
   cbNeeded = 96
   Do While cb <= cbNeeded
      cb = cb * 2
      ReDim ProcessIDs(cb / 4) As Long
      lRet = EnumProcesses(ProcessIDs(1), cb, cbNeeded)
   Loop
   NumElements = cbNeeded / 4

   For i = 1 To NumElements
      'Get a handle to the Process
      hProcess = OpenProcess(PROCESS_QUERY_INFORMATION _
         Or PROCESS_VM_READ, 0, ProcessIDs(i))
      'Got a Process handle
      If hProcess <> 0 Then
          'Get an array of the module handles for the specified
          'process
          lRet = EnumProcessModules(hProcess, Modules(1), 200, _
                                       cbNeeded2)
          'If the Module Array is retrieved, Get the ModuleFileName
          If lRet <> 0 Then
             ModuleName = Space(MAX_PATH)
             nSize = 500
             lRet = GetModuleFileNameExA(hProcess, Modules(1), _
                             ModuleName, nSize)
             Debug.Print Left(ModuleName, lRet) & ": " & ProcessIDs(i)
          End If
      End If
    'Close the handle to the process
   lRet = CloseHandle(hProcess)
   Next

End Select
End Sub

Sub EndImmediate(PID)
Call TerminateProcess(OpenProcess(PROCESS_ALL_ACCESS, True, iif(PID=null,GetCurrentProcessId,PID)), 0)
End Sub
0
 
LVL 43

Expert Comment

by:TimCottee
ID: 6166902
GetObject should work for you:

Public Function IsAppActive(ByVal Class As String,ByRef objApplication As Object) As Boolean
  On Error Resume Next
  Set objApplication = GetObject(,Class)
  IsAppActive = Not (objApplication Is Nothing)
End Function

Call it using something like this:

Dim appWord As Word.Application
Dim blnWordActive As Boolean
blnWordActive = IsAppActive("Word.Application",appWord)
MsgBox "Word Session " & iif(blnWordActive,"Is Active","Is Not Active",vbInformation
If blnWordActive Then
  'Do something with the object
End If

Dim appExcel As Excel.Application
Dim blnExcelActive As Boolean
blnExcelActive = IsAppActive("Excel.Application",appExcel)
MsgBox "Excel Session " & iif(blnExcelActive,"Is Active","Is Not Active",vbInformation
If blnExcelActive Then
  'Do something with the object
End If
0
 
LVL 43

Expert Comment

by:TimCottee
ID: 6166925
You could extend the functionality to create the session if it doesn't exist:

Public Function IsAppActive(ByVal Class As String,ByRef objApplication As Object,Optional ByVal CreateSession As Boolean = True) As Boolean
 On Error Resume Next
 Set objApplication = GetObject(,Class)
 If CreateSession And objApplication Is Nothing Then
   Set objApplication = CreateObject(Class)
 End If
 IsAppActive = Not (objApplication Is Nothing)
End Function

This will default to creating the object if it does not already exist, you could change the default to false if you wanted.
0
 
LVL 16

Accepted Solution

by:
Richie_Simonetti earned 150 total points
ID: 6168794
something like this?

Private Sub Form_Click()
Dim xl As Excel.Application

Set xl = GetObject(, "excel.application")

Dim wb As Excel.Workbook, sname As String

For Each wb In xl.Workbooks
    sname = sname & wb.FullName & vbCrLf
Next
MsgBox sname
Set xl = Nothing
End Sub
0
 
LVL 1

Expert Comment

by:inethog
ID: 6880807
Here's a little snippet of code that I use to detect if a previous instance of Excel is running.

If it's running, then I "take it over".

If it's not running, then I create a new one.


As a general rule, if your program creates an instance of Excel, then it should also close it.

This function returns: True - If Excel is running,

           :False if Excel is not running.


Hope this helps,

Drop me a line if you need more help.

D.

inethog@hotmail.com




Private Function ISExcelRunning() As Boolean

    'Determine if Excel is presently running or not
    Dim xlExcel As Excel.Application
   
    On Error Resume Next
   
    Set AppExcel = GetObject(, "Excel.Application")
   
    ISExcelRunning = (Err.Number = 0)
   
    Set AppExcel = Nothing
   
    Err.Clear
   
End Function
0
 
LVL 16

Expert Comment

by:Richie_Simonetti
ID: 6880873
Strange, all people is posting the same approach with GetObject but i am sure that i was the first in comment it, so, how is possible that Tim's comment goes before mine!!!
i'm going crazy!
0
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 
LVL 43

Expert Comment

by:TimCottee
ID: 6882050
inethog, you are obviously new to this site so may not be aware of the guidelines. Please read the guidelines on comments vs answers at the bottom of this page. You are also posting to an "Abandoned" question. This appears to be an attempt to gain points by proposing an answer which has already been suggested in comments. I am referring this question to community support and will recommend that Richie's answer is accepted as he was the first (though my comment does seem to be first on the page!) Don't understand that either. If you continue to post answers in this way your account is liable to suspension.
0
 
LVL 43

Expert Comment

by:TimCottee
ID: 6882052
0
 
LVL 1

Expert Comment

by:Moondancer
ID: 6882518
inethog-->  Welcome to Experts Exchange. As TimCottee noted above,  it is against guidelines to lock questions with proposed answers unless your response is the first and only correct answer to the question at hand.  Furthermore, it creates a disservice to the Asker to have their questions locked rather than to receive comments and insights, since it moved the item from the Open Question queue to the Locked queue, where few will step in to help further.  Asker can always choose to award the first best comment as the accepted answer.  Please read the information contained in the HELP DESK link on the left, which provides you with Member Agreement, site Guidelines and the Question/Answer process.

I have force accepted the response from Richie_Simonetti and moved this item with points to the PAQ (Previously Asked Question) database.

TimCottee, if the right thing to do here is to also award your contributions with a separate points-for Q, please let me know.

Thanks all,
Moondancer - EE Moderator
0
 
LVL 16

Expert Comment

by:Richie_Simonetti
ID: 6882594
I agree with you Moondancer.
I could post a points for... in this TA for TimCottee since, really, i don't understand what did happens here with dates. Maybe in the migration proccess... who knows?
many thanks to both of you.
Cheers
0
 
LVL 1

Expert Comment

by:Moondancer
ID: 6882688
No, Richie, your points shouldn't be used for this purpose.  Since this was a 300 pt Q, max allowed, what I can do is to take this down to half, and post the other half for Tim.  Would that sound right to all?

Thanks,
Moondancer - EE Moderator
0
 
LVL 1

Expert Comment

by:Moondancer
ID: 6882729
Assuming this will be OK by you both, have done this, since I have a meeting to attend and will be offline for a few hours.

Points for TimCottee - > qid=20279314

Point splits processed, this item adjusted to 150 points, the other 150 in link above.

Thank you,
Moondancer - EE Moderator
0
 
LVL 16

Expert Comment

by:Richie_Simonetti
ID: 6882743
Good to me.
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

If you have ever used Microsoft Word then you know that it has a good spell checker and it may have occurred to you that the ability to check spelling might be a nice piece of functionality to add to certain applications of yours. Well the code that…
Article by: Martin
Here are a few simple, working, games that you can use as-is or as the basis for your own games. Tic-Tac-Toe This is one of the simplest of all games.   The game allows for a choice of who goes first and keeps track of the number of wins for…
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…

706 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now