Update

Notes 8.5 now has an extra column in the user activity pop up which shows deletions

I seem to have lost the comments somehow but several people recommended Ytrias (free ) tool over Notes Peek. I have tried it now and it is very good


I recently had a call from a customer to say that their application had stopped working. It turned out that a number of configuration documents had been inadvertently deleted when the user tried to archive off old documents – but which ones ?

One frustrating feature of Notes is that unless you code something special it is very difficult to find out who has deleted documents and when ( I now generally use a soft delete mechanism so that most users  cannot hard delete documents )

1) The first quick check is to look in the application properties – user activity and see if anyone has “written” a large number of documents.

Image:Finding which documents have been deleted from a database with a script solution

2) I then use a script to compare the documents in the “live” copy with the documents in a local replica or backup. This takes each document in the backup and tries to find the corresponding document in the live copy. If no matching document is found ( or just a deletion stub ) it puts that document in a folder so that I can copy it back to the live system ( note that the doc unid will change )

3) If I need to do further analysis to see when the document was deleted ( and indirectly by who using the logs ) I can now use the doc unid and NotesPeek to examine the deletion stub – I find that the search facility doesn’t always work so I tend to dump it to a text pad and search there

Image:Finding which documents have been deleted from a database with a script solution

This is the LotusScript code for step 2 ( also attached as an LSS )

‘check for deletions on the server:

Option Public
Option Declare ‘ because Rocky says you must

Sub Initialize

‘check for deletions on the server:
‘ Sean Cull, www.seancull.co.uk

‘ This agent compares two replicas and highlights documents that are in one
‘ replica but not the other. These documents are added to folders $4091_Deleted_Documents
‘, $missingdocuments or $zerolengthdocs for later examination

‘ the code is particularly usefull for finding what has been deleted from a replica

Dim ws As New notesuiworkspace
Dim session As New NotesSession
Dim thisdb As notesdatabase
Dim otherdb As notesdatabase
Dim coll As notesdocumentcollection
Dim thisdoc As notesdocument
Dim otherdoc As NotesDocument
Dim number_docs As Long
Dim var As Variant
Dim unidvar As String
Dim Error_4091_flag As Boolean

On Error Goto printerror        
On Error 4091 Goto error_4091
‘ error 4091 occurs when you use getdocumentbyunid on a deletion stub
‘ the error message is invalid universalid
‘ there are some support documents which also suggest that you sometimes do manage
‘ to get a handle on a stub so you also need to check if doc.size = 0

Set thisdb = session.CurrentDatabase
Set coll = thisdb.AllDocuments

number_docs = coll.count

Print “There are ” & Cstr(number_docs) & ” Documents to process”

‘variant = notesUIWorkspace.Prompt( type%, title$, prompt$ [, default ] [, values ] )
‘PROMPT_CHOOSEDATABASE (13)
‘variant(0) = server
‘variant(1) = path
‘variant(2) = title

var = WS.Prompt( 13, “Choose the second database”, “”)

Set otherdb = Session.GetDatabase( var(0), var(1), False )
If Not otherdb.IsOpen Then
       Msgbox “Could not open the second database”
       Exit Sub
End If

Set thisdoc = coll.GetFirstDocument
Do Until thisdoc Is Nothing
       number_docs  =         number_docs  – 1
       Print         number_docs ‘ this slows things down but I find it useful
       unidvar = thisdoc.UniversalID
       error_4091_flag = False
       Set otherdoc = otherdb.GetDocumentByUNID(unidvar)
       If error_4091_flag Then ‘ a deletion stub
               Call thisdoc.putinfolder(“$4091_Deleted_Documents”,True)                                                
       Else
               If otherdoc Is Nothing Then
               ‘ a missing document as opposed to a deleted one
                       Call thisdoc.putinfolder(“$Missing_Documents”,True)                        
               Else
                       ‘ there is a document but we need to check if it is a zero length stub
                       If otherdoc.size = 0 Then Call thisdoc.putinfolder(“$Zerolengthdocs”,True)                        
               End If                        
       End If
       Set thisdoc = coll.GetNextDocument(thisdoc)
Loop

Exit Sub

Error_4091 :
error_4091_flag = True        
Resume Next

PrintError:

If (Err() <> 0) Then
       Messagebox( “Error” & Str(Err) & “: ” & Error$)
End If

Exit Sub

End Sub