Community
Inventor Programming - iLogic, Macros, AddIns & Apprentice
Inventor iLogic, Macros, AddIns & Apprentice Forum. Share your knowledge, ask questions, and explore popular Inventor topics related to programming, creating add-ins, macros, working with the API or creating iLogic tools.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Check out the self-paced guide “My First Plug-in”

68 REPLIES 68
Reply
Message 1 of 69
wayne.brill
33988 Views, 68 Replies

Check out the self-paced guide “My First Plug-in”

Check out the Self-Paced Guide “My First Plug-in” presented by the ADN Inventor Team

www.autodesk.com/myfirstinventorplugin

 

Are you an Autodesk Inventor power user with an interest in becoming even more productive? Would you like to automate or extend the capabilities of Inventor, but are new to computer programming? If so, then this guide is designed for you.

 

“My First Plug-in” is a self-paced tutorial guide for a smooth introduction into the programming world. This is a “one-stop shop” learning path for users who know Autodesk products but are absolutely new to programming and are thinking about taking the plunge. In this guide, you will be working with the Autodesk Inventor API and the VB.NET programming language.

 

There are many resources available on the web for you to learn about the Autodesk Inventor API (Application Programming Interface), however, these resources tend to be designed for people who already know programming. This guide is different: it assumes no previous programming knowledge and yet helps you build your first plug-in quickly, without swamping you with details. You’ll have a working application within an hour of starting this material, irrespective of your current level of programming expertise.

 

The guide will start by reviewing the benefits of customizing Autodesk software before progressing onto lessons covering the use of the Autodesk Inventor API. The lessons will start by building a working plug-in before covering more detailed explanations of the underlying principles and further developing the application’s functionality.

 

Product: Autodesk Inventor

Programming Language: VB.NET

Application Programming Interface (API): Inventor API

If you have any feedback on this new guide let us know at myfirstplugin@autodesk.com



Wayne Brill
Developer Technical Services
Autodesk Developer Network

68 REPLIES 68
Message 41 of 69

Private Sub btnCreateDrawings_Click(sender As Object, e As RoutedEventArgs)
        Try
            CreateDrawings()
        Catch ex As Exception
            Dim eh As New ErrorHandler(ex)
            eh.HandleIt()
        End Try
    End Sub

 Public Sub CreateDrawings()
 Me.abortToken = New AbortToken 'a custom class to track user click quit, and check every so often to see if they did.
Dim worker As New BackgroundWorker
        worker.WorkerReportsProgress = True
        AddHandler worker.DoWork, AddressOf worker_DoWork
        AddHandler worker.ProgressChanged, AddressOf worker_ProgressChanged
        AddHandler worker.RunWorkerCompleted, AddressOf worker_RunWorkerCompleted
        Dim args As New List(Of Object)
        args.Add("CreateDrawings")
        args.Add(Me.abortToken)
        worker.RunWorkerAsync(args)
    End Sub
   Private Sub worker_ProgressChanged(sender As Object, e As ProgressChangedEventArgs)
        'pbBatch.Value = e.ProgressPercentage
        StatusList.Add(e.UserState)
        tbkStatus.Text = e.UserState
        vsStatusList.View.MoveCurrentToLast()
        If vsBatchDrawings.View IsNot Nothing Then vsBatchDrawings.View.Refresh()
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("BatchDrawings"))
        Try
            ' lbxStatus.ScrollIntoView(lbxStatus.SelectedItem)
        Catch
        End Try
    End Sub

    Private Sub worker_DoWork(sender As Object, e As DoWorkEventArgs)
        Dim strProcessName As String = String.Empty
        If TypeOf e.Argument Is List(Of Object) Then
            Dim args As List(Of Object) = e.Argument
            strProcessName = args(0)
        ElseIf TypeOf e.Argument Is String Then
            strProcessName = e.Argument
        End If
        Select Case strProcessName
            Case Is = "SelectFiles"
                If isProcessing = False Then
                    BatchDrawings.SelectFiles(sender, e)
                Else
                    MsgBox("One thing at a time please")
                End If
            Case Is = "ReadData"
                If isProcessing = False Then
                    isProcessing = True
                    BatchDrawings.ReadData(sender, e)
                    isProcessing = False
                Else
                    MsgBox("One thing at a time please")
                End If
            Case Is = "CreateDrawings"
                If isProcessing = False Then
                    isProcessing = True
                    BatchDrawings.CreateDrawings(sender, e)
                    isProcessing = False
                Else
                    MsgBox("One thing at a time please")
                End If
        End Select
    End Sub

    Private Sub worker_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs)
        StatusList.Add("Complete")
        vsStatusList.View.MoveCurrentToLast()
        tbkStatus.Text = vsStatusList.View.CurrentItem
        dgBatchList.UpdateLayout()
        isProcessing = False
    End Sub

This is the framework I use in the back code of my VB.Net WPF button control to draw stuff which can take a long process, and allows the user to abort (by throwing a wrench into the works) when they want it to stop.  Do work separates the thread, then calls this:

Public Sub CreateDrawings(sender As Object, e As DoWorkEventArgs)
        abToken = e.Argument(1)
        Dim bw As BackgroundWorker = TryCast(sender, BackgroundWorker)
        Dim rowIndex As Integer = 1
        Dim i As Integer = 0
        Do While i <= Count - 1
            If abToken.AbortProcess = True Then Exit Do
            Try
                Dim bd As BatchDrawing = Me(i)
                rowIndex += 1
                bw.ReportProgress((rowIndex / Count) * 100, "Creating Drawing - " & bd.PartNumber.Name)
                bd.CreateDrawing()
                i += 1
            Catch ex As Exception
                Dim eh As New ErrorHandler(ex)
                eh.HandleIt()
                If MsgBox(String.Format("There was an error processing: {0} Continue processing other documents?", Me(i).PartNumber), MsgBoxStyle.YesNo + MsgBoxStyle.DefaultButton1 + MsgBoxStyle.SystemModal, "Batch Drawing - Continue batch after Error") = MsgBoxResult.No Then
                    abToken.AbortProcess = True
                End If
            End Try
        Loop
        Sort()
        bw.ReportProgress(100, "Complete")
    End Sub

This is the head code of the batch drawing tool that cycles through the list and gets the job done.

There is also asynchronous coding for using parallel computing in my posts from System.Threading.Tasks.Parallel

 ''' <summary>
    ''' Finds sub occurrence based on partial name. This routine is multi-threaded with bailout.  
    ''' If the component occurrence is found in an assembly, it grabs it and bails out of that assembly.  
    ''' If it is found as a sub component in 3 assemblies, it will add then bail out of each one.  
    ''' It is not the intention of the program to find more than one component at the same level.
    ''' </summary>
    ''' <param name="cdOccurrences">Parent Assembly ComponentOccurrences reference</param>
    ''' <param name="subOccName">Name of Component to find</param>
    ''' <returns>Returns the ComponentOccurance if first level and ComponentOccuranceProxy if lower level.</returns>
    Public Function GetSubOccurrenceProxyByName(ByVal cdOccurrences As ComponentOccurrences, ByVal subOccName As String, Optional PartialName As Boolean = False, Optional FindAtSameLevel As Boolean = False) As Object
        Dim cop As Object = Nothing 'return a ComponentOccurrence at this level, or ComponentOccurrenceProxy from lower level
        System.Threading.Tasks.Parallel.For(1, cdOccurrences.Count + 1,
             Sub(index, status)
                 Dim co As ComponentOccurrence = cdOccurrences(index)
                 If PartialName = True Then
                     If co.Name.Contains(subOccName) Then
                         cop = co
                         If FindAtSameLevel = False Then status.Stop() 'this line stops the entire for loop
                         Return 'this line stops the rest of this sub from running, and code continues to run other index items
                     End If
                 Else
                     If co.Name = subOccName Then
                         cop = co
                         If FindAtSameLevel = False Then status.Stop()
                         Return
                     End If
                 End If
                 If co.DefinitionDocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then
                     If TypeOf co.Definition Is AssemblyComponentDefinition OrElse TypeOf co.Definition Is WeldmentComponentDefinition Then
                         Dim sco As ComponentOccurrence = GetSubOccurrenceProxyByName(co.Definition.Occurrences, subOccName, PartialName, FindAtSameLevel)
                         If sco IsNot Nothing Then
                             co.CreateGeometryProxy(sco, cop)
                             If FindAtSameLevel = False Then status.Stop()
                         End If
                     End If
                 End If
             End Sub)
        Return cop
    End Function

where you can run a single task like mad to really push your computer to find that needle in a haystack...

 

Any questions?

 

jvj
Message 42 of 69

My abort token class:

Public Class AbortToken

    Private mAbortProcess As Boolean = False
    Public Property AbortProcess As Boolean
        Get
            Return mAbortProcess
        End Get
        Set(value As Boolean)
            mAbortProcess = value
            If mAbortProcess = True Then
                If ShowInventor = False Then ShowInventor = True
                Dim ex As New Exception("Abort")
                Throw (ex)
            End If
        End Set
    End Property
    Public Property ShowInventor As Boolean
        Get
            If invApp IsNot Nothing Then
                Return invApp.Visible
            End If
            Return False
        End Get
        Set(value As Boolean)
            invApp.Visible = value
        End Set
    End Property

End Class
jvj
Message 43 of 69

Thanks @JamieVJohnson2.


A few questions for now, before I start testing these elements into my own code. Bear with me here because I'm a beginner in VB.net:
0 - Full disclosure, I am trying to implement a simple form plugin which has different productivity tools for Inventor. Each tool is triggered by its own button, but I want to keep a common "CANCEL" button for any tool, enabled once any processing is started (by clicking the tools' buttons). The first sample of tool I have is a simple comparison between two parts to see if the holes (cylindrical faces) found in one are aligned to the other.

1 - btnCreateDrawings_Click is a Sub that differs from the normal Button click handler subs I get when going through the tutorial from the OP (as it lacks the ending "Handles ButtonX.click"). My major problem was that once the plugin starts running one of those subs, we cannot abort by using another sub that handles a (cancel) button click. I also read about DoEvents being looked down upon, but it seems like the only alternative to a background worker.

2 - Your sub "CreateDrawings" does not seem to initialize "Count" for the loop. I also see a lot of examples that only make the background worker run and check for abort within a predefined loop. But what if my process has to cycle through, say, all the faces of a part? Wouldn't the abort cease to work after the loop iterator reaches the maximum Count number (for cases where Count < number of faces)?

Edit: my code in Form1.vb below.

Imports System
Imports System.Type
Imports System.Activator
Imports System.Runtime.InteropServices
Imports Inventor
Imports System.ComponentModel



Public Class Form1


    Dim _invApp As Inventor.Application = Nothing


    Public Sub New()

        'Add any initialization after the InitializeComponent() call.
        Try
            _invApp = Marshal.GetActiveObject("Inventor.Application")
        Catch ex As Exception
            MsgBox("Unable to find a running instance of Inventor. Please start Inventor and try again.")
            End
        End Try

        'This call is required by the designer.
        InitializeComponent()
    End Sub



    Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
        If _invApp.Documents.Count = 0 Then
            MsgBox("Please open an Inventor assembly file and try again.")
            Return
        End If
        If _invApp.ActiveDocument.DocumentType <> DocumentTypeEnum.kAssemblyDocumentObject Then
            MsgBox("Please have an Assembly file active.")
            Return
        End If

        Button1.Enabled = False     'Exit button is now inactive
        Button2.Enabled = True      'CANCEL button is now active
        Button2.BringToFront()      'Brings the CANCEL button in front of EXIT

        Button3.Enabled = False     'Check for Hole Alignment button is now inactive
        Button3.Font = New Font(Button3.Font, FontStyle.Bold)
        Button3.Text = "Acquiring parameters..."

        Dim oDoc As AssemblyDocument
        oDoc = _invApp.ActiveDocument

        Dim oCompdef As Inventor.AssemblyComponentDefinition
        oCompdef = oDoc.ComponentDefinition

        Dim oBody1 As Inventor.SurfaceBody
        Dim oBody2 As Inventor.SurfaceBody

        oBody1 = _invApp.CommandManager.Pick(Inventor.SelectionFilterEnum.kPartBodyFilter, "Select first body")
        oBody2 = _invApp.CommandManager.Pick(Inventor.SelectionFilterEnum.kPartBodyFilter, "Select a body to compare")

        Button3.Text = "Checking hole alignment..."

        Dim trans As Inventor.Transaction = _invApp.TransactionManager.StartTransaction(oDoc, "Hole Alignment")

        Try
            Dim oFace As Inventor.Face
            Dim oAxis As Inventor.WorkAxis

            ProgressBar1.Maximum = oBody1.Faces.Count

            For Each oFace In oBody1.Faces

                ProgressBar1.PerformStep()

                If oFace.SurfaceType = Inventor.SurfaceTypeEnum.kCylinderSurface Then
                    oAxis = oCompdef.WorkAxes.AddFixed(oFace.Geometry.BasePoint, oFace.Geometry.AxisVector)

                    If CompareFaces(oAxis, oBody2, oCompdef) Is Nothing Then
                        oAxis.Name = "MISALIGNED " & oAxis.Name
                    Else
                        oAxis.Delete() 'no interest in saving axes of aligned holes
                    End If

                End If

            Next

        Catch ex As Exception
            MessageBox.Show("There was an error!" & vbCrLf & ex.Message, "Please contact IT.")
            trans.Abort()
        Finally
            trans.End()
        End Try

        ProgressBar1.Value = 0

        Button3.Text = "Check hole alignment"
        Button3.Font = New Font(Button3.Font, FontStyle.Regular)
        Button3.Enabled = True      'Check for Hole Alignment button is now active

        Button1.BringToFront()      'Brings the EXIT button in front of CANCEL
        Button1.Enabled = True      'EXIT button is now active
        Button2.Enabled = False     'CANCEL button is now inactive

    End Sub


    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        'Exit button
        Me.Close()
    End Sub


    Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
        'Cancel button
        Button2.Enabled = False
        'e.Cancel = 
    End Sub


    Public Function CompareFaces(ByVal oAxis1 As WorkAxis, ByVal oBody As SurfaceBody, ByVal compDef As AssemblyComponentDefinition) As Face
        For Each oFace As Face In oBody.Faces
            If oFace.SurfaceType = SurfaceTypeEnum.kCylinderSurface Then
                Dim oAxis As WorkAxis

                oAxis = compDef.WorkAxes.AddFixed(oFace.Geometry.BasePoint, oFace.Geometry.AxisVector)

                If oAxis.Line.IsColinearTo(oAxis1.Line) Then
                    oAxis.Delete()
                    Return oFace
                    Exit Function
                Else
                    oAxis.Delete()
                End If
            End If
        Next
        Return Nothing
    End Function


    Public Function EndsWith(Str As String, ending As String) As Boolean
        Dim endingLen As Integer
        endingLen = Len(ending)
        EndsWith = (Microsoft.VisualBasic.Right(Trim(UCase(Str)), endingLen) = UCase(ending))
    End Function

End Class

 

Message 44 of 69

So yea, I definitely copied code from a huge 'system' of code.  Let me explain.  The Handles clause is missing because we are using WPF (Windows Presentation Foundation) which is like Windows Forms, but not.  Either way when you create a button handler, the code inside the handler is what matters here.  WPF 'pushes' from the front end to a routine, wheras WF pulls from the backend the handler.  Its just minor semantics.

 

Do work system (with the asyncronous option) is your Key to separating threads, It makes the thread run independent of the window control thread.

 

Create Drawings is NOT part of the window back code.  It acually belongs to a custom class that inherits list(of T) T being my custom class for a Drawing to be done workload, (file name, file type, design type, what to do, user selected options, etc.)  (FYI, I actually called those classes BatchDrawing, and BatchDrawings (inherits list(of BatchDrawing), but I can't give away ALL my secrets!).  BatchDrawings is then a PROPERTY of the windows control backend and initiated (loaded, or made new, but not set to Nothing) when the window is opened.  Then there is a listbox/datagrid control on the window that displays the Drawing work times the user has added (via a select files button for me) by loading the contents of BatchDrawings through a MVVM system object CollectionViewSource (WPF method) which acts as a visual gate keeper for the BatchDrawings class.  So when do work is calling create drawings, its created the window control backend hosted reference to the class that has all the individual drawings work items  So CreateDrawings is a sub attached to BatchDrawings, accessed through the window property BatchDrawings.

jvj
Message 45 of 69

Ok, well, my focus is more on how to call anything on the side, so I can kill it with a Cancel button. Therefore, no worries about peeking into your own process in batch drawing creation there.

Given that I am teaching myself to beat Inventor's bugs and shortcomings via code, what I needed more was something in the lines of:

-- basic subs to set up a background worker --
-- button-click sub with call to background worker --
-- button-click sub to set background worker to abort --

-- blank DoWork sub with spot for me to introduce my functionality/tool --


I'll keep reading this over and over and crunch through it, but it would be nice if the Inventor team had this done step-by-step like the First Plug-in tutorial does it. I am hoping that working with WF as the tutorial shows will not restrict my choices much versus WPF.

 

Eventually, with the Cancel figured out, all I would need from there is a way to search through all bodies in a selected Assembly, against another assembly. That's when your multi-thread code above could be even more useful.

test.jpg


Thanks again.

Message 46 of 69

Autodesk doesn't offer much help here, because we are stepping into the next level realm of Windows Threading and Apartment development.  Microsoft is going to be your best support line for this level of code.  But ****, it makes for great stuff when you master it, so keep at it.😎

jvj
Message 47 of 69

Oh yeah, I think I got what I needed from a mix of looking at your code (partial) and another partially-working code from Stack Overflow:
https://stackoverflow.com/questions/18437290/vb-net-stopping-a-backgroundworker/18437412

I just don't like how I had to use the call to:

System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = False

Otherwise my changes in Buttons 1 through 3 within DoWork (to enable/disable, or change their text) were throwing a:
"System.InvalidOperationException: 'Cross-thread operation not valid: Control 'Button3' accessed from a thread other than the thread it was created on'."

 

Not sure how to avoid it but I'll keep trying.

My little app is quite nifty now, only lacking the ability to look inside assemblies selected, and not just bodies/parts:

Imports System
Imports System.Type
Imports System.Activator
Imports System.Runtime.InteropServices
Imports Inventor
Imports System.ComponentModel



Public Class Form1


    Dim _invApp As Inventor.Application = Nothing


    Public Sub New()
        'Add any initialization after the InitializeComponent() call.
        Try
            _invApp = Marshal.GetActiveObject("Inventor.Application")
        Catch ex As Exception
            MsgBox("Unable to find a running instance of Inventor. Please start Inventor and try again.")
            End
        End Try
        'This call is required by the designer.
        InitializeComponent()
        System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = False
        BackgroundWorker1.WorkerSupportsCancellation = True
    End Sub


    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        'Exit button
        Me.Close()
    End Sub


    Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
        'Cancel button
        If BackgroundWorker1.IsBusy And BackgroundWorker1.WorkerSupportsCancellation Then BackgroundWorker1.CancelAsync()
        Button2.Enabled = False
    End Sub


    Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
        Try
            If BackgroundWorker1.IsBusy <> True Then BackgroundWorker1.RunWorkerAsync()
        Catch ex As Exception
        End Try
    End Sub


    Private Sub BackgroundWorker1_DoWork(sender As System.Object, e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        CheckHolesAlignment(e)
    End Sub

    Private Sub BackgroundWorker1_ProgressChanged(sender As System.Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
    End Sub

    Private Sub BackgroundWorker1_Completed(sender As System.Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
    End Sub


    Public Sub CheckHolesAlignment(e As DoWorkEventArgs)
        If _invApp.Documents.Count = 0 Then
            MsgBox("Please open an Inventor assembly file and try again.")
            Return
        End If
        If _invApp.ActiveDocument.DocumentType <> DocumentTypeEnum.kAssemblyDocumentObject Then
            MsgBox("Please have an Assembly file active.")
            Return
        End If

        Button3.Enabled = False     'Check for Hole Alignment button is now inactive
        Button3.Font = New Font(Button3.Font, FontStyle.Bold)
        Button3.Text = "Acquiring parameters..."

        Dim oDoc As AssemblyDocument
        oDoc = _invApp.ActiveDocument

        Dim oCompdef As Inventor.AssemblyComponentDefinition
        oCompdef = oDoc.ComponentDefinition

        Dim oBody1 As Inventor.SurfaceBody
        Dim oBody2 As Inventor.SurfaceBody

        oBody1 = _invApp.CommandManager.Pick(Inventor.SelectionFilterEnum.kPartBodyFilter, "Select first body")
        oBody2 = _invApp.CommandManager.Pick(Inventor.SelectionFilterEnum.kPartBodyFilter, "Select a body to compare")

        Button3.Text = "Checking holes alignment..."
        Button1.Enabled = False     'Exit button is now inactive
        Button2.Enabled = True      'CANCEL button is now active
        Button2.BringToFront()      'Brings the CANCEL button in front of EXIT

        Dim trans As Inventor.Transaction = _invApp.TransactionManager.StartTransaction(oDoc, "Hole Alignment")
        Try
            RemovePreviousAxes(oDoc)
            Dim oFace As Inventor.Face
            Dim oAxis As Inventor.WorkAxis
            Dim ocurrences As Integer = oBody1.Faces.Count
            ProgressBar1.Maximum = ocurrences
            For Each oFace In oBody1.Faces
                If BackgroundWorker1.CancellationPending Then
                    e.Cancel = True
                    Exit For
                End If
                ProgressBar1.PerformStep()
                If oFace.SurfaceType = Inventor.SurfaceTypeEnum.kCylinderSurface Then
                    oAxis = oCompdef.WorkAxes.AddFixed(oFace.Geometry.BasePoint, oFace.Geometry.AxisVector)
                    If CompareFaces(oAxis, oBody2, oCompdef, e) IsNot Nothing Then
                        oAxis.Delete() 'no interest in saving axes of aligned holes
                    Else
                        oAxis.Name = "MISALIGNED " & oAxis.Name
                    End If
                End If
            Next
        Catch ex As Exception
            MessageBox.Show("There was an error!" & vbCrLf & ex.Message, "Please contact IT.")
            trans.Abort()
        Finally
            trans.End()
        End Try

        ProgressBar1.Value = 0
        Button3.Text = "Check holes alignment"
        Button3.Font = New Font(Button3.Font, FontStyle.Regular)
        Button3.Enabled = True      'Check for Hole Alignment button is now active
        Button1.BringToFront()      'Brings the EXIT button in front of CANCEL
        Button1.Enabled = True      'EXIT button is now active
        Button2.Enabled = False     'CANCEL button is now inactive

    End Sub


    Public Sub RemovePreviousAxes(ByVal oDoc As AssemblyDocument)
        For Each oAxis In oDoc.ComponentDefinition.WorkAxes
            If oAxis.Name Like "MISALIGNED *" Then oAxis.Delete()
        Next
    End Sub


    Public Function CompareFaces(ByVal oAxis1 As WorkAxis, ByVal oBody As SurfaceBody, ByVal compDef As AssemblyComponentDefinition, e As DoWorkEventArgs) As Face
        Dim oAxis As WorkAxis
        For Each oFace As Face In oBody.Faces
            If BackgroundWorker1.CancellationPending Then
                e.Cancel = True
                Exit For
            End If
            If oFace.SurfaceType = SurfaceTypeEnum.kCylinderSurface Then
                oAxis = compDef.WorkAxes.AddFixed(oFace.Geometry.BasePoint, oFace.Geometry.AxisVector)
                If oAxis.Line.IsColinearTo(oAxis1.Line) Then
                    oAxis.Delete()
                    Return oFace
                Else
                    oAxis.Delete()
                End If
            End If
        Next
        Return Nothing
    End Function



End Class

 

Message 48 of 69
jjstr8
in reply to: Gabriel_Watson

Your button properties and progress bar need to be set in the UI thread, not the BackgroundWorker thread.  BackgroundWorker has a ReportProgress method that will trigger the ProgressChanged event in the UI thread.  You can pass an integer or an integer and an object.  The integer can be used for your progress bar, and the object can be a custom class with your button text and enabled states or even a simple state code.  The code at the end of your CheckHolesAlignment method should be in your BackgroundWorker1_Completed event handler.

 

Message 49 of 69
Anonymous
in reply to: wayne.brill

ten years later... there is a C# version of starting tutorials?

Message 50 of 69
yan.gauthier
in reply to: Anonymous

Yes, if you install the SDK, there are sample program written in C#, VB.Net and C++

Message 51 of 69
cadman777
in reply to: wayne.brill

To whom it may concern,

 

I just finished the "My First Plugin" tutorial and discovered what I already suspected.

It sucked.

It made me angry b/c it was a waste of my time and energy.

It's the kind of light-weight marketing-oriented 'training' that I've come to expect from Autodesk.

 

In the rest of this rant I'm going to try to be nice, but maybe not so nice.

 

3 of the top principles of EDUCATION are: RELEVANCE, SIMPLICITY and ONE-THING-AT-A-TIME. That's especially true for adults in 'continuing education'. The reason is b/c their heads are so packed full of other things that are necessary to think about, that they have little mental energy to dedicate their minds to learning the way youths do. You just can't rely on FORCE OF MEMORY with most adults.

 

This tutorial failed at all 3. First, it was IRRELEVANT to ANYTHING that most production level drafting and design people do. Second, it was TOO COMPLICATED. And Third, it was a CONGLOMERATION OF CONFUSION, that is, piles of complex code that were only partly explained (about 5% at best).

 

If you want to make a FIRST TUTORIAL relevant to NON-PROGRAMMERS, you have to touch on subjects that are relevant to their daily activities. That way they have something to hang the information on to help them remember it. You have to keep it simple, explain everything, and give many different scenarios as examples on ONE subject.

 

For example, one of THE most important aspects of daily design-drafting is NUMBERING. Inventor's Numbering sucks. It's way too generic, and has no means to customize OTHER THEN coding. That's totally unacceptable in the REAL WORLD. So instead of leaving it at that, why not have an API tutorial that shows people how to customize their NUMBERING process?

 

Another example is, iProperties and Parameters. Setup is everything, from drawing formats, to titleblocks, to drawing views, to PartsLists, to dimension styles, etc. Why not make an API tutorial that shows people how to process all of one type of file in an assembly, changing the iProperty value, while also filtering all parts of certain types that are not to be processed? Processing parts from an assembly or drawing is one of the most frequent things daily production drafters do. But nothing like that is shown in the tutorial. Instead, it shows how to make a UI to do something I doubt ANY production drafter does! If you want to show a useful UI, make it a FILEDIALOG as part of another process mentioned above. UI's are one of the least needed functions in daily production design-drafting work. In fact, I NEVER use a UI when processing files. I just RMB on a rule and RUN it. The UI tutorial is practically worthless.

 

Another example is, DRAWINGS. All, I repeat, ALL the structural steel programs have AUTOMATIC DRAWINGS and DIMENSIONING. One of the most tedious processes in design-drafting is SinglePart DRAWING PRODUCTION. Why not have a tutorial on how to process all of the SingleParts to detail drawings?

 

Unless your tutorials are RELEVANT, they won't be MEANINGFUL and the learning will be little. Unless your tutorials are SIMPLE, they will be CONFUSING and won't 'stick'. Unless your tutorials are LINEAR, they will be lost in the abyss of memory trivia.

 

Take my advice: Get rid of this worthless tutorial and give us something RELEVANT, SIMPLE and LINEAR. And give us more than one tutorial so we can BENEFIT from it in our daily work. And use VBA as well as VB.Net (definitely NOT iLogic). Maybe then you will begin to SUPPORT your customers the way you should in this area of Inventor.

... Chris
Win 7 Pro 64 bit + IV 2010 Suite
ASUS X79 Deluxe
Intel i7 3820 4.4 O/C
64 Gig ADATA RAM
Nvidia Quadro M5000 8 Gig
3d Connexion Space Navigator
Message 52 of 69
jbetz42
in reply to: cadman777

I can only agree. I am just starting with programming but am a long time Inventor user. The ressources Autodesk provides to start from scratch are simply not available, completely outdated or far away from daily working tasks. I have not found a single tutorial that could help me in my daily work routines. Instead you find decade old repositories on Github, Blogs as references that look like they've been coded on a typewriter in 1938 and simply no useful tutorials that would help to transition away from iLogics. It's just sad and frustrating because native Add-Ins could be such an interesting topic to dig into and boost productivity.

 

I simply do not understand why Autodesk does not privide some nice and daily work oriented tutorials. Why not ask in this forum which topics would be relevant and simply make a great video tutorial series that is up to date with todays IDEs and technologies? Interesting usecases are endless e.g.

  • working with the new model states
  • working with iProperties
  • creating some kind of quality checker that continously monitors design quality based on which type of document is opened
  • working with BOMs
  • creating parts in batch with data given from an Excel Sheet
  • ...
Message 53 of 69
yan.gauthier
in reply to: jbetz42

Yeah,

 

I do have an addin that

  • Works with iproperties, Bom, Exporting in step, dwg, pdf.
  • Checks with the vault that the active drawing is the most up to date.
  • Is connected to our ERP to generate the BOM within so we can then generate the purchase orders and the work orders for the project.

All of that based on WPF MVVM pattern... This was a long journey to learn all this. Unfortunately, I do not own the code I developped, so I cannot just upload it to GitHub. Building guides would take me more time than I have available...

 

If you have one precise question, I will gladly see if I have an example I could rip from my code.

Message 54 of 69
JelteDeJong
in reply to: yan.gauthier

Just finished writing my own tutorial. You can find it here: http://www.hjalte.nl/60-creating-an-inventor-addin

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

Message 55 of 69

If you want to have an start point for c# inventor addin. Have a look at my template.

 

C# Template 

Message 56 of 69

@tobias_wiesendanger,

 

Are you in the process of developing any tutorials to go with your template?

-----------------------------------------------------------------------------------------
CAD Administrator
Using Inventor 2022
Autodesk Certified Instructor
Autodesk Inventor 2020 Certified Professional
Autodesk AutoCAD 2017 Certified Professional
Message 57 of 69

There are no plans for that. I was hoping the readme is already a good start.

Message 58 of 69
JBerns
in reply to: wayne.brill

Ackn. Thanks, Tobias.

-----------------------------------------------------------------------------------------
CAD Administrator
Using Inventor 2022
Autodesk Certified Instructor
Autodesk Inventor 2020 Certified Professional
Autodesk AutoCAD 2017 Certified Professional
Message 59 of 69
llorden4
in reply to: JelteDeJong

llorden4_0-1677167070215.png

 

Looking forward to reading this, appreciated!

Autodesk Inventor Certified Professional
Message 60 of 69
JelteDeJong
in reply to: llorden4

I did forget that the link was here. Otherwise, I would have posted some updates. Now the tutorial consists of 7 parts. And I have grouped them. They aren't between all other blog posts any more. Old links still work but you can find the overview page here:

http://www.hjalte.nl/tutorials

 

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

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Technology Administrators


Autodesk Design & Make Report