I had a hard time deciding what to title this post since what I’m actually discussing here isn’t something that someone would likely be searching for. The real topic is “Issues When Using the Inventor API Out-of-Process”. The typical problems people run into because of out-of-process issues are when working with thumbnail or button images.
First, let’s define what it means to be running in-process versus out-of-process. For our purposes, a process is an executable that’s running. Inventor is an example of a process. A windows executable that you write is also an example of a process.
When Inventor is running there is an Inventor process. Add-ins, which are dll’s and not exe’s, are loaded within the Inventor process and are referred to as running in-process. VBA is only available from Microsoft as a 32-bit component, so with 32-bit Inventor VBA also runs in-process. This is illustrated in the picture below with both VBA and the Add-In running within Inventor’s process.
With 64-bit Inventor, VBA can’t be loaded since a 32-bit component can’t load within a 64-bit process. To still allow customers the use of VBA on 64-bit machines, Inventor runs a separate 32-bit process which hosts VBA. VBA then talks to Inventor through the API but is running out-of-process with respect to Inventor, as illustrated below.
So what does it matter if VBA is running in or out of Inventor’s process? There are a couple of things this affects. First, running out-of-process will be slower than in-process. There’s more overhead in passing data back and forth between processes. Second, is that bitmap data can’t be passed between two processes. Inventor uses the Microsoft IPictureDisp object to represent bitmap data and it doesn’t support being passed between processes.
The VBA programs below both get the thumbnail image from the active document. One uses the Document.Thumbnail property and the other uses the Thumbnail iProperty. Both of them will work in 32-bit Inventor since VBA runs in-process but they will fail for 64-bit Inventor. In the SaveThumbnail macro the failure happens when calling the Thumbnail property of the document because that is when the bitmap would be passed. For the iProperty example, the failure occurs when calling the Value property of the Property object. Any call that passes an IPictureDisp object won’t work when running out-of-process, including getting or setting icons for buttons.
Public Sub SaveThumbnail()
' Get the active document.
Dim doc As Document
Set doc = ThisApplication.ActiveDocument
' Get the thumbnail from the document.
Dim thumb As IPictureDisp
Set thumb = doc.Thumbnail
' Create the filename for the bmp file so it is the same
' as the document name but with a "bmp" extension.
Dim filename As String
filename = Left$(doc.FullFileName, Len(doc.FullFileName)-3)&"bmp"
' Save the thumbnail.
Call SavePicture(thumb, filename)
End Sub
Public Sub SaveThumbnailUsingiProperty()
' Get the active document.
Dim doc As Document
Set doc = ThisApplication.ActiveDocument
' Get the thumbnail from the document's iProperty.
Dim oPropSet As PropertySet
Set oPropSet = doc.PropertySets.Item( _
"Inventor Summary Information")
Dim thumb As IPictureDisp
Set thumb = oPropSet.Item("Thumbnail").Value
' Create the filename for the bmp file so it is the same
' as the document name but with a "bmp" extension.
Dim filename As String
filename = Left$(doc.FullFileName, Len(doc.FullFileName)-3)&"bmp"
' Save the thumbnail.
Call SavePicture(thumb, filename)
End Sub
Here are some other examples where you can encounter out-of-process issues. If you’ve written a windows application it will be a separate exe and will run as a separate process. It can still use the Inventor API, but it will be out-of-process and because of this will not be able to access any bitmaps through the API.
Another example is using another product’s VBA. For example, Excel is illustrated in the picture below. Excel is it’s own process and it’s version of VBA is running in-process to Excel. If Excel’s VBA is using Inventor’s API it will be accessing it out-of-process and will not have any access to bitmaps through the API.
Another way to access Inventor data is using Apprentice. Apprentice is a programming only component and doesn’t have a user-interface and can’t run on its own but will always run in-process to its host application, (which is what you write). In the example below, the primary application, Your.exe, has loaded Apprentice and Apprentice has opened a part document. When using the Apprentice API (which is a subset of the Inventor API) you can successfully get the thumbnail because Apprentice is running in-process to your application and the IPictureDisp can be passed.
If you’ve seen the program from a previous post that creates a parts list with thumbnail images you might think that it’s breaking some of these rules. It doesn’t, but these limitations did affect the choices I made as I arrived at the final design. In that program, the code is an Inventor Add-in that reads the part list data from Inventor. For each row in the parts list it accesses the associated document and gets the thumbnail. Since the add-in is running in-process to Inventor there’s no problem to read the thumbnail. As it processes each row and gets the thumbnail, it writes the thumbnail to disk. It then accesses Word through it’s API. This communication is out-of-process. Using Word’s API it has Word insert the thumbnail into the table. The Word API function to insert a bitmap into a table takes a filename as input. Word uses this to read the bitmap from disk and insert it into the table. The bitmap was never directly passed between Inventor and Word but went through the intermediate step of going to the disk. If the Word function to place the bitmap into a table had taken an iPictureDisp as input the program would not have worked and I would have had to come up with some other solution.