I haven't been in programming for AutoCAD in a while, and I have created a new Palette Set and have set it up to work around AutoCAD's intricacies, but I can't seem to stop the crash when closing Autocad error. (harmless to the user at that time, but very annoying). Here is my Palette Set activation and maintenance code:
Imports System.Windows.Forms Imports Autodesk.AutoCAD.Runtime Imports Autodesk.AutoCAD.Windows Imports Autodesk.AutoCAD.Geometry Imports Autodesk.AutoCAD.EditorInput Imports Autodesk.AutoCAD.DatabaseServices.Filters Imports Autodesk.AutoCAD.ApplicationServices Imports Autodesk.AutoCAD.DatabaseServices Imports System.Drawing Imports System.Windows.Forms.Integration Imports AApplication = Autodesk.AutoCAD.ApplicationServices.Application Public Class TTSPaletteSet Implements Autodesk.AutoCAD.Runtime.IExtensionApplication Public Sub Initialize() Implements Autodesk.AutoCAD.Runtime.IExtensionApplication.Ini
tialize AddHandler AApplication.DocumentManager.DocumentToBeDeactivat ed, AddressOf DocToBeDeactivated AddHandler AApplication.DocumentManager.DocumentToBeActivated , AddressOf DocToBeActivated AddHandler AApplication.DocumentManager.DocumentDestroyed, AddressOf DocDestroyed AddHandler AApplication.DocumentManager.DocumentCreated, AddressOf DocCreated End Sub Public Sub Terminate() Implements Autodesk.AutoCAD.Runtime.IExtensionApplication.Ter minate palSet.Dispose() End Sub Friend Shared WithEvents palSet As PaletteSet = Nothing Friend Shared WithEvents palCG As Palette = Nothing Friend Shared WithEvents ucCG As uctlCG = Nothing Friend Shared WithEvents mDoc As Autodesk.AutoCAD.ApplicationServices.Document Private Shared booActive As Boolean = False Private Shared booProcessStateChange As Boolean = True Public Shared Function doc() As Autodesk.AutoCAD.ApplicationServices.Document If mDoc Is Nothing Then mDoc = AApplication.DocumentManager.MdiActiveDocument End If Return mDoc End Function <CommandMethod("TTS")> _ Public Shared Sub BuildPalette() Try booActive = True If palSet Is Nothing Then ' Create the palette set Dim guid As New Guid(TTSPaletteGUID) palSet = New PaletteSet("TTS Tools", guid) palSet.Size = New Size(300, 600) palSet.DockEnabled = DirectCast(CInt(DockSides.Left) + CInt(DockSides.Right), DockSides) End If ShowCGPalette() Catch ex As System.Exception MsgBox(ex.ToString) End Try End Sub Public Shared Sub ShowCGPalette() If palSet IsNot Nothing Then If palCG Is Nothing Then ucCG = New uctlCG Dim host As New ElementHost host.AutoSize = True host.Dock = DockStyle.Fill host.Child = ucCG palCG = palSet.Add("CG Calculator", host) End If End If palSet.KeepFocus = True palSet.Visible = True End Sub Private Shared Sub palSet_PaletteActivated(sender As Object, e As Autodesk.AutoCAD.Windows.PaletteActivatedEventArgs ) Handles palSet.PaletteActivated 'MsgBox("PaletteSetActivated") End Sub Private Shared Sub palSet_PaletteSetDestroy(sender As Object, e As System.EventArgs) Handles palSet.PaletteSetDestroy ' MsgBox("PaletteSetDestroyed") If Not palSet Is Nothing Then booProcessStateChange = False palSet.Visible = False booProcessStateChange = True mDoc = Nothing End If End Sub Public Sub DocToBeDeactivated(sender As Object, e As DocumentCollectionEventArgs) 'get current count of documents If AApplication.DocumentManager.Count = 1 Then 'last document open, going to go to 0 document state If Not palSet Is Nothing Then mDoc = Nothing booActive = False booProcessStateChange = False palSet.Visible = False booProcessStateChange = True End If End If End Sub Public Sub DocToBeActivated(sender As Object, e As DocumentCollectionEventArgs) mDoc = e.Document End Sub Public Sub DocDestroyed(sender As Object, e As DocumentDestroyedEventArgs) If AApplication.DocumentManager.Count = 1 Then 'last document open, going to go to 0 document state If Not palSet Is Nothing Then mDoc = Nothing booProcessStateChange = False palSet.Visible = False booProcessStateChange = True End If End If End Sub Public Sub DocCreated(sender As Object, e As DocumentCollectionEventArgs) mDoc = e.Document If palSet IsNot Nothing AndAlso palSet.IsDisposed = False Then If booActive = True Then booProcessStateChange = False palSet.Visible = True booProcessStateChange = True End If End If End Sub Private Shared Sub palSet_StateChanged(sender As Object, e As Autodesk.AutoCAD.Windows.PaletteSetStateEventArgs) Handles palSet.StateChanged If booProcessStateChange = True Then If e.NewState = StateEventIndex.Hide Then booActive = False End If End If End Sub End Class
You are using Aad 2013, aren't you (because there is not PaletteSetDestroy event with my 2012 or older Acad)?
Probably you already know: once a Paletteset is instanciated in AutoCAD, it cannot be destroyed by code, it can be only visible or invisible
I'd go from firstly trying to remove code from IExtensionApplicayion.Terminate(). Have you tried to start Acad, NETLOAD you DLL, and then WITHOUT RUN YOUR COMMAND (so, the paletteSet is not instanciated), close Acad right away? In this case, the code palSet.Dispose() would be illegal, because palSet has not be set (Nothing) can cannot be called for disposing. OTH, there is really no need to dispose it: AutoCAD is shutting down, everything is AutoCAD is gone anyway.
Unless, your override PaletteSet's Dispose() method to properly dispose some other resources used in controls added to the PaletteSet. If it is this case, make sure your overriding Dispose() does not try to dispose some AutoCAD stuff, because at the stage of Terminate(), most AutoCAD stuff has already gone. In this case, you should do
If palSet IsNot Nothing Then palSet.Dispose()
But from your code, it seems you did not subclass the PaletteSet. But I'd still try to remove code in Terminate() first.
Then, you can try to remove code in PaletteSetDestroy event handler. Again, there is no need for the code as yours to set some status flags - by the time the PaletteSet is to be destroyed, AutoCAD has been in its way of shutting down without chance turning back and most Acad stuff is not reachable. Why you need to set status flags then?
--------------------------- Exception in c:\program files\autodesk\applicationplugins\sbd.bundle\conte
Perhaps I'm barking up the wrong tree? this is the crash I'm getting regularly. This will happen even if I don't activate my palette, just open AutoCAD and Close.
Infact, that crash happend, then the stop in my code for terminate took place. They are definitely un-related issues. But since we are on the topic of Palette Set's, you mentioned that I was not inheriting the Palette Set in my code (wrapping the object). Now I'm curious as to your best practice on working with a Palette Set in 2013. I am making a single Palette Set with multiple palettes for each company tool I write.
PaletteSet was sealed class (not inheritable) before Acad 2009. I'd prefer to derive my PaletteSet:
public class MyPaletteSet : Autodesk.AutoCAD.Windows.PaletteSet
public/private Windows.Forms.Control palettes;
//initialize the paletteSet
Then you can add method to clean up, if necessary. and of course you'd likely override Dispose() method of the raw PaletteSet
With derived PaleteeSet, the code is much cleaner. However, deriving it or not, it does not directly solve your issue. Since you use WPF user control as palette and hosted in PaletteSet with ElementHost, I suspect if it is the a possible cause.
As I said previously, your PaletteSet.Dispose in terminate() method was problemetic, because the PaletteSet could well be null, if user did not show the PaletteSet during the Acad session, thus the Dispose() call would fail.
If you could try to create the equivalent palette(s) with Windows.Form user controls and see if your code still crash Acad the same way?
Also, what version of ACAD you use?
I also have some .NET code on Acad Map .NET API, which causes seriuos fatal error when AutoCAD closes, harmless but annoying. I also could not find out the reason for many years with acad Map 2006/7/8/9. But is is not PaletteSet. I was so fed up with it and almost decided to rewrite the app in completely different way, just to show user that I can get rid of it. And then when I got acad Map 2012, the Acad closing fatal error is completely gone. I am trying to say is that sometimes, this type of fatal error may not be all our fault.
But again, I'd alway derive my custom PaletteSet instead of just instatiate a raw PaletteSet and use it in my command method class.
I'll have to give that derived palette set a try, because I too like that idea. When I get something up, I.ll let you know what I created. It may be a while though. I would also like to try the windows form's difference. Before this job, my palettes were based on windows forms contols. BTW I am using AutoCAD 2013 (Mechanical, as part of the Product Design Suite 2013 Premium). Thank you for your help, I'll reply to this post when I have rewritten it.
Access a broad range of knowledge to help get the most out of your products and services.