Overview
An Overview of the Custom.nsh File
In this section I'll be talking about the custom.nsh
file and it's many implimentations. The custom.nsh
file is used by PAL for anything that the launcher cannot handle itself. It allows the developer the ability to incorporate NSIS code into the launcher while maintaining the PAL framework and it's structure. While it is not required for use with the original builds?The idea behind PAL in the beginning was to make it much easier for the end-user to make PAF compliant portable applications with knowing little about NSIS or knowing nothing at all. of PAL, it is however an essential part of FukenGruven's build of the launcher. This file, for the most part, should be your main focus if you're building with FukenGruven's PAL for it's where the real magic happens.
Below is the custom.nsh
file I wrote to be used with my Process Hacker Portable. For the purpose of this section I'll go ahead and explain in detail everything that I wrote, used, and why in the making of this portable application..
Note
I'll be explaining thecustom.nsh
as it pertains to how I use PAL. All the portable applications that I make are made using my own edit of FukenGruven's PAL?I use his version released on March 15th, 2017 which may be found here.. The explainations or written below the following code block.
;= LAUNCHER
;= ################
; !define UAC true
; !define REPLACE true
; !define REGISTRY true
; !define SERVICES true
; !define DIRECTORIES_MOVE true
; !define FILES_MOVE true
; !define TrimString true
;= VARIABLES
;= ################
;= DEFINES
;= ################
!define APP ProcessHacker
!define FULLNAME `Process Hacker`
!define APPDIR `$EXEDIR\App\${APP}\x86`
!define APPDIR64 `$EXEDIR\App\${APP}\x64`
!define XML `${SET}\ProcessHacker.exe.settings.xml`
!define DEFXML `${DEFSET}\ProcessHacker.exe.settings.xml`
!define SVC `KProcessHacker3`
!define KPH `${APPDIR}\kprocesshacker.sys`
!define KPH64 `${APPDIR64}\kprocesshacker.sys`
!define SVCKEY SYSTEM\CurrentControlSet\services\${SVC}
!define HKLM HKLM\${SCKEY}
!define TASK `SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\taskmgr.exe`
!define GETV `Kernel32::GetVolumeInformation(t,t,i,*i,*i,*i,t,i) i`
!define GET `${GETV}("$0",,${NSIS_MAX_STRLEN},.r0,,,,${NSIS_MAX_STRLEN})`
!define ID `Kernel32::SetEnvironmentVariable(t "LastUniqueID", t "$0")`
!define IMPORT `"$SYSDIR\certutil.exe" -importpfx -p "" "$PLUGINSDIR\PortableAppz.p12"`
!define SET32 `Kernel32::SetEnvironmentVariable(t "PROHACK", t "x86")`
!define SET64 `Kernel32::SetEnvironmentVariable(t "PROHACK", t "x64")`
;= FUNCTIONS
;= ################
Function ReadS
!macro _ReadS _FILE _ENTRY _RESULT
Push `${_FILE}`
Push `${_ENTRY}`
Call ReadS
Pop ${_RESULT}
!macroend
!define ReadS `!insertmacro _ReadS`
!insertmacro TextFunc_BOM
Exch $1
Exch
Exch $0
Exch
Push $2
Push $3
Push $4
Push $5
ClearErrors
FileOpen $2 $0 r
IfErrors +22
FileReadWord $2 $5
IntCmp $5 0xFEFF +4
FileSeek $2 0 SET
StrCpy $TextFunc_BOM 0
Goto +2
StrCpy $TextFunc_BOM FFFE
StrLen $0 $1
StrCmpS $0 0 +14
IntCmp $5 0xFEFF +3
FileRead $2 $3
Goto +2
FileReadUTF16LE $2 $3
IfErrors +9
StrCpy $4 $3 $0
StrCmpS $4 $1 0 -6
StrCpy $0 $3 '' $0
StrCpy $4 $0 1 -1
StrCmpS $4 '$\r' +2
StrCmpS $4 '$\n' 0 +5
StrCpy $0 $0 -1
Goto -4
SetErrors
StrCpy $0 ''
FileClose $2
Pop $5
Pop $4
Pop $3
Pop $2
Pop $1
Exch $0
FunctionEnd
;= MACROS
;= ################
!define ImportDigitalSignature "!insertmacro _ImportDigitalSignature"
!macro _ImportDigitalSignature
SetOutPath `$PLUGINSDIR`
File PortableAppz.p12
ExecDos::Exec /TOSTACK `${IMPORT}`
!macroend
!define MsgBox "!insertmacro MsgBox"
!macro MsgBox
StrCpy $0 `Windows XP +`
MessageBox MB_ICONSTOP|MB_TOPMOST `$(MINREQ)`
Call Unload
Quit
!macroend
;= CUSTOM
;= ################
${SegmentFile}
${Segment.OnInit}
StrCmp $Bit 64 +3
System::Call `${SET32}`
Goto +2
System::Call `${SET64}`
!macroend
!macro RunAsAdmin
${If} ${ProcessExists} ${APP}.exe
Return
${Else}
Elevate:
!insertmacro UAC_RunElevated
${Switch} $0
${Case} 0
${IfThen} $1 = 1 ${|} Quit ${|}
${If} $3 <> 0
${Break}
${EndIf}
${If} $1 = 3
MessageBox MB_RETRYCANCEL|MB_ICONINFORMATION|MB_TOPMOST|MB_SETFOREGROUND "$(LauncherRequiresAdmin)$\r$\n$\r$\n$(LauncherNotAdminTryAgain)" IDRETRY Elevate
Quit
${EndIf}
${CaseUACCodeAlert} 1223 \
"$(LauncherRequiresAdmin)" \
"$(LauncherNotAdminLimitedFunctionality)"
${CaseUACCodeAlert} 1062 \
"$(LauncherAdminLogonServiceNotRunning)" \
"$(LauncherNotAdminLimitedFunctionality)"
${CaseUACCodeAlert} "" \
"$(LauncherAdminError)$\r$\n$(LauncherRequiresAdmin)" \
"$(LauncherAdminError)$\r$\n$(LauncherNotAdminLimitedFunctionality)"
${EndSwitch}
${EndIf}
!macroend
!macro RunAsAdminOverride
${If} $SecondaryLaunch != true
${AndIf} ${ProcessExists} ProcessHacker.exe
Quit
${EndIf}
!macroend
!macro OS
Push $0
${If} ${IsNT}
${If} ${IsWinXP}
${IfNot} ${AtLeastServicePack} 2
MessageBox MB_ICONSTOP|MB_TOPMOST `${PORTABLEAPPNAME} requires Service Pack 2 or newer`
Call Unload
Quit
${EndIf}
${ElseIfNot} ${AtLeastWinXP}
${MsgBox}
${EndIf}
${Else}
${MsgBox}
${EndIf}
Pop $0
!macroend
!macro Init
IfFileExists `${XML}` +2
CopyFiles /SILENT `${DEFXML}` `${XML}`
!macroend
${SegmentInit}
${If} ${IsAdmin}
ClearErrors
Push `${SETINI}`
Push LastUniqueID=
Call ReadS
Pop $0
IfErrors +6
StrCmpS $0 "" 0 +4
StrCpy $0 $WINDIR 3
System::Call `${GET}`
IntFmt $0 "%08X" $0
System::Call `${ID}`
${EndIf}
!macroend
${SegmentPreExec}
${If} ${IsAdmin}
StrCpy $0 $WINDIR 3
System::Call `${GET}`
IntFmt $0 "%08X" $0
WriteINIStr `${SETINI}` ${APPNAME}Settings LastUniqueID $0
ReadEnvStr $1 LastUniqueID
StrCmpS $0 $1 +2
${ImportDigitalSignature}
${EndIf}
!macroend
!macro PreServices
${If} ${AtLeastWin7}
ClearErrors
EnumRegKey $0 HKLM `${SVCKEY}` 0
IfErrors +4
${WriteRuntimeData} ${PAL} ${SVC} 1
${Registry::BackupKey} `${HKLM}` $0
${EndIf}
!macroend
!macro PrePrimaryServices
${If} ${AtLeastWin7}
${If} $Bit == 64
${SC::Create} ${SVC} `${KPH64}` kernel driver "" /DISABLEFSR $1 $2
${SC::Start} ${SVC} /DISABLEFSR $1 $2
${Else}
${SC::Create} ${SVC} `${KPH}` kernel driver "" /DISABLEFSR $1 $2
${SC::Start} ${SVC} /DISABLEFSR $1 $2
${EndIf}
${EndIf}
!macroend
!macro PostPrimaryServices
${If} ${AtLeastWin7}
${SC::Stop} ${SVC} /DISABLEFSR $1 $2
ClearErrors
${ReadRuntimeData} $0 ${PAL} ${SVC}
${If} ${Errors}
${SC::Delete} ${SVC} /DISABLEFSR $1 $2
${EndIf}
${Registry::RestoreBackupKey} `${HKLM}` $0
${EndIf}
!macroend
!macro PreReg
Push $0
ClearErrors
ReadRegStr $0 HKLM `${TASK}` Debugger
IfErrors +4
${WriteRuntimeData} ${PAL} Debugger `$0`
Pop $0
!macroend
!macro PostReg
Push $0
Push $1
ReadRegStr $0 HKLM `${TASK}` Debugger
ReadEnvStr $1 ${APP}
${If} $0 == `"${EXE}"`
DeleteRegKey HKLM `${TASK}`
ClearErrors
${ReadRuntimeData} $0 ${PAL} Debugger
IfErrors +2
WriteRegStr HKLM `${TASK}` Debugger `$0`
${EndIf}
Pop $1
Pop $0
!macroend
Launcher
This section has two purposes. The first purpose is for anyone who wants to recompile one of my PAFs. It let's them know that I've used a build by FukenGruven and what I have uncommented in the Custom Defines section of the PortableApps.comLauncher.nsi
file. If you do not see this section in one of my PAFs it means I used an original release of PAL provided by PortableApps.com to compile it.
Up until recently this section only had one purpose which was explained in the paragraph above but now it has another purpose which is to tell the PortableApps.comLauncher.nsi
file which defines to use. You had to manually edit the PortableApps.comLauncher.nsi
file which is a hassle. It's why you would see an extra folder inside the ..\App\AppInfo\Launcher
directory called Source if you've ever used a PAF made by FukenGruven. For more on how to use this within your own builds read here.