Sie sind auf Seite 1von 9

Access a specific Inventor.

Application object - Manufacturing DevBlog

http://adndevblog.typepad.com/manufacturing/2016/06/access-a-specif...

Manufacturing DevBlog
(http://adndevblog.typepad.com
/manufacturing/)
The resource for software developers working with Design, Lifecycle and Simulation
technologies from Autodesk.

06/23/2016

Access a specific Inventor.Application


object
By Adam Nagy (http://adndevblog.typepad.com/manufacturing
/adam-nagy.html)
When running multiple instances of Inventor (or AutoCAD,
Microsoft Excel, etc) then even though the ROT (Running Objects
Table) lists all the running instances, they will all return the same
Inventor.Application object that is returned by
GetActiveObject as well - i.e. the first Inventor instance. See
comments of this blog post:
http://adndevblog.typepad.com/autocad/2013/12/accessingcom-applications-from-the-running-object-table.html
(http://adndevblog.typepad.com/autocad/2013/12/accessingcom-applications-from-the-running-object-table.html)
The ROT also returns the currently open documents
(Inventor.Document object) and those have the correct COM
reference. So from those you can find the various
Inventor.Application objects. Of course this only works for the
Inventor instances which have documents open in them - and those
documents need to be unique. E.g. if in Inventor instance #2 I
open "mypart.ipt" then I also open the same file in Inventor
instance #3 then that document will only have a single reference in
the ROT and that will reference Inventor instance #2. I won't be
able to access Inventor instance #3.
If you are trying to access the Inventor instance that you create
through CreateProcess then one workaround is to create a copy of a
template document with a unique name and open that in Inventor.
using System;
using System.Diagnostics;

1 de 9

20/01/2017 23:18

Access a specific Inventor.Application object - Manufacturing DevBlog

2 de 9

http://adndevblog.typepad.com/manufacturing/2016/06/access-a-specif...

using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
namespace InventorConsoleAppCSharp
{
class Program
{
[DllImport("ole32.dll")]
static extern int CreateBindCtx(
uint reserved,
out IBindCtx ppbc);
[DllImport("ole32.dll")]
public static extern void GetRunningObjectTable(
int reserved,
out IRunningObjectTable prot);
// Requires Using System.Runtime.InteropServices.ComTypes
// Get all running instance by querying ROT
private static object GetInventorApplicationWithWindowHandle(
{
// get Running Object Table ...
IRunningObjectTable Rot = null;
GetRunningObjectTable(0, out Rot);
if (Rot == null)
return null;
// get enumerator for ROT entries
IEnumMoniker monikerEnumerator = null;
Rot.EnumRunning(out monikerEnumerator);
if (monikerEnumerator == null)
return null;
monikerEnumerator.Reset();
IntPtr pNumFetched = new IntPtr();
IMoniker[] monikers = new IMoniker[1];
// go through all entries and identifies app instances
while (monikerEnumerator.Next(1, monikers, pNumFetched) == 0)
{
IBindCtx bindCtx;
CreateBindCtx(0, out bindCtx);
if (bindCtx == null)
continue;
string displayName;
monikers[0].GetDisplayName(bindCtx, null, out displayName);

20/01/2017 23:18

Access a specific Inventor.Application object - Manufacturing DevBlog

3 de 9

http://adndevblog.typepad.com/manufacturing/2016/06/access-a-specif...

System.Console.WriteLine(displayName);
object ComObject;
Rot.GetObject(monikers[0], out ComObject);
if (ComObject == null)
continue;
try
{
dynamic invDoc = ComObject;
if (new IntPtr(invDoc.Parent.MainFrameHWND) == hwnd)
{
// The parent of the document is the Application
return invDoc.Parent;
}
}
catch { }
}
return null;
}
static void Main(string[] args)
{
// Create document with unique name
string fileName = "C:\\temp\\" + Guid.NewGuid().ToString() +
System.IO.File.Copy(
"C:\\temp\\Gusset2013.ipt",
fileName);
// Start Inventor
Process process = Process.Start(
@"C:\Program Files\Autodesk\Inventor 2016\Bin\Inventor.exe"
"\"" + fileName + "\"");
// Wait until Inventor is fully ready
process.WaitForInputIdle();
while (process.MainWindowTitle == "")
{
process.Refresh();
System.Threading.Thread.Sleep(1000);
}
// Get all the Inventor.Application objects
// registered in the ROT
// ROT = Running Objects Table
Inventor.Application app = null;
for (; app == null; System.Threading.Thread.Sleep(1000))
{

20/01/2017 23:18

Access a specific Inventor.Application object - Manufacturing DevBlog

http://adndevblog.typepad.com/manufacturing/2016/06/access-a-specif...

// Find the Inventor.Application object with


// the correct window handle
app = GetInventorApplicationWithWindowHandle(process.MainWindowHandle)
as Inventor.Application;
}
Console.WriteLine("Found Inventor.Application object with title:\n"
// Let's close file and delete it
app.Documents.get_ItemByName(fileName).Close();
System.IO.File.Delete(fileName);
// Wait for user to finish
Console.WriteLine("Press key to exit");
Console.ReadKey();
}
}
}

Posted at 09:43 AM in Adam Nagy (http://adndevblog.typepad.com/manufacturing


/adam-nagy/), Inventor (http://adndevblog.typepad.com/manufacturing
/inventor/) | Permalink (http://adndevblog.typepad.com/manufacturing/2016/06
/access-a-specific-inventorapplication-object.html)
(http://twitter.com/share?url=http%3A%2F
%2Fadndevblog.typepad.com%2Fmanufacturing%2F2016%2F06%2Faccessa-specific-inventorapplication-object.html&
text=Access%20a%20specific%20Inventor.Applicat...)
(https://plus.google.com/share?url=http://adndevblog.typepad.com
/manufacturing/2016/06/access-a-specific-inventorapplication-object.html)
(http://www.facebook.com/sharer.php?u=http%3A%2F
%2Fadndevblog.typepad.com%2Fmanufacturing%2F2016%2F06%2Faccessa-specific-inventorapplication-object.html)

Comments
Jamie Johnson said...

I'm having an issue with the 'dynamic' in line


dynamic invDoc = ComObject;
VisualStudio is reporting it as system.dynamic which is a namespace not an object
type.
Reply
07/01/2016 at 08:19 AM (http://adndevblog.typepad.com/manufacturing/2016/06
/access-a-specific-inventorapplication-object.html#comment6a0167607c2431970b01bb09198597970d)

4 de 9

20/01/2017 23:18

Access a specific Inventor.Application object - Manufacturing DevBlog

http://adndevblog.typepad.com/manufacturing/2016/06/access-a-specif...

Jamie Johnson said...

Turns out you were closer to the complete solution than you thought, check this bit
of VB code out, that I wrote while analyzing your code:
Private Function GetInventorApplicationWithWindowHandle(hwnd As IntPtr) As
Object
Dim Rot As IRunningObjectTable = Nothing
GetRunningObjectTable(0, Rot)
If Rot IsNot Nothing Then
Dim monikerEnumerator As IEnumMoniker = Nothing
Rot.EnumRunning(monikerEnumerator)
If monikerEnumerator IsNot Nothing Then
monikerEnumerator.Reset()
Dim pNumFetched As New IntPtr()
Dim monikers As IMoniker() = New IMoniker(0) {}
While monikerEnumerator.Next(1, monikers, pNumFetched) = 0
Dim bindCtx As IBindCtx = Nothing
CreateBindCtx(0, bindCtx)
If bindCtx IsNot Nothing Then
Dim displayName As String = String.Empty
monikers(0).GetDisplayName(bindCtx, Nothing, displayName)
'Dim guid As New Guid("{B6B5DC40-96E3-11d2-B774-0060B0F159EF}")
If displayName = "!{B6B5DC40-96E3-11D2-B774-0060B0F159EF}" Then
Dim ComObject As Object = Nothing
Rot.GetObject(monikers(0), ComObject)
If ComObject IsNot Nothing Then
Try
Dim invApplication As Inventor.Application = TryCast(ComObject,
Inventor.Application)
If invApplication IsNot Nothing Then Return invApplication
Catch ex As Exception
Debug.Print(ex.ToString)
End Try
End If
End If
End If
End While
End If
End If
Return Nothing
End Function
I found that your line for write line display name, was writing the exact com id of
Inventor's application object. So I grabbed exactly that, and it worked. I truly thank
you for this blog, its changed my game plan significantly. I will be posting a
completed tool in the forums. Thanks.
Reply
07/01/2016 at 09:08 AM (http://adndevblog.typepad.com/manufacturing
/2016/06/access-a-specific-inventorapplication-object.html#comment-

5 de 9

20/01/2017 23:18

Access a specific Inventor.Application object - Manufacturing DevBlog

6 de 9

http://adndevblog.typepad.com/manufacturing/2016/06/access-a-specif...

6a0167607c2431970b01b7c8761a3b970b)
Adam Nagy (http://profile.typepad.com/1236098880s16462) said...

Glad you like it Jamie! :)


Yes, you can get back the Application object as well, but as I mentioned, they will
return the same Inventor.Application object. You can easily test it by opening a
document in the first instance, then open additional Inventor's and check the
Application.Caption for each of the returned objects: they will all contain the opened
document's name in the title because they all give back the first Inventor instance.
:-s
Reply
07/01/2016 at 09:44 AM (http://adndevblog.typepad.com/manufacturing/2016/06
/access-a-specific-inventorapplication-object.html#comment6a0167607c2431970b01b8d1ffec9f970c)
Jamie Johnson said...

Ok so this is not actually doing what I thought. The code above returns 1 app for
each reported instance, but each app returned is the same first thread as is verified
by the open documents within each app. The problem is none of the items in the
ROT are the actual documents either, just apps. But if it shows 2 apps, then I should
be able to get each app's individual thread, somehow. Not giving up on this.
Reply
07/01/2016 at 09:47 AM (http://adndevblog.typepad.com/manufacturing/2016/06
/access-a-specific-inventorapplication-object.html#comment6a0167607c2431970b01b7c8761ebb970b)
Adam Nagy (http://profile.typepad.com/1236098880s16462) said in
reply to Jamie Johnson...

As I also mentioned this is not specific to Inventor, but all COM registered
applications. See comment here:
https://social.technet.microsoft.com/Forums/office/en-US/2179c726f992-4f29-9e5d-3db8adde98b0/multiple-instances-of-access-2010-runninghave-entrees-in-running-object-table-rot-butall-entrees?forum=officeitproprevious (https://social.technet.microsoft.com
/Forums/office/en-US/2179c726-f992-4f29-9e5d-3db8adde98b0/multipleinstances-of-access-2010-running-have-entrees-in-running-object-table-rot-butall-entrees?forum=officeitproprevious)
>>>>>
Theoretically, you can iterate the ROT for each individual instance, but the Office
apps don't register themselves if another instance is already in the ROT because the
moniker for itself is always the same (it couldn't be distinguished anyway). This
means that you can't attach to any instance except for the first. However, because
the Office apps also register their documents in the ROT, you can successfully attach
to other instances by iterating the ROT looking for a specific document, attaching to
it, then getting the Application object from it.
<<<<<

20/01/2017 23:18

Access a specific Inventor.Application object - Manufacturing DevBlog

7 de 9

http://adndevblog.typepad.com/manufacturing/2016/06/access-a-specif...

Reply
07/01/2016 at 09:55 AM (http://adndevblog.typepad.com/manufacturing/2016/06
/access-a-specific-inventorapplication-object.html#comment6a0167607c2431970b01b7c8761fc4970b)
Jamie Johnson said...

The running object table moniker enumerator never passed by a single document
object, because... Inventor documents that have not been saved to the file are not
listed in the ROT. So unless the document open has been saved to file, this will not
work. FYI if you find an Inventor in the ROT that does not have a file based
document open (or no documents open) you will see it in the list by its clsID =
{B6B5DC40-96E3-11d2-B774-0060B0F159EF}, and it is repeated if you have many
instances open. However turning that into a com object is difficult, because they all
have the same name and most developers handle the ROT as a hashtable (key, value
list of unique items), the multiple instances get mashed into 1 thanks to that
hashtable.
Reply
07/11/2016 at 01:44 PM (http://adndevblog.typepad.com/manufacturing/2016/06
/access-a-specific-inventorapplication-object.html#comment6a0167607c2431970b01bb091dc2a1970d)
Adam Nagy (http://profile.typepad.com/1236098880s16462) said in
reply to Jamie Johnson...

Is it the same with e.g. Excel and its documents?


So maybe the only way to do it properly is if you create an auto-load Inventor addin
that exposes all the Inventor objects?
Reply
07/11/2016 at 07:52 PM (http://adndevblog.typepad.com/manufacturing/2016/06
/access-a-specific-inventorapplication-object.html#comment6a0167607c2431970b01b8d2042f45970c)
Jamie Johnson said...

Interesting proposition, how to accomplish would be the question. Would one, force
updates to the ROT to exist with different names, or create a separate class
apartment that can listen to start up events from itself collecting all the invApps
created/destroyed, or some other idea? This does explain a lot of the 'issues' with
Autodesk add-on apps (such as vault and task manager) that complain about having
multiple Inventor's open.
Reply
07/14/2016 at 08:25 AM (http://adndevblog.typepad.com/manufacturing/2016/06
/access-a-specific-inventorapplication-object.html#comment6a0167607c2431970b01b8d20535a2970c)
Adam Nagy (http://profile.typepad.com/1236098880s16462) said in reply to Jamie
Johnson...

20/01/2017 23:18

Access a specific Inventor.Application object - Manufacturing DevBlog

8 de 9

http://adndevblog.typepad.com/manufacturing/2016/06/access-a-specif...

I guess you could create your own COM server (which would only have a single
instance) and that server instance could be accessed from each Inventor application,
from inside your addin. When your addin loads it has access to the Application
object of the Inventor instance it is running inside in, so it could register Inventor
with that COM server. When Inventor is closed down and so the add-in gets
unloaded it could unregister that COM instance with the COM server.
Reply
07/14/2016 at 08:30 AM (http://adndevblog.typepad.com/manufacturing/2016/06
/access-a-specific-inventorapplication-object.html#comment6a0167607c2431970b01b8d2053637970c)
Comment below or sign in with
Typepad (http://www.typepad.com
/sitelogin?uri=http%3A%2F
%2Fadndevblog.typepad.com%2Fmanufacturing%2F2016%2F06%2Faccessa-specific-inventorapplication-object.html&
fp=e0f5f5b4e8897987873f1a0e30f0b704&view_uri=http%3A%2F
%2Fprofile.typepad.com%2F&via=blogside&post_uri=http:
//adndevblog.typepad.com/manufacturing/2016/06/access-a-specificinventorapplication-object.html)
Facebook (http://www.typepad.com
/sitelogin?uri=http%3A%2F
%2Fadndevblog.typepad.com%2Fmanufacturing%2F2016%2F06%2Faccessa-specific-inventorapplication-object.html&
fp=e0f5f5b4e8897987873f1a0e30f0b704&view_uri=http%3A%2F
%2Fprofile.typepad.com%2F&via=blogside&service=facebook&post_uri=http:
//adndevblog.typepad.com/manufacturing/2016/06/access-a-specificinventorapplication-object.html)
Twitter (http://www.typepad.com
/sitelogin?uri=http%3A%2F
%2Fadndevblog.typepad.com%2Fmanufacturing%2F2016%2F06%2Faccessa-specific-inventorapplication-object.html&
fp=e0f5f5b4e8897987873f1a0e30f0b704&view_uri=http%3A%2F
%2Fprofile.typepad.com%2F&via=blogside&service=twitter&post_uri=http:
//adndevblog.typepad.com/manufacturing/2016/06/access-a-specificinventorapplication-object.html)
Google+ (http://www.typepad.com
/sitelogin?uri=http%3A%2F
%2Fadndevblog.typepad.com%2Fmanufacturing%2F2016%2F06%2Faccessa-specific-inventorapplication-object.html&
fp=e0f5f5b4e8897987873f1a0e30f0b704&view_uri=http%3A%2F
%2Fprofile.typepad.com%2F&via=blogside&service=gplus&post_uri=http:
//adndevblog.typepad.com/manufacturing/2016/06/access-a-specificinventorapplication-object.html) and more... (http://www.typepad.com
/sitelogin?uri=http%3A%2F
%2Fadndevblog.typepad.com%2Fmanufacturing%2F2016%2F06%2Faccessa-specific-inventorapplication-object.html&
fp=e0f5f5b4e8897987873f1a0e30f0b704&view_uri=http%3A%2F
%2Fprofile.typepad.com%2F&via=blogside&service=openid&post_uri=http:
//adndevblog.typepad.com/manufacturing/2016/06/access-a-specificinventorapplication-object.html)

20/01/2017 23:18

Access a specific Inventor.Application object - Manufacturing DevBlog

9 de 9

http://adndevblog.typepad.com/manufacturing/2016/06/access-a-specif...

(URLs automatically linked.)

Email address is not displayed with comment.

(http://www.typepad.com/)
Manufacturing DevBlog (http://adndevblog.typepad.com/manufacturing/)

20/01/2017 23:18

Das könnte Ihnen auch gefallen