Access A Specific Inventor - Application Object - Manufacturing DevBlog
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
1 de 9
20/01/2017 23:18
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
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
http://adndevblog.typepad.com/manufacturing/2016/06/access-a-specif...
Comments
Jamie Johnson said...
4 de 9
20/01/2017 23:18
http://adndevblog.typepad.com/manufacturing/2016/06/access-a-specif...
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
6 de 9
http://adndevblog.typepad.com/manufacturing/2016/06/access-a-specif...
6a0167607c2431970b01b7c8761a3b970b)
Adam Nagy (http://profile.typepad.com/1236098880s16462) 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
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...
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
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
9 de 9
http://adndevblog.typepad.com/manufacturing/2016/06/access-a-specif...
(http://www.typepad.com/)
Manufacturing DevBlog (http://adndevblog.typepad.com/manufacturing/)
20/01/2017 23:18