-1

I'm creating a program that has a "rehost workflowdesigner" (like Autodesk SubAssembly Composer did) and it fails to create the toolbox controls.

The error that occurs: System.IO.FileNotFoundException: Could not load file or assembly....

So far I understand that, because the DLL is not in the GAC, windows cannot find it.

So I tested the following hypotheses:

  1. NETLOAD for the first time, without setting DLL folder in "support file search path" when calling the command, result: ERROR

  2. Add the DLL folder to the "support file search path" and then NETLOAD when calling the command, result: WORKS

  3. Enable autoload by the "LOADCTRLS" key (defined in IExtensionApplication.Initialize), without adding the DLL in the "support file search path" when calling the command, result: ERROR

  4. Now that the dll is loaded by the registry ("LOADCTRLS" ), still without the "support file search path" when calling the command, result: ERROR

  5. In the same cad session as in step 4, add the DLL to the ""support file search path", editing the field without clicking the "Browse" button when calling the command, result: ERROR

  6. In the same cad session as in step 5, add the DLL to the ""support file search path", editing the field by clicking the "Browse" button when calling the command, result: ERROR

  7. In the same cad session as in step 6, I call the NETLOAD command (filedia=1), navigate to the DLL folder, DO NOT SELECT ANYTHING AND CLICK CANCEL when calling the command, result: WORKS

  8. I close cad, open it again, set FILEDIA=0 when calling the command, result: ERROR

  9. In the same cad session of step 8, NETLOAD, I inform the full path of the DLL when calling the command, result: ERROR

  10. In the same cad session as in step 9, FILEDIA=1, NETLOAD, I navigate to the folder, but I don't select anything, as in step 7, when calling the command, result: WORKS

So it concludes that the NETLOAD command doesn't just do an "Assembly.LoadFrom".

And the fact that it works with FILEDIA=1, makes me believe that it is the part of the code that shows the NETLOAD window that somehow makes the DLL, or its types visible and the System.IO.FileNotFoundException error does not occur

I added the code so you can look. If you can help me, thank you

"MyCustomActivity.vb"

Imports System.Activities
Imports System.Activities.Presentation
Imports System.ComponentModel
Imports System.Drawing
Imports System.Windows
Imports System.Windows.Media
Imports System.Windows.Media.Imaging

<ToolboxBitmap(GetType(MyCustomActivity), "arc.png"), Designer(GetType(MyCustomDesigner))>
Public Class MyCustomActivity
    Inherits CodeActivity

    Protected Overrides Sub Execute(context As CodeActivityContext)
        'faz alguma coisa
    End Sub
End Class

Public NotInheritable Class MyCustomDesigner
    Inherits MyActivityDesigner
    Public Sub New()
        MyBase.New(GetType(MyCustomActivity))
    End Sub
End Class


Public MustInherit Class MyActivityDesigner
    Inherits ActivityDesigner

    Public Sub New(customActivityType As Type)
        Dim toolAttrib As ToolboxBitmapAttribute = customActivityType.GetCustomAttributes(GetType(ToolboxBitmapAttribute), True)(0)
        Using bitmap As New Bitmap(toolAttrib.GetImage(customActivityType))
            Dim ImageDrawing As New ImageDrawing(System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(bitmap.GetHbitmap,
                                                                            IntPtr.Zero,
                                                                            Int32Rect.Empty,
                                                                            BitmapSizeOptions.FromEmptyOptions),
                                      New Rect(0, 0, 16, 16))
            Me.Icon = New DrawingBrush(ImageDrawing)
        End Using
    End Sub
End Class

"TestClass.VB"

Imports System.Reflection
Imports Microsoft.Win32
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.DatabaseServices
Imports System.IO

Public NotInheritable Class TesteClass
    'precisa ser public, senao IExtensionApplication nao funciona
    Implements IExtensionApplication

    Public Shared ReadOnly PRODUCTKEY As String = HostApplicationServices.Current.UserRegistryProductRootKey
    Public Shared ReadOnly LOADER As String = Reflection.Assembly.GetExecutingAssembly.Location
    Public Shared ReadOnly PASTA As String = New FileInfo(LOADER).DirectoryName

    Public Sub Initialize() Implements IExtensionApplication.Initialize
        Try

            Dim cUserApp = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(PRODUCTKEY & "\Applications", True)

            With cUserApp.CreateSubKey(My.Application.Info.Title)
                .SetValue("DESCRIPTION", My.Application.Info.Description)

                .SetValue("MANAGED", 1, RegistryValueKind.DWord)

                .SetValue("LOADCTRLS", 2, RegistryValueKind.DWord)

                .SetValue("LOADER", System.Reflection.Assembly.GetExecutingAssembly.Location)

                Try
                    .DeleteSubKey("Commands")
                Catch
                End Try

                With .CreateSubKey("Commands")
                    For Each tp As Type In Assembly.GetExecutingAssembly.GetExportedTypes()
                        For Each meth As MethodInfo In tp.GetMethods()
                            For Each obj As CommandMethodAttribute In meth.GetCustomAttributes(GetType(CommandMethodAttribute), True)
                                .SetValue(obj.GlobalName, obj.GlobalName)
                            Next
                        Next
                    Next
                End With
            End With

        Catch
        End Try

    End Sub

    Public Sub Terminate() Implements IExtensionApplication.Terminate
    End Sub

    <CommandMethod("teste")>
    Public Sub teste()

        Dim f As New Form1
        f.ShowDialog()
    End Sub
End Class

"Form1.vb"

Imports System.Activities
Imports System.Activities.Core.Presentation
Imports System.Activities.Presentation
Imports System.Activities.Presentation.Toolbox
Imports System.Activities.Statements
Imports System.Windows
Imports System.Windows.Forms



Public Class Form1
    Private Shared _firsload As Boolean = True

    Public Sub New()
        Dim dd As New DesignerMetadata()
        dd.Register()

        ' Esta chamada é requerida pelo designer.
        InitializeComponent()

        ' Adicione qualquer inicialização após a chamada InitializeComponent().

        Dim WorkflowDesigner As New WorkflowDesigner
        Dim ActivityBuilder As New ActivityBuilder With {.Implementation = New Flowchart}

        WorkflowDesigner.Load(ActivityBuilder)

        Dim ctrl As New ToolboxControl()
        'Dim item As New ToolboxItemWrapper("TesteCAD.MyCustomActivity", TesteClass.LOADER, "", "teste")
        Dim item As New ToolboxItemWrapper(GetType(MyCustomActivity), "teste")
        ctrl.Categories.Add(New ToolboxCategory("teste") From {item})

        ElementHost1.Child = ctrl
        ElementHost2.Child = WorkflowDesigner.View
    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
        Dim wd As New WorkflowDesigner

        Using lixo As New Form With {.Size = New System.Drawing.Size(1, 1), .ShowInTaskbar = False, .FormBorderStyle = FormBorderStyle.None}
            Dim elementHost As New Integration.ElementHost
            lixo.Controls.Add(elementHost)
            elementHost.Child = wd.View

            AddHandler lixo.Activated, Sub()
                                           Forms.Application.DoEvents()
                                           lixo.Close()
                                       End Sub
            lixo.ShowDialog()
        End Using

    End Sub
End Class

"Form1.Designer.vb"

Imports System.Windows.Forms

<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Class Form1
    Inherits System.Windows.Forms.Form

    'Descartar substituições de formulário para limpar a lista de componentes.
    <System.Diagnostics.DebuggerNonUserCode()> _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub

    'Exigido pelo Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'OBSERVAÇÃO: o procedimento a seguir é exigido pelo Windows Form Designer
    'Pode ser modificado usando o Windows Form Designer.  
    'Não o modifique usando o editor de códigos.
    <System.Diagnostics.DebuggerStepThrough()> _
    Private Sub InitializeComponent()
        Me.SplitContainer1 = New System.Windows.Forms.SplitContainer()
        Me.ElementHost1 = New System.Windows.Forms.Integration.ElementHost()
        Me.ElementHost2 = New System.Windows.Forms.Integration.ElementHost()
        CType(Me.SplitContainer1, System.ComponentModel.ISupportInitialize).BeginInit()
        Me.SplitContainer1.Panel1.SuspendLayout()
        Me.SplitContainer1.Panel2.SuspendLayout()
        Me.SplitContainer1.SuspendLayout()
        Me.SuspendLayout()
        '
        'SplitContainer1
        '
        Me.SplitContainer1.Dock = System.Windows.Forms.DockStyle.Fill
        Me.SplitContainer1.Location = New System.Drawing.Point(0, 0)
        Me.SplitContainer1.Name = "SplitContainer1"
        '
        'SplitContainer1.Panel1
        '
        Me.SplitContainer1.Panel1.Controls.Add(Me.ElementHost1)
        '
        'SplitContainer1.Panel2
        '
        Me.SplitContainer1.Panel2.Controls.Add(Me.ElementHost2)
        Me.SplitContainer1.Size = New System.Drawing.Size(800, 450)
        Me.SplitContainer1.SplitterDistance = 266
        Me.SplitContainer1.TabIndex = 0
        '
        'ElementHost1
        '
        Me.ElementHost1.Dock = System.Windows.Forms.DockStyle.Fill
        Me.ElementHost1.Location = New System.Drawing.Point(0, 0)
        Me.ElementHost1.Name = "ElementHost1"
        Me.ElementHost1.Size = New System.Drawing.Size(266, 450)
        Me.ElementHost1.TabIndex = 0
        Me.ElementHost1.Text = "ElementHost1"
        Me.ElementHost1.Child = Nothing
        '
        'ElementHost2
        '
        Me.ElementHost2.Dock = System.Windows.Forms.DockStyle.Fill
        Me.ElementHost2.Location = New System.Drawing.Point(0, 0)
        Me.ElementHost2.Name = "ElementHost2"
        Me.ElementHost2.Size = New System.Drawing.Size(530, 450)
        Me.ElementHost2.TabIndex = 0
        Me.ElementHost2.Text = "ElementHost2"
        Me.ElementHost2.Child = Nothing
        '
        'Form1
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.ClientSize = New System.Drawing.Size(800, 450)
        Me.Controls.Add(Me.SplitContainer1)
        Me.Name = "Form1"
        Me.Text = "Form1"
        Me.SplitContainer1.Panel1.ResumeLayout(False)
        Me.SplitContainer1.Panel2.ResumeLayout(False)
        CType(Me.SplitContainer1, System.ComponentModel.ISupportInitialize).EndInit()
        Me.SplitContainer1.ResumeLayout(False)
        Me.ResumeLayout(False)

    End Sub

    Friend WithEvents SplitContainer1 As SplitContainer
    Friend WithEvents ElementHost1 As Integration.ElementHost
    Friend WithEvents ElementHost2 As Integration.ElementHost
End Class
  • Could you tell use which DLL(s) is causing the issue and perhaps where the issue is occurring? Is it actually at runtime in your code posted above or is it a build issue? – Hursey Jan 18 '22 at 19:41
  • The exception System.IO.FileNotFoundException Occurs when 'System.Activities.Presentation.Toolbox.ToolboxItemWrapper.ResolveToolboxItem' tries to 'discover' the activity type – Neyton Luiz Dalle Molle Jan 20 '22 at 11:46
  • Note, changing this line: Dim item As New ToolboxItemWrapper(GetType(MyCustomActivity), "teste") To: Dim item As New ToolboxItemWrapper("TesteCAD.MyCustomActivity", TesteClass.LOADER, "", "teste") On "Form1.vb" The form opens, but the activity does not drag/drop – Neyton Luiz Dalle Molle Jan 20 '22 at 11:46

1 Answers1

0

I found a solution by adding an AssemblyResolve event to the current AppDomain:

Private Shared Function MyHandler(ByVal source As Object, ByVal e As ResolveEventArgs) As Assembly
        Return If(e.Name = GetType(TesteClass).Assembly.FullName, Assembly.LoadFile(LOADER), Nothing)
    End Function

And I added the following line in 'Initialize':

AddHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf MyHandler

Worked perfectly!!!