Append Lotus Notes text in Microsoft Notepad to avoid text size limits

VIEW MEMBER FEEDACK TO THIS TIP
This LotusScript code allows users to open, copy and append any Lotus Notes text in Microsoft Notepad. The benefit of this is that unlimited text strings can be appended without the Lotus Notes text size limitation.

As a sample program, I've configured the code to retrieve any Lotus Domino Server notes.ini listing in Microsoft Notepad. It uses the Microsoft kernel32.dll and user32.dll APIs, and can be used in a LotusScript library or agent.

 
'Code to use in an agent or in a Lotusscript library

'Declarations
Const notepad = "Notepad.exe"
'define notepad program file path if Notepad 
is not in Windows path

Private Type PROCESS_INFORMATION
 hProcess As Long
 hThread As Long
 dwProcessID As Long
 dwThreadID As Long
End Type

Private Type STARTUPINFO 

Related resources from SearchDomino.com:
Tip: How to fix the size limitation on Lotus Notes summary text fields

LotusScript Learning Guide

FAQ: LotusScript advice

LotusScript Reference Center

cb As Long lpReserved As String lpDesktop As String lpTitle As String dwX As Long dwY As Long dwXSize As Long dwYSize As Long dwXCountChars As Long dwYCountChars As Long dwFillAttribute As Long dwFlags As Long wShowWindow As Integer cbReserved2 As Integer lpReserved2 As Long hStdInput As Long hStdOutput As Long hStdError As Long End Type Declare Private Function CreateProcessA Lib "kernel32.dll" Alias "CreateProcessA" _ (Byval lpApplicationName As Long, Byval lpCommandLine As String, _ Byval lpProcessAttributes As Long, Byval lpThreadAttributes As Long, _ Byval bInheritHandles As Long, Byval dwCreationFlags As Long, _ Byval lpEnvironment As Long, Byval lpCurrentDirectory As Long, _ lpStartupInfo As STARTUPINFO, lpProcInfo As PROCESS_INFORMATION) As Long Declare Private Function CloseHandle Lib "kernel32.dll" Alias "CloseHandle" _ (Byval hObject As Long) As Long Declare Private Function WaitForInputIdle Lib "user32.dll" Alias "WaitForInputIdle" _ (Byval hProcess As Long, Byval dwMilliseconds As Long) As Long Declare Private Function FindWindow Lib "user32.dll" Alias "FindWindowA" _ (Byval wClass As Any, Byval wName As Any) As Integer Declare Private Function GetWindow Lib "user32.dll" Alias "GetWindow" _ (Byval hWnd As Long, Byval wCmd As Long) As Long Declare Private Function GetWindowThreadProcessId Lib "user32.dll" Alias "GetWindowThreadProcessId" _ (Byval hWnd As Long, lpdwProcessId As Long) As Long Declare Private Function GetParent Lib "user32.dll" (Byval hWnd As Long) As Long Declare Private Function FindWindowEx Lib "user32.dll" Alias "FindWindowExA" _ (Byval hWndParent As Long, Byval hWndChildAfter As Long, _ Byval lpszClass As String, Byval lpszWindow As String) As Long Declare Private Function SendMessage Lib "user32.dll" Alias "SendMessageA" _ (Byval hWnd As Long, Byval Msg As Long, wParam As Any, lParam As Any) As Long Declare Private Function PostMessage Lib "user32.dll" Alias "PostMessageA" _ (Byval hWnd As Long, Byval Msg As Long, Byval wParam As Long, Byval lParam As Long) As Long 'SendMessage wait for execution, postMessage don't (asynchronous) Public Function CopyTextToNotepad (txt As String) As Long Const NORMAL_PRIORITY_CLASS = &H20 Const INFINITE = -1& Const GW_HWNDFIRST = 0 Const GW_HWNDNEXT = 2 Const WM_SETTEXT = &HC ' * Initialise Return Value for Function CopyTextToNotepad = 0 ' * Get Notepad Task Handle Dim result As Long Dim startup As STARTUPINFO Dim processInfo As PROCESS_INFORMATION startup.cb = Len (startup) '(must be 68) result = CreateProcessA (0, notepad, 0, 0, 1, NORMAL_PRIORITY_CLASS, 0, 0, startup, processInfo) If result <> 0 Then ' * Wait process is ready Call WaitForInputIdle (processInfo.hProcess, INFINITE) '* Scan all Windows Process to find Notepad Process Window Handle Dim hWnd As Long hWnd = FindWindow (0, 0) hWnd = GetWindow (hWnd, GW_HWNDFIRST) Do While (hWnd <> 0) Dim id As Long Call GetWindowThreadProcessId (hWnd, id) If id = processInfo.DwProcessId Then Exit Do hWnd = GetWindow (hWnd, GW_HWNDNEXT) Loop ' * Now scan all Parent Process to get Top Notepad (parent) Process Window Handle Do While (hWnd <> 0) Dim hPWnd As Long hPWnd = getParent (hWnd) If hPWnd = 0 Then Exit Do hWnd = hPWnd Loop ' * Now get Edit Process Handle and Copy Text If hWnd <> 0 Then Dim hWNEdit As Long hWNEdit = FindWindowEx (hWnd, 0, "Edit", "") If hWNEdit <> 0 Then result = SendMessage (hWNEdit, WM_SETTEXT, Byval 0, Byval txt) If result <> 0 Then CopyTextToNotepad = hWNEdit End If ' * And to finish, close main Process Handles Call CloseHandle (processInfo.hThread) Call CloseHandle (processInfo.hProcess) End If End Function Public Function AppendTextToNotepad (hWNEdit As Long, txt As String) As Long Const WM_GETTEXTLENGTH = &HE Const EM_SETSEL = &HB1 Const EM_REPLACESEL = &HC2 If hWNEdit = 0 Then AppendTextToNotepad = CopyTextToNotepad (txt) Else Dim lg As Long Dim result As Long lg = SendMessage (hWNEdit, WM_GETTEXTLENGTH, Byval 0, Byval 0) result = SendMessage (hWNEdit, EM_SETSEL, Byval lg, Byval lg) If result <> 0 Then result = SendMessage (hWNEdit, EM_REPLACESEL, Byval 0, Byval txt) If result = 0 Then AppendTextToNotepad = 0 Else AppendTextToNotepad = hWNEdit End If End Function %rem 'To use it in an agent: 'Define notepad filePath if notepad.exe is not in the Windows path 'Separate lines by CRLF : chr$(13) + chr$ (10) Dim crLf as String Dim myText as String Dim hNotepad as Long crLf = chr$ (13) + chr$ (10) myText = "This is the first line" + crLf + "This is the second line." + crLf hNotepad = copyTextToNotepad (myText) ' or call copyTextToNotepad (myText) if you don't have to append more text ' or call appendTextToNotepad (0, myText) ' or hNotepad = appendTextToNotepad (0, myText) 'To append Text: you must use the notepad Handle (hNotepad) returned 'by first copyTextToNotepad or appendTextToNotepad dim appendText as String appendText = "This is a new line to append" call appendTextToNotepad (hNotepad, appendText) %end rem 'Sample usage: Get a server notes.ini file in Notepad (lines are sorted in alphabetical order) '------------------------------------------------------- 'Nota: Server must allow Remote Console ... 'First, declare following API's Declare Function OSLockObjectString Lib "nnotes.dll" Alias "OSLockObject" _ (Byval hObject as Long) As String Declare Function OSUnlockObject Lib "nnotes.dll" Alias "OSUnlockObject" _ (Byval handle As Long) As Integer Declare Function OSMemFree Lib "nnotes.dll" Alias "OSMemFree" _ (Byval handle As Long) As Integer Declare Function NSFRemoteConsole Lib "nnotes.dll" Alias "NSFRemoteConsole" _ (Byval Server As String, Byval cmd As String, ret As Long ) As Long 'Now the program (agent or library function) Sub initialize Dim rc As Long Dim result as String Dim hBuffer As Long Dim cmdLine as String dim serverName as string 'define ServerName (or put it as parameter of your function ...) cmdLine = "Show Config *" rc = NSFRemoteConsole (serverName, cmdLine, hBuffer) If rc = 0 Then result = OSLockObjectString (hBuffer) Call OSUnLockObject (hBuffer) Call OSMemFree (hBuffer) Else result = "Console Error : " + Cstr (rc) End If Call copyTextToNotepad (result) End Sub

MEMBER FEEDBACK TO THIS TIP

Assuming you're using at least Lotus Notes 6, I recommend using the NotesStream class instead. This allows you to append or read text files without using API calls. Similarly, Lotus Notes 6 added a .SendConsoleCommand method to the NotesSession class, so the "Show Config" example can also be achieved without using API calls.
—Tim T.

Do you have comments on this tip? Let us know.

This tip was submitted to the SearchDomino.com tip library by member Christian Cavantou. Please let others know how useful it is via the rating scale below. Do you have a useful Lotus Notes, Domino, Workplace or WebSphere tip or code snippet to share? Submit it to our monthly tip contest and you could win a prize.

This was first published in March 2008

Disclaimer: Our Tips Exchange is a forum for you to share technical advice and expertise with your peers and to learn from other enterprise IT professionals. TechTarget provides the infrastructure to facilitate this sharing of information. However, we cannot guarantee the accuracy or validity of the material submitted. You agree that your use of the Ask The Expert services and your reliance on any questions, answers, information or other materials received through this Web site is at your own risk.