I think that many people have a hate-love relationship with the design doctor. Of course, you never want to see that red cross at the top of your screen. But stuff breaks and you need to know about it and solve it. This is where the design doctor should shine. It should help you identify all problems and help you to solve them.

 If you have a look at the "Inventor idea forum" you will find a lot of improvement ideas. (I found 39 ideas.) Lots of those ideas come down to the same problems. But these 2 I want to highlight:

  • Clicking through the problem tree to see the actual problem is annoying.  I just want to see the problems directly!
  • Finding the feature, occurrence or ... can be a pain. I want to be able to see the problem in the model browser.

Therefore my thoughts would be to create my own "Design Doctor" based on the original.  But Brian Ekins (one of the designers of the Inventor API) wrote:
"There were plans at one point to expose the Design Doctor through the API but it never happened.  However, you can still get some failure or error information by interrogating the model."

So I needed to get the health information of objects in another way. lucky for me it seems that many objects in Inventor API have the property "HealthStatus". In the help, I found more than 400 objects with this property. I guess their use is quite self-explanatory. The problem is finding and feeding them, in an efficient way, to some function that checks the property and saves problems to a list. I managed to do that but I'm don't think I got all objects. I guess that I managed to get around 80% of the objects.

The next problem is creating a window. As you might know, there is an iLogic function to create listed windows. In this rule, I used that function to create a window that shows you a list of all problems. If you select 1 of them and click on "OK" the document containing the problem will be opened and the feature, occurrence or ... will be selected.

The whole look is a bit rough. I don't like how the window looks like. Also, the error text could be much clearer. If this would have been an addon I would definitely improve this. But for now, I will leave this up to you. However, I know of some recourse that might help you. Creating a new window from scratch is a nice challenge (but will make this code probably twice as long). more information you can find on this page "Create a Windows Form, from one iLogic Rule". If you want to change the text in the list you just need to change the "HealtProblem.ToString()" (This is the last function of the rule.)

Public Class ThisRule
    Public Sub Main()
              
               Dim doc As Document = ThisDoc.Document
              
        Dim problemFinder As New ProblemFinder(doc)
 
        Dim problems As List(Of HealtProblem) = problemFinder.Problems
 
               If (problems.Count = 0) Then
                       MsgBox("No problems found!")
                       return
               End If
                      
               Dim selectedProblem As HealtProblem = InputListBox(
                               "Select the problem that you want to solve today.",
                               problems, problems.Item(1),
                               Title := "Design Doctor",
                               ListName := "Problems",
                               Width := 600,
                               Height := 400)
              
               If selectedProblem Is Nothing Then Return
                      
               ThisApplication.Documents.Open(selectedProblem.Document.FullFileName)
              
               HiglightInBrowser(selectedProblem)           
    End Sub
       
    Public Sub HiglightInBrowser(problem As HealtProblem)
        Try
            Dim oNativeBrowserNodeDef As NativeBrowserNodeDefinition = problem.Document.BrowserPanes.
            GetNativeBrowserNodeDefinition(problem.ProblemObject)
            Dim oTopBrowserNode As BrowserNode = problem.Document.BrowserPanes.ActivePane.TopNode
            Dim oWorkPlaneNode As BrowserNode = oTopBrowserNode.AllReferencedNodes(oNativeBrowserNodeDef).Item(1)
            oWorkPlaneNode.Expanded = True
                       oWorkPlaneNode.Expanded = False
                      
                       problem.Document.SelectSet.Clear()
                       problem.Document.SelectSet.Select(problem.ProblemObject)
        Catch ex As Exception
            Dim msg = String.Format("Could not select problem node in document: " & problem.Document.DisplayName)
        End Try
    End Sub
End Class
 
Public Class ProblemFinder
    Public Property Problems As New List(Of HealtProblem)
    Sub New(doc As Document)
              
        If (doc.DocumentType = DocumentTypeEnum.kPartDocumentObject) Then
            FindPartProblems(doc)
        ElseIf (doc.DocumentType = DocumentTypeEnum.kAssemblyDocumentObject) Then
            FindAssemblyProblems(doc)
        End If
 
        Dim partDocs = doc.AllReferencedDocuments.Cast(Of Document).
            Where(Function(d) d.DocumentType = DocumentTypeEnum.kPartDocumentObject).ToList()
        For Each partDoc As PartDocument In partDocs
            FindPartProblems(partDoc)
        Next
 
        Dim assemblyDocs = doc.AllReferencedDocuments.Cast(Of Document).
            Where(Function(d) d.DocumentType = DocumentTypeEnum.kAssemblyDocumentObject).ToList()
        For Each assemblyDoc As AssemblyDocument In assemblyDocs
            FindAssemblyProblems(assemblyDoc)
        Next
    End Sub
 
    Public Sub FindAssemblyProblems(doc As AssemblyDocument)
        FindProblemsInList(doc, doc.ComponentDefinition.Constraints.Cast(Of AssemblyConstraint))
        FindProblemsInList(doc, doc.ComponentDefinition.Sketches.Cast(Of PlanarSketch))
        FindProblemsInList(doc, doc.ComponentDefinition.OccurrencePatterns.Cast(Of OccurrencePattern))
        FindProblemsInList(doc, doc.ComponentDefinition.WorkPlanes.Cast(Of WorkPlane))
        FindProblemsInList(doc, doc.ComponentDefinition.Parameters.Cast(Of Parameter))
    End Sub
    Public Sub FindPartProblems(doc As PartDocument)
        FindProblemsInList(doc, doc.ComponentDefinition.Features.Cast(Of PartFeature))
        FindProblemsInList(doc, doc.ComponentDefinition.Sketches.Cast(Of PlanarSketch))
        FindProblemsInList(doc, doc.ComponentDefinition.WorkPlanes.Cast(Of WorkPlane))
        FindProblemsInList(doc, doc.ComponentDefinition.Parameters.Cast(Of Parameter))
        FindProblemsInList(doc, doc.ComponentDefinition.ModelAnnotations.Cast(Of ModelAnnotation))
    End Sub
 
    Public Sub FindProblemsInList(doc As Document, list As IEnumerable(Of Object))
        Try
            For Each obj As Object In list
                If (obj.HealthStatus = HealthStatusEnum.kCannotComputeHealth Or
                    obj.HealthStatus = HealthStatusEnum.kDeletedHealth Or
                    obj.HealthStatus = HealthStatusEnum.kDriverLostHealth Or
                    obj.HealthStatus = HealthStatusEnum.kInconsistentHealth Or
                    obj.HealthStatus = HealthStatusEnum.kInErrorHealth Or
                    obj.HealthStatus = HealthStatusEnum.kInvalidLimitsHealth Or
                    obj.HealthStatus = HealthStatusEnum.kJointDOFLockedHealth Or
                    obj.HealthStatus = HealthStatusEnum.kNewlyAddedHealth Or
                    obj.HealthStatus = HealthStatusEnum.kOutOfDateHealth Or
                    obj.HealthStatus = HealthStatusEnum.kRedundantHealth Or
                    obj.HealthStatus = HealthStatusEnum.kUnknownHealth) Then
 
                    Problems.Add(New HealtProblem(doc, obj))
                End If                   
            Next
        Catch ex As Exception
            MsgBox("Problems while parisng problems in document: " & doc.DisplayName)
        End Try
    End Sub
 
End Class
    ' Copyright 2022
    '
    ' This code was written by Jelte de Jong, and published on www.hjalte.nl
    '
    ' Permission Is hereby granted, free of charge, to any person obtaining a copy of this
    ' software And associated documentation files (the "Software"), to deal in the Software
    ' without restriction, including without limitation the rights to use, copy, modify, merge,
    ' publish, distribute, sublicense, And/Or sell copies of the Software, And to permit persons
    ' to whom the Software Is furnished to do so, subject to the following conditions:
    '
    ' The above copyright notice And this permission notice shall be included In all copies Or
    ' substantial portions Of the Software.
    '
    ' THE SOFTWARE Is PROVIDED "AS IS", WITHOUT WARRANTY Of ANY KIND, EXPRESS Or IMPLIED,
    ' INCLUDING BUT Not LIMITED To THE WARRANTIES Of MERCHANTABILITY, FITNESS For A PARTICULAR
    ' PURPOSE And NONINFRINGEMENT. In NO Event SHALL THE AUTHORS Or COPYRIGHT HOLDERS BE LIABLE
    ' For ANY CLAIM, DAMAGES Or OTHER LIABILITY, WHETHER In AN ACTION Of CONTRACT, TORT Or
    ' OTHERWISE, ARISING FROM, OUT Of Or In CONNECTION With THE SOFTWARE Or THE USE Or OTHER
    ' DEALINGS In THE SOFTWARE.
 
Public Class HealtProblem
    Public Sub New(doc As Document, problemObject As Object)
        Me.Document = doc
        Me.ProblemObject = problemObject
    End Sub
    Public Property Document As Document
    Public Property ProblemObject As Object
       
    Public Overrides Function ToString() As String
        Return String.Format("{0}: {1} ({2})",
            Document.DisplayName, ProblemObject.Name,
                       CType(ProblemObject.HealthStatus, HealthStatusEnum).ToString())
    End Function
End Class

Edit:

On LinkedIn I did get the following comment from Felix Rodermund:

"Sad that the HealthEnum does not at least have a common name that can be returned with TypeName like e. g. partfeatures in the ObjectTypeEnum. On the other hand the HealthStatusEnum is not too big, just looked it up. ... Okay here we go, just wrote it. Wasn't as much pain as I suspected."

And in my mail, I found the following class. You can use it to replace the HealthProblem class in my rule. This replacement class will give you a better description text than my class.

Public Class HealtProblem
    Public Sub New(doc As Document, problemObject As Object)
        Me.Document = doc
        Me.ProblemObject = problemObject
    End Sub

    Public Property Document As Document
    Public Property ProblemObject As Object

    Public Overrides Function ToString() As String

        ' Change this function if you want to see other texts in you list
        Dim ErrorMsg As String = ""

        Select Case ProblemObject.HealthStatus
            Case HealthStatusEnum.kBeyondStopNodeHealth
                ErrorMsg = "Object is beyond stop node in the browser."

            Case HealthStatusEnum.kCannotComputeHealth
                ErrorMsg = "Object cannot be evaluated."

            Case HealthStatusEnum.kDeletedHealth
                ErrorMsg = "Object has been destroyed. You may be holding on to an empty 'shell' of the Object."

            Case HealthStatusEnum.kDriverLostHealth
                ErrorMsg = "Object is driven by data from other Object(s), and one or more of them have been disconnected."

            Case HealthStatusEnum.kInconsistentHealth
                ErrorMsg = "Object is inconsistent with another object."

            Case HealthStatusEnum.kInErrorHealth
                ErrorMsg = "Object's internal state is in error."

            Case HealthStatusEnum.kInvalidLimitsHealth
                ErrorMsg = "Object has bad limits. e.g. max < min."

            Case HealthStatusEnum.kJointDOFLockedHealth
                ErrorMsg = "Object is locked Joint."

            Case HealthStatusEnum.kNewlyAddedHealth
                ErrorMsg = "Object is newly added or unsuppressed and has not been solved yet."

            Case HealthStatusEnum.kOutOfDateHealth
                ErrorMsg = "Object needs to be recomputed with respect to its 'driver(s)'."

            Case HealthStatusEnum.kRedundantHealth
                ErrorMsg = "Object's solution is redundant with another object."

            Case HealthStatusEnum.kSuppressedHealth
                ErrorMsg = "Object has been suppressed."

            Case HealthStatusEnum.kUnknownHealth
                ErrorMsg = "Object's status is not known."

            Case HealthStatusEnum.kUpToDateHealth
                ErrorMsg = "Object is up to date."

        End Select

        Return String.Format("{0} ==> {1}: '{2}' ({3})",
        Document.DisplayName, ProblemObject.Name, ErrorMsg,
        System.Enum.GetName(GetType(HealthStatusEnum), ProblemObject.HealthStatus))

    End Function

End Class

Skills:

Autodesk Inventor, Vault, Git, C#, vb, .net, php HTML, css, js

Education:

University computer science.
HBO Mechanical engineer.
MBO Fine mechanics.

Experience:

Programmer and Mechanical engineer at Kelvion
(2016 - 20..)

Mechanical engineer at Strukton
(2009 - 2016)

Mechanical engineer at RDG-engineering
(2007 - 2009)

CNC Programmer at VMC
(2005 - 2007)

volunteer at Taizé
(2007)

Certifications:

Objectgeoriënteerd analyseren en ontwerpen, Objectgeoriënteerd programmeren in Java, Webapplicaties: de clientkant, Databases, Security Aware Programmer, Web Security Specialist