@echo off
:setup
set "app.version=1.0.0"
set "app.name=VirtViewer Dark Mode"
set "app.rc=0"
if not defined app.IsConsole call :IsConsole app.IsConsole
call :IsElevated app.elevated
:main
call :HelpRequested %*
if not errorlevel 1 (call :Usage & goto :end)
call :CheckDependencies
if errorlevel 1 (set "app.rc=%errorlevel%" & goto :end)
if /i "%app.elevated%" NEQ "true" call :SelfElevate %*
if /i "%app.elevated%" NEQ "true" set "app.rc=%errorlevel%"
if /i "%app.elevated%" NEQ "true" if "%app.rc%"=="0" set "app.skipPause=true"
if /i "%app.elevated%" NEQ "true" if not "%app.rc%"=="0" >&2 echo ERROR: Administrator elevation failed or was cancelled. Return code: %app.rc%
if /i "%app.elevated%" NEQ "true" goto :end
call :EnableVirtViewerDarkMode
set "app.rc=%errorlevel%"
:end
if /i "%app.skipPause%" NEQ "true" if /i "%app.IsConsole%" NEQ "true" pause
call :SetErrorLevel %app.rc%
GoTo :EOF
:: ============================================================
:: :HelpRequested
:: Detects whether the command line contains a help switch.
::
:: Version:
:: 1.0.0
::
:: Usage: call :HelpRequested [arguments...]
::
:: Arguments:
:: arguments command-line arguments to inspect
::
:: Output:
:: None
::
:: Returns:
:: 0 when a supported help switch is present
:: 1 otherwise
:: ============================================================
:HelpRequested
for /f "tokens=1 delims==" %%v in ('set hlp_ 2^>nul') do set "%%v="
if defined _hlp_rc (set "_hlp_rc=" & exit /b %_hlp_rc%)
:_HelpRequested_scan
if "%~1"=="" exit /b 1
if /i "%~1"=="--help" exit /b 0
if /i "%~1"=="-h" exit /b 0
if /i "%~1"=="-?" exit /b 0
if /i "%~1"=="/h" exit /b 0
if /i "%~1"=="/?" exit /b 0
shift
goto :_HelpRequested_scan
:: ============================================================
:: :Usage
:: Prints command-line usage.
::
:: Version:
:: 1.0.0
::
:: Usage: call :Usage
::
:: Arguments:
:: None
::
:: Output:
:: Usage text to stdout
::
:: Returns:
:: 0
:: ============================================================
:Usage
for /f "tokens=1 delims==" %%v in ('set usg_ 2^>nul') do set "%%v="
if defined _usg_rc (set "_usg_rc=" & exit /b %_usg_rc%)
echo %app.name% %app.version%
echo(
echo Usage:
echo %~nx0% [--help]
echo(
echo Finds the application registered to open .vv files, derives its
echo installation directory, and writes a program-specific GTK 3
echo settings.ini requesting the dark theme variant.
echo(
echo An existing settings.ini is backed up as settings.ini.bak before
echo it is replaced.
echo(
echo Supported help switches:
echo --help -h -? /h /?
exit /b 0
:: ============================================================
:: :CheckDependencies
:: Verifies external commands required by this script.
::
:: Version:
:: 1.0.0
::
:: Usage: call :CheckDependencies
::
:: Arguments:
:: None
::
:: Output:
:: An error message to stderr when a dependency is unavailable
::
:: Returns:
:: 0 when all dependencies are available
:: 2 when powershell.exe is unavailable
:: 3 when reg.exe is unavailable
:: 4 when findstr.exe is unavailable
:: ============================================================
:CheckDependencies
for /f "tokens=1 delims==" %%v in ('set dep_ 2^>nul') do set "%%v="
if defined _dep_rc (set "_dep_rc=" & exit /b %_dep_rc%)
where.exe powershell.exe >nul 2>&1
if errorlevel 1 (>&2 echo ERROR: powershell.exe was not found. & set "_dep_rc=2" & goto :CheckDependencies)
where.exe reg.exe >nul 2>&1
if errorlevel 1 (>&2 echo ERROR: reg.exe was not found. & set "_dep_rc=3" & goto :CheckDependencies)
where.exe findstr.exe >nul 2>&1
if errorlevel 1 (>&2 echo ERROR: findstr.exe was not found. & set "_dep_rc=4" & goto :CheckDependencies)
exit /b 0
:: ============================================================
:: :EnableVirtViewerDarkMode
:: Resolves the .vv handler, locates its GTK 3 configuration
:: directory, and writes the program-specific dark-mode setting.
::
:: Version:
:: 1.0.0
::
:: Usage: call :EnableVirtViewerDarkMode
::
:: Arguments:
:: None
::
:: Output:
:: Progress and resulting paths to stdout; errors to stderr
::
:: Returns:
:: 0 on success
:: a nonzero code propagated from a called helper on failure
::
:: Dependencies:
:: :ResolveVvExecutable
:: :GetInstallDirectory
:: :SelectGtkDirectory
:: :WriteGtkSettings
:: ============================================================
:EnableVirtViewerDarkMode
for /f "tokens=1 delims==" %%v in ('set evd_ 2^>nul') do set "%%v="
if defined _evd_rc (set "_evd_rc=" & exit /b %_evd_rc%)
echo(
echo Resolving the registered .vv application...
call :ResolveVvExecutable evd_exe
if errorlevel 1 (set "_evd_rc=%errorlevel%" & >&2 echo ERROR: Could not resolve the executable registered for .vv files. & goto :EnableVirtViewerDarkMode)
echo Registered .vv handler:
echo %evd_exe%
call :GetInstallDirectory "%evd_exe%" evd_install
if errorlevel 1 (set "_evd_rc=%errorlevel%" & >&2 echo ERROR: Could not derive the VirtViewer installation directory. & goto :EnableVirtViewerDarkMode)
echo Installation directory:
echo %evd_install%
call :SelectGtkDirectory "%evd_install%" evd_gtk
if errorlevel 1 (set "_evd_rc=%errorlevel%" & >&2 echo ERROR: Could not select a GTK 3 configuration directory. & goto :EnableVirtViewerDarkMode)
call :WriteGtkSettings "%evd_gtk%" evd_settings
if errorlevel 1 (set "_evd_rc=%errorlevel%" & >&2 echo ERROR: Could not write the GTK 3 dark-mode configuration. & goto :EnableVirtViewerDarkMode)
echo GTK configuration:
echo %evd_settings%
echo(
echo Dark mode enabled. Restart VirtViewer / Remote Viewer for the change to take effect.
exit /b 0
:: ============================================================
:: :ResolveVvExecutable
:: Resolves the executable registered to open .vv files.
::
:: Version:
:: 1.0.0
::
:: Usage: call :ResolveVvExecutable outputVariable
::
:: Arguments:
:: outputVariable variable that receives the executable path
::
:: Output:
:: outputVariable full path to the registered executable
::
:: Returns:
:: 0 on success
:: 2 for invalid arguments
:: 3 when no .vv ProgID can be resolved
:: 4 when no open command exists for the ProgID
:: 5 when the executable cannot be parsed from the command
:: 6 when the parsed executable does not exist
::
:: Dependencies:
:: reg.exe
:: findstr.exe
:: powershell.exe
::
:: Notes:
:: The current-user UserChoice ProgID is checked first because
:: it takes precedence over the default HKCR\.vv association.
:: PowerShell is used only to parse the executable token from
:: the registered command and expand environment variables.
:: ============================================================
:ResolveVvExecutable
for /f "tokens=1 delims==" %%v in ('set rvv_ 2^>nul') do set "%%v="
if defined _rvv_rc (set "_rvv_rc=" & exit /b %_rvv_rc%)
set "rvv_out=%~1"
if not defined rvv_out (set "_rvv_rc=2" & goto :ResolveVvExecutable)
for /f "tokens=2,*" %%A in ('reg.exe query "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.vv\UserChoice" /v ProgId 2^>nul ^| findstr.exe /i /c:"REG_SZ"') do if not defined rvv_progid set "rvv_progid=%%B"
if not defined rvv_progid for /f "tokens=2,*" %%A in ('reg.exe query "HKCR\.vv" /ve 2^>nul ^| findstr.exe /i /c:"REG_SZ" /c:"REG_EXPAND_SZ"') do if not defined rvv_progid set "rvv_progid=%%B"
if not defined rvv_progid (set "_rvv_rc=3" & goto :ResolveVvExecutable)
for /f "tokens=2,*" %%A in ('reg.exe query "HKCR\%rvv_progid%\shell\open\command" /ve 2^>nul ^| findstr.exe /i /c:"REG_SZ" /c:"REG_EXPAND_SZ"') do if not defined rvv_command set "rvv_command=%%B"
if not defined rvv_command (set "_rvv_rc=4" & goto :ResolveVvExecutable)
for /f "usebackq delims=" %%P in (`powershell.exe -NoLogo -NoProfile -NonInteractive -Command "$c=([string]$env:rvv_command).Trim(); if(!$c){exit 2}; if($c.StartsWith([char]34)){ $n=$c.IndexOf([char]34,1); if($n -le 1){exit 2}; $e=$c.Substring(1,$n-1) } else { $e=($c -split '\s+',2)[0] }; [Environment]::ExpandEnvironmentVariables($e)"`) do if not defined rvv_exe set "rvv_exe=%%P"
if not defined rvv_exe (set "_rvv_rc=5" & goto :ResolveVvExecutable)
if not exist "%rvv_exe%" (set "_rvv_rc=6" & goto :ResolveVvExecutable)
set "%rvv_out%=%rvv_exe%"
exit /b 0
:: ============================================================
:: :GetInstallDirectory
:: Derives an application installation directory from an
:: executable path, treating a containing "bin" directory as a
:: conventional child of the installation root.
::
:: Version:
:: 1.0.0
::
:: Usage: call :GetInstallDirectory "executablePath" outputVariable
::
:: Arguments:
:: executablePath full path to an existing executable
:: outputVariable variable that receives the installation path
::
:: Output:
:: outputVariable derived installation directory
::
:: Returns:
:: 0 on success
:: 2 for invalid arguments
:: 3 when the executable does not exist
:: ============================================================
:GetInstallDirectory
for /f "tokens=1 delims==" %%v in ('set gid_ 2^>nul') do set "%%v="
if defined _gid_rc (set "_gid_rc=" & exit /b %_gid_rc%)
set "gid_exe=%~1" & set "gid_out=%~2"
if not defined gid_exe (set "_gid_rc=2" & goto :GetInstallDirectory)
if not defined gid_out (set "_gid_rc=2" & goto :GetInstallDirectory)
if not exist "%gid_exe%" (set "_gid_rc=3" & goto :GetInstallDirectory)
for %%P in ("%gid_exe%") do set "gid_dir=%%~dpP"
for %%P in ("%gid_dir:~0,-1%") do set "gid_leaf=%%~nxP"
if /i "%gid_leaf%"=="bin" for %%P in ("%gid_dir%..") do set "gid_install=%%~fP"
if not defined gid_install for %%P in ("%gid_dir%.") do set "gid_install=%%~fP"
set "%gid_out%=%gid_install%"
exit /b 0
:: ============================================================
:: :SelectGtkDirectory
:: Selects the program-specific GTK 3 configuration directory.
::
:: Version:
:: 1.0.0
::
:: Usage: call :SelectGtkDirectory "installDirectory" outputVariable
::
:: Arguments:
:: installDirectory application installation directory
:: outputVariable variable that receives the GTK directory
::
:: Output:
:: outputVariable existing share\gtk-3.0, otherwise existing
:: etc\gtk-3.0, otherwise share\gtk-3.0
::
:: Returns:
:: 0 on success
:: 2 for invalid arguments
:: 3 when the installation directory does not exist
:: ============================================================
:SelectGtkDirectory
for /f "tokens=1 delims==" %%v in ('set sgd_ 2^>nul') do set "%%v="
if defined _sgd_rc (set "_sgd_rc=" & exit /b %_sgd_rc%)
set "sgd_install=%~1" & set "sgd_out=%~2"
if not defined sgd_install (set "_sgd_rc=2" & goto :SelectGtkDirectory)
if not defined sgd_out (set "_sgd_rc=2" & goto :SelectGtkDirectory)
if not exist "%sgd_install%\" (set "_sgd_rc=3" & goto :SelectGtkDirectory)
set "sgd_share=%sgd_install%\share\gtk-3.0" & set "sgd_etc=%sgd_install%\etc\gtk-3.0"
if exist "%sgd_share%\" set "sgd_result=%sgd_share%"
if not defined sgd_result if exist "%sgd_etc%\" set "sgd_result=%sgd_etc%"
if not defined sgd_result set "sgd_result=%sgd_share%"
set "%sgd_out%=%sgd_result%"
exit /b 0
:: ============================================================
:: :WriteGtkSettings
:: Creates the selected GTK 3 directory as needed, backs up an
:: existing settings.ini, and writes the dark-theme preference.
::
:: Version:
:: 1.0.0
::
:: Usage: call :WriteGtkSettings "gtkDirectory" outputVariable
::
:: Arguments:
:: gtkDirectory target GTK 3 configuration directory
:: outputVariable variable that receives the settings.ini path
::
:: Output:
:: outputVariable full path to settings.ini
:: settings.ini.bak when a previous settings.ini existed
::
:: Returns:
:: 0 on success
:: 2 for invalid arguments
:: 3 when the GTK directory cannot be created
:: 4 when an existing settings.ini cannot be backed up
:: 5 when settings.ini cannot be written
::
:: Side Effects:
:: Creates the GTK directory when absent.
:: Replaces settings.ini after creating settings.ini.bak when
:: a previous file exists.
:: ============================================================
:WriteGtkSettings
for /f "tokens=1 delims==" %%v in ('set wgs_ 2^>nul') do set "%%v="
if defined _wgs_rc (set "_wgs_rc=" & exit /b %_wgs_rc%)
set "wgs_dir=%~1" & set "wgs_out=%~2"
if not defined wgs_dir (set "_wgs_rc=2" & goto :WriteGtkSettings)
if not defined wgs_out (set "_wgs_rc=2" & goto :WriteGtkSettings)
if not exist "%wgs_dir%\" mkdir "%wgs_dir%" >nul 2>&1
if not exist "%wgs_dir%\" (set "_wgs_rc=3" & goto :WriteGtkSettings)
set "wgs_file=%wgs_dir%\settings.ini"
if not exist "%wgs_file%" goto :_WriteGtkSettings_write
copy /y "%wgs_file%" "%wgs_file%.bak" >nul 2>&1
if errorlevel 1 (set "_wgs_rc=4" & goto :WriteGtkSettings)
:_WriteGtkSettings_write
> "%wgs_file%" echo [Settings]
if errorlevel 1 (set "_wgs_rc=5" & goto :WriteGtkSettings)
>> "%wgs_file%" echo gtk-application-prefer-dark-theme = true
if errorlevel 1 (set "_wgs_rc=5" & goto :WriteGtkSettings)
set "%wgs_out%=%wgs_file%"
exit /b 0
:: ============================================================
:: :IsConsole
:: Detects whether this batch appears to be running from an
:: already-open console.
::
:: Version:
:: 1.0.1
::
:: Usage: call :IsConsole outputVariable
::
:: Arguments:
:: outputVariable variable that receives the result
::
:: Output:
:: outputVariable set to true when running from a console
:: or false otherwise
::
:: Returns:
:: 0 if running from an already-open console
:: 1 if cmd.exe appears to have been launched for this batch
:: ============================================================
:IsConsole
set "iscon_out=%~1"
set "iscon_cmdline=%CMDCMDLINE:"=%"
setlocal EnableDelayedExpansion
echo(!iscon_cmdline!| find /i "%~f0" >nul 2>&1
if not errorlevel 1 (endlocal & set "%iscon_out%=false" & exit /b 1)
echo(!iscon_cmdline!| find /i "%~nx0" >nul 2>&1
if not errorlevel 1 (endlocal & set "%iscon_out%=false" & exit /b 1)
endlocal
set "%iscon_out%=true"
exit /b 0
:: ============================================================
:: :IsElevated
:: Detects whether the current process has an elevated
:: administrator token.
::
:: Version:
:: 1.0.1
::
:: Usage: call :IsElevated outputVariable
::
:: Arguments:
:: outputVariable variable that receives the result
::
:: Output:
:: outputVariable true when elevated, false otherwise
::
:: Returns:
:: 0 if elevated
:: 1 if not elevated
:: ============================================================
:IsElevated
for /f "tokens=1 delims==" %%v in ('set isel_ 2^>nul') do set "%%v="
if defined _isel_rc (set "_isel_rc=" & exit /b %_isel_rc%)
set "isel_out=%~1"
fltmc >nul 2>&1
if errorlevel 1 (set "%isel_out%=false" & set "_isel_rc=1" & goto :IsElevated)
set "%isel_out%=true"
exit /b 0