Advanced Font Installation: Difference between revisions

From NSIS Wiki
Jump to navigationJump to search
No edit summary
Line 16: Line 16:
== The Script ==
== The Script ==
<highlight-nsis>var FONT_DIR
<highlight-nsis>var FONT_DIR
var FONT_DIR
!ifndef CSIDL_FONTS
!ifndef CSIDL_FONTS
   !define CSIDL_FONTS '0x14' ;Fonts directory path constant
   !define CSIDL_FONTS '0x14' ;Fonts directory path constant
Line 22: Line 24:
   !define CSIDL_FLAG_CREATE 0x8000
   !define CSIDL_FLAG_CREATE 0x8000
!endif
!endif
### Modified Code from FileFunc.nsh    ###
### Original by Instructor and kichik  ###
!ifmacrondef GetFileNameCall
        !macro GetFileNameCall _PATHSTRING _RESULT
                Push `${_PATHSTRING}`
              Call GetFileName
              Pop ${_RESULT}
        !macroend
!endif
!ifndef GetFileName
!define GetFileName `!insertmacro GetFileNameCall`
Function GetFileName
Exch $0
Push $1
Push $2
StrCpy $2 $0 1 -1
StrCmp $2 '\' 0 +3
StrCpy $0 $0 -1
goto -3
StrCpy $1 0
IntOp $1 $1 - 1
StrCpy $2 $0 1 $1
StrCmp $2 '' end
StrCmp $2 '\' 0 -3
IntOp $1 $1 + 1
StrCpy $0 $0 '' $1
end:
Pop $2
Pop $1
Exch $0
FunctionEnd
!endif
### End Code From ###


!macro InstallTTF FontFile
!macro InstallTTF FontFile
  Push $0 
   Push $R0
   Push $R0
   Push $R1
   Push $R1
Line 30: Line 74:
    
    
   !define Index 'Line${__LINE__}'
   !define Index 'Line${__LINE__}'
 
; Get the Font's File name
  ${GetFileName} ${FontFile} $0
  !define FontFileName $0


   SetOutPath $FONT_DIR
   SetOutPath $FONT_DIR
   IfFileExists "$FONT_DIR\${FontFile}" ${Index} "${Index}-New"
   IfFileExists "$FONT_DIR\${FontFileName}" ${Index} "${Index}-New"
    
    
   !ifdef FontBackup
   !ifdef FontBackup
     "${Index}-New:"
     "${Index}-New:"
     ;Implementation of Font Backup Store
     ;Implementation of Font Backup Store
       WriteRegStr HKLM "${FontBackup}" "${FontFile}" "OK"
       WriteRegStr HKLM "${FontBackup}" "${FontFileName}" "OK"
       File '${FontFile}'
       File '${FontFile}'
       goto ${Index}
       goto ${Index}
Line 61: Line 109:
"${Index}-GO:"
"${Index}-GO:"
   ClearErrors
   ClearErrors
   !insertmacro FontName "$FONT_DIR\${FontFile}"
   !insertmacro FontName "$FONT_DIR\${FontFileName}"
   pop $R2
   pop $R2
   IfErrors 0 "${Index}-Add"
   IfErrors 0 "${Index}-Add"
Line 72: Line 120:
   ReadRegStr $R0 HKLM "$R1" "$R2"
   ReadRegStr $R0 HKLM "$R1" "$R2"
   IfErrors 0 "${Index}-End"
   IfErrors 0 "${Index}-End"
     System::Call "GDI32::AddFontResourceA(t) i ('${FontFile}') .s"
     System::Call "GDI32::AddFontResourceA(t) i ('${FontFileName}') .s"
     WriteRegStr HKLM "$R1" "$R2" "${FontFile}"
     WriteRegStr HKLM "$R1" "$R2" "${FontFileName}"
     goto "${Index}-End"
     goto "${Index}-End"


Line 79: Line 127:


   !undef Index
   !undef Index
  !undef FontFileName
    
    
   pop $R3
   pop $R3
   pop $R2
   pop $R2
   pop $R1
   pop $R1
   pop $R0
   Pop $R0
  Pop $0
!macroend
!macroend


!macro InstallFON FontFile FontName
!macro InstallFON FontFile FontName
  Push $0 
   Push $R0
   Push $R0
   Push $R1
   Push $R1


   !define Index 'Line${__LINE__}'
   !define Index 'Line${__LINE__}'
 
; Get the Font's File name
  ${GetFileName} ${FontFile} $0
  !define FontFileName $0
    
    
   SetOutPath $FONT_DIR
   SetOutPath $FONT_DIR
   IfFileExists "$FONT_DIR\${FontFile}" ${Index} "${Index}-New"
   IfFileExists "$FONT_DIR\${FontFileName}" ${Index} "${Index}-New"


   !ifdef FontBackup
   !ifdef FontBackup
     "${Index}-New:"
     "${Index}-New:"
     ;Implementation of Font Backup Store
     ;Implementation of Font Backup Store
       WriteRegStr HKLM "${FontBackup}" "${FontFile}" "OK"
       WriteRegStr HKLM "${FontBackup}" "${FontFileName}" "OK"
       File '${FontFile}'
       File '${FontFile}'
       goto ${Index}
       goto ${Index}
Line 124: Line 179:
   ReadRegStr $R0 HKLM "$R1" "${FontName}"
   ReadRegStr $R0 HKLM "$R1" "${FontName}"
   IfErrors 0 "${Index}-End"
   IfErrors 0 "${Index}-End"
     System::Call "GDI32::AddFontResourceA(t) i ('${FontFile}') .s"
     System::Call "GDI32::AddFontResourceA(t) i ('${FontFileName}') .s"
     WriteRegStr HKLM "$R1" "${FontName}" "${FontFile}"
     WriteRegStr HKLM "$R1" "${FontName}" "${FontFileName}"
     goto "${Index}-End"
     goto "${Index}-End"


Line 131: Line 186:


   !undef Index
   !undef Index
  !undef FontFileName


   pop $R1
   pop $R1
   pop $R0
   Pop $R0
  Pop $0
!macroend
!macroend


Line 139: Line 196:


!macro RemoveTTF FontFile
!macro RemoveTTF FontFile
Push $R0
  Push $0 
Push $R1
  Push $R0
Push $R2
  Push $R1
Push $R3
  Push $R2
Push $R4
  Push $R3
  Push $R4


   !define Index 'Line${__LINE__}'
   !define Index 'Line${__LINE__}'
 
; Get the Font's File name
  ${GetFileName} ${FontFile} $0
  !define FontFileName $0


   IfFileExists "$FONT_DIR\${FontFile}" ${Index} "${Index}-End"
   IfFileExists "$FONT_DIR\${FontFileName}" ${Index} "${Index}-End"


${Index}:
${Index}:
Line 166: Line 228:
   ;Implementation of Font Backup Store
   ;Implementation of Font Backup Store
     StrCpy $R2 ''
     StrCpy $R2 ''
     ReadRegStr $R2 HKLM "${FontBackup}" "${FontFile}"
     ReadRegStr $R2 HKLM "${FontBackup}" "${FontFileName}"
     StrCmp $R2 'OK' 0 "${Index}-Skip"
     StrCmp $R2 'OK' 0 "${Index}-Skip"


     ClearErrors
     ClearErrors
     !insertmacro FontName "$FONT_DIR\${FontFile}"
     !insertmacro FontName "$FONT_DIR\${FontFileName}"
     pop $R2
     pop $R2
     IfErrors 0 "${Index}-Remove"
     IfErrors 0 "${Index}-Remove"
Line 178: Line 240:
   "${Index}-Remove:"
   "${Index}-Remove:"
     StrCpy $R2 "$R2 (TrueType)"
     StrCpy $R2 "$R2 (TrueType)"
     System::Call "GDI32::RemoveFontResourceA(t) i ('${FontFile}') .s"
     System::Call "GDI32::RemoveFontResourceA(t) i ('${FontFileName}') .s"
     DeleteRegValue HKLM "$R1" "$R2"
     DeleteRegValue HKLM "$R1" "$R2"
     DeleteRegValue HKLM "${FontBackup}" "${FontFile}"
     DeleteRegValue HKLM "${FontBackup}" "${FontFileName}"
     EnumRegValue $R4 HKLM "${FontBackup}" 0
     EnumRegValue $R4 HKLM "${FontBackup}" 0
     IfErrors 0 "${Index}-NoError"
     IfErrors 0 "${Index}-NoError"
       MessageBox MB_OK "FONT (${FontFile}) Removal.$\r$\n(Registry Key Error: $R4)$\r$\nRestart computer and try again. If problem persists contact your supplier."
       MessageBox MB_OK "FONT (${FontFileName}) Removal.$\r$\n(Registry Key Error: $R4)$\r$\nRestart computer and try again. If problem persists contact your supplier."
       Abort "EnumRegValue Error: ${FontFile} triggered error in EnumRegValue for Key $R4."
       Abort "EnumRegValue Error: ${FontFileName} triggered error in EnumRegValue for Key $R4."
   "${Index}-NoError:"
   "${Index}-NoError:"
     StrCmp $R4 "" 0 "${Index}-NotEmpty"
     StrCmp $R4 "" 0 "${Index}-NotEmpty"
       DeleteRegKey HKLM "${FontBackup}" ; This will delete the key if there are no more fonts...
       DeleteRegKey HKLM "${FontBackup}" ; This will delete the key if there are no more fonts...
   "${Index}-NotEmpty:"
   "${Index}-NotEmpty:"
     Delete /REBOOTOK "$FONT_DIR\${FontFile}"
     Delete /REBOOTOK "$FONT_DIR\${FontFileName}"
     goto "${Index}-End"
     goto "${Index}-End"
   "${Index}-Skip:"
   "${Index}-Skip:"
Line 197: Line 259:
      
      
     ClearErrors
     ClearErrors
     !insertmacro FontName "$FONT_DIR\${FontFile}"
     !insertmacro FontName "$FONT_DIR\${FontFileName}"
     pop $R2
     pop $R2
     IfErrors 0 "${Index}-Remove"
     IfErrors 0 "${Index}-Remove"
Line 205: Line 267:
   "${Index}-Remove:"
   "${Index}-Remove:"
     StrCpy $R2 "$R2 (TrueType)"
     StrCpy $R2 "$R2 (TrueType)"
     System::Call "GDI32::RemoveFontResourceA(t) i ('${FontFile}') .s"
     System::Call "GDI32::RemoveFontResourceA(t) i ('${FontFileName}') .s"
     DeleteRegValue HKLM "$R1" "$R2"
     DeleteRegValue HKLM "$R1" "$R2"
     delete /REBOOTOK "$FONT_DIR\${FontFile}"
     delete /REBOOTOK "$FONT_DIR\${FontFileName}"
     goto "${Index}-End"
     goto "${Index}-End"
   !endif
   !endif
Line 213: Line 275:
"${Index}-End:"
"${Index}-End:"


!undef Index
  !undef Index
  !undef FontFileName


pop $R4
  pop $R4
pop $R3
  pop $R3
pop $R2
  pop $R2
pop $R1
  pop $R1
pop $R0
  Pop $R0
  Pop $0
!macroend
!macroend


!macro RemoveFON FontFile FontName
!macro RemoveFON FontFile FontName
Push $R0
  Push $0 
Push $R1
  Push $R0
Push $R2
  Push $R1
Push $R3
  Push $R2
Push $R4
  Push $R3
  Push $R4


   !define Index 'Line${__LINE__}'
   !define Index 'Line${__LINE__}'


   IfFileExists "$FONT_DIR\${FontFile}" ${Index} "${Index}-End"
; Get the Font's File name
  ${GetFileName} ${FontFile} $0
  !define FontFileName $0
 
   IfFileExists "$FONT_DIR\${FontFileName}" ${Index} "${Index}-End"


${Index}:
${Index}:
Line 250: Line 319:
   ;Implementation of Font Backup Store
   ;Implementation of Font Backup Store
     StrCpy $R2 ''
     StrCpy $R2 ''
     ReadRegStr $R2 HKLM "${FontBackup}" "${FontFile}"
     ReadRegStr $R2 HKLM "${FontBackup}" "${FontFileName}"
     StrCmp $R2 'OK' "${Index}-Remove" "${Index}-Skip"
     StrCmp $R2 'OK' "${Index}-Remove" "${Index}-Skip"


   "${Index}-Remove:"
   "${Index}-Remove:"
     System::Call "GDI32::RemoveFontResourceA(t) i ('${FontFile}') .s"
     System::Call "GDI32::RemoveFontResourceA(t) i ('${FontFileName}') .s"
     DeleteRegValue HKLM "$R1" "${FontName}"
     DeleteRegValue HKLM "$R1" "${FontName}"
     DeleteRegValue HKLM "${FontBackup}" "${FontFile}"
     DeleteRegValue HKLM "${FontBackup}" "${FontFileName}"
     EnumRegValue $R4 HKLM "${FontBackup}" 0
     EnumRegValue $R4 HKLM "${FontBackup}" 0
     IfErrors 0 "${Index}-NoError"
     IfErrors 0 "${Index}-NoError"
       MessageBox MB_OK "FONT (${FontFile}) Removal.$\r$\n(Registry Key Error: $R4)$\r$\nRestart computer and try again. If problem persists contact your supplier."
       MessageBox MB_OK "FONT (${FontFileName}) Removal.$\r$\n(Registry Key Error: $R4)$\r$\nRestart computer and try again. If problem persists contact your supplier."
       Abort "EnumRegValue Error: ${FontFile} triggered error in EnumRegValue for Key $R4."
       Abort "EnumRegValue Error: ${FontFileName} triggered error in EnumRegValue for Key $R4."
   "${Index}-NoError:"
   "${Index}-NoError:"
     StrCmp $R4 "" 0 "${Index}-NotEmpty"
     StrCmp $R4 "" 0 "${Index}-NotEmpty"
       DeleteRegKey HKLM "${FontBackup}" ; This will delete the key if there are no more fonts...
       DeleteRegKey HKLM "${FontBackup}" ; This will delete the key if there are no more fonts...
   "${Index}-NotEmpty:"
   "${Index}-NotEmpty:"
     Delete /REBOOTOK "$FONT_DIR\${FontFile}"
     Delete /REBOOTOK "$FONT_DIR\${FontFileName}"
     goto "${Index}-End"
     goto "${Index}-End"
   "${Index}-Skip:"
   "${Index}-Skip:"
Line 271: Line 340:
   !else
   !else
   "${Index}-GO:"
   "${Index}-GO:"
     System::Call "GDI32::RemoveFontResourceA(t) i ('${FontFile}') .s"
     System::Call "GDI32::RemoveFontResourceA(t) i ('${FontFileName}') .s"
     DeleteRegValue HKLM "$R1" "${FontName}"
     DeleteRegValue HKLM "$R1" "${FontName}"
     delete /REBOOTOK "$FONT_DIR\${FontFile}"
     delete /REBOOTOK "$FONT_DIR\${FontFileName}"
     goto "${Index}-End"
     goto "${Index}-End"
   !endif
   !endif
Line 279: Line 348:
"${Index}-End:"
"${Index}-End:"


!undef Index
  !undef Index
  !undef FontFileName


pop $R4
  pop $R4
pop $R3
  pop $R3
pop $R2
  pop $R2
pop $R1
  pop $R1
pop $R0
  Pop $R0
  Pop $0
!macroend</highlight-nsis>
!macroend</highlight-nsis>
After including that file in your script you should make sure that the '$FONT_DIR' variable is set to the right fonts directory of the target machine and make sure that you define the FontBackup variable to point to the location were you would like to store the names of the fonts that were not present on the users machine when the installer was executed and thus should be safe to remove when uninstalling provided that no newer program are using this font.  Also of note is the last command in the fonts Section, it enables Windows and other programs to refresh their fonts lists without the need to restart the computer.  Fonts will most likely not be completely removed until the PC is restarted as fonts are only removed if no programs are using the fonts list.
Please note that FontFile parameter should be '''just''' the font filename, without a preceding path.  If the fonts are not stored in the same location as the script you should use the '!cd' command to change the compiler path to the location of the fonts before calling the font macros.
Calling the RemoveTTF and RemoveFON macros is identical to their installation variants.
You should note that you must also include the FontName.nsh file available with the FontName plugin.
<highlight-nsis>!include FontRegAdv.nsh
!include FontName.nsh
!define FontBackup Reg\key\To\Backup\Fonts\entries\To'
[...]
Section "Fonts"
; Alternate for older versions of NSIS: pre NSIS v2.0rc1
;  push $1
;  System::Call "Shell32::SHGetSpecialFolderLocation(i $HWNDPARENT, i ${CSIDL_FONTS}|${CSIDL_FLAG_CREATE}, *i .r0)"
;  System::Call "Shell32::SHGetPathFromIDList(i r0, t .r1)"
;  System::Call 'shell32::SHGetMalloc(*i . r2)' ; IMalloc
;  System::Call '$2->5(i r0)' ; ->Free
;  System::Call '$2->2()' ; ->Release
;  StrCpy $FONT_DIR $1
;  pop $1
 
  StrCpy $FONT_DIR $FONTS
  !insertmacro InstallTTF 'ARLRDBD.TTF'
  !insertmacro InstallTTF 'LUCON.TTF'
  !insertmacro InstallTTF 'OCRAEXT.TTF'
  !insertmacro InstallFON 'ROMAN.FON'  'Roman (All res)'
  !insertmacro InstallFON 'SMALLE.FON'  'Small Fonts (VGA res)'
  SendMessage ${HWND_BROADCAST} ${WM_FONTCHANGE} 0 0 /TIMEOUT=5000
SectionEnd
Section "un.Fonts"
; Alternate for older versions of NSIS: pre NSIS v2.0rc1
;  push $1
;  System::Call "Shell32::SHGetSpecialFolderLocation(i $HWNDPARENT, i ${CSIDL_FONTS}|${CSIDL_FLAG_CREATE}, *i .r0)"
;  System::Call "Shell32::SHGetPathFromIDList(i r0, t .r1)"
;  System::Call 'shell32::SHGetMalloc(*i . r2)' ; IMalloc
;  System::Call '$2->5(i r0)' ; ->Free
;  System::Call '$2->2()' ; ->Release
;  StrCpy $FONT_DIR $1
;  pop $1
 
  StrCpy $FONT_DIR $FONTS
  !insertmacro RemoveTTF 'ARLRDBD.TTF'
  !insertmacro RemoveTTF 'LUCON.TTF'
  !insertmacro RemoveTTF 'OCRAEXT.TTF'
  !insertmacro RemoveFON 'ROMAN.FON'  'Roman (All res)'
  !insertmacro RemoveFON 'SMALLE.FON'  'Small Fonts (VGA res)'
  SendMessage ${HWND_BROADCAST} ${WM_FONTCHANGE} 0 0 /TIMEOUT=5000
SectionEnd</highlight-nsis>


A few notes about using InstallFON macro:  You should copy the 'FontName' out of the registry of the Source machine as the fonts might not work if the wrong name or type is specified.
A few notes about using InstallFON macro:  You should copy the 'FontName' out of the registry of the Source machine as the fonts might not work if the wrong name or type is specified.

Revision as of 15:27, 22 October 2005

Author: Vytautas (talk, contrib)


Note

This script is now included in the FontName plugin by default.

Description

This page uses the functionality of the FontName plugin. This will allow you to register TTF fonts without the need to supply the font's registry name. The second macro is designed to register FON fonts and still requires the input of the font's name. If you do not wish to use the FontName plugin you should use the FON font macro to install TTF fonts.

These macros have been designed to work with NSIS 2.0b4 (CVS), although it could possibly be modified to work with earlier versions of NSIS.

These macros allow the user to uninstall fonts in the uninstaller as does the standard version the main difference being that if you define FontBackup to a 'registry store' of the fonts the installer created it will only remove fonts that were not present before the program was installed.

Please note that uninstalling fonts is generally not a good idea since other programs might depend on them. Exceptions would be custom created fonts which would only be used by your program or when installing an *huge* amount of fonts.

Save this script as a NSIS Include file in the Include directory of NSIS so that then you can easily get font registration functionality in any script by simply including this file. (Suggested file name: FontRegAdv.nsh)

The Script

var FONT_DIR
var FONT_DIR
 
!ifndef CSIDL_FONTS
  !define CSIDL_FONTS '0x14' ;Fonts directory path constant
!endif
!ifndef CSIDL_FLAG_CREATE
  !define CSIDL_FLAG_CREATE 0x8000
!endif
 
### Modified Code from FileFunc.nsh    ###
### Original by Instructor and kichik  ###
 
!ifmacrondef GetFileNameCall
        !macro GetFileNameCall _PATHSTRING _RESULT
                Push `${_PATHSTRING}`
              	Call GetFileName
               	Pop ${_RESULT}
        !macroend
!endif
 
!ifndef GetFileName
	!define GetFileName `!insertmacro GetFileNameCall`
 
	Function GetFileName
		Exch $0
		Push $1
		Push $2
 
		StrCpy $2 $0 1 -1
		StrCmp $2 '\' 0 +3
		StrCpy $0 $0 -1
		goto -3
 
		StrCpy $1 0
		IntOp $1 $1 - 1
		StrCpy $2 $0 1 $1
		StrCmp $2 '' end
		StrCmp $2 '\' 0 -3
		IntOp $1 $1 + 1
		StrCpy $0 $0 '' $1
 
		end:
		Pop $2
		Pop $1
		Exch $0
	FunctionEnd
!endif
 
### End Code From ###
 
!macro InstallTTF FontFile
  Push $0  
  Push $R0
  Push $R1
  Push $R2
  Push $R3
 
  !define Index 'Line${__LINE__}'
 
; Get the Font's File name
  ${GetFileName} ${FontFile} $0
  !define FontFileName $0
 
  SetOutPath $FONT_DIR
  IfFileExists "$FONT_DIR\${FontFileName}" ${Index} "${Index}-New"
 
  !ifdef FontBackup
    "${Index}-New:"
    ;Implementation of Font Backup Store
      WriteRegStr HKLM "${FontBackup}" "${FontFileName}" "OK"
      File '${FontFile}'
      goto ${Index}
  !else
    "${Index}-New:"
      File '${FontFile}'
      goto ${Index}
  !endif
 
${Index}:
  ClearErrors
  ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" "CurrentVersion"
  IfErrors "${Index}-9x" "${Index}-NT"
 
"${Index}-NT:"
  StrCpy $R1 "Software\Microsoft\Windows NT\CurrentVersion\Fonts"
  goto "${Index}-GO"
 
"${Index}-9x:"
  StrCpy $R1 "Software\Microsoft\Windows\CurrentVersion\Fonts"
  goto "${Index}-GO"
 
"${Index}-GO:"
  ClearErrors
  !insertmacro FontName "$FONT_DIR\${FontFileName}"
  pop $R2
  IfErrors 0 "${Index}-Add"
    MessageBox MB_OK "$R2"
    goto "${Index}-End"
 
"${Index}-Add:"
  StrCpy $R2 "$R2 (TrueType)"
  ClearErrors
  ReadRegStr $R0 HKLM "$R1" "$R2"
  IfErrors 0 "${Index}-End"
    System::Call "GDI32::AddFontResourceA(t) i ('${FontFileName}') .s"
    WriteRegStr HKLM "$R1" "$R2" "${FontFileName}"
    goto "${Index}-End"
 
"${Index}-End:"
 
  !undef Index
  !undef FontFileName
 
  pop $R3
  pop $R2
  pop $R1
  Pop $R0  
  Pop $0
!macroend
 
!macro InstallFON FontFile FontName
  Push $0  
  Push $R0
  Push $R1
 
  !define Index 'Line${__LINE__}'
 
; Get the Font's File name
  ${GetFileName} ${FontFile} $0
  !define FontFileName $0
 
  SetOutPath $FONT_DIR
  IfFileExists "$FONT_DIR\${FontFileName}" ${Index} "${Index}-New"
 
  !ifdef FontBackup
    "${Index}-New:"
    ;Implementation of Font Backup Store
      WriteRegStr HKLM "${FontBackup}" "${FontFileName}" "OK"
      File '${FontFile}'
      goto ${Index}
  !else
    "${Index}-New:"
      File '${FontFile}'
      goto ${Index}
  !endif
 
${Index}:
  ClearErrors
  ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" "CurrentVersion"
  IfErrors "${Index}-9x" "${Index}-NT"
 
"${Index}-NT:"
  StrCpy $R1 "Software\Microsoft\Windows NT\CurrentVersion\Fonts"
  goto "${Index}-GO"
 
"${Index}-9x:"
  StrCpy $R1 "Software\Microsoft\Windows\CurrentVersion\Fonts"
  goto "${Index}-GO"
 
"${Index}-GO:"
  ClearErrors
  ReadRegStr $R0 HKLM "$R1" "${FontName}"
  IfErrors 0 "${Index}-End"
    System::Call "GDI32::AddFontResourceA(t) i ('${FontFileName}') .s"
    WriteRegStr HKLM "$R1" "${FontName}" "${FontFileName}"
    goto "${Index}-End"
 
"${Index}-End:"
 
  !undef Index
  !undef FontFileName
 
  pop $R1
  Pop $R0  
  Pop $0
!macroend
 
; Uninstaller entries
 
!macro RemoveTTF FontFile
  Push $0  
  Push $R0
  Push $R1
  Push $R2
  Push $R3
  Push $R4
 
  !define Index 'Line${__LINE__}'
 
; Get the Font's File name
  ${GetFileName} ${FontFile} $0
  !define FontFileName $0
 
  IfFileExists "$FONT_DIR\${FontFileName}" ${Index} "${Index}-End"
 
${Index}:
  ClearErrors
  ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" "CurrentVersion"
  IfErrors "${Index}-9x" "${Index}-NT"
 
"${Index}-NT:"
  StrCpy $R1 "Software\Microsoft\Windows NT\CurrentVersion\Fonts"
  goto "${Index}-GO"
 
"${Index}-9x:"
  StrCpy $R1 "Software\Microsoft\Windows\CurrentVersion\Fonts"
  goto "${Index}-GO"
 
  !ifdef FontBackup
  "${Index}-GO:"
  ;Implementation of Font Backup Store
    StrCpy $R2 ''
    ReadRegStr $R2 HKLM "${FontBackup}" "${FontFileName}"
    StrCmp $R2 'OK' 0 "${Index}-Skip"
 
    ClearErrors
    !insertmacro FontName "$FONT_DIR\${FontFileName}"
    pop $R2
    IfErrors 0 "${Index}-Remove"
    MessageBox MB_OK "$R2"
    goto "${Index}-End"    
 
  "${Index}-Remove:"
    StrCpy $R2 "$R2 (TrueType)"
    System::Call "GDI32::RemoveFontResourceA(t) i ('${FontFileName}') .s"
    DeleteRegValue HKLM "$R1" "$R2"
    DeleteRegValue HKLM "${FontBackup}" "${FontFileName}"
    EnumRegValue $R4 HKLM "${FontBackup}" 0
    IfErrors 0 "${Index}-NoError"
      MessageBox MB_OK "FONT (${FontFileName}) Removal.$\r$\n(Registry Key Error: $R4)$\r$\nRestart computer and try again. If problem persists contact your supplier."
      Abort "EnumRegValue Error: ${FontFileName} triggered error in EnumRegValue for Key $R4."
  "${Index}-NoError:"
    StrCmp $R4 "" 0 "${Index}-NotEmpty"
      DeleteRegKey HKLM "${FontBackup}" ; This will delete the key if there are no more fonts...
  "${Index}-NotEmpty:"
    Delete /REBOOTOK "$FONT_DIR\${FontFileName}"
    goto "${Index}-End"
  "${Index}-Skip:"
    goto "${Index}-End"
  !else
  "${Index}-GO:"
 
    ClearErrors
    !insertmacro FontName "$FONT_DIR\${FontFileName}"
    pop $R2
    IfErrors 0 "${Index}-Remove"
    MessageBox MB_OK "$R2"
    goto "${Index}-End"
 
  "${Index}-Remove:"
    StrCpy $R2 "$R2 (TrueType)"
    System::Call "GDI32::RemoveFontResourceA(t) i ('${FontFileName}') .s"
    DeleteRegValue HKLM "$R1" "$R2"
    delete /REBOOTOK "$FONT_DIR\${FontFileName}"
    goto "${Index}-End"
  !endif
 
"${Index}-End:"
 
  !undef Index
  !undef FontFileName
 
  pop $R4
  pop $R3
  pop $R2
  pop $R1
  Pop $R0  
  Pop $0
!macroend
 
!macro RemoveFON FontFile FontName
  Push $0  
  Push $R0
  Push $R1
  Push $R2
  Push $R3
  Push $R4
 
  !define Index 'Line${__LINE__}'
 
; Get the Font's File name
  ${GetFileName} ${FontFile} $0
  !define FontFileName $0
 
  IfFileExists "$FONT_DIR\${FontFileName}" ${Index} "${Index}-End"
 
${Index}:
  ClearErrors
  ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" "CurrentVersion"
  IfErrors "${Index}-9x" "${Index}-NT"
 
"${Index}-NT:"
  StrCpy $R1 "Software\Microsoft\Windows NT\CurrentVersion\Fonts"
  goto "${Index}-GO"
 
"${Index}-9x:"
  StrCpy $R1 "Software\Microsoft\Windows\CurrentVersion\Fonts"
  goto "${Index}-GO"
 
  !ifdef FontBackup
  "${Index}-GO:"
  ;Implementation of Font Backup Store
    StrCpy $R2 ''
    ReadRegStr $R2 HKLM "${FontBackup}" "${FontFileName}"
    StrCmp $R2 'OK' "${Index}-Remove" "${Index}-Skip"
 
  "${Index}-Remove:"
    System::Call "GDI32::RemoveFontResourceA(t) i ('${FontFileName}') .s"
    DeleteRegValue HKLM "$R1" "${FontName}"
    DeleteRegValue HKLM "${FontBackup}" "${FontFileName}"
    EnumRegValue $R4 HKLM "${FontBackup}" 0
    IfErrors 0 "${Index}-NoError"
      MessageBox MB_OK "FONT (${FontFileName}) Removal.$\r$\n(Registry Key Error: $R4)$\r$\nRestart computer and try again. If problem persists contact your supplier."
      Abort "EnumRegValue Error: ${FontFileName} triggered error in EnumRegValue for Key $R4."
  "${Index}-NoError:"
    StrCmp $R4 "" 0 "${Index}-NotEmpty"
      DeleteRegKey HKLM "${FontBackup}" ; This will delete the key if there are no more fonts...
  "${Index}-NotEmpty:"
    Delete /REBOOTOK "$FONT_DIR\${FontFileName}"
    goto "${Index}-End"
  "${Index}-Skip:"
    goto "${Index}-End"
  !else
  "${Index}-GO:"
    System::Call "GDI32::RemoveFontResourceA(t) i ('${FontFileName}') .s"
    DeleteRegValue HKLM "$R1" "${FontName}"
    delete /REBOOTOK "$FONT_DIR\${FontFileName}"
    goto "${Index}-End"
  !endif
 
"${Index}-End:"
 
  !undef Index
  !undef FontFileName
 
  pop $R4
  pop $R3
  pop $R2
  pop $R1
  Pop $R0  
  Pop $0
!macroend

A few notes about using InstallFON macro: You should copy the 'FontName' out of the registry of the Source machine as the fonts might not work if the wrong name or type is specified. The location of the fonts folder can be attained in a number of different ways, reading a registry key from the target machine or the way shown above, obtained from an example by Joel. Note that this way uses the System plug-in and if the size of your installer is a *very* big issue reading the registry might save a few bytes in the final installer size.

Some recent bugs: Do not put a trailing backslash onto the $FONT_DIR. This will make the font install, but be 0 Kilabytes. Some all uppercase font filenames generate errors. By changing the font to all lowercase, the font was automagically found.

Version History

[Update 2005-01-18]
Fixed problem with FON installation as reported by Francois Gelinas
[Update 2004-01-29]
Updated to use FontName v0.6
[Update 2003-12-29]
Added definition of CSIDL_FLAG_CREATE flag.
[Update 2003-12-28]
Added a note about $FONTS variable first included in NSIS v2.0rc1
[Update 2003-12-23]
Fixed some typos in the documentation and notes.
[Update 2003-12-07]
Fixed problem with remove macros removing only the first font, thanks to lewellyn for bug report and solution.
[Update 2003-12-05]
Added a note about the font filenames and macro usage if fonts not in the same folder as the script.
[Update 2003-11-28]
Fixed problem with TTF font installation on Windows 9x with help from brainsucker and kichik. Added error reporting functionality for the FontName plugin.
[Update 2003-11-21]
Fixed macro name mismatch.

Vytautas