By Adam Nagy
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/accessing-com-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; 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(IntPtr hwnd) { // 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); 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() + ".ipt"; System.IO.File.Copy( "C:\temp\Gusset2013.ipt", fileName); // Start Inventor Process process = Process.Start( @"C:Program FilesAutodeskInventor 2016BinInventor.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)) { // 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" + app.Caption); // 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(); } } }

Leave a Reply to Adam NagyCancel reply