how execute code or add code while the document be closing

how execute code or add code while the document be closing

Anonymous
Not applicable
2,286 Views
10 Replies
Message 1 of 11

how execute code or add code while the document be closing

Anonymous
Not applicable

Hi everyone
i am developing my plugin using VB.NET 2012, i need my aplication execute a code while the document revit be closing.
for example show me a message "¿sure close the document?" or add a code more complex.

¿is possible to make this?, somebody give me a code example to make this

 

regards

 

  

0 Likes
2,287 Views
10 Replies
Replies (10)
Message 2 of 11

arnostlobel
Alumni
Alumni

Hello marcosmateo:

 

Please refer to the Application.DocumentClosing event in the SDK documentation (RevitAPI.chm file) for details.

Arnošt Löbel
0 Likes
Message 3 of 11

Anonymous
Not applicable

Thank You arnostlobel

 

My application has a counter revit documents, when open a document, start a timer and capture the document name. when the document is closing the application stops the timer and stored in a data base access the counter value and the name of the document.

 

see the SDK documentation. now i am using DocumentClosing event. this is my code: 

 

Private Sub DocumentClosing(sender As Object, e As Autodesk.Revit.DB.Events.DocumentClosingEventArgs)
 
  If Not FileOpened = "" Then
     Try
          Dim frm As New Frm_Registro
          frm.Show()
          frm.Parar_timer()
          Dim sql As String = "UPDATE CONTROL_MODELO SET ACTIVIDAD = '" + frm.txtactividad.Text + "' WHERE ID_CONTROL = " + CodigoControl + ""
          Dim comandos_up As New OleDb.OleDbCommand
          comandos_up = New OleDb.OleDbCommand(sql, cn)
          comandos_up.ExecuteNonQuery()
          MessageBox.Show("The document is closing", "DCV Consultores", MessageBoxButtons.OK, MessageBoxIcon.Asterisk)
          frm.Reset_timer()
          frm.Close()
          FileOpened = ""
     Catch ex As Exception
          MsgBox("Error: " & ex.Message, MsgBoxStyle.Critical, "DCV Consultores")
     End Try

   End If

End Sub

 

works, but when I click on the "ok" button in the dialog workset revit, run the event documentClosing. 

 

 

Sin título.png

 

this is a error!!. the aplication should execute the DocumentClosing event when closed the document revit and not to close a dialog box

 

you cant help me please?

 

 

 

 

 

 

0 Likes
Message 4 of 11

arnostlobel
Alumni
Alumni

You are right; if there is an observable document being closed without Revit raising both DocumentClosing and DocumentClosed events, it would be a bug. However, I cannot  yet confirm that what you experience is indeed a bug in Revit. For that I need to be able reproduce the steps you took, and I do not know what they are yet.  First of all, I need to know the version of Revit you use. Then I need to know a bit more about the actual situation, like: What kind of document you are closing? How did you open it? Via the API or via the UI? Is it the only document open or are there more documents still open in Revit at the time of that one document being close? Then, I would like you to report the exact steps you took to close the document? You provided a screenshot, but it is a bit too small for me to read it, unfortunately. Is it the dialog prompting to relinquish worksets? Please always provide as detailed information as you can, especially when you suspect you found a bug in Revit. You can never be too detailed. 

 

One more thing that may be of use to your application. You should know that receiving a DocumentClosing event is not an indication that a document is going to be closed. It is just an indication of the user's (end-user or and addin) intention to close a document. After that event there are still going to be opportunities for canceling the closing action. There will, however, be a DocumentClosed event raised after that which will indicate whether the closing action actually finished or not. Thus, if your application needs to rely on actual closing, I suggest you make it listening to the latter event instead.

 

Thank you

Arnošt Löbel
0 Likes
Message 5 of 11

Anonymous
Not applicable

Thank's Arnošt

 

My plugin is a activity control that counts the time used in the development of a project.

 

I using Win7 (64 Bits), Revit 2014, VB.Net 2012, access 2010 (64 bist)

 

i am open the document revit (*.rvt) from the revit api following this steps:

 

  1. create ribbon panel and pushBotton
  2. call a OpenFiledialog, select document revit (*.rvt)  and open file
  3. capture the file name revit (.rvt) in the variable fileopened
  4. start the timer of my form frm_registro

if the user closed the document

 

5.  stop timer

6.  save value timer and file name revit in my data base access 2010 (64 Bits)

7.  reset timer and emply the variable fileopened

 

this is my code for open file:

 

 Public Function Execute(
      ByVal commandData As ExternalCommandData,
      ByRef message As String,
      ByVal elements As ElementSet) _
    As Result Implements IExternalCommand.Execute

        Dim uiapp As UIApplication = commandData.Application
        Dim uidoc As UIDocument = uiapp.ActiveUIDocument
        Dim app As Autodesk.Revit.ApplicationServices.Application = uiapp.Application

        Dim frm As New Frm_Registro
        For Each Form In Windows.Forms.Application.OpenForms
            If (Form.Name = "Frm_Registro") Then
                frm = Form
            End If
        Next
        frm.Show()

        With frm.OpenFileDialog1

            .Title = "DCV Consultores - Buscar Proyecto BIM"
            .Filter = "Revit Files|*.rvt"

            .RestoreDirectory = True

            If frm.OpenFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then

                uiapp.OpenAndActivateDocument(.FileName)
                FileOpened = commandData.Application.ActiveUIDocument.Document.PathName()

                Try
                    Dim FECHA As String = DateTime.Today
                    Dim HORA As String = Now.ToString("HH:mm:ss")
                    'Dim parteruta() As String = FileOpened.Split("\")
                    'Dim int As Integer = parteruta.LongLength

                    'codigo para separar la ruta del modelo central por \
                    Dim parteruta() As String = FileOpened.Split("\")
                    'contar cuantos segmentos hay en la variable cargada con la ruta del modelo central
                    Dim int As Integer = parteruta.LongLength - 1

                    cliente = parteruta(int - 4) ' asignando parte de la ruta (cliente) al txtcliente
                    proyecto = parteruta(int - 3) ' asignando parte de la cadena (proyecto) al txtproyecto
                    especialidad = parteruta(int - 2) ' asignando parte de la cadena (especialidad) al txtespecialidad
                    archivo = parteruta(int) ' asignando parte de la cadena (nombre archivo central) a la variable mod_local

                    conectarDB()
                    Dim comandos As New OleDbCommand
                    Dim sql As String = "insert into CONTROL_MODELO (USUARIO, CLIENTE, PROYECTO, ESPECIALIDAD, ARCHIVO, FECHA, HORA_INI, ACTIVIDAD, OBSERVACION)" _
                                        & "VALUES (@USUARIO, @CLIENTE, @PROYECTO, @ESPECIALIDAD, @ARCHIVO, @FECHA, @HORA_INI, @ACTIVIDAD, @OBSERVACION)"
                    comandos = New OleDbCommand(sql, cn)
                    comandos.Parameters.AddWithValue("@USUARIO", Windows.Forms.SystemInformation.ComputerName & " - " & Windows.Forms.SystemInformation.UserName)
                    comandos.Parameters.AddWithValue("@CLIENTE", cliente)
                    comandos.Parameters.AddWithValue("@PROYECTO", proyecto)
                    comandos.Parameters.AddWithValue("@ESPECIALIDAD", especialidad)
                    comandos.Parameters.AddWithValue("@ARCHIVO", archivo)
                    comandos.Parameters.AddWithValue("@FECHA", FECHA)
                    comandos.Parameters.AddWithValue("@HORA_INI", HORA)
                    comandos.Parameters.AddWithValue("@ACTIVIDAD", 0)
                    comandos.Parameters.AddWithValue("@OBSERVACION", "")
                    comandos.ExecuteNonQuery()

                    Dim str As String = "SELECT MAX(ID_CONTROL) as ULT_NRO FROM CONTROL_MODELO"
                    Dim cmmd As New OleDbCommand(str, cn)
                    Dim id_avance As Integer = Convert.ToInt32(cmmd.ExecuteScalar())
                    CodigoControl = Convert.ToString(id_avance + 0)

                    MsgBox("Inicio de Actividad, el Modelo " & .SafeFileName & " se encuentra disponible", MsgBoxStyle.Information, "DCV Consultores")

                    frm.Iniciar_Timer()
                    'frm.ocultar()

                Catch ex As Exception
                    MsgBox("Error: " & Err.Description, MsgBoxStyle.Critical, "DCV Consultores")

                End Try

            End If
        End With

        Return Result.Succeeded
    End Function

End Class

 

this is my code when closed document

 

Private Sub DocumentClosing(sender As Object, e As Autodesk.Revit.DB.Events.DocumentClosingEventArgs)

        If Not FileOpened = "" Then
            Try
                Dim frm As New Frm_Registro
                frm.Show()
                frm.Parar_timer()

                Dim sql As String = "UPDATE CONTROL_MODELO SET ACTIVIDAD = '" & frm.txtactividad.Text & "' WHERE ID_CONTROL = " & CodigoControl & ""
                ' Dim sql As String = "UPDATE CONTROL_MODELO SET ACTIVIDAD = '" & Cronometro & "' WHERE ID_CONTROL = " & CodigoControl & ""
                Dim comandos_up As New OleDb.OleDbCommand
                comandos_up = New OleDb.OleDbCommand(sql, cn)
                comandos_up.ExecuteNonQuery()
                MessageBox.Show("Se esta cerrando el modelo " & FileOpened & ", " & frm.txtactividad.Text, "DCV Consultores", MessageBoxButtons.OK, MessageBoxIcon.Asterisk)
                frm.Reset_timer()
                frm.Close()
                FileOpened = ""
            Catch ex As Exception
                MsgBox("Error: " & ex.Message, MsgBoxStyle.Critical, "DCV Consultores")
            End Try
        End If

    End Sub

  this is the image the error

 

 

Sin título.png

 

 

It's all the details of my application, il will use the documentclosed event following your recommendation.

thank you very much, i hope cant help me.

 

regards from Peru!!!!

 

0 Likes
Message 6 of 11

arnostlobel
Alumni
Alumni

Even though you did not answer many of my questions, I think I may be able to point you to a possible solution, since you stated that you posted all the details of your application. If the code is really all there is, it would seem that you do not actually subscribe to the DocumentClosing event. At least I fail to find it anywhere in the provided code. You do have the DocumentClosing handler, but that alone is not enough. Revit does not call an event handler just because it exists somewhere. You must let Revit know that you want your method called when such an event occurs in Revit. I do not remember the VB syntax from top of my head, but the details is definitely something you are sure to find in either the RevitAPI.CHM file or, even better, in many of the SDK code samples we provide. For illustration, in C# subscribing to the event would look like this (for an application-wide event):

 

uiapp.Application.DocumentClosing += MyDocumentClosingHandller;

 

or for a single document event:

 

uidoc.Document.DocumentClosing += MyDocumentClosingHandler;

 

What this does is it lets Revit know that your method is another delegate that Revit should invoke when the event happens.

 

Again, I strongly recommend you study some of the samples in the SDK.

 

I hope this helps.

Arnošt Löbel
Message 7 of 11

GonçaloFeio1321
Enthusiast
Enthusiast

Your method should be executed only when the DocumentClosed event is fired.

DocumentClosing is canceable, and should subscribe it to store the DocumentId integer (also used by the DocumentClosedEventArgs).

 

0 Likes
Message 8 of 11

Anonymous
Not applicable

i'm Sorry Arnost:

 

do not send my main class.

 

#Region "Imported Namespaces"
Imports System.Windows.Forms
Imports Autodesk.Revit.ApplicationServices
Imports Autodesk.Revit.Attributes
Imports Autodesk.Revit.DB
Imports Autodesk.Revit.UI
Imports System.Windows.Media.Imaging
Imports System.IO
Imports System.Data.OleDb
#End Region

Public Class AvailabilityNoOpenDocumen
    Implements IExternalCommandAvailability

    Public Function IsCommandAvailable(a As UIApplication, b As CategorySet) _
        As Boolean Implements IExternalCommandAvailability.IsCommandAvailable

        Return True
    End Function

End Class

<Transaction(TransactionMode.Manual)>
Class Addin_DCV

    Implements IExternalApplication
    Dim UserName As String = System.Windows.Forms.SystemInformation.UserName
    Public Ruta_Img As String = "C:\Program Files\DCV Addin\Img\"

    Public Function OnStartup(ByVal app As UIControlledApplication) As Result Implements IExternalApplication.OnStartup

        app.CreateRibbonTab("DCV")

        Dim Panel As RibbonPanel = app.CreateRibbonPanel("DCV", "Proyectos BIM")

        Dim btt_1 As New PushButtonData("Btt_1", "Abrir Modelo", _
                             System.Reflection.Assembly.GetExecutingAssembly() _
                             .Location, GetType(Registro).FullName)
        btt_1.AvailabilityClassName = GetType(AvailabilityNoOpenDocumen).FullName
        btt_1.LargeImage = NewBitmapImage("commercial.png")
        Panel.AddItem(btt_1)

        AddHandler app.ControlledApplication.DocumentClosing, AddressOf DocumentClosing

Return Result.Succeeded End Function Private Sub DocumentClosing(sender As Object, e As Autodesk.Revit.DB.Events.DocumentClosingEventArgs) If Not FileOpened = "" Then Try Dim frm As New Frm_Registro For Each Form In Windows.Forms.Application.OpenForms If (Form.Name = "Frm_Registro") Then frm = Form End If Next frm.Show() frm.Parar_timer() Dim sql As String = "UPDATE CONTROL_MODELO SET ACTIVIDAD = '" & frm.txtactividad.Text & "' WHERE ID_CONTROL = " & CodigoControl & "" Dim comandos_up As New OleDb.OleDbCommand comandos_up = New OleDb.OleDbCommand(sql, cn) comandos_up.ExecuteNonQuery() MessageBox.Show("Se esta cerrando el modelo " & FileOpened & ", " & frm.txtactividad.Text, "DCV Consultores", MessageBoxButtons.OK, MessageBoxIcon.Asterisk) frm.Reset_timer() frm.Close() FileOpened = "" Catch ex As Exception MsgBox("Error: " & ex.Message, MsgBoxStyle.Critical, "DCV Consultores") End Try End If End Sub Function NewBitmapImage(ByVal imageName As String) As BitmapImage Return New BitmapImage(New Uri(Path.Combine(Me.Ruta_Img, imageName))) End Function Public Function OnShutdown( ByVal app As UIControlledApplication) _ As Result Implements IExternalApplication.OnShutdown Return Result.Succeeded End Function End Class

 

In the OnStartup function is the event used to call the event DocumentClosing

 

i will work with your suggestions.

Thank you

regards!!

 

 

0 Likes
Message 9 of 11

arnostlobel
Alumni
Alumni
All right; So you do subscribe to the event properly. That's good. Now back to the mystery that needs solving be returning to my original questions that have not been answered yet:


1. What kind of document is it that you are closing? Possible answers include: A Local Model, Local workshared model, Central file, Family document, Model template, Family template. Etc.

2. Is it the only one document still opened in Revit at the time of the document being closed? Possible answers: Yes, or No. If No, how many other document are there and what are they?

3. What are the exact steps leading to your closing the document. There is a lot of possible ways, so please be as specific as you can. Include all steps taken, do not leave out any dialog that opens along the way.

I apologies for being so thorough, but the thing is that we have not heard about the document events failing. Events seem to be working for our API users just fine. It must thus be something special there is about your particular case and I am simply just trying to find out what that is. Ideally, if I apply the steps you take exactly here in my work environment I should be able to experience the same problem. And that would be a start for my figuring out a solution.

Thank you
Arnošt Löbel
0 Likes
Message 10 of 11

Anonymous
Not applicable

answers:

 

  1. the document type is local model or central file
  2. generally one, maybe more documents open
  3. the user can close the document: closing de file, closing revit or press crtrl+alt+sup, this last no comun

remember
my plugin is a control activity that counts the time used in the development of a project.

 

when the user open file revit (*.rvt) the plugin start a timer control and capture file name the document opened

 

when the user closed the document. the aplication stop timer control, save value timer and save name file opened in my data base access 2010.

 

this method work with central file, however while using local model and open worksets dialog box and clic "ok" button, or "Cancel Button" o close dialog box, the code add in the documentClosed event run and the activity user is over. but i not closed document. this is the problem, please help me

 

now i'm using DocumentClosed.

0 Likes
Message 11 of 11

arnostlobel
Alumni
Alumni

Marco,

 

OK, I think I am getting what you have been saying. Please allow me to rephrase and correct me if I am wrong.

 

You are not complaining about not receiving an DocumentClosed event when a document is closed. Instead, you are complaining about unexpectedly receiving an even just when the user leaves the Workset dialog but does not in fact closing any document. Is that right?

 

Because if it is the case, it would make some sense to me, actually. It has been reported in the past that Revit sometimes raised document events even for documents that the user does not observe. It is indeed a bug. However, I believe it has been fixed already, and if it was not in R2015 (which I think it was), then in R2016 it will be fixed for sure.

 

This is what used to be happening: There is a lot more documents open in Revit internally than the documents an end user can observe. Revit often opens temporary documents, especially in work-shared environment. Naturally, such temporary documents are not for the user to see and know about, thus the user should also never receive any events regarding those documents. However, a bug had caused certain events to escape, which is most likely what you still experience.

 

Fortunately, the fix should be rather easy for you to implement. In fact, you may always want do what I am about to suggest. If you want to do anything at the time of closing a document that you have been tracking somehow (e.g. with a timer, in your particular case), you need to make sure that the closing event you receive is for the document you have been tracking. At your current sample I do not see any code that tries to figure if it is indeed the document that you previously opened in your external command. All I see you tests is the FileOpened variable, but that is naturally not enough. You need to test that your FileOpened is actually the one that is being closed. There should be enough information in the arguments of DocumentClsoing and DocumentClosed events for you to make an informed decision about whether it was “your” document that has just gotten closed. I am afraid you will need to subscribe to both events though in order to get all the necessary information.

Arnošt Löbel
0 Likes