Lotus Notes, Windows 7, and Horizon Mirage

By | February 3, 2014

lotus-notes-logo_0IBM’s Lotus Notes has a long history of not conforming to the standards of most every other Windows application. Recently I did  a Horizon Mirage Windows XP to 7 migration proof of concept for a client running 11 different versions of Notes on 10’s of thousands of clients. Along with migrating to Windows 7 the client also decided to use this time to to standardize everyone on Notes 8.5.3. This was challenging to say the least.

Out of everything it took to pull this off, there are two things that caused serious issues in testing. The first major issue was the fact that the default USMT migapp.xml works for all Notes 6, 7 , and 8; but only if 8 is not in Single User Mode. Almost everyone, including this client, uses Notes in Single User Mode. The second was figuring out how to migrate some settings, but not all, from all the versions of the Notes.ini.

Here is what I did.

Fixing migapp.xml

migapp.xml has sections for quite a few common applications. It has two sections for Notes, one for versions 6 and 7 and one for version 8. The default file makes reference to %CSIDL_LOCAL_APPDATA%\Lotus\Notes\Data for the Notes data path. In Single User Mode the path is actually C:\Program Files (x86)\IBM\Lotus\Notes\Data. 

The easy way to correct this is to delete everything in the section  <!– Lotus Notes 8.x –> and replace it with the following:

<!– Lotus Notes 8.x –>
<component context=”User” type=”Application”>
<displayName _locID=”migapp.lotusnotes8″>Lotus Notes 8</displayName>
<detects>
<detect>
<condition>MigXmlHelper.DoesFileVersionMatch(“%NotesInstPath%\notes.exe”,”ProductVersion”,”8.*”)</condition>
</detect>
</detects>
<environment>
<variable name=”NotesInstPath”>
<script>MigXmlHelper.GetStringContent(“Registry”,”HKCU\Software\Lotus\Notes\Installer [PROGDIR]”)</script>
</variable>
<variable name=”NotesDataPath”>
<script>MigXmlHelper.GetStringContent(“Registry”,”HKCU\Software\Lotus\Notes\Installer [DATADIR]”)</script>
</variable>
<variable name=”NotesInstallType”>
<script>MigXmlHelper.GetStringContent(“Registry”,”HKCU\Software\Lotus\Notes\Installer [ApplicationUsers]”)</script>
</variable>
</environment>
<role role=”Settings”>
<rules context=”User”>
<condition>MigXmlHelper.DoesStringContentEqual(“Registry”,”%NotesInstallType%”,”OnlyCurrentUser”)</condition>
<include>
<objectSet>
<pattern type=”Registry”>HKCU\Software\Lotus\Notes\Installer [USENOTESFOREMAIL]</pattern>
<pattern type=”File”>%NotesDataPath%\ [bookmark.nsf]</pattern>
<pattern type=”File”>%NotesDataPath%\ [desktop8.ndk]</pattern>
<pattern type=”File”>%NotesDataPath%\ [headline.nsf]</pattern>
<pattern type=”File”>%NotesDataPath%\ [names.nsf]</pattern>
<pattern type=”File”>%NotesDataPath%\ [*.dic]</pattern>
<pattern type=”File”>%NotesDataPath%\ [*.id]</pattern>
<pattern type=”File”>%NotesDataPath%\workspace\* [*]</pattern>
</objectSet>
</include>
<exclude>
<objectSet>
<pattern type=”File”>%NotesDataPath%\workspace\logs\* [*]</pattern>
</objectSet>
</exclude>
<locationModify script=”MigXmlHelper.RelativeMove(‘%NotesDataPath%’,’%NotesDataPath%’)”>
<objectSet>
<pattern type=”File”>%NotesDataPath%\ [bookmark.nsf]</pattern>
<pattern type=”File”>%NotesDataPath%\ [desktop8.ndk]</pattern>
<pattern type=”File”>%NotesDataPath%\ [headline.nsf]</pattern>
<pattern type=”File”>%NotesDataPath%\ [names.nsf]</pattern>
<pattern type=”File”>%NotesDataPath%\ [*.dic]</pattern>
<pattern type=”File”>%NotesDataPath%\ [*.id]</pattern>
<pattern type=”File”>%NotesDataPath%\workspace\* [*]</pattern>
</objectSet>
</locationModify>
<merge script=”MigXmlHelper.SourcePriority()”>
<objectSet>
<pattern type=”File”>%NotesDataPath%\ [bookmark.nsf]</pattern>
<pattern type=”File”>%NotesDataPath%\ [desktop8.ndk]</pattern>
<pattern type=”File”>%NotesDataPath%\ [headline.nsf]</pattern>
<pattern type=”File”>%NotesDataPath%\ [names.nsf]</pattern>
<pattern type=”File”>%NotesDataPath%\ [*.dic]</pattern>
<pattern type=”File”>%NotesDataPath%\ [*.id]</pattern>
<pattern type=”File”>%NotesDataPath%\workspace\* [*]</pattern>
</objectSet>
</merge>
</rules>
<rules context=”User”>
<condition>MigXmlHelper.DoesStringContentEqual(“Registry”,”%NotesInstallType%”,”AllUsers”)</condition>
<include>
<objectSet>
<pattern type=”Registry”>HKCU\Software\Lotus\Notes\Installer [USENOTESFOREMAIL]</pattern>
<pattern type=”File”>%CSIDL_LOCAL_APPDATA%\Lotus\Notes\Data [bookmark.nsf]</pattern>
<pattern type=”File”>%CSIDL_LOCAL_APPDATA%\Lotus\Notes\Data [desktop6.ndk]</pattern>
<pattern type=”File”>%CSIDL_LOCAL_APPDATA%\Lotus\Notes\Data [headline.nsf]</pattern>
<pattern type=”File”>%CSIDL_LOCAL_APPDATA%\Lotus\Notes\Data [names.nsf]</pattern>
<pattern type=”File”>%CSIDL_LOCAL_APPDATA%\Lotus\Notes\Data [user.dic]</pattern>
<pattern type=”File”>%CSIDL_LOCAL_APPDATA%\Lotus\Notes\Data [user.id]</pattern>
<pattern type=”File”>%CSIDL_LOCAL_APPDATA%\Lotus\Notes\Data\workspace\* [*]</pattern>
<pattern type=”Ini”>%CSIDL_LOCAL_APPDATA%\Lotus\Notes\Data\notes.ini|Notes[*]</pattern>
</objectSet>
</include>
<exclude>
<objectSet>
<pattern type=”File”>%CSIDL_LOCAL_APPDATA%\Lotus\Notes\Data\workspace\logs\* [*]</pattern>
<pattern type=”Ini”>%CSIDL_LOCAL_APPDATA%\Lotus\Notes\Data\notes.ini|Notes[KitType]</pattern>
<pattern type=”Ini”>%CSIDL_LOCAL_APPDATA%\Lotus\Notes\Data\notes.ini|Notes[SharedDataDirectory]</pattern>
<pattern type=”Ini”>%CSIDL_LOCAL_APPDATA%\Lotus\Notes\Data\notes.ini|Notes[InstallType]</pattern>
<pattern type=”Ini”>%CSIDL_LOCAL_APPDATA%\Lotus\Notes\Data\notes.ini|Notes[InstallMode]</pattern>
<pattern type=”Ini”>%CSIDL_LOCAL_APPDATA%\Lotus\Notes\Data\notes.ini|Notes[Directory]</pattern>
<pattern type=”Ini”>%CSIDL_LOCAL_APPDATA%\Lotus\Notes\Data\notes.ini|Notes[FaultRecovery_Build]</pattern>
<pattern type=”Ini”>%CSIDL_LOCAL_APPDATA%\Lotus\Notes\Data\notes.ini|Notes[DefaultMailTemplate]</pattern>
<pattern type=”Ini”>%CSIDL_LOCAL_APPDATA%\Lotus\Notes\Data\notes.ini|Notes[FileDlgDirectory]</pattern>
<pattern type=”Ini”>%CSIDL_LOCAL_APPDATA%\Lotus\Notes\Data\notes.ini|Notes[SU_*]</pattern>
<pattern type=”Ini”>%CSIDL_LOCAL_APPDATA%\Lotus\Notes\Data\notes.ini|Notes[SUT_*]</pattern>
<pattern type=”Ini”>%CSIDL_LOCAL_APPDATA%\Lotus\Notes\Data\notes.ini|Notes[AUTO_SAVE_USER*]</pattern>
</objectSet>
</exclude>
<merge script=”MigXmlHelper.SourcePriority()”>
<objectSet>
<pattern type=”File”>%CSIDL_LOCAL_APPDATA%\Lotus\Notes\Data [bookmark.nsf]</pattern>
<pattern type=”File”>%CSIDL_LOCAL_APPDATA%\Lotus\Notes\Data [desktop6.ndk]</pattern>
<pattern type=”File”>%CSIDL_LOCAL_APPDATA%\Lotus\Notes\Data [headline.nsf]</pattern>
<pattern type=”File”>%CSIDL_LOCAL_APPDATA%\Lotus\Notes\Data [names.nsf]</pattern>
<pattern type=”File”>%CSIDL_LOCAL_APPDATA%\Lotus\Notes\Data [user.dic]</pattern>
<pattern type=”File”>%CSIDL_LOCAL_APPDATA%\Lotus\Notes\Data [user.id]</pattern>
<pattern type=”File”>%CSIDL_LOCAL_APPDATA%\Lotus\Notes\Data\workspace\* [*]</pattern>
</objectSet>
</merge>
</rules>
</role>
</component>

 

Migrating Notes.ini

For several reasons Notes 8.5.3 was installed on the base Windows 7 image and not as an app layer. The default 8.5.3 Notes.ini contains the following:

[Notes]
KitType=1
Directory=C:\Program Files (x86)\Notes\Data
InstallType=6
InstallMode=1
NotesProgram=C:\Program Files (x86)\Notes\
FaultRecovery_Build=Release 8.5.3FP1
DSTLAW=3,2,1,11,1,1
USING_LOCAL_SHARED_MEM=1
LOCAL_SHARED_MEM_SESSION_ID=0
FileDlgDirectory=C:\Users\Administrator\Documents
ExtMgr_Addins=NLNVP.DLL

Every version of Notes.ini that the client had installed contained the following keys that needed to be copied into the new Notes.ini:

KeyFileName=
KeyFileName_Owner=
MailServer=
MailType=
MailFile=
Location=

The catch is these keys needed to be copied over, but no others. This was done by running the following VBS script in the post migration options.

Option Explicit
Dim objFSO, strOldIni, strData, strNewIni, StrLine, arrLines, i, objFilestrOldIni = “C:\Windows.Old\Program Files\Notes\notes.ini”
Set ObjFSO = CreateObject(“Scripting.FileSystemObject”)
strData = ObjFSO.OpenTextFile(strOldIni,1).ReadAll
arrLines = Split(strData,vbCrLf)strNewIni = “C:\Program Files (x86)\Notes\notes.ini”
Set ObjFSO = CreateObject(“Scripting.FileSystemObject”)
set objFile = objFSO.OpenTextFile(strNewIni,8, True)

For Each strLine in arrLines

i= instr(strLine,”=”)

if isnull(i) = false then

if ucase(left(strLine,i-1)) = ucase(“KeyFileName”) then
objFile.WriteLine(strline)
Else

if ucase(left(strLine,i-1)) = ucase(“KeyFileName_Owner”) then
objFile.WriteLine(strline)
Else
if ucase(left(strLine,i-1)) = ucase(“MailServer”) then
objFile.WriteLine(strline)
Else
if ucase(left(strLine,i-1)) = ucase(“MailType”) then
objFile.WriteLine(strline)
Else
if ucase(left(strLine,i-1)) = ucase(“MailFile”) then
objFile.WriteLine(strline)
Else
if ucase(left(strLine,i-1)) = ucase(“Location”) then
objFile.WriteLine(strline)
Else

end if
End if
End If
End If
End if
End if
End if

Next

objFile.Close

 

Hope this helps and good luck.

  • Syed Hassan Gilani

    Hi Byron,
    Many thanks for sharing the information, very informative.

    I am facing somewhat similar problem.
    In my scenario, we are doing a hardware migration from XP to Win7. The issue i am facing is that I dont even see the Lotus Notes files getting copied to Windows.Old folder.

    I have even tried to put exceptions in Mirage policy to point to specific folder but to no avail.
    If I copy the notes files anywhere outside the “Program Files” Folder, then I am able to see it getting migrated over but if its inside the “Program Files” folder then nope.

    Any advice,
    thanks
    Hassan