Skip to content

Commit

Permalink
Merge pull request #79 from vQuagliaro/file-association-on-windows
Browse files Browse the repository at this point in the history
File association on windows
  • Loading branch information
stefanjudis committed Dec 21, 2015
2 parents 74078fa + e3b170a commit 0e8e88f
Show file tree
Hide file tree
Showing 4 changed files with 220 additions and 5 deletions.
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,11 @@ config.json.sample:
"title" : "Loopline Systems",
"version" : "x.x.x.x",
"icon" : "assets/win/icon.ico",
"nsiTemplate" : "path/to/custom/installer.nsi.tpl"
"nsiTemplate" : "path/to/custom/installer.nsi.tpl", // optional
"fileAssociation": { // optional
"extension": ".loop",
"fileType": "Loopline Systems File"
}
}
}
```
Expand Down Expand Up @@ -139,6 +143,11 @@ Icon to be shown in installation process.
### `win.nsiTemplate` *( optional )*
Option to define a custom NSI installation file.

### `win.fileAssociation` *( optional )*
Option to define a custom file association on Windows.
Caution: when you use `win.nsiTemplate` option, `win.fileAssociation` option should only work
if the custom nsi template is based on the original one.

**Note:** You need to add something that might have value for others? Please consider a PR. ;)


Expand Down
190 changes: 190 additions & 0 deletions assets/win/FileAssociation.nsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
/*
_____________________________________________________________________________
File Association
_____________________________________________________________________________
Based on code taken from http://nsis.sourceforge.net/File_Association
Usage in script:
1. !include "FileAssociation.nsh"
2. [Section|Function]
${FileAssociationFunction} "Param1" "Param2" "..." $var
[SectionEnd|FunctionEnd]
FileAssociationFunction=[RegisterExtension|UnRegisterExtension]
_____________________________________________________________________________
${RegisterExtension} "[executable]" "[extension]" "[description]"
"[executable]" ; executable which opens the file format
;
"[extension]" ; extension, which represents the file format to open
;
"[description]" ; description for the extension. This will be display in Windows Explorer.
;
${UnRegisterExtension} "[extension]" "[description]"
"[extension]" ; extension, which represents the file format to open
;
"[description]" ; description for the extension. This will be display in Windows Explorer.
;
_____________________________________________________________________________
Macros
_____________________________________________________________________________
Change log window verbosity (default: 3=no script)
Example:
!include "FileAssociation.nsh"
!insertmacro RegisterExtension
${FileAssociation_VERBOSE} 4 # all verbosity
!insertmacro UnRegisterExtension
${FileAssociation_VERBOSE} 3 # no script
*/


!ifndef FileAssociation_INCLUDED
!define FileAssociation_INCLUDED

!include Util.nsh

!verbose push
!verbose 3
!ifndef _FileAssociation_VERBOSE
!define _FileAssociation_VERBOSE 3
!endif
!verbose ${_FileAssociation_VERBOSE}
!define FileAssociation_VERBOSE `!insertmacro FileAssociation_VERBOSE`
!verbose pop

!macro FileAssociation_VERBOSE _VERBOSE
!verbose push
!verbose 3
!undef _FileAssociation_VERBOSE
!define _FileAssociation_VERBOSE ${_VERBOSE}
!verbose pop
!macroend



!macro RegisterExtensionCall _EXECUTABLE _EXTENSION _DESCRIPTION
!verbose push
!verbose ${_FileAssociation_VERBOSE}
Push `${_DESCRIPTION}`
Push `${_EXTENSION}`
Push `${_EXECUTABLE}`
${CallArtificialFunction} RegisterExtension_
!verbose pop
!macroend

!macro UnRegisterExtensionCall _EXTENSION _DESCRIPTION
!verbose push
!verbose ${_FileAssociation_VERBOSE}
Push `${_EXTENSION}`
Push `${_DESCRIPTION}`
${CallArtificialFunction} UnRegisterExtension_
!verbose pop
!macroend



!define RegisterExtension `!insertmacro RegisterExtensionCall`
!define un.RegisterExtension `!insertmacro RegisterExtensionCall`

!macro RegisterExtension
!macroend

!macro un.RegisterExtension
!macroend

!macro RegisterExtension_
!verbose push
!verbose ${_FileAssociation_VERBOSE}

Exch $R2 ;exe
Exch
Exch $R1 ;ext
Exch
Exch 2
Exch $R0 ;desc
Exch 2
Push $0
Push $1

ReadRegStr $1 HKCR $R1 "" ; read current file association
StrCmp "$1" "" NoBackup ; is it empty
StrCmp "$1" "$R0" NoBackup ; is it our own
WriteRegStr HKCR $R1 "backup_val" "$1" ; backup current value
NoBackup:
WriteRegStr HKCR $R1 "" "$R0" ; set our file association

ReadRegStr $0 HKCR $R0 ""
StrCmp $0 "" 0 Skip
WriteRegStr HKCR "$R0" "" "$R0"
WriteRegStr HKCR "$R0\shell" "" "open"
WriteRegStr HKCR "$R0\DefaultIcon" "" "$R2,0"
Skip:
WriteRegStr HKCR "$R0\shell\open\command" "" '"$R2" "%1"'
WriteRegStr HKCR "$R0\shell\edit" "" "Edit $R0"
WriteRegStr HKCR "$R0\shell\edit\command" "" '"$R2" "%1"'

Pop $1
Pop $0
Pop $R2
Pop $R1
Pop $R0

!verbose pop
!macroend



!define UnRegisterExtension `!insertmacro UnRegisterExtensionCall`
!define un.UnRegisterExtension `!insertmacro UnRegisterExtensionCall`

!macro UnRegisterExtension
!macroend

!macro un.UnRegisterExtension
!macroend

!macro UnRegisterExtension_
!verbose push
!verbose ${_FileAssociation_VERBOSE}

Exch $R1 ;desc
Exch
Exch $R0 ;ext
Exch
Push $0
Push $1

ReadRegStr $1 HKCR $R0 ""
StrCmp $1 $R1 0 NoOwn ; only do this if we own it
ReadRegStr $1 HKCR $R0 "backup_val"
StrCmp $1 "" 0 Restore ; if backup="" then delete the whole key
DeleteRegKey HKCR $R0
Goto NoOwn

Restore:
WriteRegStr HKCR $R0 "" $1
DeleteRegValue HKCR $R0 "backup_val"
DeleteRegKey HKCR $R1 ;Delete key with association name settings

NoOwn:

Pop $1
Pop $0
Pop $R1
Pop $R0

!verbose pop
!macroend

!endif # !FileAssociation_INCLUDED
14 changes: 10 additions & 4 deletions lib/win.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,11 @@ var WinBuilder = {
var nsiTemplate = options.config.win.nsiTemplate || path.join( __dirname, '..', 'templates/installer.nsi.tpl' );

var configFilePath = writeConfigFile( nsiTemplate, {
appPath : _windowsify( options.appPath ),
name : options.config.win.title,
version : options.config.win.version,
out : _windowsify( options.out )
appPath : _windowsify( options.appPath ),
name : options.config.win.title,
version : options.config.win.version,
fileAssociation : options.config.win.fileAssociation,
out : _windowsify( options.out )
} );

_copyAssetsToTmpFolder( options );
Expand Down Expand Up @@ -106,6 +107,11 @@ function _copyAssetsToTmpFolder( options ) {
path.join( tmpDir, 'nsProcess.nsh' )
);

fs.copySync(
path.join( __dirname, '..', 'assets', 'win', 'FileAssociation.nsh' ),
path.join( tmpDir, 'FileAssociation.nsh' )
);

fs.copySync(
path.join( __dirname, '..', 'assets', 'win', 'nsProcess.dll' ),
path.join( tmpDir, 'nsProcess.dll' )
Expand Down
10 changes: 10 additions & 0 deletions templates/installer.nsi.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ Name "${APP_NAME}"
!addplugindir .
!include "nsProcess.nsh"

<% if(fileAssociation){ %>
# include file association script
!include "FileAssociation.nsh"
<% } %>

BrandingText "${APP_NAME} ${APP_VERSION}"

# define the resulting installer's name
Expand Down Expand Up @@ -61,6 +66,11 @@ Section
# specify icon to go in the output path
File "icon.ico"

<% if(fileAssociation){ %>
# specify file association
${registerExtension} "$INSTDIR\${APP_NAME}.exe" "<%= fileAssociation.extension %>" "<%= fileAssociation.fileType %>"
<% } %>

# create the uninstaller
WriteUninstaller "$INSTDIR\Uninstall ${APP_NAME}.exe"

Expand Down

0 comments on commit 0e8e88f

Please sign in to comment.