My Document.Database.beginsave event only fires once.
After I try saving the file again the .beginsave event doesn't trigger.
Why isn't the Autocad firing the .BeginSave each time I save or qsave?
Am I using the correct event?
Public Sub AddDocEvents() Try DocMan = AcApp.DocumentManager 'Adds Document Created Handler AddHandler DocMan.DocumentCreated, AddressOf callback_documentCreated 'Adds Document BeingSave/SaveComplete Handlers Dim doc As Document For Each doc In DocMan Dim db As Database = doc.Database AddHandler db.BeginSave, AddressOf callback_BeginSave AddHandler db.SaveComplete, AddressOf callback_SaveComplete Next ed.WriteMessage("<<[Register]: AddDocEvent>>" & Environment.NewLine) Catch ex As Exception ed.WriteMessage("<<[Error]: AddDocEvents>>" & Environment.NewLine) End Try End Sub
Private Sub callback_documentCreated(ByVal sender As Object, ByVal e As DocumentCollectionEventArgs) If e.Document = Nothing Then Exit Sub End If 'Step 1 -Add Document BeginSave & SaveComplete Handlers Dim db As Database = e.Document.Database AddHandler db.BeginSave, AddressOf callback_BeginSave AddHandler db.SaveComplete, AddressOf callback_SaveComplete 'Step 2- Check for Pstyles Mode modAcadDoc.Fix_DWGs_Without_A_CTB_Style() End Sub
Private Sub callback_BeginSave(ByVal sender As Object, ByVal e As DatabaseIOEventArgs) Dim myDwg As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument AcApp.ShowAlertDialog("BeginSave: " + e.FileName) 'Step 1: Update Drawing Stamp Dim Stamp As New clsDwgStamp If modRegistry.DWGSTAMP.ToString = eDWGSTAMP.StampOn Then MsgBox("STAMP ON") Stamp.UpdateDWGSTAMP() End Sub
Solved! Go to Solution.
Solved by StephenPreston. Go to Solution.
Hi VB_AutoCad_Guy,
If I had to guess, I'd say that an exception is being thrown in one of your events handlers. You don't enclose your event handler code in Try...Catch blocks - this is extremely dangerous. Any managed exception thrown by your code is getting passed back to AutoCAD - and AutoCAD's behavior when handling exceptions thrown by your code are passed across the managed/unmanaged code boundary is not defined. I'm suggesting this as a possible cause because I've seen this exact behavior before - events being disabled by unhandled exceptions.
Try setting your debugger to stop when an exception is thrown instead of just when its not handled and see if that's the reason. If its not, then sorry for the incorrect suggestion - but you need to add that exception handing anyway.
Cheers,
Stephen Preston
Autodesk Developer Network
Good Morning Stephen,
Thank you so much for your response.
We'll I've had problems before when my Intialize Procedure had errors in it and the rest of the Autocad .NET DLL didn't load properly. This is where I learned that it needs to load cleanly. As an exception will prevent the entire dll to stop working properly.
Could you please expound upon how to handle some the exceptions I'm possibly dealing with?
This is a subject I could afford to learn more about. As I'm new to VB.NET. Or maybe a good web-site to read up more about exception handling and properly dealing with them.
Can you tell me how to set my Debug Preference to Stop when there is an exception?
I know where the setting is in VBA... but VB.NET haven't found that setting as of yet.
This is my best guess.
Ah Hah!
We'll I've discovered the problem.
I commented one line of code out which reads my registry for a startup value.
So I've isolated the problem.
' If modRegistry.DWGSTAMP.ToString = eDWGSTAMP.StampOn Then MsgBox("STAMP ON")
The point in my modregistry.dwgstamp function is to have a Boolean flag for User Mode versus Admin Mode.
As Admin mode we don't want our Drawing Stamps Updated as our Admin's do batch processing of files for maintenance purposes.
So Yes... I'm getting an error or exception. (What's the difference between an error and an exception?)
I'm a self-taught programmer so forgive my ignorance.
#Region "Imports" Imports Autodesk.AutoCAD.Runtime Imports Autodesk.AutoCAD.DatabaseServices Imports Autodesk.AutoCAD.ApplicationServices Imports AcApp = Autodesk.AutoCAD.ApplicationServices.Application #End Region <Assembly: ExtensionApplication(GetType(clsEvents))> Public Class clsEvents Implements Autodesk.AutoCAD.Runtime.IExtensionApplication 'Variables Private DocMan As DocumentCollection 'Initialize sub ''' <summary> ''' Initializes Trigger -This Code runs when the .NET dll is loaded into Autocad ''' </summary> ''' <remarks><para>This Code Intializes All Application And Document Events</para> ''' <para>See http://forums.autodesk.com/autodesk/attachments/autodesk/152/15076/1/VB%20-%20Ext%20App%20Monitor%20...</para> ''' <para>See http://through-the-interface.typepad.com/through_the_interface/2006/09/initialization_.html</para> ''' <para>See http://msdn.microsoft.com/en-us/library/cb6t8dtz(v=vs.80).aspxFor how to flag the Registry to Auto Load the .NET Dll into Autocad </para> ''' <para>SEE Autocad 2011 Activate.vbs for the Script to Run And Edit the Registry so the .NET DLL Security Permission And Flag are set properly.</para> ''' </remarks> Public Sub Initialize() Implements Autodesk.AutoCAD.Runtime.IExtensionApplication.Initialize 'Step1 -Write Message to Acad Console Window ed.WriteMessage("<<[Initializing] - VB.NET:ClassAutocad2011.dll Loaded>>" & Environment.NewLine) 'Step2 -Check to see if Autocad is Setup Already If Not (modRegistry.IsAcadSetup) Then MsgBox("Please Run the Command 'RunSetup'" & vbCrLf & _ "Your Autocad is NOT Setup Properly." & vbCrLf & vbCrLf & _ " Regards, Your Autocad Administrator") ' modAcadSetup.RunSetup_AC2K11() End If 'Step3 -Initalize All Application Events AddAppEvents() 'Step4 -Initalize All Document Events AddDocEvents() 'Step5 -Add SFR Tab to the Options Dialog ctrlSFROptionsTab1.LoadIt() 'Step6 -Standard Startup Variables modAcadSetup.TurnFileDialogOn() 'Step7 -Write to Access DB Signaling that Autocad is being used by this User modAcadSetup.UserLoggedOn() 'Step8 -Setup Support Paths modAcadSetup.SetupAcadSupportPaths() 'Step9 -Check if SFAR_ISO_UTIL Lisp Routines need to be loaded If modRegistry.IsISOUTIL_ON = True Then Dim acInterface As New clsInterface acInterface.LoadIsoUtilLispRoutines() ed.WriteMessage("<<[Loading] Iso Lisp Routines >>" & Environment.NewLine) End If 'Step10 -Write Message to Acad Console Window of Success ed.WriteMessage("<<[Finished Initializing] ClassAutocad2011.dll is Successful >>" & Environment.NewLine) End Sub 'Terminate sub Public Sub Terminate() Implements Autodesk.AutoCAD.Runtime.IExtensionApplication.Terminate 'RemoveAppEvents() 'RemoveDocEvents() End Sub ''' <summary> ''' 'Register Application Events ''' </summary> ''' <remarks>This Activates the Application Events -Such as Begin Quit</remarks> Public Sub AddAppEvents() AddHandler Application.BeginQuit, AddressOf appBeginQuit ed.WriteMessage("<<[Register]: AddAppEvent>>" & Environment.NewLine) End Sub ''' <summary> ''' Removes Applications Events Upon Closing of .NET DLL ''' </summary> ''' <remarks></remarks> Public Sub RemoveAppEvents() 'RemoveHandler Application.BeginQuit, AddressOf appBeginQuit End Sub ''' <summary> ''' App Event Sub Routine to Run Each Time Event is Triggered ''' </summary> ''' <param name="senderObj"></param> ''' <param name="sysAppBeginQuitArgs"></param> ''' <remarks></remarks> Public Sub appBeginQuit(ByVal senderObj As Object, _ ByVal sysAppBeginQuitArgs As System.EventArgs) modAcadSetup.UserLoggedOff() End Sub ''' <summary> ''' Add Document Events ''' </summary> ''' <remarks>This Activates the Autocad Document Events for Autocad</remarks> ''' Public Sub AddDocEvents() DocMan = AcApp.DocumentManager 'Adds Document Created Handler AddHandler DocMan.DocumentCreated, AddressOf callback_documentCreated 'Adds Document BeingSave/SaveComplete Handlers Dim doc As Document For Each doc In DocMan Dim db As Database = doc.Database AddHandler db.BeginSave, AddressOf callback_BeginSave AddHandler db.SaveComplete, AddressOf callback_SaveComplete Next ed.WriteMessage("<<[Register]: AddDocEvent>>" & Environment.NewLine) End Sub Public Sub RemoveDocEvents() 'RemoveHandler DocMan.DocumentCreated, AddressOf callback_documentCreated End Sub Private Sub callback_BlockInserted(ByVal Sender As Object, ByVal e As System.EventArgs) End Sub ''' <summary> ''' documentCreated handler ''' </summary> ''' <param name="sender"></param> ''' <param name="e"></param> ''' <remarks></remarks> Private Sub callback_documentCreated(ByVal sender As Object, ByVal e As DocumentCollectionEventArgs) If e.Document = Nothing Then Exit Sub End If 'Step 1 -Add Document BeginSave And SaveComplete Handlers Dim db As Database = e.Document.Database AddHandler db.BeginSave, AddressOf callback_BeginSave AddHandler db.SaveComplete, AddressOf callback_SaveComplete 'Step 2- Check for Pstyles Mode modAcadDoc.Fix_DWGs_Without_A_CTB_Style() End Sub ''' <summary> ''' SaveBegin handler ''' </summary> ''' <param name="sender"></param> ''' <param name="e"></param> ''' <remarks>Place Code here that runs off the BeginSave Event</remarks> Private Sub callback_BeginSave(ByVal sender As Object, ByVal e As DatabaseIOEventArgs) Dim myDwg As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument AcApp.ShowAlertDialog("BeginSave: " + e.FileName) 'Step 1: Update Drawing Stamp Dim Stamp As New clsDwgStamp ' If modRegistry.DWGSTAMP.ToString = eDWGSTAMP.StampOn Then MsgBox("STAMP ON") Stamp.UpdateDWGSTAMP() End Sub ''' <summary> ''' SaveComplete handler ''' </summary> ''' <param name="sender"></param> ''' <param name="e"></param> ''' <remarks></remarks> Private Sub callback_SaveComplete(ByVal sender As Object, ByVal e As DatabaseIOEventArgs) Dim myDwg As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument AcApp.ShowAlertDialog("SaveComplete: " + e.FileName) 'myDwg.Database.Save() End Sub End Class
Friend Enum eDWGSTAMP
StampOn = 1
StampOff = 0
End Enum
Public Property DWGSTAMP() As eDWGSTAMP Get Dim ThisKey As RegistryKey Dim sKeyValue As String Try If Registry.CurrentUser.OpenSubKey(SFRSubKey) Is Nothing Then CreateSFRSubKey() ThisKey = Registry.CurrentUser.OpenSubKey(SFRSubKey, True) sKeyValue = ThisKey.GetValue(cDWGSTAMP, Nothing) DWGSTAMP = sKeyValue debug.writeline("<<DWGSTAMP: " & sKeyValue & ">>" & Environment.NewLine) ThisKey.Close() Catch DWGSTAMP = "" debug.writeline("Error on Registry: DWGSTAMP") End Try End Get Set(ByVal Value As eDWGSTAMP) Dim ThisKey As RegistryKey Try If Registry.CurrentUser.OpenSubKey(SFRSubKey) Is Nothing Then CreateSFRSubKey() ThisKey = Registry.CurrentUser.OpenSubKey(SFRRodeoSubKey, True) Dim iInputValue As Integer Select Case Value Case eDWGSTAMP.StampOff iInputValue = 0 ThisKey.SetValue(cDWGSTAMP, iInputValue) Case eDWGSTAMP.StampOn iInputValue = 1 ThisKey.SetValue(cDWGSTAMP, iInputValue) End Select ThisKey.Close() debug.writeline("<<DWGSTAMP: " & Value & ">>" & Environment.NewLine) Catch debug.writeline("Error on Registry: DWGSTAMP ") End Try End Set End Property
Cool. I'm glad you found the problem.
To stop when an exception is thrown, go to the VS Debug menu, select the Exceptions... menu item (CTRL+ALT+E on my setup - I'm using a professional VS version - not sure if its there for Express). You'll see a list of exception types there with a checkbox next to each under the heading 'Thrown'. Set the checkbox for each Exception type you want to stop for as its thrown. Hint - Don't set these options until you're close to executing the piece of code you think the exception is coming from. An Exception isn't necessarily an error - its just an unusual (exceptional) event. When you start up AutoCAD, you'll probably see lots of Exceptions thrown if you look for them, but AutoCAD handles them, and moves on. Same for any significant application.
And always bear in mind that the AutoCAD .NET API is a thin wrapper on top of the unmanaged C++ ObjectARX API. Not catching exceptions in your event handlers is something of a special case. You'll normally get away with it if an exception isn't handled in a CommandMethod - AutoCAD will usually display an unhandled exception dialog and then allow you to continue. (Although your users probably won't be very happy if they start seeing those dialogs appearing all over the place
I don't have any specific recommendation for an article on exception handling, but it should be covered in any good (.NET) programming book, and googling for 'exception handling' will return some useful online articles.
Hope this helps.
Cheers,
Stephen