Posts Tagged: ‘tipps’
Tools for my handbag – Part 3: Mouse whitout Borders
Easy updates for your Notes applications
I don’t like the whole template and design update/replace handling with Notes Applications. It’s ok when you have access to the server and application you want to update, but usually I don’t have such access. I’m developing for customers and many of them have no deep Notes knowledge. So in most of the cases, when I’m sending out new versions of applications, I get an answer like this: “Can we install the update together in a Teamviewer session?”.
This is not only the case for customers, but also for all these Notes to Exchange projects currently happening… I’m developing some tools for my colleagues working on those projects, but they usually don’t have much Notes know-how and I always have to update these applications by myself or in a remote session.
To get all these updates done more easily, I thought about a little update function for my applications. It should be easier to use than the standard process. Finally, yesterday I found a little bit of time to implement this. It is the first version, so there is still a lot of room for improvements and I also have a lot of more ideas for the future.
For the moment, that’s the code. One Agent and one script library. You just have to add them to your application to get the update function running. Agents won’t get updated to preserve settings and signatures. When executed using the actions menu, it asks for the source database, deletes all design elements (ATTENTION!!) of the current database except agents. At last it copies all design elements from the selected source database to the current one and your application should be updated to the new version.
Any recommendations, bug reports and contributions are welcome!
As always, use the code with caution and at your own risk.
Agent “VersionUpdate”
%REM
Agent VersionUpdate
Created Mar 30, 2016 by Stephan Kopp
%END REM
Option Public
Option Declare
Use "stdlib_update"
Sub Initialize
Dim l_update As New DBUpdate
Call l_update.funcUIStartUpdate()
End Sub
Script Library “stdlib_update”
%REM
Library stdlib_update
Created Mar 30, 2016 by Stephan Kopp
%END REM
Option Public
Option Declare
Public Const lsERR_NOTES_DBNOACCESS = 4060
Public Const lsERR_NOTES_DATABASE_NOTOPEN = 4063
%REM
<b>Class DBUpdate</b>
<u>Created:</u>
Mar 30, 2016 by Fritz & Macziol
<u>Contributors:</u>
Stephan Kopp, Fritz & Macziol
<u>Description:</u>
%END REM
Public Class DBUpdate
private m_source As NotesDatabase
Private m_target As NotesDatabase
Private m_session As NotesSession
Private m_uiw As NotesUIWorkspace
Private m_thisdb As NotesDatabase
Sub New
Set me.m_uiw = New NotesUIWorkspace
Set me.m_session = New NotesSession
Set me.m_thisdb = me.m_session.Currentdatabase
'at the moment, target is always the current database
Call me.funcSetTarget(me.m_thisdb.Server, me.m_thisdb.Filepath)
End Sub
%REM
<b>Function funcSelectSource</b>
<p><u>Description:</u>
Ask for the source database and save it for further processing.
</p>
%ENDREM
private Function funcUISelectSource
On Error GoTo catch
funcUISelectSource = False
Dim aw As Variant
aw = m_uiw.Prompt(13, "Select your source template", "Select the source database or template to use for update")
If IsEmpty(aw) Then GoTo done
funcUISelectSource = me.funcSetSource(aw(0), aw(1))
If not funcUISelectSource Then
MessageBox "Can't open your selected database, please check log for details"
End If
done:
Exit Function
catch:
Print "ERROR: " & Error & " (" & CStr(Err) & " / Line: " & CStr(Erl) & ")"
Exit Function
End Function
%REM
<b>Function funcSetSource</b>
<p><u>Description:</u>
Set the source database used for the update procedure.
</p>
<p><u>Return value:</u>
true if sucessfully opened the source database
</p>
%ENDREM
private function funcSetSource(p_server As String, p_file As string) As boolean
On Error GoTo catch
On Error lsERR_NOTES_DBNOACCESS GoTo noAccess
On Error lsERR_NOTES_DATABASE_NOTOPEN GoTo noAccess
Set me.m_source = me.m_session.Getdatabase(p_server, p_file)
If me.m_source.Isopen Then
funcSetSource = true
Else
funcSetSource = false
End If
done:
Exit Function
catch:
print "ERROR: " & Error & " (" & CStr(Err) & " / Line: " & CStr(Erl) & ")"
Exit Function
noAccess:
funcSetSource = False
Print "ERROR, Can't open database: " & p_server & "!!" & p_file
GoTo done
End Function
%REM
<b>Function funcSetTarget</b>
<p><u>Description:</u>
Set the target database to update with the source databse.
ATTENTION! All design elements of this database will be overwritten!
</p>
<p><u>Return value:</u>
true if sucessfully opened the target database
</p>
%ENDREM
Private Function funcSetTarget(p_server As String, p_file As String) As Boolean
On Error GoTo catch
On Error lsERR_NOTES_DBNOACCESS GoTo noAccess
On Error lsERR_NOTES_DATABASE_NOTOPEN GoTo noAccess
Set me.m_target = me.m_session.Getdatabase(p_server, p_file)
If me.m_target.Isopen Then
funcSetTarget = True
Else
funcSetTarget = False
End If
done:
Exit Function
catch:
Print "ERROR: " & Error & " (" & CStr(Err) & " / Line: " & CStr(Erl) & ")"
Exit Function
noAccess:
funcSetTarget = False
Print "ERROR, Can't open database: " & p_server & "!!" & p_file
GoTo done
End Function
%REM
<b>Function funcStartUpdate</b>
%ENDREM
Public Function funcUIStartUpdate As Boolean
On Error GoTo catch
If not me.funcUISelectSource() Then
'exit
GoTo done
End If
'show message to the user with details and ask again if update should be started
Dim aw As Variant
aw = m_uiw.Prompt(PROMPT_YESNO, "Are you sure?", "Do you really want to start the update?" & Chr(13)_
& "All design elements (except agents) in the target database will be overwritten!" & Chr(13)_
& "Source: " & me.m_source.Server & "!!" & me.m_source.Filepath & Chr(13)_
& "Target: " & me.m_target.Server & "!!" & me.m_target.Filepath)
If aw <> 1 Then GoTo done
'maybe later we can add an option mask to select some types of design elements to update
'e.g. All, Script Libraries only, etc.
'start update
funcUIStartUpdate = me.funcStartUpdate()
If funcUIStartUpdate Then
Messagebox "Update successfull, please restart your Notes Client"
Else
MessageBox "Something went wrong, please try again or contact Stephan Kopp"
End If
done:
Exit Function
catch:
funcUIStartUpdate = false
Print "ERROR: " & Error & " (" & CStr(Err) & " / Line: " & CStr(Erl) & ")"
Exit Function
End Function
%REM
<b>Function funcStartUpdate</b>
<p><u>Description:</u>
Start the update process
</p>
%ENDREM
Private Function funcStartUpdate As Boolean
On Error GoTo catch
funcStartUpdate = False
'delete design elements
funcStartUpdate = me.funcDeleteAllDesignElements()
If funcStartUpdate = False Then GoTo done
'copy design elements
funcStartUpdate = me.funcCopyAllDesignElements()
'do some checks?
'send notify?
'sign database?
done:
'print message
If funcStartUpdate Then
Print "Update successfull, please restart your Notes Client"
Else
Print "Something went wrong, please try again or contact Stephan Kopp"
End If
Exit Function
catch:
funcStartUpdate = false
Print "ERROR: " & Error & " (" & CStr(Err) & " / Line: " & CStr(Erl) & ")"
Exit Function
End Function
%REM
<b>Function funcDeleteAllDesignElements</b>
<p><u>Description:</u>
Deletes all design elements in selected target database except agents.
Agents won't be updated to preserve scheduling and signatures.
</p>
%ENDREM
Private Function funcDeleteAllDesignElements As Boolean
On Error GoTo catch
funcDeleteAllDesignElements = False
'create a note collection with all design elements except agents
Dim l_nodecol As NotesNoteCollection
Set l_nodecol = funcCreateNoteCollection(me.m_target)
Print "Found " & CStr(l_nodecol.Count) & " design elements to delete..."
Dim l_count As Integer
Dim l_nodeid As String
l_nodeid = l_nodecol.Getfirstnoteid()
While l_nodeid <> ""
l_count = l_count+1
Dim l_doc As NotesDocument
Set l_doc = me.m_target.Getdocumentbyid(l_nodeid)
If not l_doc Is Nothing Then
Print "deleting element " & CStr(l_count) & " of " & CStr(l_nodecol.Count)
Call l_doc.Remove(true)
End If
l_nodeid = l_nodecol.Getnextnoteid(l_nodeid)
Wend
funcDeleteAllDesignElements = true
done:
Exit Function
catch:
funcDeleteAllDesignElements = False
Print "ERROR: " & Error & " (" & CStr(Err) & " / Line: " & CStr(Erl) & ")"
Exit Function
End Function
%REM
<b>Function funcCreateNoteCollection</b>
<p><u>Description:</u>
Creates a notecollection used for delete and copy of design elements.
</p>
%ENDREM
Private Function funcCreateNoteCollection(p_db As NotesDatabase) As NotesNoteCollection
On Error GoTo catch
Dim l_nodecol As NotesNoteCollection
Set l_nodecol = p_db.Createnotecollection(True) 'select all
l_nodecol.Selectacl = False
l_nodecol.Selectagents = False
l_nodecol.Selectdocuments = False
l_nodecol.Selectprofiles = False
Call l_nodecol.Selectalldatanotes(False)
Call l_nodecol.Selectalladminnotes(False)
Call l_nodecol.Buildcollection()
Set funcCreateNoteCollection = l_nodecol
done:
Exit Function
catch:
Set funcCreateNoteCollection = nothing
Print "ERROR: " & Error & " (" & CStr(Err) & " / Line: " & CStr(Erl) & ")"
Exit Function
End Function
%REM
<b>Function funcCopyAllDesignElements</b>
<p><u>Description:</u>
Copies all design elements from selected source db to target db except agents.
Agents won't be updated to preserve scheduling and signatures.
</p>
%ENDREM
Private Function funcCopyAllDesignElements As Boolean
On Error GoTo catch
On Error GoTo catch
funcCopyAllDesignElements = False
'create a note collection with all design elements except agents
Dim l_nodecol As NotesNoteCollection
Set l_nodecol = funcCreateNoteCollection(me.m_source)
Print "Found " & CStr(l_nodecol.Count) & " design elements to copy..."
Dim l_count As Integer
Dim l_nodeid As String
l_nodeid = l_nodecol.Getfirstnoteid()
While l_nodeid <> ""
l_count = l_count+1
Dim l_doc As NotesDocument
Set l_doc = me.m_source.Getdocumentbyid(l_nodeid)
If Not l_doc Is Nothing Then
Print "copy element " & CStr(l_count) & " of " & CStr(l_nodecol.Count)
Call l_doc.Copytodatabase(me.m_target)
End If
l_nodeid = l_nodecol.Getnextnoteid(l_nodeid)
Wend
funcCopyAllDesignElements = True
done:
Exit Function
catch:
funcCopyAllDesignElements = false
Print "ERROR: " & Error & " (" & CStr(Err) & " / Line: " & CStr(Erl) & ")"
Exit Function
End Function
End Class
Ideas for the future:
- Update also Notes Agents, but save and restore all scheduling and other settings
- Download updates from a hosted web service automatically
- Download and apply updates automatically by a server agent in background
Filed under: IBM Notes/Domino