Inventor API - C# Visual Studio

Inventor API - C# Visual Studio

christoph.steidle
Participant Participant
10,250 Views
21 Replies
Message 1 of 22

Inventor API - C# Visual Studio

christoph.steidle
Participant
Participant

Hello all,

I am desperately trying to find a simple code and hope that you can help me out here.

 

public Application inventor;
public Document document;

 inventor = (Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Inventor.Application");
            document = inventor.ActiveDocument;
            PartDocument doc = (PartDocument)inventor.ActiveDocument;
            //PartDocument doc = (PartDocument)inventor.Documents.Add(DocumentTypeEnum.kPartDocumentObject, inventor.FileManager.GetTemplateFile(DocumentTypeEnum.kPartDocumentObject), true);

            var _count = doc.ComponentDefinition.Features.Count;
            var _count2 = doc.ComponentDefinition.Features.ExtendFeatures.Count;
            var _count3 = doc.ComponentDefinition.Features.ExtrudeFeatures.Count;

            foreach (var feature in doc.ComponentDefinition.Features)
            {
                Console.WriteLine(feature.ToString());
                var List = feature;
            }

I would like to establish a connection to Inventor via VS and C#.
This has already worked.

Now I simply want to count all components and assemblies and save them in a list.

Unfortunately, this does not work.
I suspect there is already an error with PartDocument?

Unfortunately, I am stuck here and am grateful for any help.

 

Greetings

0 Likes
Accepted solutions (1)
10,251 Views
21 Replies
Replies (21)
Message 2 of 22

JelteDeJong
Mentor
Mentor

i expect that you are getting an exception and you want to know what the problem is. To help you it would be helpfull if you could tell: 

  • What does the exception description say?
  • At which line do you get the exception?

Jelte de Jong
Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.

EESignature


Blog: hjalte.nl - github.com

0 Likes
Message 3 of 22

christoph.steidle
Participant
Participant

Danke für die schnelle Antwort hier ein Screenshot zu der Ausnahme.

 

--

"Thanks for the quick reply, here is a screenshot to the exception."
DeepL Translation

image.png

0 Likes
Message 4 of 22

JelteDeJong
Mentor
Mentor

Usually you get this exception if the active document in inventor is not a part document. So this will not work for assemblies for example.

Jelte de Jong
Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.

EESignature


Blog: hjalte.nl - github.com

0 Likes
Message 5 of 22

christoph.steidle
Participant
Participant

Es tut mir Leid aber ich bin relativ neu in dem Feld und weiß nicht genau was du damit meinst?

Ich hab in Inventor ein Dokument mit Baugruppen und Bauteilen offen.

 

--

"I'm sorry but I'm relatively new to the field and don't know exactly what you mean by this?

I have a document open in Inventor with assemblies and parts."

DeepL Translation

0 Likes
Message 6 of 22

etaCAD
Advocate
Advocate

In dieser Zeile 

PartDocument doc = (PartDocument)inventor.ActiveDocument;

holst du das aktive Dokument und änderst den Typ in ein PartDocument. So wie du weiter unten schreibst ist das ActiveDocument aber eine Baugruppe (AssemblyDocument). Das lässt sich nicht in ein PartDocument umwandeln und verursacht den Fehler.

Öffne ein Bauteil (PartDocument (.ipt)) und versuche deinen Code erneut.

Andreas
etaCAD

0 Likes
Message 7 of 22

christoph.steidle
Participant
Participant

Ah ok verstanden.

 

Kannst du mir aber vielleicht noch weiterhelfen und mir sagen wie der Code aussehen muss wenn ich diese Baugruppen und Bauteile auslesen möchte?

 

--

"Ah ok understood.

 

But can you help me further and tell me how the code must look like if I want to read these assemblies and components?"
Deepl translation

christophsteidle_0-1637658625216.png

 

0 Likes
Message 8 of 22

etaCAD
Advocate
Advocate

An alle referenzierten Dokumente kommst du mit

AssemblyDocument.AllReferencedDocuments() As DocumentsEnumerator

 

--

"You can get to all referenced documents with

AssemblyDocument.AllReferencedDocuments() As DocumentsEnumerator"

Deepl translation

Andreas
etaCAD

0 Likes
Message 9 of 22

christoph.steidle
Participant
Participant

Danke hat mir alles schon mal sehr viel geholfen. Bin nun auch schon einiges weiter und möchte nun die Bauteile in JT exportieren.

Bekomme hier aktuell noch folgende Fehlermeldung.

 

Was genau hat es damit auf sich?

christophsteidle_0-1637676935149.png

 

--

"Thank you everything has already helped me a lot. I am now quite a bit further and would now like to export the components in JT.

I still get the following error message."

Deepl Translation

0 Likes
Message 10 of 22

etaCAD
Advocate
Advocate

Die Fehlermeldung sagt, dass ein Parameter der Funktion SaveCopyAs() falsch ist.

 

Um detaillierte Hilfe zu erhalten ist es hier üblich den Quellcode zu veröffentlichen. Die Forumsteilnehmer sind Inventor-Experten und keine Hellseher.

Ich schaue jetzt aber mal in die Glaskugel und nehme an, dass es der erste Parameter ist. In der Hilfe wird für diesen der Typ 'Object' angegeben, in den Beispielen aber stets ein 'Document' übergeben. Bei Dir ist es ein 'ComponentOccurrence'. Von daher könntest Du es mal stattdessen mit oCompOcc.Definition.Document versuchen.

Außerdem vermute ich, dass bei der nameValueMap der Wert für Export_Acad_Inifile bei einem JT-Export keinen Sinn macht. Aber wie gesagt, das sehe ich alles nur in meiner Glaskugel.

 

--

"

The error message says that one parameter of the SaveCopyAs() function is wrong.

 

To get detailed help it is common here to post the source code. The forum participants are Inventor experts and not psychics.

However, I'll look into the crystal ball now and assume that it is the first parameter. In the help the type 'Object' is given for this, but in the examples always a 'Document' is passed. In your case it is a 'ComponentOccurrence'. Therefore you could try oCompOcc.Definition.Document instead.

Also, I suspect that with the nameValueMap, the value for Export_Acad_Inifile doesn't make sense with a JT export. But as I said, I see all this only in my crystal ball.
"
Deepl Translation

Andreas
etaCAD

0 Likes
Message 11 of 22

christoph.steidle
Participant
Participant

Vielen Dank für deine Antwort.

 

Hier natürlich der Source Code.

 

Habe nun einen anderen versuch unternommen der joch leider auch noch nicht klappt. Vllt ist es so nun besser nachzuvollziehen? 🙂

Im Prinzip geht es mir eben darum jedes Teil als .jt einzeln abzuspeichern.

 

 

public Application inventor;
        public Document document;
        public AssemblyDocument doc;
        public TranslatorAddIn translateAddIn;
        public TranslationContext translateContext;
        public NameValueMap nameValueMap;
        public DataMedium dataMedium;
        string path = "C:\\TEMP\\Inventor\\";
        List<string> _listRefKeysCompOccurrence = new();
        List<string> _listNameCompOccurrence = new();
        List<int> _listLevel = new();
        List<ComponentOccurrence> _listComponentOccurence = new();
        int counter;

        public void InitializeInventor()
        {
            try
            {
                inventor = (Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Inventor.Application");
                document = inventor.ActiveDocument;
                doc = (AssemblyDocument)inventor.ActiveDocument;
            }
            catch
            {
                Console.WriteLine("Inventor not open");
            }
            _listRefKeysCompOccurrence.Clear();
            _listNameCompOccurrence.Clear();
            _listLevel.Clear();
            _listComponentOccurence.Clear();

            GetOccurences(doc.ComponentDefinition.Occurrences, 1);

            Export();
        }

        public void GetOccurences(ComponentOccurrences compOcc, int level)
        {
            foreach (ComponentOccurrence oCompOcc in compOcc)
            {
                byte[] myRefKey = { };
                oCompOcc.GetReferenceKey(ref myRefKey, doc.ReferenceKeyManager.CreateKeyContext());
                _listRefKeysCompOccurrence.Add(doc.ReferenceKeyManager.KeyToString(myRefKey));
                _listNameCompOccurrence.Add(oCompOcc.Name);
                _listLevel.Add(level);
                _listComponentOccurence.Add(oCompOcc);

                if (oCompOcc.DefinitionDocumentType == DocumentTypeEnum.kAssemblyDocumentObject)
                    GetOccurences((ComponentOccurrences)oCompOcc.SubOccurrences, level + 1);
            }
        }

        public void Export()
        {
            //Alle offenwen Dokumente durchsuchen
            //Dim oRefDocs As DocumentsEnumerator = oAsmDoc.AllReferencedDocuments
            //For Each oRefDoc As Document In oRefDocs

            translateAddIn = (TranslatorAddIn)inventor.ApplicationAddIns.ItemById["{16625A0E-F58C-4488-A969-E7EC4F99CACD}"];
            translateContext = inventor.TransientObjects.CreateTranslationContext();
            nameValueMap = inventor.TransientObjects.CreateNameValueMap();
            dataMedium = inventor.TransientObjects.CreateDataMedium();
            translateContext.Type = IOMechanismEnum.kFileBrowseIOMechanism;

            //Create folder if it does not exist
            if (!System.IO.Directory.Exists(path))
                System.IO.Directory.CreateDirectory(path);

            foreach (ComponentOccurrence oCompOcc in _listComponentOccurence)
            {
                //Delete files
                if (System.IO.File.Exists(oCompOcc.Name))
                    System.IO.File.Delete(oCompOcc.Name);
                try
                {
                    dataMedium.FileName = path + oCompOcc.Name + ".jt";

                    inventor.SilentOperation = true;
                    if (oCompOcc.DefinitionDocumentType == DocumentTypeEnum.kPartDocumentObject)
                    {
                        var oNewDoc = (PartDocument)inventor.Documents.Add(oCompOcc.DefinitionDocumentType, "", false);
                        translateAddIn.SaveCopyAs(oNewDoc, translateContext, nameValueMap, dataMedium);
                        //oNewDoc.SaveAs(path + oCompOcc.Name + ".jt", true);
                    }
                    inventor.SilentOperation = false;
                }
                catch (Exception)
                {
                    //System.Windows.Forms.MessageBox.Show("Error processing " + oCompOcc.Name);
                }
            }
        }

 

 

 

Ich bekomme 0 byte-Dateien als ergebnis

christophsteidle_0-1637766673113.png

 

 

--

 

"Thanks for your answer.

 

Here of course the source code.

 

I have now made another attempt which unfortunately does not work yet. Maybe it is now better to understand? 🙂

In principle, I just want to save each part as .jt individually."

"I get 0 byte files as result"

Deepl translation

0 Likes
Message 12 of 22

christoph.steidle
Participant
Participant

Sorry fürs nachhaken aber wollte nur nochmal nachfragen ob mir hier jemand weiterhelfen kann?

 

--

"Sorry for asking but just wanted to ask again if someone can help me here?"

0 Likes
Message 13 of 22

etaCAD
Advocate
Advocate

Bei mir funktioniert es mit diesem Code.

Ich starte über ein Form, was aber keine Rolle spielt.

 

--

"

For me it works with this code.

I start via a form, but that does not matter."

 

 

Inventor.Application _invApp;
      string path = "C:\\TEMP\\Inventor\\";

      public Form1()
      {
         InitializeComponent();
      }

      private void Form1_Load(object sender, EventArgs e)
      {
         try
         {
            _invApp = (Inventor.Application)Marshal.GetActiveObject("Inventor.Application");

            if (_invApp.ActiveDocument != null)
               if (_invApp.ActiveDocument.DocumentType == DocumentTypeEnum.kAssemblyDocumentObject)
                  jtExport((AssemblyDocument)_invApp.ActiveDocument);
         }
         catch (Exception ex) { MessageBox.Show("Start a session of Inventor."); }
      }

      private void jtExport(AssemblyDocument asmDoc)
      {
         try
         {
            TranslatorAddIn translateAddIn = (TranslatorAddIn)_invApp.ApplicationAddIns.ItemById["{16625A0E-F58C-4488-A969-E7EC4F99CACD}"];

            TranslationContext translateContext = _invApp.TransientObjects.CreateTranslationContext();
            translateContext.Type = IOMechanismEnum.kFileBrowseIOMechanism;
            NameValueMap nameValueMap = _invApp.TransientObjects.CreateNameValueMap();
            DataMedium dataMedium = _invApp.TransientObjects.CreateDataMedium();

            foreach (Document doc in asmDoc.ReferencedDocuments)
               if (doc.DocumentType == DocumentTypeEnum.kPartDocumentObject)
               {
                  dataMedium.FileName = path + doc.DisplayName + ".jt";
                  translateAddIn.SaveCopyAs(doc, translateContext, nameValueMap, dataMedium);
               }
         }
         catch (Exception ex) { MessageBox.Show("Fehler Export: " + ex.Message); }
      }

 

 

 

Andreas
etaCAD

0 Likes
Message 14 of 22

christoph.steidle
Participant
Participant

Ich denke der Unterschied besteht darin, das du das Dokument als .jt speicherst.

Ich möchte an der Stelle jedoch jedes Teil als extra jt-File abspeichern.

Dazu erstelle ich neue Dokumente mit den jeweiligen Bauteilen und möchte die dann speichern.

 

Oder sehe ich hier etwas falsch?

 

 

Hab meinen Code nochmal etwas vereinfacht.

 

 

public Application inventor;
        public Document document;
        public AssemblyDocument doc;
        public TranslatorAddIn translateAddIn;
        public TranslationContext translateContext;
        public NameValueMap nameValueMap;
        public DataMedium dataMedium;
        string path = "C:\\TEMP\\Inventor\\";
        readonly List<string> _listRefKeysCompOccurrence = new();
        readonly List<string> _listNameCompOccurrence = new();
        readonly List<int> _listLevel = new();
        readonly List<ComponentOccurrence> _listComponentOccurence = new();

        public void InitializeInventor()
        {
            try
            {
                inventor = (Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Inventor.Application");
                document = inventor.ActiveDocument;
                doc = (AssemblyDocument)inventor.ActiveDocument;
            }
            catch
            {
                Console.WriteLine("Inventor not open");
            }
            _listRefKeysCompOccurrence.Clear();
            _listNameCompOccurrence.Clear();
            _listLevel.Clear();
            _listComponentOccurence.Clear();

            ExportJt(doc.ComponentDefinition.Occurrences, 1);
        }

        public void ExportJt(ComponentOccurrences compOcc, int level)
        {
            //Alle offenwen Dokumente durchsuchen
            //Dim oRefDocs As DocumentsEnumerator = oAsmDoc.AllReferencedDocuments
            //For Each oRefDoc As Document In oRefDocs

            translateAddIn = (TranslatorAddIn)inventor.ApplicationAddIns.ItemById["{16625A0E-F58C-4488-A969-E7EC4F99CACD}"];
            translateContext = inventor.TransientObjects.CreateTranslationContext();
            translateContext.Type = IOMechanismEnum.kFileBrowseIOMechanism;
            nameValueMap = inventor.TransientObjects.CreateNameValueMap();
            dataMedium = inventor.TransientObjects.CreateDataMedium();

            //Create folder if it does not exist
            if (!System.IO.Directory.Exists(path))
                System.IO.Directory.CreateDirectory(path);

            foreach (ComponentOccurrence oCompOcc in compOcc)
            {
                byte[] myRefKey = { };
                oCompOcc.GetReferenceKey(ref myRefKey, doc.ReferenceKeyManager.CreateKeyContext());
                _listRefKeysCompOccurrence.Add(doc.ReferenceKeyManager.KeyToString(myRefKey));
                _listNameCompOccurrence.Add(oCompOcc.Name);
                _listLevel.Add(level);
                _listComponentOccurence.Add(oCompOcc);

                if (oCompOcc.DefinitionDocumentType == DocumentTypeEnum.kAssemblyDocumentObject)
                    ExportJt((ComponentOccurrences)oCompOcc.SubOccurrences, level + 1);
            
                //Delete files
                if (System.IO.File.Exists(oCompOcc.Name))
                    System.IO.File.Delete(oCompOcc.Name);
                try
                {
                    dataMedium.FileName = path + oCompOcc.Name + ".jt";

                    inventor.SilentOperation = true;
                    
                    if (oCompOcc.DefinitionDocumentType == DocumentTypeEnum.kPartDocumentObject)
                    {
                        var oNewDoc = (PartDocument)inventor.Documents.Add(oCompOcc.DefinitionDocumentType, "", false);
                        translateAddIn.SaveCopyAs(oNewDoc, translateContext, nameValueMap, dataMedium);
                    }
                    inventor.SilentOperation = false;
                }
                catch (Exception)
                {
                    //System.Windows.Forms.MessageBox.Show("Error processing " + oCompOcc.Name);
                }
            }
        }

 

0 Likes
Message 15 of 22

christoph.steidle
Participant
Participant

Ich wollte nochmal nachfragen ob mir nicht doch noch jemand weiterhelfen kann?

Wäre echt super 🙂

 

Ich vermute mal das hier irgendwo der Fehler sitzt.

 

 

try
                {
                    dataMedium.FileName = path + oCompOcc.Name + ".jt";

                    inventor.SilentOperation = true;
                    
                    if (oCompOcc.DefinitionDocumentType == DocumentTypeEnum.kPartDocumentObject)
                    {
                        var oNewDoc = (PartDocument)inventor.Documents.Add(oCompOcc.DefinitionDocumentType, "", false);
                        translateAddIn.SaveCopyAs(oNewDoc, translateContext, nameValueMap, dataMedium);
                    }
                    inventor.SilentOperation = false;
                }

 

 

--

"

I wanted to ask again if someone can help me?

Would be really great 🙂

 

I suspect that somewhere here lies the error."

0 Likes
Message 16 of 22

etaCAD
Advocate
Advocate

The common language here is english. So if you write your questions also in english there are much more people who are able to read the posts and probably write a qualified answer.

 

It would be also good to learn something more about your background regarding programming and Inventor skills.

This could help to understand why you are working with ReferenceKeys, Occurrences, Level... This is not needed.

 

Your assumption is correct. With the line below you create a new (empty) part document that will be exported later. These steps are not useful.

var oNewDoc = (PartDocument)inventor.Documents.Add(oCompOcc.DefinitionDocumentType, "", false);

 

 You don't need to create new part documents or try to open them because when you open an assembly, all related parts are already opened as well.

Andreas
etaCAD

0 Likes
Message 17 of 22

christoph.steidle
Participant
Participant

Thank you very much for your answer.
Of course I can also answer here in English.

 

I need ReferenceKeys and Level for further processing in another programme for the export, which is not yet relevant here, but is already included here. My Inventor skills are not too great, I have experience in C# but little experience with this Inventor interface.

 

I use Occurences to go through all the components from the project.
My goal is to export every component in the project as a jt file.
Since I can only export documents and not components as jt-files (please tell me better if I am wrong in my assumption) I thought the best way is to create a new document with a component and then export it. And exactly at this point I fail.

0 Likes
Message 18 of 22

etaCAD
Advocate
Advocate

Ok, I think the problem is to understand the relation between components (occurrences) and documents. Let me explain. A document is an unique thing. It exists only once per session and is related to a file.

Occurrences are are just pointers to documents and represent the document in the assembly. This means that several occurrences can point to the same document.

 

So you can only export documents and not occurrences. But if you want to work with occurrences this works as well because each occurrence knows the related document: ComponentOccurrence.Definition.Document

 

Documents.Add(...) creates a new (empty) document. This is the wrong practice.

 

Better try this line

translateAddIn.SaveCopyAs(oCompOcc.Definition.Document, translateContext, nameValueMap, dataMedium);

 

Andreas
etaCAD

0 Likes
Message 19 of 22

christoph.steidle
Participant
Participant

Thank you very much for your answer.

I understood what you meant and of course I tested it immediately.

Unfortunately, it still drops files with 0 bytes?

 

try
                {
                    dataMedium.FileName = path + oCompOcc.Name + ".jt";

                    inventor.SilentOperation = true;
                    
                    if (oCompOcc.DefinitionDocumentType == DocumentTypeEnum.kPartDocumentObject)
                    {
                        //var oNewDoc = (PartDocument)inventor.Documents.Add(oCompOcc.DefinitionDocumentType, "", false);
                        //translateAddIn.SaveCopyAs(oNewDoc, translateContext, nameValueMap, dataMedium);
                        translateAddIn.SaveCopyAs(oCompOcc.Definition.Document, translateContext, nameValueMap, dataMedium);
                    }
                    inventor.SilentOperation = false;
                }
                catch (Exception)
                {
                    //System.Windows.Forms.MessageBox.Show("Error processing " + oCompOcc.Name);
                }

 

christophsteidle_0-1638279112282.png

 

0 Likes
Message 20 of 22

etaCAD
Advocate
Advocate

Did you try my code from this post to check if there is a general problem with your JT-Export? This code works fine on my PC.

 

Perhaps you better set SilentOperation to false and watch for error messages from Inventor.

Andreas
etaCAD

0 Likes