Link to home
Start Free TrialLog in
Avatar of AndyAinscow
AndyAinscowFlag for Switzerland

asked on

Process handle from a CreateObject in VBA

Using the following line of VBA code
Set objPwrPnt = CreateObject("Powerpoint.application")

Open in new window

How do I determine the HANDLE of the newly created process (objPwrPnt) ?

I require a HANDLE for some calls into the windows API.
Avatar of aikimark
aikimark
Flag of United States of America image

Do you need an hwnd value or something else?
Have you tried using 0 for the handle?

In what VBA run-time environment are you doing this?
Avatar of AndyAinscow

ASKER

Ideally a HWND, but the HANDLE of the process ID attached to the object I should be able to convert into a HWND of the main app window of that process.

In the above example I want to get the HWND of the main powerpoint window.  The VBA is an Access 2013 environment.


ps.  I can use FindWindow and so on with the window caption but that seems rather a long way round.
Try this:
objPwrPnt.hwnd

Open in new window

I can use FindWindow and so on with the window caption but that seems rather a long way round.
Myself, I don't know any other way around it.  Unless...
You DON'T use VBA to do the CreateObject.
If you have the facility to write something more WinAPIish-C++ish-C#ish to create PowerPoint so that you have it's handle immediately, and then GetObject in VBA to pick up the existing object.

But maybe its not so long a ways around.
Have a look here
http://www.vb-helper.com/howto_shell_get_hwnd.html

But the caveat seems to be that it no linger plays nicely in A2002+
Poking at aikimark's suggestion, Access has the hWndAccessApp method for returning the hwnd of the main window.
One wonders if PowerPoint has something similar?

But I think ShellExecute will be your winner
http://www.suodenjoki.dk/us/productions/articles/vbashellexecute.htm
Thanks for the responses.

I have no problem creating the powerpoint object in VBA.

I **need** that object because of the automation code being run on that object in the ensuing VBA code.  Code that has been running for years with stability, now on changing to new PC's with new versions of office and newer operating system  the code works on my development PC but fails intermittently in the real life situation.  I want to get at the newly running instance and use some windows API calls to check some things.

Unfortunately there does not seem to be a process instance handle or HWND of the app made available - at least I haven't found it yet.  (Unlike numbers of examples on the internet using an internetexplorer object, which does expose a hwnd member, for doing what I wanted.  Or as already mentioned the hWndAccessApp exposed in Access.)

Using the window caption and class name of the powerpoint app I have been able to get what I wanted, but it still could theoretically not get the correct instance as well as being like using a sledgehammer to crack a nut.  It surprises me such information is not exposed simply in the object I use for the automation.
The return value of ShellExecute is the hwnd.
My apologies.  I had done a quick test with Excel and the automation object had an hwnd property.  I assumed that all the Office automation objects would share a common set of properties.
I tested before asking the question:
User generated image
>>I assumed that all the Office automation objects would share a common set of properties.
To much to hope for, it has only been around, what 20 years or so.
I've requested that this question be deleted for the following reason:

Looks like there isn't a simple way for powerpoint after all.
Microsoft recommends using the FindWindow API using the window class for powerpoint:
Example:
' PP12FrameClass for PowerPoint 2007
' PP11FrameClass for PowerPoint 2003

reference: http://support.microsoft.com/kb/258511

===========
Alternatively, I would anticipate that you could use WMI to get the process.  This would be an alternative to the API, probably even wrapping the API under the covers.
~40 lines of code, total
Sample attached.
Check if ppt is open, bail if it is
API code to open ppt and return the hwnd
GetObject to automate it within VBA
Very odd things would have to occur to screw this up.

16 lines of WinAPI code
Alter as required
FirePPT.mdb
I must agree with Nick.  There are ways to get the handle, but not directly from the Powerpoint automation object.
How do I determine the HANDLE of the newly created process (objPwrPnt)
I think my sample has that licked.
But I'll definitely agrees with
It surprises me such information is not exposed simply in the object I use for the automation.
>>I assumed that all the Office automation objects would share a common set of properties.
Too much to hope for, it has only been around, what 20 years or so.


MS hasn't really done much with the VBA-powered platforms since O2003
They've been busy chasing their SharePoint/Azure/Cloud tails.
The numbers trumpeted for O365 sound soooooooooooooooo impressive
Until you realize there's a billion Windows machines in the world.
And then you know it's the dead cat bounce.

Hopefully they wake up and start working on the platform that matters, instead of the niche products that most of us could care less about.
>>I think my sample has that licked.

I'd disagree.  I've had a quick look.  It doesn't take an existing powerpoint object and find the handle or hwnd of that.  It bails out if powerpoint is already running.  I'm not going to discuss anything with the hard coded paths.  It looks to actually open powerpoint twice but I might have not got the logic down correctly.  I'm not too certain of the reliability of the GetForegroundWindow call actually grabbing powerpoint.

As I mentioned rather earlier I can get at the hwnd of an existing powerpoint object with a high degree of certainty, just rather a long winded way.

I had hoped there would be a function that I didn't know that would take an object and return information about it such as the handle or hwnd.
eg.  hwnd = ObjectInfo(objPwrPnt, OI_HWND) or processID = ObjectInfo(objPwrPnt, OI_PID)
:)
Now don't go moving the goalposts!  You posted code that created a PPT instance.  I went you one better and posted code that ensures ONLY a newly created PPT would be running and returned the Hwnd of that instance.  That was the Q.  Now, hunting down the Hwnd of a particular instance of multiple PPT's, that's harder to do.

As for the path, ShellExecute will happily take an ppt or pps file path as an argument.  Create a string path to it and you are in business.  One assumes that you have a presentation to manipulate.

It looks to actually open powerpoint twice but I might have not got the logic down correctly.  Since you asked for a new instance, it calls GetObject to see if there's a PPT in existence, first.  If that succeeds, the sub exits and bails.  If that fails, it'll return null and set the Boolean to false.  The code then creates the PPT and calls GetObject to return an object for your use in VBA The very next thing that goes on is the ForeGroundWindow call  Something odd would have to occur that interposed between the call to open PPT and the call to determine the window that some other window would become the foreground object.  It's not impossible, but highly unlikely.
And please don't delete this question.
Learning about ShellExecute and the fact that it'll take a filepath was incredibly useful.
I wish I had known the implications of that a long time ago.
It strikes me as convenient to open a file and then get the automation object, rather than firing up the automation object and then opening the file.

Firing up a Word document for example
  Dim oApp As Object
   Set oApp = CreateObject(Class:="Word.Application")
   oApp.Visible = True
   'Open the Document
    oApp.Documents.Open SomeValidPath


Have ShellExecute on the go, though and
Call ShellExecute(0, "open", SomeValidPath, "", "", 3)
will get it done

There's something to be said for that.
ASKER CERTIFIED SOLUTION
Avatar of AndyAinscow
AndyAinscow
Flag of Switzerland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Maybe what you wrote and what you had in mind had some discordance

Using the following line of VBA code
Set objPwrPnt = CreateObject("Powerpoint.application")                                
 How do I determine the HANDLE of the newly created process (objPwrPnt) ?


Perhaps you meant that as 'I am going to create a PowerPoint automation object, and I'd like to get the Hwnd of that object at some point afterwards.'

I ran with 'newly created'
I read it as 'I want to create a PowerPoint automation object and immediately know its Hwnd for use with WinAPI code'

'Newly created' is fairly simple and I've demo'd that.
 'some point afterwards' is not simple at all -- and if multiple applications of a class are running, its basically impossible to tell which Hwnd corresponds to the automation object.

And that isn't telling you anything you didn't already know.

It was an interesting question.
Sorry that what I've given you isn't what you wanted.

Nick67
Ah, now I see where your goalposts came from.

Any apologies ought to be from Microsoft - the Windows API uses HANDLEs and HWNDs but they don't provide an easy way to obtain them from an automation object.  


>>and if multiple applications of a class are running, its basically impossible to tell which Hwnd corresponds to the automation object.
Using the caption and class one an have a pretty good stab at it - not absolutely certain but very likely to be a match.
Using the caption and class one an have a pretty good stab at it - not absolutely certain but very likely to be a match.
:D

I set the bar pretty high when it comes to that.  There's possible (99% certainty that it'll work correctly) and impossible.
Users will forgive a 1 in 100 error rate.  Start going lower than that and they start getting grumpy.

Now, I haven't been happy with MS's neglect of the VBA platform for quite some time already, but in their defense:  How often is anybody using automation and WinAPI with Word and PowerPoint?  It has probably never been a high priority.
In terms of 'where is all the VBA code' its
Access --> Excel --> Outlook --> Word --> PowerPoint.
What's available in Access is pretty close to the full enchilada available in VB6.
It starts going downhill from there.

What really upsets me is that while Access and VB6 were closely related, absolutely NOTHING substantive has been done to bring the .Net platforms and VBA closer together.
There is neglect and there is lack of consistency.
Some office apps do this and others not.  I've asked another question recently and the same object exposes different methods depending on which office app it is embedded in - wow!
To keep this thread available for future users.