move all nsis files from the main repository

This commit is contained in:
dkanada 2020-03-22 17:25:24 +09:00
parent eee93a3ffc
commit a0d24f537d
13 changed files with 1501 additions and 0 deletions

190
nsis/build-jellyfin.ps1 Normal file
View File

@ -0,0 +1,190 @@
[CmdletBinding()]
param(
[switch]$MakeNSIS,
[switch]$InstallNSIS,
[switch]$InstallFFMPEG,
[switch]$InstallNSSM,
[switch]$SkipJellyfinBuild,
[switch]$GenerateZip,
[string]$InstallLocation = "./dist/jellyfin-win-nsis",
[string]$UXLocation = "../jellyfin-ux",
[switch]$InstallTrayApp,
[ValidateSet('Debug','Release')][string]$BuildType = 'Release',
[ValidateSet('Quiet','Minimal', 'Normal')][string]$DotNetVerbosity = 'Minimal',
[ValidateSet('win','win7', 'win8','win81','win10')][string]$WindowsVersion = 'win',
[ValidateSet('x64','x86', 'arm', 'arm64')][string]$Architecture = 'x64'
)
$ProgressPreference = 'SilentlyContinue' # Speedup all downloads by hiding progress bars.
#PowershellCore and *nix check to make determine which temp dir to use.
if(($PSVersionTable.PSEdition -eq 'Core') -and (-not $IsWindows)){
$TempDir = mktemp -d
}else{
$TempDir = $env:Temp
}
#Create staging dir
New-Item -ItemType Directory -Force -Path $InstallLocation
$ResolvedInstallLocation = Resolve-Path $InstallLocation
$ResolvedUXLocation = Resolve-Path $UXLocation
function Build-JellyFin {
if(($Architecture -eq 'arm64') -and ($WindowsVersion -ne 'win10')){
Write-Error "arm64 only supported with Windows10 Version"
exit
}
if(($Architecture -eq 'arm') -and ($WindowsVersion -notin @('win10','win81','win8'))){
Write-Error "arm only supported with Windows 8 or higher"
exit
}
Write-Verbose "windowsversion-Architecture: $windowsversion-$Architecture"
Write-Verbose "InstallLocation: $ResolvedInstallLocation"
Write-Verbose "DotNetVerbosity: $DotNetVerbosity"
dotnet publish --self-contained -c $BuildType --output $ResolvedInstallLocation -v $DotNetVerbosity -p:GenerateDocumentationFile=false -p:DebugSymbols=false -p:DebugType=none --runtime `"$windowsversion-$Architecture`" Jellyfin.Server
}
function Install-FFMPEG {
param(
[string]$ResolvedInstallLocation,
[string]$Architecture,
[string]$FFMPEGVersionX86 = "ffmpeg-4.2.1-win32-shared"
)
Write-Verbose "Checking Architecture"
if($Architecture -notin @('x86','x64')){
Write-Warning "No builds available for your selected architecture of $Architecture"
Write-Warning "FFMPEG will not be installed"
}elseif($Architecture -eq 'x64'){
Write-Verbose "Downloading 64 bit FFMPEG"
Invoke-WebRequest -Uri https://repo.jellyfin.org/releases/server/windows/ffmpeg/jellyfin-ffmpeg.zip -UseBasicParsing -OutFile "$tempdir/ffmpeg.zip" | Write-Verbose
}else{
Write-Verbose "Downloading 32 bit FFMPEG"
Invoke-WebRequest -Uri https://ffmpeg.zeranoe.com/builds/win32/shared/$FFMPEGVersionX86.zip -UseBasicParsing -OutFile "$tempdir/ffmpeg.zip" | Write-Verbose
}
Expand-Archive "$tempdir/ffmpeg.zip" -DestinationPath "$tempdir/ffmpeg/" -Force | Write-Verbose
if($Architecture -eq 'x64'){
Write-Verbose "Copying Binaries to Jellyfin location"
Get-ChildItem "$tempdir/ffmpeg" | ForEach-Object {
Copy-Item $_.FullName -Destination $installLocation | Write-Verbose
}
}else{
Write-Verbose "Copying Binaries to Jellyfin location"
Get-ChildItem "$tempdir/ffmpeg/$FFMPEGVersionX86/bin" | ForEach-Object {
Copy-Item $_.FullName -Destination $installLocation | Write-Verbose
}
}
Remove-Item "$tempdir/ffmpeg/" -Recurse -Force -ErrorAction Continue | Write-Verbose
Remove-Item "$tempdir/ffmpeg.zip" -Force -ErrorAction Continue | Write-Verbose
}
function Install-NSSM {
param(
[string]$ResolvedInstallLocation,
[string]$Architecture
)
Write-Verbose "Checking Architecture"
if($Architecture -notin @('x86','x64')){
Write-Warning "No builds available for your selected architecture of $Architecture"
Write-Warning "NSSM will not be installed"
}else{
Write-Verbose "Downloading NSSM"
# [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
# Temporary workaround, file is hosted in an azure blob with a custom domain in front for brevity
Invoke-WebRequest -Uri http://files.evilt.win/nssm/nssm-2.24-101-g897c7ad.zip -UseBasicParsing -OutFile "$tempdir/nssm.zip" | Write-Verbose
}
Expand-Archive "$tempdir/nssm.zip" -DestinationPath "$tempdir/nssm/" -Force | Write-Verbose
if($Architecture -eq 'x64'){
Write-Verbose "Copying Binaries to Jellyfin location"
Get-ChildItem "$tempdir/nssm/nssm-2.24-101-g897c7ad/win64" | ForEach-Object {
Copy-Item $_.FullName -Destination $installLocation | Write-Verbose
}
}else{
Write-Verbose "Copying Binaries to Jellyfin location"
Get-ChildItem "$tempdir/nssm/nssm-2.24-101-g897c7ad/win32" | ForEach-Object {
Copy-Item $_.FullName -Destination $installLocation | Write-Verbose
}
}
Remove-Item "$tempdir/nssm/" -Recurse -Force -ErrorAction Continue | Write-Verbose
Remove-Item "$tempdir/nssm.zip" -Force -ErrorAction Continue | Write-Verbose
}
function Make-NSIS {
param(
[string]$ResolvedInstallLocation
)
$env:InstallLocation = $ResolvedInstallLocation
if($InstallNSIS.IsPresent -or ($InstallNSIS -eq $true)){
& "$tempdir/nsis/nsis-3.04/makensis.exe" /D$Architecture /DUXPATH=$ResolvedUXLocation ".\deployment\windows\jellyfin.nsi"
} else {
& "makensis" /D$Architecture /DUXPATH=$ResolvedUXLocation ".\deployment\windows\jellyfin.nsi"
}
Copy-Item .\deployment\windows\jellyfin_*.exe $ResolvedInstallLocation\..\
}
function Install-NSIS {
Write-Verbose "Downloading NSIS"
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Invoke-WebRequest -Uri https://nchc.dl.sourceforge.net/project/nsis/NSIS%203/3.04/nsis-3.04.zip -UseBasicParsing -OutFile "$tempdir/nsis.zip" | Write-Verbose
Expand-Archive "$tempdir/nsis.zip" -DestinationPath "$tempdir/nsis/" -Force | Write-Verbose
}
function Cleanup-NSIS {
Remove-Item "$tempdir/nsis/" -Recurse -Force -ErrorAction Continue | Write-Verbose
Remove-Item "$tempdir/nsis.zip" -Force -ErrorAction Continue | Write-Verbose
}
function Install-TrayApp {
param(
[string]$ResolvedInstallLocation,
[string]$Architecture
)
Write-Verbose "Checking Architecture"
if($Architecture -ne 'x64'){
Write-Warning "No builds available for your selected architecture of $Architecture"
Write-Warning "The tray app will not be available."
}else{
Write-Verbose "Downloading Tray App and copying to Jellyfin location"
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Invoke-WebRequest -Uri https://github.com/jellyfin/jellyfin-windows-tray/releases/latest/download/JellyfinTray.exe -UseBasicParsing -OutFile "$installLocation/JellyfinTray.exe" | Write-Verbose
}
}
if(-not $SkipJellyfinBuild.IsPresent -and -not ($InstallNSIS -eq $true)){
Write-Verbose "Starting Build Process: Selected Environment is $WindowsVersion-$Architecture"
Build-JellyFin
}
if($InstallFFMPEG.IsPresent -or ($InstallFFMPEG -eq $true)){
Write-Verbose "Starting FFMPEG Install"
Install-FFMPEG $ResolvedInstallLocation $Architecture
}
if($InstallNSSM.IsPresent -or ($InstallNSSM -eq $true)){
Write-Verbose "Starting NSSM Install"
Install-NSSM $ResolvedInstallLocation $Architecture
}
if($InstallTrayApp.IsPresent -or ($InstallTrayApp -eq $true)){
Write-Verbose "Downloading Windows Tray App"
Install-TrayApp $ResolvedInstallLocation $Architecture
}
#Copy-Item .\deployment\windows\install-jellyfin.ps1 $ResolvedInstallLocation\install-jellyfin.ps1
#Copy-Item .\deployment\windows\install.bat $ResolvedInstallLocation\install.bat
Copy-Item .\LICENSE $ResolvedInstallLocation\LICENSE
if($InstallNSIS.IsPresent -or ($InstallNSIS -eq $true)){
Write-Verbose "Installing NSIS"
Install-NSIS
}
if($MakeNSIS.IsPresent -or ($MakeNSIS -eq $true)){
Write-Verbose "Starting NSIS Package creation"
Make-NSIS $ResolvedInstallLocation
}
if($InstallNSIS.IsPresent -or ($InstallNSIS -eq $true)){
Write-Verbose "Cleanup NSIS"
Cleanup-NSIS
}
if($GenerateZip.IsPresent -or ($GenerateZip -eq $true)){
Compress-Archive -Path $ResolvedInstallLocation -DestinationPath "$ResolvedInstallLocation/jellyfin.zip" -Force
}
Write-Verbose "Finished"

2
nsis/dependencies.txt Normal file
View File

@ -0,0 +1,2 @@
dotnet
nsis

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This file was created by NSISDialogDesigner 1.4.4.0
http://coolsoft.altervista.org/nsisdialogdesigner
Do not edit manually!
-->
<Dialog Name="confirmation" Title="Confirmation Page" Subtitle="Please confirm your choices for Jellyfin Server installation" GenerateShowFunction="False">
<HeaderCustomScript>!include "helpers\StrSlash.nsh"</HeaderCustomScript>
<CreateFunctionCustomScript>${StrSlash} '$0' $INSTDIR
${StrSlash} '$1' $_JELLYFINDATADIR_
${NSD_SetText} $hCtl_confirmation_ConfirmRichText "{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1043\viewkind4\uc1 \
\pard\widctlpar\sa160\sl252\slmult1\b The installer will proceed based on the following inputs gathered on earlier screens.\par \
Installation Folder:\b0 $0\line\b \
Service install:\b0 $_INSTALLSERVICE_\line\b \
Service start:\b0 $_SERVICESTART_\line\b \
Service account:\b0 $_SERVICEACCOUNTTYPE_\line\b \
Jellyfin Data Folder:\b0 $1\par \
\
\pard\sa200\sl276\slmult1\f1\lang1043\par \
}"</CreateFunctionCustomScript>
<RichText Name="ConfirmRichText" Location="12, 12" Size="426, 204" TabIndex="0" ExStyle="WS_EX_STATICEDGE" />
</Dialog>

View File

@ -0,0 +1,61 @@
; =========================================================
; This file was generated by NSISDialogDesigner 1.4.4.0
; http://coolsoft.altervista.org/nsisdialogdesigner
;
; Do not edit it manually, use NSISDialogDesigner instead!
; Modified by EraYaN (2019-09-01)
; =========================================================
; handle variables
Var hCtl_confirmation
Var hCtl_confirmation_ConfirmRichText
; HeaderCustomScript
!include "helpers\StrSlash.nsh"
; dialog create function
Function fnc_confirmation_Create
; === confirmation (type: Dialog) ===
nsDialogs::Create 1018
Pop $hCtl_confirmation
${If} $hCtl_confirmation == error
Abort
${EndIf}
!insertmacro MUI_HEADER_TEXT "Confirmation Page" "Please confirm your choices for Jellyfin Server installation"
; === ConfirmRichText (type: RichText) ===
nsDialogs::CreateControl /NOUNLOAD "RichEdit20A" ${ES_READONLY}|${WS_VISIBLE}|${WS_CHILD}|${WS_TABSTOP}|${WS_VSCROLL}|${ES_MULTILINE}|${ES_WANTRETURN} ${WS_EX_STATICEDGE} 8u 7u 280u 126u ""
Pop $hCtl_confirmation_ConfirmRichText
${NSD_AddExStyle} $hCtl_confirmation_ConfirmRichText ${WS_EX_STATICEDGE}
; CreateFunctionCustomScript
${StrSlash} '$0' $INSTDIR
${StrSlash} '$1' $_JELLYFINDATADIR_
${If} $_INSTALLSERVICE_ == "Yes"
${NSD_SetText} $hCtl_confirmation_ConfirmRichText "{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1043\viewkind4\uc1 \
\pard\widctlpar\sa160\sl252\slmult1\b The installer will proceed based on the following inputs gathered on earlier screens.\par \
Installation Folder:\b0 $0\line\b \
Service install:\b0 $_INSTALLSERVICE_\line\b \
Service start:\b0 $_SERVICESTART_\line\b \
Service account:\b0 $_SERVICEACCOUNTTYPE_\line\b \
Jellyfin Data Folder:\b0 $1\par \
\
\pard\sa200\sl276\slmult1\f1\lang1043\par \
}"
${Else}
${NSD_SetText} $hCtl_confirmation_ConfirmRichText "{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1043\viewkind4\uc1 \
\pard\widctlpar\sa160\sl252\slmult1\b The installer will proceed based on the following inputs gathered on earlier screens.\par \
Installation Folder:\b0 $0\line\b \
Service install:\b0 $_INSTALLSERVICE_\line\b \
Jellyfin Data Folder:\b0 $1\par \
\
\pard\sa200\sl276\slmult1\f1\lang1043\par \
}"
${EndIf}
FunctionEnd

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This file was created by NSISDialogDesigner 1.4.4.0
http://coolsoft.altervista.org/nsisdialogdesigner
Do not edit manually!
-->
<Dialog Name="service_config" Title="CoOnfigure the service" Subtitle="This controls what type of access the server gets to this system." GenerateShowFunction="False">
<CheckBox Name="StartServiceAfterInstall" Location="12, 192" Size="426, 24" Text="Start Service after Install" Checked="True" TabIndex="0" />
<Label Name="LocalSystemAccountLabel" Location="12, 115" Size="426, 46" Text="The Local System account has full access to every resource and file on the system. This can have very real security implications, do not use unless absolutely neseccary." TabIndex="1" />
<Label Name="NetworkServiceAccountLabel" Location="12, 39" Size="426, 46" Text="The NetworkService account is a predefined local account used by the service control manager. It is the recommended way to install the Jellyfin Server service." TabIndex="2" />
<RadioButton Name="UseLocalSystemAccount" Location="12, 88" Size="426, 24" Text="Use Local System account" TabIndex="3" />
<RadioButton Name="UseNetworkServiceAccount" Location="12, 12" Size="426, 24" Text="Use Network Service account (Recommended)" Font="Microsoft Sans Serif, 8.25pt, style=Bold" Checked="True" TabIndex="4" />
</Dialog>

View File

@ -0,0 +1,56 @@
; =========================================================
; This file was generated by NSISDialogDesigner 1.4.4.0
; http://coolsoft.altervista.org/nsisdialogdesigner
;
; Do not edit it manually, use NSISDialogDesigner instead!
; =========================================================
; handle variables
Var hCtl_service_config
Var hCtl_service_config_StartServiceAfterInstall
Var hCtl_service_config_LocalSystemAccountLabel
Var hCtl_service_config_NetworkServiceAccountLabel
Var hCtl_service_config_UseLocalSystemAccount
Var hCtl_service_config_UseNetworkServiceAccount
Var hCtl_service_config_Font1
; dialog create function
Function fnc_service_config_Create
; custom font definitions
CreateFont $hCtl_service_config_Font1 "Microsoft Sans Serif" "8.25" "700"
; === service_config (type: Dialog) ===
nsDialogs::Create 1018
Pop $hCtl_service_config
${If} $hCtl_service_config == error
Abort
${EndIf}
!insertmacro MUI_HEADER_TEXT "Configure the service" "This controls what type of access the server gets to this system."
; === StartServiceAfterInstall (type: Checkbox) ===
${NSD_CreateCheckbox} 8u 118u 280u 15u "Start Service after Install"
Pop $hCtl_service_config_StartServiceAfterInstall
${NSD_Check} $hCtl_service_config_StartServiceAfterInstall
; === LocalSystemAccountLabel (type: Label) ===
${NSD_CreateLabel} 8u 71u 280u 28u "The Local System account has full access to every resource and file on the system. This can have very real security implications, do not use unless absolutely neseccary."
Pop $hCtl_service_config_LocalSystemAccountLabel
; === NetworkServiceAccountLabel (type: Label) ===
${NSD_CreateLabel} 8u 24u 280u 28u "The NetworkService account is a predefined local account used by the service control manager. It is the recommended way to install the Jellyfin Server service."
Pop $hCtl_service_config_NetworkServiceAccountLabel
; === UseLocalSystemAccount (type: RadioButton) ===
${NSD_CreateRadioButton} 8u 54u 280u 15u "Use Local System account"
Pop $hCtl_service_config_UseLocalSystemAccount
${NSD_AddStyle} $hCtl_service_config_UseLocalSystemAccount ${WS_GROUP}
; === UseNetworkServiceAccount (type: RadioButton) ===
${NSD_CreateRadioButton} 8u 7u 280u 15u "Use Network Service account (Recommended)"
Pop $hCtl_service_config_UseNetworkServiceAccount
SendMessage $hCtl_service_config_UseNetworkServiceAccount ${WM_SETFONT} $hCtl_service_config_Font1 0
${NSD_Check} $hCtl_service_config_UseNetworkServiceAccount
FunctionEnd

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This file was created by NSISDialogDesigner 1.4.4.0
http://coolsoft.altervista.org/nsisdialogdesigner
Do not edit manually!
-->
<Dialog Name="setuptype" Title="Setup Type" Subtitle="Control how Jellyfin is installed.">
<Label Name="InstallasaServiceLabel" Location="12, 115" Size="426, 46" Text="Install Jellyfin as a service. This method is recommended for Advanced Users. Additional setup is required to access network shares." TabIndex="0" />
<RadioButton Name="InstallasaService" Location="12, 88" Size="426, 24" Text="Install as a Service (Advanced Users)" TabIndex="1" />
<Label Name="BasicInstallLabel" Location="12, 39" Size="426, 46" Text="The basic install will run Jellyfin in your current user account.$\nThis is recommended for new users and those with existing Jellyfin installs older than 10.4." TabIndex="2" />
<RadioButton Name="BasicInstall" Location="12, 12" Size="426, 24" Text="Basic Install (Recommended)" Font="Microsoft Sans Serif, 8.25pt, style=Bold" Checked="True" TabIndex="3" />
</Dialog>

View File

@ -0,0 +1,50 @@
; =========================================================
; This file was generated by NSISDialogDesigner 1.4.4.0
; http://coolsoft.altervista.org/nsisdialogdesigner
;
; Do not edit it manually, use NSISDialogDesigner instead!
; =========================================================
; handle variables
Var hCtl_setuptype
Var hCtl_setuptype_InstallasaServiceLabel
Var hCtl_setuptype_InstallasaService
Var hCtl_setuptype_BasicInstallLabel
Var hCtl_setuptype_BasicInstall
Var hCtl_setuptype_Font1
; dialog create function
Function fnc_setuptype_Create
; custom font definitions
CreateFont $hCtl_setuptype_Font1 "Microsoft Sans Serif" "8.25" "700"
; === setuptype (type: Dialog) ===
nsDialogs::Create 1018
Pop $hCtl_setuptype
${If} $hCtl_setuptype == error
Abort
${EndIf}
!insertmacro MUI_HEADER_TEXT "Setup Type" "Control how Jellyfin is installed."
; === InstallasaServiceLabel (type: Label) ===
${NSD_CreateLabel} 8u 71u 280u 28u "Install Jellyfin as a service. This method is recommended for Advanced Users. Additional setup is required to access network shares."
Pop $hCtl_setuptype_InstallasaServiceLabel
; === InstallasaService (type: RadioButton) ===
${NSD_CreateRadioButton} 8u 54u 280u 15u "Install as a Service (Advanced Users)"
Pop $hCtl_setuptype_InstallasaService
${NSD_AddStyle} $hCtl_setuptype_InstallasaService ${WS_GROUP}
; === BasicInstallLabel (type: Label) ===
${NSD_CreateLabel} 8u 24u 280u 28u "The basic install will run Jellyfin in your current user account.$\nThis is recommended for new users and those with existing Jellyfin installs older than 10.4."
Pop $hCtl_setuptype_BasicInstallLabel
; === BasicInstall (type: RadioButton) ===
${NSD_CreateRadioButton} 8u 7u 280u 15u "Basic Install (Recommended)"
Pop $hCtl_setuptype_BasicInstall
SendMessage $hCtl_setuptype_BasicInstall ${WM_SETFONT} $hCtl_setuptype_Font1 0
${NSD_Check} $hCtl_setuptype_BasicInstall
FunctionEnd

View File

@ -0,0 +1,10 @@
; Show error
!macro ShowError TEXT RETRYLABEL
MessageBox MB_ABORTRETRYIGNORE|MB_ICONSTOP "${TEXT}" IDIGNORE +2 IDRETRY ${RETRYLABEL}
Abort
!macroend
!macro ShowErrorFinal TEXT
MessageBox MB_OK|MB_ICONSTOP "${TEXT}"
Abort
!macroend

47
nsis/helpers/StrSlash.nsh Normal file
View File

@ -0,0 +1,47 @@
; Adapted from: https://nsis.sourceforge.io/Another_String_Replace_(and_Slash/BackSlash_Converter) (2019-08-31)
!macro _StrSlashConstructor out in
Push "${in}"
Push "\"
Call StrSlash
Pop ${out}
!macroend
!define StrSlash '!insertmacro "_StrSlashConstructor"'
; Push $filenamestring (e.g. 'c:\this\and\that\filename.htm')
; Push "\"
; Call StrSlash
; Pop $R0
; ;Now $R0 contains 'c:/this/and/that/filename.htm'
Function StrSlash
Exch $R3 ; $R3 = needle ("\" or "/")
Exch
Exch $R1 ; $R1 = String to replacement in (haystack)
Push $R2 ; Replaced haystack
Push $R4 ; $R4 = not $R3 ("/" or "\")
Push $R6
Push $R7 ; Scratch reg
StrCpy $R2 ""
StrLen $R6 $R1
StrCpy $R4 "\"
StrCmp $R3 "/" loop
StrCpy $R4 "/"
loop:
StrCpy $R7 $R1 1
StrCpy $R1 $R1 $R6 1
StrCmp $R7 $R3 found
StrCpy $R2 "$R2$R7"
StrCmp $R1 "" done loop
found:
StrCpy $R2 "$R2$R4"
StrCmp $R1 "" done loop
done:
StrCpy $R3 $R2
Pop $R7
Pop $R6
Pop $R4
Pop $R2
Pop $R1
Exch $R3
FunctionEnd

575
nsis/jellyfin.nsi Normal file
View File

@ -0,0 +1,575 @@
!verbose 3
SetCompressor /SOLID bzip2
ShowInstDetails show
ShowUninstDetails show
Unicode True
;--------------------------------
!define SF_USELECTED 0 ; used to check selected options status, rest are inherited from Sections.nsh
!include "MUI2.nsh"
!include "Sections.nsh"
!include "LogicLib.nsh"
!include "helpers\ShowError.nsh"
; Global variables that we'll use
Var _JELLYFINVERSION_
Var _JELLYFINDATADIR_
Var _SETUPTYPE_
Var _INSTALLSERVICE_
Var _SERVICESTART_
Var _SERVICEACCOUNTTYPE_
Var _EXISTINGINSTALLATION_
Var _EXISTINGSERVICE_
Var _MAKESHORTCUTS_
Var _FOLDEREXISTS_
;
!ifdef x64
!define ARCH "x64"
!define NAMESUFFIX "(64 bit)"
!define INSTALL_DIRECTORY "$PROGRAMFILES64\Jellyfin\Server"
!endif
!ifdef x84
!define ARCH "x86"
!define NAMESUFFIX "(32 bit)"
!define INSTALL_DIRECTORY "$PROGRAMFILES32\Jellyfin\Server"
!endif
!ifndef ARCH
!error "Set the Arch with /Dx86 or /Dx64"
!endif
;--------------------------------
!define REG_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\JellyfinServer" ;Registry to show up in Add/Remove Programs
!define REG_CONFIG_KEY "Software\Jellyfin\Server" ;Registry to store all configuration
!getdllversion "$%InstallLocation%\jellyfin.dll" ver_ ;Align installer version with jellyfin.dll version
Name "Jellyfin Server ${ver_1}.${ver_2}.${ver_3} ${NAMESUFFIX}" ; This is referred in various header text labels
OutFile "jellyfin_${ver_1}.${ver_2}.${ver_3}_windows-${ARCH}.exe" ; Naming convention jellyfin_{version}_windows-{arch].exe
BrandingText "Jellyfin Server ${ver_1}.${ver_2}.${ver_3} Installer" ; This shows in just over the buttons
; installer attributes, these show up in details tab on installer properties
VIProductVersion "${ver_1}.${ver_2}.${ver_3}.0" ; VIProductVersion format, should be X.X.X.X
VIFileVersion "${ver_1}.${ver_2}.${ver_3}.0" ; VIFileVersion format, should be X.X.X.X
VIAddVersionKey "ProductName" "Jellyfin Server"
VIAddVersionKey "FileVersion" "${ver_1}.${ver_2}.${ver_3}.0"
VIAddVersionKey "LegalCopyright" "(c) 2019 Jellyfin Contributors. Code released under the GNU General Public License"
VIAddVersionKey "FileDescription" "Jellyfin Server: The Free Software Media System"
;TODO, check defaults
InstallDir ${INSTALL_DIRECTORY} ;Default installation folder
InstallDirRegKey HKLM "${REG_CONFIG_KEY}" "InstallFolder" ;Read the registry for install folder,
RequestExecutionLevel admin ; ask it upfront for service control, and installing in priv folders
CRCCheck on ; make sure the installer wasn't corrupted while downloading
!define MUI_ABORTWARNING ;Prompts user in case of aborting install
; TODO: Replace with nice Jellyfin Icons
!ifdef UXPATH
!define MUI_ICON "${UXPATH}\branding\NSIS\modern-install.ico" ; Installer Icon
!define MUI_UNICON "${UXPATH}\branding\NSIS\modern-install.ico" ; Uninstaller Icon
!define MUI_HEADERIMAGE
!define MUI_HEADERIMAGE_BITMAP "${UXPATH}\branding\NSIS\installer-header.bmp"
!define MUI_WELCOMEFINISHPAGE_BITMAP "${UXPATH}\branding\NSIS\installer-right.bmp"
!define MUI_UNWELCOMEFINISHPAGE_BITMAP "${UXPATH}\branding\NSIS\installer-right.bmp"
!endif
;--------------------------------
;Pages
; Welcome Page
!define MUI_WELCOMEPAGE_TEXT "The installer will ask for details to install Jellyfin Server."
!insertmacro MUI_PAGE_WELCOME
; License Page
!insertmacro MUI_PAGE_LICENSE "$%InstallLocation%\LICENSE" ; picking up generic GPL
; Setup Type Page
Page custom ShowSetupTypePage SetupTypePage_Config
; Components Page
!define MUI_PAGE_CUSTOMFUNCTION_PRE HideComponentsPage
!insertmacro MUI_PAGE_COMPONENTS
!define MUI_PAGE_CUSTOMFUNCTION_PRE HideInstallDirectoryPage ; Controls when to hide / show
!define MUI_DIRECTORYPAGE_TEXT_DESTINATION "Install folder" ; shows just above the folder selection dialog
!insertmacro MUI_PAGE_DIRECTORY
; Data folder Page
!define MUI_PAGE_CUSTOMFUNCTION_PRE HideDataDirectoryPage ; Controls when to hide / show
!define MUI_PAGE_HEADER_TEXT "Choose Data Location"
!define MUI_PAGE_HEADER_SUBTEXT "Choose the folder in which to install the Jellyfin Server data."
!define MUI_DIRECTORYPAGE_TEXT_TOP "The installer will set the following folder for Jellyfin Server data. To install in a different folder, click Browse and select another folder. Please make sure the folder exists and is accessible. Click Next to continue."
!define MUI_DIRECTORYPAGE_TEXT_DESTINATION "Data folder"
!define MUI_DIRECTORYPAGE_VARIABLE $_JELLYFINDATADIR_
!insertmacro MUI_PAGE_DIRECTORY
; Custom Dialogs
!include "dialogs\setuptype.nsdinc"
!include "dialogs\service-config.nsdinc"
!include "dialogs\confirmation.nsdinc"
; Select service account type
#!define MUI_PAGE_CUSTOMFUNCTION_PRE HideServiceConfigPage ; Controls when to hide / show (This does not work for Page, might need to go PageEx)
#!define MUI_PAGE_CUSTOMFUNCTION_SHOW fnc_service_config_Show
#!define MUI_PAGE_CUSTOMFUNCTION_LEAVE ServiceConfigPage_Config
#!insertmacro MUI_PAGE_CUSTOM ServiceAccountType
Page custom ShowServiceConfigPage ServiceConfigPage_Config
; Confirmation Page
Page custom ShowConfirmationPage ; just letting the user know what they chose to install
; Actual Installion Page
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
#!insertmacro MUI_UNPAGE_FINISH
;--------------------------------
;Languages; Add more languages later here if needed
!insertmacro MUI_LANGUAGE "English"
;--------------------------------
;Installer Sections
Section "!Jellyfin Server (required)" InstallJellyfinServer
SectionIn RO ; Mandatory section, isn't this the whole purpose to run the installer.
StrCmp "$_EXISTINGINSTALLATION_" "Yes" RunUninstaller CarryOn ; Silently uninstall in case of previous installation
RunUninstaller:
DetailPrint "Looking for uninstaller at $INSTDIR"
FindFirst $0 $1 "$INSTDIR\Uninstall.exe"
FindClose $0
StrCmp $1 "" CarryOn ; the registry key was there but uninstaller was not found
DetailPrint "Silently running the uninstaller at $INSTDIR"
ExecWait '"$INSTDIR\Uninstall.exe" /S _?=$INSTDIR' $0
DetailPrint "Uninstall finished, $0"
CarryOn:
${If} $_EXISTINGSERVICE_ == 'Yes'
ExecWait '"$INSTDIR\nssm.exe" stop JellyfinServer' $0
${If} $0 <> 0
MessageBox MB_OK|MB_ICONSTOP "Could not stop the Jellyfin Server service."
Abort
${EndIf}
DetailPrint "Stopped Jellyfin Server service, $0"
${EndIf}
SetOutPath "$INSTDIR"
File "/oname=icon.ico" "${UXPATH}\branding\NSIS\modern-install.ico"
File /r $%InstallLocation%\*
; Write the InstallFolder, DataFolder, Network Service info into the registry for later use
WriteRegExpandStr HKLM "${REG_CONFIG_KEY}" "InstallFolder" "$INSTDIR"
WriteRegExpandStr HKLM "${REG_CONFIG_KEY}" "DataFolder" "$_JELLYFINDATADIR_"
WriteRegStr HKLM "${REG_CONFIG_KEY}" "ServiceAccountType" "$_SERVICEACCOUNTTYPE_"
!getdllversion "$%InstallLocation%\jellyfin.dll" ver_
StrCpy $_JELLYFINVERSION_ "${ver_1}.${ver_2}.${ver_3}" ;
; Write the uninstall keys for Windows
WriteRegStr HKLM "${REG_UNINST_KEY}" "DisplayName" "Jellyfin Server $_JELLYFINVERSION_ ${NAMESUFFIX}"
WriteRegExpandStr HKLM "${REG_UNINST_KEY}" "UninstallString" '"$INSTDIR\Uninstall.exe"'
WriteRegStr HKLM "${REG_UNINST_KEY}" "DisplayIcon" '"$INSTDIR\Uninstall.exe",0'
WriteRegStr HKLM "${REG_UNINST_KEY}" "Publisher" "The Jellyfin Project"
WriteRegStr HKLM "${REG_UNINST_KEY}" "URLInfoAbout" "https://jellyfin.org/"
WriteRegStr HKLM "${REG_UNINST_KEY}" "DisplayVersion" "$_JELLYFINVERSION_"
WriteRegDWORD HKLM "${REG_UNINST_KEY}" "NoModify" 1
WriteRegDWORD HKLM "${REG_UNINST_KEY}" "NoRepair" 1
;Create uninstaller
WriteUninstaller "$INSTDIR\Uninstall.exe"
SectionEnd
Section "Jellyfin Server Service" InstallService
${If} $_INSTALLSERVICE_ == "Yes" ; Only run this if we're going to install the service!
ExecWait '"$INSTDIR\nssm.exe" statuscode JellyfinServer' $0
DetailPrint "Jellyfin Server service statuscode, $0"
${If} $0 == 0
InstallRetry:
ExecWait '"$INSTDIR\nssm.exe" install JellyfinServer "$INSTDIR\jellyfin.exe" --service --datadir \"$_JELLYFINDATADIR_\"' $0
${If} $0 <> 0
!insertmacro ShowError "Could not install the Jellyfin Server service." InstallRetry
${EndIf}
DetailPrint "Jellyfin Server Service install, $0"
${Else}
DetailPrint "Jellyfin Server Service exists, updating..."
ConfigureApplicationRetry:
ExecWait '"$INSTDIR\nssm.exe" set JellyfinServer Application "$INSTDIR\jellyfin.exe"' $0
${If} $0 <> 0
!insertmacro ShowError "Could not configure the Jellyfin Server service." ConfigureApplicationRetry
${EndIf}
DetailPrint "Jellyfin Server Service setting (Application), $0"
ConfigureAppParametersRetry:
ExecWait '"$INSTDIR\nssm.exe" set JellyfinServer AppParameters --service --datadir \"$_JELLYFINDATADIR_\"' $0
${If} $0 <> 0
!insertmacro ShowError "Could not configure the Jellyfin Server service." ConfigureAppParametersRetry
${EndIf}
DetailPrint "Jellyfin Server Service setting (AppParameters), $0"
${EndIf}
Sleep 3000 ; Give time for Windows to catchup
ConfigureStartRetry:
ExecWait '"$INSTDIR\nssm.exe" set JellyfinServer Start SERVICE_DELAYED_AUTO_START' $0
${If} $0 <> 0
!insertmacro ShowError "Could not configure the Jellyfin Server service." ConfigureStartRetry
${EndIf}
DetailPrint "Jellyfin Server Service setting (Start), $0"
ConfigureDescriptionRetry:
ExecWait '"$INSTDIR\nssm.exe" set JellyfinServer Description "Jellyfin Server: The Free Software Media System"' $0
${If} $0 <> 0
!insertmacro ShowError "Could not configure the Jellyfin Server service." ConfigureDescriptionRetry
${EndIf}
DetailPrint "Jellyfin Server Service setting (Description), $0"
ConfigureDisplayNameRetry:
ExecWait '"$INSTDIR\nssm.exe" set JellyfinServer DisplayName "Jellyfin Server"' $0
${If} $0 <> 0
!insertmacro ShowError "Could not configure the Jellyfin Server service." ConfigureDisplayNameRetry
${EndIf}
DetailPrint "Jellyfin Server Service setting (DisplayName), $0"
Sleep 3000
${If} $_SERVICEACCOUNTTYPE_ == "NetworkService" ; the default install using NSSM is Local System
ConfigureNetworkServiceRetry:
ExecWait '"$INSTDIR\nssm.exe" set JellyfinServer Objectname "Network Service"' $0
${If} $0 <> 0
!insertmacro ShowError "Could not configure the Jellyfin Server service account." ConfigureNetworkServiceRetry
${EndIf}
DetailPrint "Jellyfin Server service account change, $0"
${EndIf}
Sleep 3000
ConfigureDefaultAppExit:
ExecWait '"$INSTDIR\nssm.exe" set JellyfinServer AppExit Default Exit' $0
${If} $0 <> 0
!insertmacro ShowError "Could not configure the Jellyfin Server service app exit action." ConfigureDefaultAppExit
${EndIf}
DetailPrint "Jellyfin Server service exit action set, $0"
${EndIf}
SectionEnd
Section "-start service" StartService
${If} $_SERVICESTART_ == "Yes"
${AndIf} $_INSTALLSERVICE_ == "Yes"
StartRetry:
ExecWait '"$INSTDIR\nssm.exe" start JellyfinServer' $0
${If} $0 <> 0
!insertmacro ShowError "Could not start the Jellyfin Server service." StartRetry
${EndIf}
DetailPrint "Jellyfin Server service start, $0"
${EndIf}
SectionEnd
Section "Create Shortcuts" CreateWinShortcuts
${If} $_MAKESHORTCUTS_ == "Yes"
CreateDirectory "$SMPROGRAMS\Jellyfin Server"
CreateShortCut "$SMPROGRAMS\Jellyfin Server\Jellyfin (View Console).lnk" "$INSTDIR\jellyfin.exe" "--datadir $\"$_JELLYFINDATADIR_$\"" "$INSTDIR\icon.ico" 0 SW_SHOWMAXIMIZED
CreateShortCut "$SMPROGRAMS\Jellyfin Server\Jellyfin Tray App.lnk" "$INSTDIR\jellyfintray.exe" "" "$INSTDIR\icon.ico" 0
;CreateShortCut "$DESKTOP\Jellyfin Server.lnk" "$INSTDIR\jellyfin.exe" "--datadir $\"$_JELLYFINDATADIR_$\"" "$INSTDIR\icon.ico" 0 SW_SHOWMINIMIZED
CreateShortCut "$DESKTOP\Jellyfin Server\Jellyfin Server.lnk" "$INSTDIR\jellyfintray.exe" "" "$INSTDIR\icon.ico" 0
${EndIf}
SectionEnd
;--------------------------------
;Descriptions
;Language strings
LangString DESC_InstallJellyfinServer ${LANG_ENGLISH} "Install Jellyfin Server"
LangString DESC_InstallService ${LANG_ENGLISH} "Install As a Service"
;Assign language strings to sections
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
!insertmacro MUI_DESCRIPTION_TEXT ${InstallJellyfinServer} $(DESC_InstallJellyfinServer)
!insertmacro MUI_DESCRIPTION_TEXT ${InstallService} $(DESC_InstallService)
!insertmacro MUI_FUNCTION_DESCRIPTION_END
;--------------------------------
;Uninstaller Section
Section "Uninstall"
ReadRegStr $INSTDIR HKLM "${REG_CONFIG_KEY}" "InstallFolder" ; read the installation folder
ReadRegStr $_JELLYFINDATADIR_ HKLM "${REG_CONFIG_KEY}" "DataFolder" ; read the data folder
ReadRegStr $_SERVICEACCOUNTTYPE_ HKLM "${REG_CONFIG_KEY}" "ServiceAccountType" ; read the account name
DetailPrint "Jellyfin Install location: $INSTDIR"
DetailPrint "Jellyfin Data folder: $_JELLYFINDATADIR_"
MessageBox MB_YESNO|MB_ICONINFORMATION "Do you want to retain the Jellyfin Server data folder? The media will not be touched. $\r$\nIf unsure choose YES." /SD IDYES IDYES PreserveData
RMDir /r /REBOOTOK "$_JELLYFINDATADIR_"
PreserveData:
ExecWait '"$INSTDIR\nssm.exe" statuscode JellyfinServer' $0
DetailPrint "Jellyfin Server service statuscode, $0"
IntCmp $0 0 NoServiceUninstall ; service doesn't exist, may be run from desktop shortcut
Sleep 3000 ; Give time for Windows to catchup
UninstallStopRetry:
ExecWait '"$INSTDIR\nssm.exe" stop JellyfinServer' $0
${If} $0 <> 0
!insertmacro ShowError "Could not stop the Jellyfin Server service." UninstallStopRetry
${EndIf}
DetailPrint "Stopped Jellyfin Server service, $0"
UninstallRemoveRetry:
ExecWait '"$INSTDIR\nssm.exe" remove JellyfinServer confirm' $0
${If} $0 <> 0
!insertmacro ShowError "Could not remove the Jellyfin Server service." UninstallRemoveRetry
${EndIf}
DetailPrint "Removed Jellyfin Server service, $0"
Sleep 3000 ; Give time for Windows to catchup
NoServiceUninstall: ; existing install was present but no service was detected. Remove shortcuts if account is set to none
${If} $_SERVICEACCOUNTTYPE_ == "None"
RMDir /r "$SMPROGRAMS\Jellyfin Server"
Delete "$DESKTOP\Jellyfin Server.lnk"
DetailPrint "Removed old shortcuts..."
${EndIf}
Delete "$INSTDIR\*.*"
RMDir /r /REBOOTOK "$INSTDIR\jellyfin-web"
Delete "$INSTDIR\Uninstall.exe"
RMDir /r /REBOOTOK "$INSTDIR"
DeleteRegKey HKLM "Software\Jellyfin"
DeleteRegKey HKLM "${REG_UNINST_KEY}"
SectionEnd
Function .onInit
; Setting up defaults
StrCpy $_INSTALLSERVICE_ "Yes"
StrCpy $_SERVICESTART_ "Yes"
StrCpy $_SERVICEACCOUNTTYPE_ "NetworkService"
StrCpy $_EXISTINGINSTALLATION_ "No"
StrCpy $_EXISTINGSERVICE_ "No"
StrCpy $_MAKESHORTCUTS_ "No"
SetShellVarContext current
StrCpy $_JELLYFINDATADIR_ "$%ProgramData%\Jellyfin\Server"
System::Call 'kernel32::CreateMutex(p 0, i 0, t "JellyfinServerMutex") p .r1 ?e'
Pop $R0
StrCmp $R0 0 +3
!insertmacro ShowErrorFinal "The installer is already running."
;Detect if Jellyfin is already installed.
; In case it is installed, let the user choose either
; 1. Exit installer
; 2. Upgrade without messing with data
; 2a. Don't ask for any details, uninstall and install afresh with old settings
; Read Registry for previous installation
ClearErrors
ReadRegStr "$0" HKLM "${REG_CONFIG_KEY}" "InstallFolder"
IfErrors NoExisitingInstall
DetailPrint "Existing Jellyfin Server detected at: $0"
StrCpy "$INSTDIR" "$0" ; set the location fro registry as new default
StrCpy $_EXISTINGINSTALLATION_ "Yes" ; Set our flag to be used later
SectionSetText ${InstallJellyfinServer} "Upgrade Jellyfin Server (required)" ; Change install text to "Upgrade"
; check if service was run using Network Service account
ClearErrors
ReadRegStr $_SERVICEACCOUNTTYPE_ HKLM "${REG_CONFIG_KEY}" "ServiceAccountType" ; in case of error _SERVICEACCOUNTTYPE_ will be NetworkService as default
ClearErrors
ReadRegStr $_JELLYFINDATADIR_ HKLM "${REG_CONFIG_KEY}" "DataFolder" ; in case of error, the default holds
; Hide sections which will not be needed in case of previous install
; SectionSetText ${InstallService} ""
; check if there is a service called Jellyfin, there should be
; hack : nssm statuscode Jellyfin will return non zero return code in case it exists
ExecWait '"$INSTDIR\nssm.exe" statuscode JellyfinServer' $0
DetailPrint "Jellyfin Server service statuscode, $0"
IntCmp $0 0 NoService ; service doesn't exist, may be run from desktop shortcut
; if service was detected, set defaults going forward.
StrCpy $_EXISTINGSERVICE_ "Yes"
StrCpy $_INSTALLSERVICE_ "Yes"
StrCpy $_SERVICESTART_ "Yes"
StrCpy $_MAKESHORTCUTS_ "No"
SectionSetText ${CreateWinShortcuts} ""
NoService: ; existing install was present but no service was detected
${If} $_SERVICEACCOUNTTYPE_ == "None"
StrCpy $_SETUPTYPE_ "Basic"
StrCpy $_INSTALLSERVICE_ "No"
StrCpy $_SERVICESTART_ "No"
StrCpy $_MAKESHORTCUTS_ "Yes"
${EndIf}
; Let the user know that we'll upgrade and provide an option to quit.
MessageBox MB_OKCANCEL|MB_ICONINFORMATION "Existing installation of Jellyfin Server was detected, it'll be upgraded, settings will be retained. \
$\r$\nClick OK to proceed, Cancel to exit installer." /SD IDOK IDOK ProceedWithUpgrade
Quit ; Quit if the user is not sure about upgrade
ProceedWithUpgrade:
NoExisitingInstall: ; by this time, the variables have been correctly set to reflect previous install details
FunctionEnd
Function HideInstallDirectoryPage
${If} $_EXISTINGINSTALLATION_ == "Yes" ; Existing installation detected, so don't ask for InstallFolder
Abort
${EndIf}
FunctionEnd
Function HideDataDirectoryPage
${If} $_EXISTINGINSTALLATION_ == "Yes" ; Existing installation detected, so don't ask for InstallFolder
Abort
${EndIf}
FunctionEnd
Function HideServiceConfigPage
${If} $_INSTALLSERVICE_ == "No" ; Not running as a service, don't ask for service type
${OrIf} $_EXISTINGINSTALLATION_ == "Yes" ; Existing installation detected, so don't ask for InstallFolder
Abort
${EndIf}
FunctionEnd
Function HideConfirmationPage
${If} $_EXISTINGINSTALLATION_ == "Yes" ; Existing installation detected, so don't ask for InstallFolder
Abort
${EndIf}
FunctionEnd
Function HideSetupTypePage
${If} $_EXISTINGINSTALLATION_ == "Yes" ; Existing installation detected, so don't ask for SetupType
Abort
${EndIf}
FunctionEnd
Function HideComponentsPage
${If} $_SETUPTYPE_ == "Basic" ; Basic installation chosen, don't show components choice
Abort
${EndIf}
FunctionEnd
; Setup Type dialog show function
Function ShowSetupTypePage
Call HideSetupTypePage
Call fnc_setuptype_Create
nsDialogs::Show
FunctionEnd
; Service Config dialog show function
Function ShowServiceConfigPage
Call HideServiceConfigPage
Call fnc_service_config_Create
nsDialogs::Show
FunctionEnd
; Confirmation dialog show function
Function ShowConfirmationPage
Call HideConfirmationPage
Call fnc_confirmation_Create
nsDialogs::Show
FunctionEnd
; Declare temp variables to read the options from the custom page.
Var StartServiceAfterInstall
Var UseNetworkServiceAccount
Var UseLocalSystemAccount
Var BasicInstall
Function SetupTypePage_Config
${NSD_GetState} $hCtl_setuptype_BasicInstall $BasicInstall
IfFileExists "$LOCALAPPDATA\Jellyfin" folderfound foldernotfound ; if the folder exists, use this, otherwise, go with new default
folderfound:
StrCpy $_FOLDEREXISTS_ "Yes"
Goto InstallCheck
foldernotfound:
StrCpy $_FOLDEREXISTS_ "No"
Goto InstallCheck
InstallCheck:
${If} $BasicInstall == 1
StrCpy $_SETUPTYPE_ "Basic"
StrCpy $_INSTALLSERVICE_ "No"
StrCpy $_SERVICESTART_ "No"
StrCpy $_SERVICEACCOUNTTYPE_ "None"
StrCpy $_MAKESHORTCUTS_ "Yes"
${If} $_FOLDEREXISTS_ == "Yes"
StrCpy $_JELLYFINDATADIR_ "$LOCALAPPDATA\Jellyfin\"
${EndIf}
${Else}
StrCpy $_SETUPTYPE_ "Advanced"
StrCpy $_INSTALLSERVICE_ "Yes"
StrCpy $_MAKESHORTCUTS_ "No"
${If} $_FOLDEREXISTS_ == "Yes"
MessageBox MB_OKCANCEL|MB_ICONINFORMATION "An existing data folder was detected.\
$\r$\nBasic Setup is highly recommended.\
$\r$\nIf you proceed, you will need to set up Jellyfin again." IDOK GoAhead IDCANCEL GoBack
GoBack:
Abort
${EndIf}
GoAhead:
StrCpy $_JELLYFINDATADIR_ "$%ProgramData%\Jellyfin\Server"
SectionSetText ${CreateWinShortcuts} ""
${EndIf}
FunctionEnd
Function ServiceConfigPage_Config
${NSD_GetState} $hCtl_service_config_StartServiceAfterInstall $StartServiceAfterInstall
${If} $StartServiceAfterInstall == 1
StrCpy $_SERVICESTART_ "Yes"
${Else}
StrCpy $_SERVICESTART_ "No"
${EndIf}
${NSD_GetState} $hCtl_service_config_UseNetworkServiceAccount $UseNetworkServiceAccount
${NSD_GetState} $hCtl_service_config_UseLocalSystemAccount $UseLocalSystemAccount
${If} $UseNetworkServiceAccount == 1
StrCpy $_SERVICEACCOUNTTYPE_ "NetworkService"
${ElseIf} $UseLocalSystemAccount == 1
StrCpy $_SERVICEACCOUNTTYPE_ "LocalSystem"
${Else}
!insertmacro ShowErrorFinal "Service account type not properly configured."
${EndIf}
FunctionEnd
; This function handles the choices during component selection
Function .onSelChange
; If we are not installing service, we don't need to set the NetworkService account or StartService
SectionGetFlags ${InstallService} $0
${If} $0 = ${SF_SELECTED}
StrCpy $_INSTALLSERVICE_ "Yes"
${Else}
StrCpy $_INSTALLSERVICE_ "No"
StrCpy $_SERVICESTART_ "No"
StrCpy $_SERVICEACCOUNTTYPE_ "None"
${EndIf}
FunctionEnd
Function .onInstSuccess
#ExecShell "open" "http://localhost:8096"
FunctionEnd

View File

@ -0,0 +1,460 @@
[CmdletBinding()]
param(
[Switch]$Quiet,
[Switch]$InstallAsService,
[System.Management.Automation.pscredential]$ServiceUser,
[switch]$CreateDesktopShorcut,
[switch]$LaunchJellyfin,
[switch]$MigrateEmbyLibrary,
[string]$InstallLocation,
[string]$EmbyLibraryLocation,
[string]$JellyfinLibraryLocation
)
<# This form was created using POSHGUI.com a free online gui designer for PowerShell
.NAME
Install-Jellyfin
#>
#This doesn't need to be used by default anymore, but I am keeping it in as a function for future use.
function Elevate-Window {
# Get the ID and security principal of the current user account
$myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()
$myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID)
# Get the security principal for the Administrator role
$adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator
# Check to see if we are currently running "as Administrator"
if ($myWindowsPrincipal.IsInRole($adminRole))
{
# We are running "as Administrator" - so change the title and background color to indicate this
$Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Elevated)"
$Host.UI.RawUI.BackgroundColor = "DarkBlue"
clear-host
}
else
{
# We are not running "as Administrator" - so relaunch as administrator
# Create a new process object that starts PowerShell
$newProcess = new-object System.Diagnostics.ProcessStartInfo "PowerShell";
# Specify the current script path and name as a parameter
$newProcess.Arguments = $myInvocation.MyCommand.Definition;
# Indicate that the process should be elevated
$newProcess.Verb = "runas";
# Start the new process
[System.Diagnostics.Process]::Start($newProcess);
# Exit from the current, unelevated, process
exit
}
}
#FIXME The install methods should be a function that takes all the params, the quiet flag should be a paramset
if($Quiet.IsPresent -or $Quiet -eq $true){
if([string]::IsNullOrEmpty($JellyfinLibraryLocation)){
$Script:JellyfinDataDir = "$env:LOCALAPPDATA\jellyfin\"
}else{
$Script:JellyfinDataDir = $JellyfinLibraryLocation
}
if([string]::IsNullOrEmpty($InstallLocation)){
$Script:DefaultJellyfinInstallDirectory = "$env:Appdata\jellyfin\"
}else{
$Script:DefaultJellyfinInstallDirectory = $InstallLocation
}
if([string]::IsNullOrEmpty($EmbyLibraryLocation)){
$Script:defaultEmbyDataDir = "$env:Appdata\Emby-Server\data\"
}else{
$Script:defaultEmbyDataDir = $EmbyLibraryLocation
}
if($InstallAsService.IsPresent -or $InstallAsService -eq $true){
$Script:InstallAsService = $true
}else{$Script:InstallAsService = $false}
if($null -eq $ServiceUser){
$Script:InstallServiceAsUser = $false
}else{
$Script:InstallServiceAsUser = $true
$Script:UserCredentials = $ServiceUser
$Script:JellyfinDataDir = "$env:HOMEDRIVE\Users\$($Script:UserCredentials.UserName)\Appdata\Local\jellyfin\"}
if($CreateDesktopShorcut.IsPresent -or $CreateDesktopShorcut -eq $true) {$Script:CreateShortcut = $true}else{$Script:CreateShortcut = $false}
if($MigrateEmbyLibrary.IsPresent -or $MigrateEmbyLibrary -eq $true){$Script:MigrateLibrary = $true}else{$Script:MigrateLibrary = $false}
if($LaunchJellyfin.IsPresent -or $LaunchJellyfin -eq $true){$Script:StartJellyfin = $true}else{$Script:StartJellyfin = $false}
if(-not (Test-Path $Script:DefaultJellyfinInstallDirectory)){
mkdir $Script:DefaultJellyfinInstallDirectory
}
Copy-Item -Path $PSScriptRoot/* -DestinationPath "$Script:DefaultJellyfinInstallDirectory/" -Force -Recurse
if($Script:InstallAsService){
if($Script:InstallServiceAsUser){
&"$Script:DefaultJellyfinInstallDirectory\nssm.exe" install Jellyfin `"$Script:DefaultJellyfinInstallDirectory\jellyfin.exe`" --datadir `"$Script:JellyfinDataDir`"
Start-Sleep -Milliseconds 500
&sc.exe config Jellyfin obj=".\$($Script:UserCredentials.UserName)" password="$($Script:UserCredentials.GetNetworkCredential().Password)"
&"$Script:DefaultJellyfinInstallDirectory\nssm.exe" set Jellyfin Start SERVICE_DELAYED_AUTO_START
}else{
&"$Script:DefaultJellyfinInstallDirectory\nssm.exe" install Jellyfin `"$Script:DefaultJellyfinInstallDirectory\jellyfin.exe`" --datadir `"$Script:JellyfinDataDir`"
Start-Sleep -Milliseconds 500
#&"$Script:DefaultJellyfinInstallDirectory\nssm.exe" set Jellyfin ObjectName $Script:UserCredentials.UserName $Script:UserCredentials.GetNetworkCredential().Password
#Set-Service -Name Jellyfin -Credential $Script:UserCredentials
&"$Script:DefaultJellyfinInstallDirectory\nssm.exe" set Jellyfin Start SERVICE_DELAYED_AUTO_START
}
}
if($Script:MigrateLibrary){
Copy-Item -Path $Script:defaultEmbyDataDir/config -Destination $Script:JellyfinDataDir -force -Recurse
Copy-Item -Path $Script:defaultEmbyDataDir/cache -Destination $Script:JellyfinDataDir -force -Recurse
Copy-Item -Path $Script:defaultEmbyDataDir/data -Destination $Script:JellyfinDataDir -force -Recurse
Copy-Item -Path $Script:defaultEmbyDataDir/metadata -Destination $Script:JellyfinDataDir -force -Recurse
Copy-Item -Path $Script:defaultEmbyDataDir/root -Destination $Script:JellyfinDataDir -force -Recurse
}
if($Script:CreateShortcut){
$WshShell = New-Object -comObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut("$Home\Desktop\Jellyfin.lnk")
$Shortcut.TargetPath = "$Script:DefaultJellyfinInstallDirectory\jellyfin.exe"
$Shortcut.Save()
}
if($Script:StartJellyfin){
if($Script:InstallAsService){
Get-Service Jellyfin | Start-Service
}else{
Start-Process -FilePath $Script:DefaultJellyfinInstallDirectory\jellyfin.exe -PassThru
}
}
}else{
}
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()
$Script:JellyFinDataDir = "$env:LOCALAPPDATA\jellyfin\"
$Script:DefaultJellyfinInstallDirectory = "$env:Appdata\jellyfin\"
$Script:defaultEmbyDataDir = "$env:Appdata\Emby-Server\"
$Script:InstallAsService = $False
$Script:InstallServiceAsUser = $false
$Script:CreateShortcut = $false
$Script:MigrateLibrary = $false
$Script:StartJellyfin = $false
function InstallJellyfin {
Write-Host "Install as service: $Script:InstallAsService"
Write-Host "Install as serviceuser: $Script:InstallServiceAsUser"
Write-Host "Create Shortcut: $Script:CreateShortcut"
Write-Host "MigrateLibrary: $Script:MigrateLibrary"
$GUIElementsCollection | ForEach-Object {
$_.Enabled = $false
}
Write-Host "Making Jellyfin directory"
$ProgressBar.Minimum = 1
$ProgressBar.Maximum = 100
$ProgressBar.Value = 1
if($Script:DefaultJellyfinInstallDirectory -ne $InstallLocationBox.Text){
Write-Host "Custom Install Location Chosen: $($InstallLocationBox.Text)"
$Script:DefaultJellyfinInstallDirectory = $InstallLocationBox.Text
}
if($Script:JellyfinDataDir -ne $CustomLibraryBox.Text){
Write-Host "Custom Library Location Chosen: $($CustomLibraryBox.Text)"
$Script:JellyfinDataDir = $CustomLibraryBox.Text
}
if(-not (Test-Path $Script:DefaultJellyfinInstallDirectory)){
mkdir $Script:DefaultJellyfinInstallDirectory
}
Write-Host "Copying Jellyfin Data"
$progressbar.Value = 10
Copy-Item -Path $PSScriptRoot/* -Destination $Script:DefaultJellyfinInstallDirectory/ -Force -Recurse
Write-Host "Finished Copying"
$ProgressBar.Value = 50
if($Script:InstallAsService){
if($Script:InstallServiceAsUser){
Write-Host "Installing Service as user $($Script:UserCredentials.UserName)"
&"$Script:DefaultJellyfinInstallDirectory\nssm.exe" install Jellyfin `"$Script:DefaultJellyfinInstallDirectory\jellyfin.exe`" --datadir `"$Script:JellyfinDataDir`"
Start-Sleep -Milliseconds 2000
&sc.exe config Jellyfin obj=".\$($Script:UserCredentials.UserName)" password="$($Script:UserCredentials.GetNetworkCredential().Password)"
&"$Script:DefaultJellyfinInstallDirectory\nssm.exe" set Jellyfin Start SERVICE_DELAYED_AUTO_START
}else{
Write-Host "Installing Service as LocalSystem"
&"$Script:DefaultJellyfinInstallDirectory\nssm.exe" install Jellyfin `"$Script:DefaultJellyfinInstallDirectory\jellyfin.exe`" --datadir `"$Script:JellyfinDataDir`"
Start-Sleep -Milliseconds 2000
&"$Script:DefaultJellyfinInstallDirectory\nssm.exe" set Jellyfin Start SERVICE_DELAYED_AUTO_START
}
}
$progressbar.Value = 60
if($Script:MigrateLibrary){
if($Script:defaultEmbyDataDir -ne $LibraryLocationBox.Text){
Write-Host "Custom location defined for emby library: $($LibraryLocationBox.Text)"
$Script:defaultEmbyDataDir = $LibraryLocationBox.Text
}
Write-Host "Copying emby library from $Script:defaultEmbyDataDir to $Script:JellyFinDataDir"
Write-Host "This could take a while depending on the size of your library. Please be patient"
Write-Host "Copying config"
Copy-Item -Path $Script:defaultEmbyDataDir/config -Destination $Script:JellyfinDataDir -force -Recurse
Write-Host "Copying cache"
Copy-Item -Path $Script:defaultEmbyDataDir/cache -Destination $Script:JellyfinDataDir -force -Recurse
Write-Host "Copying data"
Copy-Item -Path $Script:defaultEmbyDataDir/data -Destination $Script:JellyfinDataDir -force -Recurse
Write-Host "Copying metadata"
Copy-Item -Path $Script:defaultEmbyDataDir/metadata -Destination $Script:JellyfinDataDir -force -Recurse
Write-Host "Copying root dir"
Copy-Item -Path $Script:defaultEmbyDataDir/root -Destination $Script:JellyfinDataDir -force -Recurse
}
$progressbar.Value = 80
if($Script:CreateShortcut){
Write-Host "Creating Shortcut"
$WshShell = New-Object -comObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut("$Home\Desktop\Jellyfin.lnk")
$Shortcut.TargetPath = "$Script:DefaultJellyfinInstallDirectory\jellyfin.exe"
$Shortcut.Save()
}
$ProgressBar.Value = 90
if($Script:StartJellyfin){
if($Script:InstallAsService){
Write-Host "Starting Jellyfin Service"
Get-Service Jellyfin | Start-Service
}else{
Write-Host "Starting Jellyfin"
Start-Process -FilePath $Script:DefaultJellyfinInstallDirectory\jellyfin.exe -PassThru
}
}
$progressbar.Value = 100
Write-Host Finished
$wshell = New-Object -ComObject Wscript.Shell
$wshell.Popup("Operation Completed",0,"Done",0x1)
$InstallForm.Close()
}
function ServiceBoxCheckChanged {
if($InstallAsServiceCheck.Checked){
$Script:InstallAsService = $true
$ServiceUserLabel.Visible = $true
$ServiceUserLabel.Enabled = $true
$ServiceUserBox.Visible = $true
$ServiceUserBox.Enabled = $true
}else{
$Script:InstallAsService = $false
$ServiceUserLabel.Visible = $false
$ServiceUserLabel.Enabled = $false
$ServiceUserBox.Visible = $false
$ServiceUserBox.Enabled = $false
}
}
function UserSelect {
if($ServiceUserBox.Text -eq 'Local System')
{
$Script:InstallServiceAsUser = $false
$Script:UserCredentials = $null
$ServiceUserBox.Items.RemoveAt(1)
$ServiceUserBox.Items.Add("Custom User")
}elseif($ServiceUserBox.Text -eq 'Custom User'){
$Script:InstallServiceAsUser = $true
$Script:UserCredentials = Get-Credential -Message "Please enter the credentials of the user you with to run Jellyfin Service as" -UserName $env:USERNAME
$ServiceUserBox.Items[1] = "$($Script:UserCredentials.UserName)"
}
}
function CreateShortcutBoxCheckChanged {
if($CreateShortcutCheck.Checked){
$Script:CreateShortcut = $true
}else{
$Script:CreateShortcut = $False
}
}
function StartJellyFinBoxCheckChanged {
if($StartProgramCheck.Checked){
$Script:StartJellyfin = $true
}else{
$Script:StartJellyfin = $false
}
}
function CustomLibraryCheckChanged {
if($CustomLibraryCheck.Checked){
$Script:UseCustomLibrary = $true
$CustomLibraryBox.Enabled = $true
}else{
$Script:UseCustomLibrary = $false
$CustomLibraryBox.Enabled = $false
}
}
function MigrateLibraryCheckboxChanged {
if($MigrateLibraryCheck.Checked){
$Script:MigrateLibrary = $true
$LibraryMigrationLabel.Visible = $true
$LibraryMigrationLabel.Enabled = $true
$LibraryLocationBox.Visible = $true
$LibraryLocationBox.Enabled = $true
}else{
$Script:MigrateLibrary = $false
$LibraryMigrationLabel.Visible = $false
$LibraryMigrationLabel.Enabled = $false
$LibraryLocationBox.Visible = $false
$LibraryLocationBox.Enabled = $false
}
}
#region begin GUI{
$InstallForm = New-Object system.Windows.Forms.Form
$InstallForm.ClientSize = '320,240'
$InstallForm.text = "Terrible Jellyfin Installer"
$InstallForm.TopMost = $false
$GUIElementsCollection = @()
$InstallButton = New-Object system.Windows.Forms.Button
$InstallButton.text = "Install"
$InstallButton.width = 60
$InstallButton.height = 30
$InstallButton.location = New-Object System.Drawing.Point(5,5)
$InstallButton.Font = 'Microsoft Sans Serif,10'
$GUIElementsCollection += $InstallButton
$ProgressBar = New-Object system.Windows.Forms.ProgressBar
$ProgressBar.width = 245
$ProgressBar.height = 30
$ProgressBar.location = New-Object System.Drawing.Point(70,5)
$InstallLocationLabel = New-Object system.Windows.Forms.Label
$InstallLocationLabel.text = "Install Location"
$InstallLocationLabel.TextAlign = [System.Drawing.ContentAlignment]::MiddleLeft
$InstallLocationLabel.AutoSize = $true
$InstallLocationLabel.width = 100
$InstallLocationLabel.height = 20
$InstallLocationLabel.location = New-Object System.Drawing.Point(5,50)
$InstallLocationLabel.Font = 'Microsoft Sans Serif,10'
$GUIElementsCollection += $InstallLocationLabel
$InstallLocationBox = New-Object system.Windows.Forms.TextBox
$InstallLocationBox.multiline = $false
$InstallLocationBox.width = 205
$InstallLocationBox.height = 20
$InstallLocationBox.location = New-Object System.Drawing.Point(110,50)
$InstallLocationBox.Text = $Script:DefaultJellyfinInstallDirectory
$InstallLocationBox.Font = 'Microsoft Sans Serif,10'
$GUIElementsCollection += $InstallLocationBox
$CustomLibraryCheck = New-Object system.Windows.Forms.CheckBox
$CustomLibraryCheck.text = "Custom Library Location:"
$CustomLibraryCheck.TextAlign = [System.Drawing.ContentAlignment]::MiddleLeft
$CustomLibraryCheck.AutoSize = $false
$CustomLibraryCheck.width = 180
$CustomLibraryCheck.height = 20
$CustomLibraryCheck.location = New-Object System.Drawing.Point(5,75)
$CustomLibraryCheck.Font = 'Microsoft Sans Serif,10'
$GUIElementsCollection += $CustomLibraryCheck
$CustomLibraryBox = New-Object system.Windows.Forms.TextBox
$CustomLibraryBox.multiline = $false
$CustomLibraryBox.width = 130
$CustomLibraryBox.height = 20
$CustomLibraryBox.location = New-Object System.Drawing.Point(185,75)
$CustomLibraryBox.Text = $Script:JellyFinDataDir
$CustomLibraryBox.Font = 'Microsoft Sans Serif,10'
$CustomLibraryBox.Enabled = $false
$GUIElementsCollection += $CustomLibraryBox
$InstallAsServiceCheck = New-Object system.Windows.Forms.CheckBox
$InstallAsServiceCheck.text = "Install as Service"
$InstallAsServiceCheck.AutoSize = $false
$InstallAsServiceCheck.width = 140
$InstallAsServiceCheck.height = 20
$InstallAsServiceCheck.location = New-Object System.Drawing.Point(5,125)
$InstallAsServiceCheck.Font = 'Microsoft Sans Serif,10'
$GUIElementsCollection += $InstallAsServiceCheck
$ServiceUserLabel = New-Object system.Windows.Forms.Label
$ServiceUserLabel.text = "Run Service As:"
$ServiceUserLabel.AutoSize = $true
$ServiceUserLabel.TextAlign = [System.Drawing.ContentAlignment]::MiddleLeft
$ServiceUserLabel.width = 100
$ServiceUserLabel.height = 20
$ServiceUserLabel.location = New-Object System.Drawing.Point(15,145)
$ServiceUserLabel.Font = 'Microsoft Sans Serif,10'
$ServiceUserLabel.Visible = $false
$ServiceUserLabel.Enabled = $false
$GUIElementsCollection += $ServiceUserLabel
$ServiceUserBox = New-Object system.Windows.Forms.ComboBox
$ServiceUserBox.text = "Run Service As"
$ServiceUserBox.width = 195
$ServiceUserBox.height = 20
@('Local System','Custom User') | ForEach-Object {[void] $ServiceUserBox.Items.Add($_)}
$ServiceUserBox.location = New-Object System.Drawing.Point(120,145)
$ServiceUserBox.Font = 'Microsoft Sans Serif,10'
$ServiceUserBox.Visible = $false
$ServiceUserBox.Enabled = $false
$ServiceUserBox.DropDownStyle = [System.Windows.Forms.ComboBoxStyle]::DropDownList
$GUIElementsCollection += $ServiceUserBox
$MigrateLibraryCheck = New-Object system.Windows.Forms.CheckBox
$MigrateLibraryCheck.text = "Import Emby/Old JF Library"
$MigrateLibraryCheck.AutoSize = $false
$MigrateLibraryCheck.width = 160
$MigrateLibraryCheck.height = 20
$MigrateLibraryCheck.location = New-Object System.Drawing.Point(5,170)
$MigrateLibraryCheck.Font = 'Microsoft Sans Serif,10'
$GUIElementsCollection += $MigrateLibraryCheck
$LibraryMigrationLabel = New-Object system.Windows.Forms.Label
$LibraryMigrationLabel.text = "Emby/Old JF Library Path"
$LibraryMigrationLabel.TextAlign = [System.Drawing.ContentAlignment]::MiddleLeft
$LibraryMigrationLabel.AutoSize = $false
$LibraryMigrationLabel.width = 120
$LibraryMigrationLabel.height = 20
$LibraryMigrationLabel.location = New-Object System.Drawing.Point(15,190)
$LibraryMigrationLabel.Font = 'Microsoft Sans Serif,10'
$LibraryMigrationLabel.Visible = $false
$LibraryMigrationLabel.Enabled = $false
$GUIElementsCollection += $LibraryMigrationLabel
$LibraryLocationBox = New-Object system.Windows.Forms.TextBox
$LibraryLocationBox.multiline = $false
$LibraryLocationBox.width = 175
$LibraryLocationBox.height = 20
$LibraryLocationBox.location = New-Object System.Drawing.Point(140,190)
$LibraryLocationBox.Text = $Script:defaultEmbyDataDir
$LibraryLocationBox.Font = 'Microsoft Sans Serif,10'
$LibraryLocationBox.Visible = $false
$LibraryLocationBox.Enabled = $false
$GUIElementsCollection += $LibraryLocationBox
$CreateShortcutCheck = New-Object system.Windows.Forms.CheckBox
$CreateShortcutCheck.text = "Desktop Shortcut"
$CreateShortcutCheck.AutoSize = $false
$CreateShortcutCheck.width = 150
$CreateShortcutCheck.height = 20
$CreateShortcutCheck.location = New-Object System.Drawing.Point(5,215)
$CreateShortcutCheck.Font = 'Microsoft Sans Serif,10'
$GUIElementsCollection += $CreateShortcutCheck
$StartProgramCheck = New-Object system.Windows.Forms.CheckBox
$StartProgramCheck.text = "Start Jellyfin"
$StartProgramCheck.AutoSize = $false
$StartProgramCheck.width = 160
$StartProgramCheck.height = 20
$StartProgramCheck.location = New-Object System.Drawing.Point(160,215)
$StartProgramCheck.Font = 'Microsoft Sans Serif,10'
$GUIElementsCollection += $StartProgramCheck
$InstallForm.controls.AddRange($GUIElementsCollection)
$InstallForm.Controls.Add($ProgressBar)
#region gui events {
$InstallButton.Add_Click({ InstallJellyfin })
$CustomLibraryCheck.Add_CheckedChanged({CustomLibraryCheckChanged})
$InstallAsServiceCheck.Add_CheckedChanged({ServiceBoxCheckChanged})
$ServiceUserBox.Add_SelectedValueChanged({ UserSelect })
$MigrateLibraryCheck.Add_CheckedChanged({MigrateLibraryCheckboxChanged})
$CreateShortcutCheck.Add_CheckedChanged({CreateShortcutBoxCheckChanged})
$StartProgramCheck.Add_CheckedChanged({StartJellyFinBoxCheckChanged})
#endregion events }
#endregion GUI }
[void]$InstallForm.ShowDialog()

1
nsis/legacy/install.bat Normal file
View File

@ -0,0 +1 @@
powershell.exe -executionpolicy Bypass -file install-jellyfin.ps1