/* _____________________________________________________________________________ Application Capabilities (Default Programs) _____________________________________________________________________________ By Joel Spadin Loosely based on code taken from http://nsis.sourceforge.net/File_Association These functions register an application with Windows Vista's and Windows 7's Default Programs window. Usage: !include "Capabilities.nsh" !define CAPABILITIES_NAME "[program name]" !define CAPABILITIES_DESCRIPTION "[description]" !define CAPABILITIES_PROGID "[progid]" !define CAPABILITIES_PATH "[path]" ... During install, call ${RegisterCapabilities}, then use the other register macros to create file type, MIME, and protocol associations. During uninstall, call ${UnRegisterCapabilities} _______________________________________________________________________________ More information about Default Programs and Client Types can be found here: http://msdn.microsoft.com/en-us/library/cc144154(VS.85).aspx http://msdn.microsoft.com/en-us/library/cc144109(v=VS.85).aspx Defines: All defines not marked [optional] are required. CAPABILITIES_NAME The canonical name of the program. CAPABILITIES_LOCAL_NAME [optional] The localized name of the program as it appears in Default Programs. This should be in the format "@FilePath,-StringID" where FilePath is the path to a .dll or .exe file and StringID is the ID of a resource contained in the file. CAPABILITIES_DESCRIPTION The localized description shown in Default Programs. This can be either a string or in the same format as CAPABILITIES_LOCAL_NAME CAPABILITIES_PROGID An identifier used in file associations. Usually, this is the name of the program. This should not have any spaces in it. CAPABILITIES_PATH The location where capabilities info is stored in the registry. The "Capabilities" key will automatically be added. If the application is a client of some sort, (browser, email, media player, etc.) use "Software\Clients\[ClientType]\[ProgramName]". Otherwise, use "Software\[CompanyName]\[ProgramName]" or just "Software\[ProgramName]". CAPABILITIES_ICON [optional] The icon shown in Default Programs. This should be in the format "FilePath,IconIndex" where FilePath is the path to a file containing the icon. If IconIndex is positive, the number is used as the index of the zero-based array of icons stored in the file. If IconIndex is negative, the absolute value is used as a resource ID. CAPABILITIES_REINSTALL [optional] The command executed when a user uses Set Program Access and Computer Defaults to select this application as the default for its client type. This command should launch a program that associates the application with all the file and protocol types it can handle. CAPABILITIES_HIDE_ICONS [optional] The command executed when a user uses Set Program Access and Computer Defaults to disable access to this application. This command should launch a program that hides all shortcuts and access points to this application. It should also prevent the application from being run automatically and update the IconsVisible registry value to 0. CAPABILITIES_SHOW_ICONS [optional] The command executed when a user uses Set Program Access and Computer Defaults to enable access to this application. This command should launch a program that restores shortcuts and access points to the application, allows the program to run, and updates the IconsVisible registry value to 1. Macros: ${RegisterCapabilities} Registers the program with Default Programs. Call this once on install before using any other functions. ${UnRegisterCapabilities} Un-registers the program and all its associations. Call this once on uninstall to clean up all installed registry values. ${RegisterFileType} "[extension]" "[executable]" "[icon]" "[description]" Registers a file type with the program extension: The file extension to register (ex: .txt) executable: The executable that opens the file type icon: The icon shown for the file type description: Description for the file type shown in Explorer ${RegisterMediaType} "[extension]" "[executable]" "[icon]" "[description]" Registers a media file type with the program (has a "Play" command) (arguments are same as RegisterFileType) ${RegisterMimeType} "[mime type]" "[shortname]" "[clsid]" Registers a mime type with the program mime type: The MIME type to register (ex: audio/mp3) shortname: A short identifier for the type (ex: mp3) clsid: The CLSID of the program to handle files of this type ${RegisterProtocol} "[protocol]" "[executable]" "[icon]" "[description]" Registers a URL protocol with the program protocol: The protocol to register (ex: http) (other arguments are same as RegisterFileType) ${UnRegisterFileType} "[extension]" Un-registers a previously registered file type extension: The file extension to un-register ${UnRegisterMimeType} "[mime type]" Un-registers a previously registered MEME type mime type: The MIME type to un-register ${UnRegisterProtocol} "[protocol]" Un-registers a previously registered URL protocol protocol: The URL protocol to un-register */ !ifndef Capabilities_INCLUDED !define Capabilities_INCLUDED !include "Util.nsh" !include "StrFunc.nsh" ${StrCase} !verbose push !verbose 3 !ifndef _Capabilities_VERBOSE !define _Capabilities_VERBOSE 3 !endif !verbose ${_Capabilities_VERBOSE} !define Capabilities_VERBOSE `!insertmacro Capabilities_VERBOSE` !verbose pop !macro Capabilities_VERBOSE _VERBOSE !verbose push !verbose 3 !undef _Capabilities_VERBOSE !define _Capabilities_VERBOSE ${_VERBOSE} !verbose pop !macroend !macro RegisterCapabilitiesCall !verbose push !verbose ${_Capabilities_VERBOSE} ${CallArtificialFunction} RegisterCapabilities_ !verbose pop !macroend !macro UnRegisterCapabilitiesCall !verbose push !verbose ${_Capabilities_VERBOSE} ${CallArtificialFunction} UnRegisterCapabilities_ !verbose pop !macroend !macro RegisterFileTypeCall _EXTENSION _EXECUTABLE _ICON _DESCRIPTION !verbose push !verbose ${_Capabilities_VERBOSE} Push `${_DESCRIPTION}` Push `${_ICON}` Push `${_EXECUTABLE}` Push `${_EXTENSION}` ${CallArtificialFunction} RegisterFileType_ !verbose pop !macroend !macro RegisterMediaTypeCall _EXTENSION _EXECUTABLE _ICON _DESCRIPTION !verbose push !verbose ${_Capabilities_VERBOSE} Push `${_DESCRIPTION}` Push `${_ICON}` Push `${_EXECUTABLE}` Push `${_EXTENSION}` ${CallArtificialFunction} RegisterMediaType_ !verbose pop !macroend !macro RegisterMimeTypeCall _MIMETYPE _SHORTNAME _CLSID !verbose push !verbose ${_Capabilities_VERBOSE} Push `${_CLSID}` Push `${_SHORTNAME}` Push `${_MIMETYPE}` ${CallArtificialFunction} RegisterMimeType_ !verbose pop !macroend !macro RegisterProtocolCall _PROTOCOL _EXECUTABLE _ICON _DESCRIPTION !verbose push !verbose ${_Capabilities_VERBOSE} Push `${_DESCRIPTION}` Push `${_ICON}` Push `${_EXECUTABLE}` Push `${_PROTOCOL}` ${CallArtificialFunction} RegisterProtocol_ !verbose pop !macroend !macro UnRegisterFileTypeCall _EXTENSION !verbose push !verbose ${_Capabilities_VERBOSE} Push `${_EXTENSION}` ${CallArtificialFunction} UnRegisterFileType_ !verbose pop !macroend !macro UnRegisterMimeTypeCall _MIMETYPE !verbose push !verbose ${_Capabilities_VERBOSE} Push `${_MIMETYPE}` ${CallArtificialFunction} UnRegisterMimeType_ !verbose pop !macroend !macro UnRegisterProtocolCall _PROTOCOL !verbose push !verbose ${_Capabilities_VERBOSE} Push `${_MIMETYPE}` ${CallArtificialFunction} UnRegisterProtocol_ !verbose pop !macroend !define RegisterCapabilities `!insertmacro RegisterCapabilitiesCall` !define un.RegisterCapabilities `!insertmacro RegisterCapabilitiesCall` !macro RegisterCapabilities !macroend !macro un.RegisterCapabilities !macroend !macro RegisterCapabilities_ !verbose push !verbose ${_Capabilities_VERBOSE} Push $0 !ifndef CAPABILITIES_PATH !error "CAPABILITIES_PATH not defined" !endif !ifndef CAPABILITIES_NAME !error "CAPABILITIES_NAME not defined" !endif !ifndef CAPABILITIES_PROGID !error "CAPABILITIES_PROGID not defined" !endif !ifndef CAPABILITIES_DESCRIPTION !error "CAPABILITIES_DESCRIPTION not defined" !endif StrCpy $0 "${CAPABILITIES_PATH}\Capabilities" ; add the application to RegisteredApplications WriteRegStr HKLM "Software\RegisteredApplications" "${CAPABILITIES_NAME}" "$0" ; write application info WriteRegStr HKLM "${CAPABILITIES_PATH}" "" "${CAPABILITIES_NAME}" !ifdef CAPABILITIES_LOCAL_NAME WriteRegStr HKLM "${CAPABILITIES_PATH}" "LocalizedString" "${CAPABILITIES_LOCAL_NAME}" !endif !ifdef CAPABILITIES_ICON WriteRegStr HKLM "${CAPABILITIES_PATH}\DefaultIcon" "" "${CAPABILITIES_ICON}" !endif ; write installinfo if defined !ifdef CAPABILITIES_REINSTALL WriteRegStr HKLM "${CAPABILITIES_PATH}\InstallInfo" "ReinstallCommand" "${CAPABILITIES_REINSTALL}" !endif !ifdef CAPABILITIES_HIDE_ICONS WriteRegStr HKLM "${CAPABILITIES_PATH}\InstallInfo" "HideIconsCommand" "${CAPABILITIES_HIDE_ICONS}" WriteRegDWORD HKLM "${CAPABILITIES_PATH}\InstallInfo" "IconsVisible" 0x1 !endif !ifdef CAPABILITIES_SHOW_ICONS WriteRegStr HKLM "${CAPABILITIES_PATH}\InstallInfo" "ShowIconsCommand" "${CAPABILITIES_SHOW_ICONS}" WriteRegDWORD HKLM "${CAPABILITIES_PATH}\InstallInfo" "IconsVisible" 0x1 !endif ; write application capabilities info !ifdef CAPABILITIES_LOCAL_NAME WriteRegStr HKLM "$0" "ApplicationName" "${CAPABILITIES_LOCAL_NAME}" !else WriteRegStr HKLM "$0" "ApplicationName" "${CAPABILITIES_NAME}" !endif WriteRegStr HKLM "$0" "ApplicationDescription" "${CAPABILITIES_DESCRIPTION}" Pop $0 !verbose pop !macroend !define UnRegisterCapabilities `!insertmacro UnRegisterCapabilitiesCall` !define un.UnRegisterCapabilities `!insertmacro UnRegisterCapabilitiesCall` !macro UnRegisterCapabilities !macroend !macro un.UnRegisterCapabilities !macroend !macro UnRegisterCapabilities_ !define MacroID ${__LINE__} !verbose push !verbose ${_Capabilities_VERBOSE} Push $0 Push $1 ; remove all file associations FileTypeLoop_${MacroID}: EnumRegValue $0 HKLM "${CAPABILITIES_PATH}\Capabilities\FileAssociations" 0 StrCmp $0 "" FileTypeDone_${MacroID} ReadRegStr $1 HKLM "${CAPABILITIES_PATH}\Capabilities\FileAssociations" "$0" DeleteRegKey HKCR $1 DeleteRegValue HKLM "${CAPABILITIES_PATH}\Capabilities\FileAssociations" "$0" Goto FileTypeLoop_${MacroID} FileTypeDone_${MacroID}: ; remove all MIME associations MimeTypeLoop_${MacroID}: EnumRegValue $0 HKLM "${CAPABILITIES_PATH}\Capabilities\MimeAssociations" 0 StrCmp $0 "" MimeTypeDone_${MacroID} ReadRegStr $1 HKLM "${CAPABILITIES_PATH}\Capabilities\MimeAssociations" "$0" DeleteRegKey HKCR "$1" DeleteRegValue HKLM "${CAPABILITIES_PATH}\Capabilities\MimeAssociations" "$0" Goto MimeTypeLoop_${MacroID} MimeTypeDone_${MacroID}: ; remove all protocol associations ProtocolLoop_${MacroID}: EnumRegValue $0 HKLM "${CAPABILITIES_PATH}\Capabilities\UrlAssociations" 0 StrCmp $0 "" ProtocolDone_${MacroID} ReadRegStr $1 HKLM "${CAPABILITIES_PATH}\Capabilities\UrlAssociations" "$0" DeleteRegKey HKCR "$1" DeleteRegValue HKLM "${CAPABILITIES_PATH}\Capabilities\UrlAssociations" "$0" Goto ProtocolLoop_${MacroID} ProtocolDone_${MacroID}: ; remove capabilities keys DeleteRegValue HKLM "Software\RegisteredApplications" "${CAPABILITIES_NAME}" DeleteRegKey HKLM ${CAPABILITIES_PATH} Pop $1 Pop $0 !verbose pop !undef MacroID !macroend !define RegisterFileType `!insertmacro RegisterFileTypeCall` !define un.RegisterFileType `!insertmacro RegisterFileTypeCall` !macro RegisterFileType !macroend !macro un.RegisterFileType !macroend !macro RegisterFileType_ !verbose push !verbose ${_Capabilities_VERBOSE} Exch $R3 ;ext Exch Exch $R2 ;exe Exch 2 Exch $R1 ;icon Exch Exch 3 Exch $R0 ;desc Push $0 ; create an association name ; ex: .mp3 becomes ProgID.AssocFile.MP3 ${StrCase} $0 "$R3" "U" StrCpy $0 "${CAPABILITIES_PROGID}.AssocFile$0" ; link capabilities to association in classes root WriteRegStr HKLM "${CAPABILITIES_PATH}\Capabilities\FileAssociations" "$R3" "$0" ; write file association in classes root WriteRegStr HKCR "$0" "" "$R0" WriteRegStr HKCR "$0\DefaultIcon" "" "$R1" WriteRegStr HKCR "$0\shell" "" "Open" WriteRegStr HKCR "$0\shell\open" "" "&Open" WriteRegStr HKCR "$0\shell\open\command" "" '"$R2" "%1"' Pop $0 Pop $R0 Pop $R1 Pop $R2 Pop $R3 !verbose pop !macroend !define RegisterMediaType `!insertmacro RegisterMediaTypeCall` !define un.RegisterMediaType `!insertmacro RegisterMediaTypeCall` !macro RegisterMediaType !macroend !macro un.RegisterMediaType !macroend !macro RegisterMediaType_ !verbose push !verbose ${_Capabilities_VERBOSE} Exch $R3 ;ext Exch Exch $R2 ;exe Exch 2 Exch $R1 ;icon Exch Exch 3 Exch $R0 ;desc Push $0 ; create an association name ; ex: .mp3 becomes ProgID.AssocFile.MP3 ${StrCase} $0 "$R3" "U" StrCpy $0 "${CAPABILITIES_PROGID}.AssocFile$0" ; link capabilities to association in classes root WriteRegStr HKLM "${CAPABILITIES_PATH}\Capabilities\FileAssociations" "$R3" "$0" ; write file association in classes root WriteRegStr HKCR "$0" "" "$R0" WriteRegStr HKCR "$0\DefaultIcon" "" "$R1" WriteRegStr HKCR "$0\shell" "" "Play" WriteRegStr HKCR "$0\shell\open" "" "&Open" WriteRegStr HKCR "$0\shell\open\command" "" '"$R2" "%1"' WriteRegStr HKCR "$0\shell\play" "" "&Play" WriteRegStr HKCR "$0\shell\play\command" "" '"$R2" "%L"' Pop $0 Pop $R0 Pop $R1 Pop $R2 Pop $R3 !verbose pop !macroend !define RegisterMimeType `!insertmacro RegisterMimeTypeCall` !define un.RegisterMimeType `!insertmacro RegisterMimeTypeCall` !macro RegisterMimeType !macroend !macro un.RegisterMimeType !macroend !macro RegisterMimeType_ !verbose push !verbose ${_Capabilities_VERBOSE} Exch $R2 ;mime Exch Exch $R1 ;shortname Exch Exch 2 Exch $R0 ;clsid Push $0 ; create an association name ; ex: audio/mp3 becomes ProgID.AssocMIME.MP3 ${StrCase} $0 "$R1" "U" StrCpy $0 "${CAPABILITIES_PROGID}.AssocMIME.$0" ; link capabilities to association in classes root WriteRegStr HKLM "${CAPABILITIES_PATH}\Capabilities\MimeAssociations" "$R2" "$0" ; write file association in classes root WriteRegStr HKCR "$0\CLSID" "" "$R0" Pop $0 Pop $R0 Pop $R1 !verbose pop !macroend !define RegisterProtocol `!insertmacro RegisterProtocolCall` !define un.RegisterProtocol `!insertmacro RegisterProtocolCall` !macro RegisterProtocol !macroend !macro un.RegisterProtocol !macroend !macro RegisterProtocol_ !verbose push !verbose ${_Capabilities_VERBOSE} Exch $R3 ;protocol Exch Exch $R2 ;exe Exch 2 Exch $R1 ;icon Exch Exch 3 Exch $R0 ;desc Push $0 ; create an association name ; ex: http becomes ProgID.AssocProtocol.HTTP ${StrCase} $0 "$R3" "U" StrCpy $0 "${CAPABILITIES_PROGID}.AssocProtocol.$0" ; link capabilities to association in classes root WriteRegStr HKLM "${CAPABILITIES_PATH}\Capabilities\UrlAssociations" "$R3" "$0" ; write file association in classes root WriteRegStr HKCR "$0" "" "$R0" WriteRegStr HKCR "$0\DefaultIcon" "" "$R1" WriteRegStr HKCR "$0\shell\open" "" "&Open" WriteRegStr HKCR "$0\shell\open\command" "" '"$R2" "%1"' Pop $0 Pop $R0 Pop $R1 Pop $R2 Pop $R3 !verbose pop !macroend !define UnRegisterFileType `!insertmacro UnRegisterFileTypeCall` !define un.UnRegisterFileType `!insertmacro UnRegisterFileTypeCall` !macro UnRegisterFileType !macroend !macro un.UnRegisterFileType !macroend !macro UnRegisterFileType_ !define MacroID ${__LINE__} !verbose push !verbose ${_Capabilities_VERBOSE} Exch $R0 ;ext Push $0 ReadRegStr $0 HKLM "${CAPABILITIES_PATH}\Capabilities\FileAssociations" "$R0" StrCmp $0 "" skip_${MacroID} DeleteRegKey HKCR "$0" DeleteRegValue HKLM "${CAPABILITIES_PATH}\Capabilities\FileAssociations" "$R0" skip_${MacroID}: Pop $0 Pop $R0 !verbose pop !undef MacroID !macroend !define UnRegisterMimeType `!insertmacro UnRegisterMimeTypeCall` !define un.UnRegisterMimeType `!insertmacro UnRegisterMimeTypeCall` !macro UnRegisterMimeType !macroend !macro un.UnRegisterMimeType !macroend !macro UnRegisterMimeType_ !define MacroID ${__LINE__} !verbose push !verbose ${_Capabilities_VERBOSE} Exch $R0 ;mime Push $0 ReadRegStr $0 HKLM "${CAPABILITIES_PATH}\Capabilities\MimeAssociations" "$R0" StrCmp $0 "" skip_${MacroID} DeleteRegKey HKCR "$0" DeleteRegValue HKLM "${CAPABILITIES_PATH}\Capabilities\MimeAssociations" "$R0" skip_${MacroID}: Pop $0 Pop $R0 !verbose pop !undef MacroID !macroend !define UnRegisterProtocol `!insertmacro UnRegisterProtocolCall` !define un.UnRegisterProtocol `!insertmacro UnRegisterProtocolCall` !macro UnRegisterProtocol !macroend !macro un.UnRegisterProtocol !macroend !macro UnRegisterProtocol_ !define MacroID ${__LINE__} !verbose push !verbose ${_Capabilities_VERBOSE} Exch $R0 ;protocol Push $0 ReadRegStr $0 HKLM "${CAPABILITIES_PATH}\Capabilities\UrlAssociations" "$R0" StrCmp $0 "" skip_${MacroID} DeleteRegKey HKCR "$0" DeleteRegValue HKLM "${CAPABILITIES_PATH}\Capabilities\UrlAssociations" "$R0" skip_${MacroID}: Pop $0 Pop $R0 !verbose pop !undef MacroID !macroend !endif