Refactor Windows installer and scripts to enhance user access and installation behavior
Some checks reported errors
farmcontrol/farmcontrol-ui/pipeline/head Something is wrong with the build of this commit

- Updated `package.json` to change installation scope from `perMachine` to `perUser`, allowing installations for standard users without admin rights.
- Modified `farmcontrol.nsi` to adjust installation directory and registry keys to use `HKCU` instead of `HKLM`, improving accessibility for non-admin users.
- Refined `installer.nsh` and related scripts to ensure proper handling of the farmcontrol URI handler and shortcuts, aligning with the new user access model.
- Removed references to the `grant-users-access.nsh` script, as user access permissions are now managed directly within the installer.
This commit is contained in:
Tom Butcher 2026-08-03 01:17:00 +01:00
parent 7d48ab6e85
commit 9bd581ee03
7 changed files with 81 additions and 67 deletions

View File

@ -245,12 +245,12 @@
"oneClick": false, "oneClick": false,
"allowToChangeInstallationDirectory": true, "allowToChangeInstallationDirectory": true,
"include": "scripts/installer.nsh", "include": "scripts/installer.nsh",
"perMachine": true "perMachine": false
}, },
"msiWrapped": { "msiWrapped": {
"upgradeCode": "{735812DB-E33B-57A0-8FBC-5FC3155925AA}", "upgradeCode": "{735812DB-E33B-57A0-8FBC-5FC3155925AA}",
"perMachine": true, "perMachine": false,
"impersonate": false, "impersonate": true,
"wrappedInstallerArgs": "/S" "wrappedInstallerArgs": "/S"
} }
} }

View File

@ -20,9 +20,9 @@
Name "Farm Control" Name "Farm Control"
OutFile "${OUTFILE}" OutFile "${OUTFILE}"
InstallDir "$PROGRAMFILES64\Farm Control" InstallDir "$LOCALAPPDATA\Programs\Farm Control"
InstallDirRegKey HKLM "Software\Tom Butcher\Farm Control" "InstallDir" InstallDirRegKey HKCU "Software\Tom Butcher\Farm Control" "InstallDir"
RequestExecutionLevel admin RequestExecutionLevel user
!define MUI_ABORTWARNING !define MUI_ABORTWARNING
@ -58,23 +58,21 @@ Section "Farm Control" SecMain
!insertmacro customInstall !insertmacro customInstall
WriteRegStr HKLM "Software\Tom Butcher\Farm Control" "InstallDir" $INSTDIR WriteRegStr HKCU "Software\Tom Butcher\Farm Control" "InstallDir" $INSTDIR
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Farm Control" \ WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\Farm Control" \
"DisplayName" "Farm Control" "DisplayName" "Farm Control"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Farm Control" \ WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\Farm Control" \
"DisplayVersion" "${VERSION}" "DisplayVersion" "${VERSION}"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Farm Control" \ WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\Farm Control" \
"Publisher" "Tom Butcher" "Publisher" "Tom Butcher"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Farm Control" \ WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\Farm Control" \
"UninstallString" "$INSTDIR\Uninstall.exe" "UninstallString" "$INSTDIR\Uninstall.exe"
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Farm Control" \ WriteRegDWORD HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\Farm Control" \
"NoModify" 1 "NoModify" 1
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Farm Control" \ WriteRegDWORD HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\Farm Control" \
"NoRepair" 1 "NoRepair" 1
WriteUninstaller "$INSTDIR\Uninstall.exe" WriteUninstaller "$INSTDIR\Uninstall.exe"
!insertmacro grantUsersInstallAccess
SectionEnd SectionEnd
Section "Uninstall" Section "Uninstall"
@ -83,6 +81,6 @@ Section "Uninstall"
Delete "$INSTDIR\Uninstall.exe" Delete "$INSTDIR\Uninstall.exe"
RMDir /r "$INSTDIR" RMDir /r "$INSTDIR"
DeleteRegKey HKLM "Software\Tom Butcher\Farm Control" DeleteRegKey HKCU "Software\Tom Butcher\Farm Control"
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Farm Control" DeleteRegKey HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\Farm Control"
SectionEnd SectionEnd

View File

@ -5,16 +5,30 @@
!macro uninstallPreviousFarmControl !macro uninstallPreviousFarmControl
ClearErrors ClearErrors
ReadRegStr $R0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Farm Control" "UninstallString" ReadRegStr $R0 HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\Farm Control" "UninstallString"
StrCmp $R0 "" check_install_dir run_uninstall StrCmp $R0 "" check_install_dir run_uninstall
check_install_dir: check_install_dir:
ReadRegStr $R0 HKCU "Software\Tom Butcher\Farm Control" "InstallDir"
StrCmp $R0 "" check_legacy_uninstall
StrCpy $R0 "$R0\Uninstall.exe"
Goto run_uninstall
check_legacy_uninstall:
ReadRegStr $R0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Farm Control" "UninstallString"
StrCmp $R0 "" check_legacy_install_dir run_uninstall
check_legacy_install_dir:
ReadRegStr $R0 HKLM "Software\Tom Butcher\Farm Control" "InstallDir" ReadRegStr $R0 HKLM "Software\Tom Butcher\Farm Control" "InstallDir"
StrCmp $R0 "" check_default_dir StrCmp $R0 "" check_default_dir
StrCpy $R0 "$R0\Uninstall.exe" StrCpy $R0 "$R0\Uninstall.exe"
Goto run_uninstall Goto run_uninstall
check_default_dir: check_default_dir:
StrCpy $R0 "$LOCALAPPDATA\Programs\Farm Control\Uninstall.exe"
IfFileExists $R0 run_uninstall check_legacy_default_dir
check_legacy_default_dir:
StrCpy $R0 "$PROGRAMFILES64\Farm Control\Uninstall.exe" StrCpy $R0 "$PROGRAMFILES64\Farm Control\Uninstall.exe"
IfFileExists $R0 run_uninstall done_uninstall IfFileExists $R0 run_uninstall done_uninstall
@ -52,40 +66,38 @@
!macroend !macroend
!macro createDesktopShortcut !macro createDesktopShortcut
SetShellVarContext all SetShellVarContext current
CreateShortCut "$DESKTOP\Farm Control.lnk" "$INSTDIR\bin\launcher.exe" "" "$INSTDIR\bin\launcher.exe" 0 SW_SHOWNORMAL "" "Farm Control" CreateShortCut "$DESKTOP\Farm Control.lnk" "$INSTDIR\bin\launcher.exe" "" "$INSTDIR\bin\launcher.exe" 0 SW_SHOWNORMAL "" "Farm Control"
!insertmacro fixShortcutWorkingDir "$DESKTOP\Farm Control.lnk" "$INSTDIR\bin" !insertmacro fixShortcutWorkingDir "$DESKTOP\Farm Control.lnk" "$INSTDIR\bin"
!macroend !macroend
!macro createStartMenuShortcut !macro createStartMenuShortcut
SetShellVarContext all SetShellVarContext current
CreateDirectory "$SMPROGRAMS\Farm Control" CreateDirectory "$SMPROGRAMS\Farm Control"
CreateShortCut "$SMPROGRAMS\Farm Control\Farm Control.lnk" "$INSTDIR\bin\launcher.exe" "" "$INSTDIR\bin\launcher.exe" 0 SW_SHOWNORMAL "" "Farm Control" CreateShortCut "$SMPROGRAMS\Farm Control\Farm Control.lnk" "$INSTDIR\bin\launcher.exe" "" "$INSTDIR\bin\launcher.exe" 0 SW_SHOWNORMAL "" "Farm Control"
!insertmacro fixShortcutWorkingDir "$SMPROGRAMS\Farm Control\Farm Control.lnk" "$INSTDIR\bin" !insertmacro fixShortcutWorkingDir "$SMPROGRAMS\Farm Control\Farm Control.lnk" "$INSTDIR\bin"
!macroend !macroend
!macro removeDesktopShortcut !macro removeDesktopShortcut
SetShellVarContext all SetShellVarContext current
Delete "$DESKTOP\Farm Control.lnk" Delete "$DESKTOP\Farm Control.lnk"
!macroend !macroend
!macro removeStartMenuShortcut !macro removeStartMenuShortcut
SetShellVarContext all SetShellVarContext current
Delete "$SMPROGRAMS\Farm Control\Farm Control.lnk" Delete "$SMPROGRAMS\Farm Control\Farm Control.lnk"
RMDir "$SMPROGRAMS\Farm Control" RMDir "$SMPROGRAMS\Farm Control"
!macroend !macroend
!include "grant-users-access.nsh"
!macro customInstall !macro customInstall
DetailPrint "Register farmcontrol URI Handler" DetailPrint "Register farmcontrol URI Handler"
DeleteRegKey HKCR "farmcontrol" DeleteRegKey HKCU "Software\Classes\farmcontrol"
WriteRegStr HKCR "farmcontrol" "" "URL:farmcontrol" WriteRegStr HKCU "Software\Classes\farmcontrol" "" "URL:farmcontrol"
WriteRegStr HKCR "farmcontrol" "URL Protocol" "" WriteRegStr HKCU "Software\Classes\farmcontrol" "URL Protocol" ""
WriteRegStr HKCR "farmcontrol\DefaultIcon" "" "$INSTDIR\bin\launcher.exe" WriteRegStr HKCU "Software\Classes\farmcontrol\DefaultIcon" "" "$INSTDIR\bin\launcher.exe"
WriteRegStr HKCR "farmcontrol\shell" "" "" WriteRegStr HKCU "Software\Classes\farmcontrol\shell" "" ""
WriteRegStr HKCR "farmcontrol\shell\Open" "" "" WriteRegStr HKCU "Software\Classes\farmcontrol\shell\Open" "" ""
WriteRegStr HKCR "farmcontrol\shell\Open\command" "" '"$INSTDIR\bin\bun.exe" "$INSTDIR\bin\deeplink.js" "%1"' WriteRegStr HKCU "Software\Classes\farmcontrol\shell\Open\command" "" '"$INSTDIR\bin\bun.exe" "$INSTDIR\bin\deeplink.js" "%1"'
DetailPrint "Creating shortcuts" DetailPrint "Creating shortcuts"
!insertmacro createDesktopShortcut !insertmacro createDesktopShortcut
@ -95,5 +107,5 @@
!macro customUnInstall !macro customUnInstall
!insertmacro removeDesktopShortcut !insertmacro removeDesktopShortcut
!insertmacro removeStartMenuShortcut !insertmacro removeStartMenuShortcut
DeleteRegKey HKCR "farmcontrol" DeleteRegKey HKCU "Software\Classes\farmcontrol"
!macroend !macroend

View File

@ -10,7 +10,7 @@
<Package <Package
InstallerVersion="500" InstallerVersion="500"
Compressed="yes" Compressed="yes"
InstallScope="perMachine" InstallScope="perUser"
Platform="x64" /> Platform="x64" />
<Condition Message="Windows 7 and above is required"><![CDATA[Installed OR VersionNT >= 601]]></Condition> <Condition Message="Windows 7 and above is required"><![CDATA[Installed OR VersionNT >= 601]]></Condition>
@ -28,7 +28,7 @@
<Property Id="PREVIOUS_UNINSTALL_CMD"> <Property Id="PREVIOUS_UNINSTALL_CMD">
<RegistrySearch <RegistrySearch
Id="PreviousUninstallCmdSearch" Id="PreviousUninstallCmdSearch"
Root="HKLM" Root="HKCU"
Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\Farm Control" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\Farm Control"
Name="UninstallString" Name="UninstallString"
Type="raw" /> Type="raw" />
@ -37,7 +37,7 @@
<Property Id="PREVIOUS_INSTALL_DIR"> <Property Id="PREVIOUS_INSTALL_DIR">
<RegistrySearch <RegistrySearch
Id="PreviousInstallDirSearch" Id="PreviousInstallDirSearch"
Root="HKLM" Root="HKCU"
Key="Software\Tom Butcher\Farm Control" Key="Software\Tom Butcher\Farm Control"
Name="InstallDir" Name="InstallDir"
Type="directory" /> Type="directory" />
@ -49,24 +49,24 @@
Id="KillFarmControl" Id="KillFarmControl"
BinaryKey="WixCA" BinaryKey="WixCA"
DllEntry="WixQuietExec" DllEntry="WixQuietExec"
Execute="deferred" Execute="immediate"
Impersonate="no" Impersonate="yes"
Return="ignore" /> Return="ignore" />
<CustomAction <CustomAction
Id="UninstallPrevious" Id="UninstallPrevious"
BinaryKey="WixCA" BinaryKey="WixCA"
DllEntry="WixQuietExec" DllEntry="WixQuietExec"
Execute="deferred" Execute="immediate"
Impersonate="no" Impersonate="yes"
Return="ignore" /> Return="ignore" />
<CustomAction <CustomAction
Id="RunInstaller" Id="RunInstaller"
BinaryKey="WrappedExe" BinaryKey="WrappedExe"
ExeCommand="/S" ExeCommand="/S"
Execute="deferred" Execute="immediate"
Impersonate="no" Impersonate="yes"
Return="check" /> Return="check" />
<Directory Id="TARGETDIR" Name="SourceDir"> <Directory Id="TARGETDIR" Name="SourceDir">

View File

@ -48,7 +48,6 @@ function Get-DirectoryBytes {
$rootDir = Split-Path -Parent $PSScriptRoot $rootDir = Split-Path -Parent $PSScriptRoot
$nsiPath = Join-Path $rootDir "packaging/windows/farmcontrol.nsi" $nsiPath = Join-Path $rootDir "packaging/windows/farmcontrol.nsi"
$installerInclude = Join-Path $rootDir "packaging/windows/installer.nsh" $installerInclude = Join-Path $rootDir "packaging/windows/installer.nsh"
$grantUsersAccessInclude = Join-Path $rootDir "packaging/windows/grant-users-access.nsh"
$workDir = Join-Path $env:TEMP "farmcontrol-nsis" $workDir = Join-Path $env:TEMP "farmcontrol-nsis"
$localInstallerName = "farmcontrol-installer.exe" $localInstallerName = "farmcontrol-installer.exe"
@ -81,7 +80,6 @@ if (-not (Test-Path $requiredDeeplinkScript)) {
Copy-Item -LiteralPath $nsiPath -Destination (Join-Path $workDir "farmcontrol.nsi") Copy-Item -LiteralPath $nsiPath -Destination (Join-Path $workDir "farmcontrol.nsi")
Copy-Item -LiteralPath $installerInclude -Destination (Join-Path $workDir "installer.nsh") Copy-Item -LiteralPath $installerInclude -Destination (Join-Path $workDir "installer.nsh")
Copy-Item -LiteralPath $grantUsersAccessInclude -Destination (Join-Path $workDir "grant-users-access.nsh")
$iconPath = Join-Path $rootDir "assets\installer.ico" $iconPath = Join-Path $rootDir "assets\installer.ico"
if (Test-Path $iconPath) { if (Test-Path $iconPath) {

View File

@ -1,14 +1,10 @@
!include "packaging\windows\grant-users-access.nsh" !macro customInstall
!macro customInstall
!insertmacro grantUsersInstallAccess
DetailPrint "Register farmcontrol URI Handler" DetailPrint "Register farmcontrol URI Handler"
DeleteRegKey HKCR "farmcontrol" DeleteRegKey HKCU "Software\Classes\farmcontrol"
WriteRegStr HKCR "farmcontrol" "" "URL:farmcontrol" WriteRegStr HKCU "Software\Classes\farmcontrol" "" "URL:farmcontrol"
WriteRegStr HKCR "farmcontrol" "URL Protocol" "" WriteRegStr HKCU "Software\Classes\farmcontrol" "URL Protocol" ""
WriteRegStr HKCR "farmcontrol\DefaultIcon" "" "$INSTDIR\${APP_EXECUTABLE_FILENAME}" WriteRegStr HKCU "Software\Classes\farmcontrol\DefaultIcon" "" "$INSTDIR\${APP_EXECUTABLE_FILENAME}"
WriteRegStr HKCR "farmcontrol\shell" "" "" WriteRegStr HKCU "Software\Classes\farmcontrol\shell" "" ""
WriteRegStr HKCR "farmcontrol\shell\Open" "" "" WriteRegStr HKCU "Software\Classes\farmcontrol\shell\Open" "" ""
WriteRegStr HKCR "farmcontrol\shell\Open\command" "" "$INSTDIR\${APP_EXECUTABLE_FILENAME} %1" WriteRegStr HKCU "Software\Classes\farmcontrol\shell\Open\command" "" "$INSTDIR\${APP_EXECUTABLE_FILENAME} %1"
!macroend !macroend

View File

@ -5,10 +5,13 @@ import path from 'node:path'
import process from 'node:process' import process from 'node:process'
const MAC_APP_NAME = 'Farm Control.app' const MAC_APP_NAME = 'Farm Control.app'
const WINDOWS_INSTALL_DIR_KEY = const WINDOWS_INSTALL_DIR_KEYS = [
'HKCU\\Software\\Tom Butcher\\Farm Control',
'HKLM\\Software\\Tom Butcher\\Farm Control' 'HKLM\\Software\\Tom Butcher\\Farm Control'
]
const WINDOWS_DEFAULT_LAUNCHER = path.join( const WINDOWS_DEFAULT_LAUNCHER = path.join(
process.env.ProgramFiles || 'C:\\Program Files', process.env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local'),
'Programs',
'Farm Control', 'Farm Control',
'bin', 'bin',
'launcher.exe' 'launcher.exe'
@ -39,16 +42,23 @@ const findMacAppBundle = (startPath) => {
} }
const readWindowsInstallDirFromRegistry = () => { const readWindowsInstallDirFromRegistry = () => {
try { for (const registryKey of WINDOWS_INSTALL_DIR_KEYS) {
const output = execSync( try {
`reg query ${quoteBatchArg(WINDOWS_INSTALL_DIR_KEY)} /v InstallDir`, const output = execSync(
{ encoding: 'utf8', windowsHide: true } `reg query ${quoteBatchArg(registryKey)} /v InstallDir`,
) { encoding: 'utf8', windowsHide: true }
const match = output.match(/InstallDir\s+REG_\w+\s+(.+)/i) )
return match?.[1]?.trim() || null const match = output.match(/InstallDir\s+REG_\w+\s+(.+)/i)
} catch { const installDir = match?.[1]?.trim()
return null if (installDir) {
return installDir
}
} catch {
// Try the next registry key.
}
} }
return null
} }
export const resolveAppLaunchPath = () => { export const resolveAppLaunchPath = () => {