Monthly Archives: January 2012
Code: Accessing Windows Clipboard
Several years ago, I found some code to access the Win32 functions for the Windows Clipboard. I don't remember where I found it, who wrote it or if it was VB code that I modified or already written for Lotusscript. I rewrote the the code as a class and put it in a script library called "Class.Win32.ClipBoard". The complete code is listed below. In my next blog entry I will describe how I am using this class for some very convenient functions.
Option Public
Option Declare
Declare Private Function GetClipboardData Lib "User32" (Byval wFormat As Long) As Long
Declare Private Function SetClipboardData Lib "user32" (Byval wFormat As Long, Byval hData As Long) As Long
Declare Private Function OpenClipboard Lib "User32" Alias "OpenClipboard" (Byval hwnd As Long) As Long
Declare Private Function CloseClipboard Lib "User32" Alias "CloseClipboard" () As Long
Declare Private Function GlobalLock Lib "kernel32" Alias "GlobalLock" (Byval hMem As Long) As Long
Declare Private Function GlobalUnlock Lib "kernel32" Alias "GlobalUnlock" (Byval hMem As Long) As Long
Declare Private Function GlobalAlloc Lib "kernel32" (Byval wFlags As Long, Byval dwBytes As Long) As Long
Declare Private Function GlobalFree Lib "kernel32" (Byval hMem As Long) As Long
Declare Private Function EmptyClipboard Lib "user32" () As Long
Declare Private Function lstrcpyLP2Str Lib "kernel32" Alias "lstrcpyA" (Byval lpString1 As String, _
Byval lpString2 As Long) As Long
Declare Private Function lstrlenLP Lib "kernel32" Alias "lstrlenA" (Byval lpString As Long) As Long
Declare Private Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" (Byval strDest As Any, _
Byval lpSource As Any, Byval Length As Any)
Declare Private Function GetFocus Lib "User32" Alias "GetFocus" () As Long
Private Const CF_TEXT = 1
Private Const GMEM_MOVABLE = &H2&
Private Const GMEM_DDESHARE = &H2000&
Class WindowsClipboard
Public Property Get Contents As String
Dim hClipboard As Long
Dim LpStrl As Long
Dim Resultl As Long
Dim Clipboardstr As String
If (OpenClipboard(0&) <> 0) Then
hClipboard = GetClipboardData(CF_TEXT)
If (hClipboard <> 0) Then
LpStrl = GlobalLock(hClipboard)
Clipboardstr = Space$(lstrlenLP(LpStrl))
Resultl = lstrcpyLP2Str(Clipboardstr, LpStrl)
GlobalUnlock(hClipboard)
Else
Clipboardstr = "NULL"
End If
Call CloseClipboard()
&nbs
p; Else
Clipboardstr = ""
End If
Contents = Clipboardstr
End Property ' Ends the "Get" method for the "Contents" property
Public Property Set Contents As String
Dim lSize As Long
Dim hMem As Long
Dim pMemory As Long
Dim temp As Variant
lSize = Len(Contents)+1
hMem = GlobalAlloc(GMEM_MOVABLE Or GMEM_DDESHARE, lSize)
If hMem = 0 Or Isnull(hMem) Then Exit Property
pMemory = GlobalLock(hMem)
If pMemory = 0 Or Isnull(pMemory) Then
GlobalFree(hMem)
Exit Property
End If
Call MoveMemory(pMemory, Contents, lSize)
Call GlobalUnlock(hMem)
If (OpenClipboard(0&) <> 0) Then
If (EmptyClipboard() <> 0) Then
temp = SetClipboardData(CF_TEXT, hMem)
End If
temp = CloseClipboard()
End If
GlobalFree(hMem)
End Property ' Ends the "Set" method for the "Contents" property
End Class
14 Years Ago…
This Sunday it was 14 years ago I stepped onto an airplane in Stockholm, Sweden. In the morning hourse of January 1, 1998, my dad and my sister took me to the airport for my move to the US. I had married Angie back in August, and soon after that she told me she wanted to move back to the US. I applied for and got a resident visa (green card) and got a job with IDG in Boston. Initially we had planned to move to Seattle, but when I was offered the job in Boston I took that one instead.
Some 18 hours later I landed in Spokane, WA, where Angie met me. She had been staying with her mom, who lived in northern Idaho, while I got our appartment in Sweden packed up in 13 moving boxes (that is what I could afford to ship) and I got everything finished at my previous job at IDG in Sweden. My last task was to build an editorial system in Lotus Notes 4.6, that I built in 3 weeks. By the way, this system is still in use today, having survived several attempts to have it replaced with different other publishing systems.
After four days of driving cross-country from Idaho to Boston, we got an apartment and I started working as a full-time Lotus Notes developer on January 7.
Much have happened since. In 2000 we had our son Erik, in May 2002 we moved to Texas and I started working at Deep South as a Sr. Lotus Notes developer, in late summer of 2002 we moved into our first house, and then in July 2003 Angie and I separated and finally divorced aftyer 6 years of marriage.
It is interesting that I now have been working with Lotus Notes almost three times the time I was married, despite all the claims I have seen for many years that "Notes is Dead"…
As always, it will be exciting to see what the coming year brings me, both on a personal and professional level. Perhaps I will finally get the time to learn Xpages and/or Java?
Free Tool: Clean your NAB
As a follow-up to my previous tool that let you analyze the ACL of a database, I built another tool for my admin. For different reasons, we need to keep the mailbox of terminated users, sometimes for a shorter time but sometimes for long periods of time. As far as I understand it, if a traditional approach was used to remove a user from the system, the mail file would also be deleted. So the admin put the terminated user in the Deny Access group and change the ACL of the mailfile to include a manager, supervisor or replacement.
But because of this process, AdminP will not remove the terminated user from all the groups he/she is listed in. When you have hundreds of groups, many of them nested, this could be a real headache. So I was asked to build something simple that allows us to remove one or more specified users from all groups in the Domino Directory. Below is the result. Enjoy!
Update: I tweaked the code slightly, to avoid three separate calls to GetItemValue() and to make a line shorter. The modified code is in the end, where I update the deletelog list.
First I created a form with 3 fields:
‘SaveOptions’ has a default value of “0” (to prevent the form from being saved).
‘Users’ is a Names field, getting it’s values using the addresses dialog. The field is multi-value and using New Line as separator.
‘LogResult’ is a multi-value text field, again with New Line as separator.
Finally I added a button to the action bar to remove the user(s). The Lotusscript code is listed below. It is using my class for mail notifications that I blogged about in November, to send a confirmation to the user running the agent. This is useful for example when you need to log all data changes done to a system.
Use "Class.MailNotification"
Sub Click(Source As Button)
Dim ws As New NotesUIWorkspace
Dim uidoc As NotesUIDocument
Dim session As New NotesSession
Dim nab As NotesDatabase
Dim view As NotesView
Dim doc As NotesDocument
Dim members As Variant
Dim newmembers List As String
Dim delmembers List As String
Dim users As Variant
Dim userlist List As String
Dim user As NotesName
Dim nmcnt As Integer
Dim newarray() As String
Dim ret As Integer
Dim removelog List As String
Dim userarr As Variant
Dim mail As NotesMail
Dim mailtext As String
Dim listname as String
Dim updated As Boolean
' *** Make sure the operator is sure
ret = Msgbox("Are you sure?",4+32+256,"WARNING")
If ret = 7 Then
Exit Sub
End If
' *** Get a list of users in field 'Users'
Set uidoc = ws.CurrentDocument
users = Split(uidoc.FieldGetText("Users"),Chr$(13))
Forall u In users
Set user = New NotesName(u)
userlist(Fulltrim(user.Common)) = Fulltrim(user.Common)
End Forall
' *** Get all groups in NAB and process them one by one
Set nab = New NotesDatabase(session.CurrentDatabase.Server,"names.nsf")
Set view = nab.GetView("Groups")
Set doc = view.GetFirstDocument
Do While Not doc Is Nothing
Print "Processing " & doc.GetItemValue("Listname")(0)
Erase newmembers
Erase delmembers
updated = False
' *** Get members in the group and create a list of the ones to keep
members = doc.GetItemValue("Members")
nmcnt = 0
Forall m In members
Set user = New NotesName(m)
If Iselement(userlist(Fulltrim(user.Common))) = False Then
' User is not among the ones to delete
newmembers(Fulltrim(user.Common)) = Fulltrim(m)
nmcnt = nmcnt + 1
Else
delmembers(Fulltrim(user.Common)) = Fulltrim(m)
updated = True
End If
End Forall
' *** Build array of members to keep
Redim newarray(nmcnt) As String
nmcnt = 0
Forall nm In newmembers
newarray(nmcnt) = nm
nmcnt = nmcnt + 1
End Forall
' *** Write array of new members back to document and save it
If updated = True Then
Call doc.ReplaceItemValue("Members", Fulltrim(newarray))
Call doc.Save(True,False)
listname = doc.GetItemValue("Listname")(0)
Print "Updating " & listname
End If
Forall dm In delmembers
removelog(listname) = removelog(listname) & dm & ";"
End Forall
Set doc = view.GetNextDocument(doc)
Loop
' *** We are all done
mailtext = ""
Forall rl In removelog
Call uidoc.FieldAppendText("LogResult", "Group '" & Listtag(rl) & "':" & Chr$(10))
mailtext = mailtext & "Group '" & Listtag(rl) & "':" & Chr$(10)
userarr = Split(Cstr(rl),";")
Forall u In userarr
Set user = New NotesName(u)
Call uidoc.FieldAppendText("LogResult", user.Common & Chr$(10))
mailtext = mailtext & user.Common & Chr$(10)
End Forall
' Call uidoc.FieldAppendText("LogResult", Chr$(10))
End Forall
Set mail = New NotesMail()
mail.MailTo = session.CommonUserName
mail.Subject = "[Notification] - Users removed from NAB"
Call mail.AppendText(mailtext)
mail.Principal = "IT Programs"
Call mail.Send()
Msgbox "Done removing specified user(s) from Domino Directory.",64,"Finished"
End Sub
