windowsbatch-filecmdregistrytailscale

automate the installation process of tailscale


I'm writing a Windows batch script to automate the installation process of Tailscale, thus I need a way to install it without prompt and any graphical window and I'm struggle on getting the error:

This installation package could not be
opened. Verify that the package exists and
that you can access it, or contact the
application vendor to verify that this is a
valid Windows Installer package.

The message box with this error message occurs on running from within a PowerShell console opened as administrator the following two command lines:

cd C:\mysys64\home\ryuu\
msiexec /L .\install.log /i ./tailscale-setup-1.74.0-amd64.msi TS_NOLAUNCH=yes TS_INSTALLUPDATES=always TS_ALLOWINCOMINGCONNECTIONS=always TS_UNATTENDEDMODE=always

I follow the Tailscale documentation page: Installing Tailscale on Windows with MSI

Here is the full script that I'm working on:

@echo off
setlocal

REM TODO: abort the process if the internet connection is down.

if [%1] == [] goto :usage

goto :install_msys2

:usage
echo USAGE: .\automate.bat "your-auth-key"
echo DESCRIPTION: the script to automate the installation process of msys2, tailscale and openssh
echo also automatically configure the sshd_config file to only accept public key auth method and connect your machine to tailnet.
echo note: you need to manually copy your public key to authorized_keys file

goto :eof

:install_msys2
REM Check if MSYS2 is in the system PATH
where msys2.exe >nul 2>nul
if %errorlevel% NEQ 0 (
    echo [WARN] Failed to search MSYS2 in the PATH.
)

echo [ACTION] Trying to search MSYS2 on the default location: C:\msys64\msys2.exe
REM Check for MSYS2 in default installation directory
if not exist "C:\msys64\msys2.exe" (
    echo [ERROR] can't found MSYS2 on the default location
    echo [ERROR] Exit the script... MSYS2 is not installed.
    REM TODO: download and install the msys2 instead of exit
    REM https://www.msys2.org/docs/installer/
    REM .\msys2-x86_64-latest.exe in --confirm-command --accept-messages --root C:/msys64
    exit /b 1
)

echo [INFO] MSYS2 software is installed on: ...

:install_openssh
REM Check the status of msys2_sshd service
sc query msys2_sshd | findstr /i "STATE" >nul 2>nul

if %errorlevel%==0 (
    echo [INFO] msys2_sshd service is installed.
    sc query msys2_sshd | findstr /i "RUNNING" >nul 2>nul
    if %errorlevel%==0 (
    echo [INFO] msys2_sshd service is already running.
    ) else (
    echo [INFO] msys2_sshd service is not running.
    REM TODO: ensure the service will automatically started on next boot
    net start msys2_sshd
    )
) else (
    echo [ERROR] msys2_sshd service is not installed
    echo [ACTION] starting to install it...
    REM TODO: install openssh according to https://www.msys2.org/wiki/Setting-up-SSHd/
)

:install_tailscale
REM Check if tailscale is in the system PATH
where tailscale.exe >nul 2>nul
if %errorlevel% NEQ 0 (
    echo [WARNING] Failed to search tailscale in the PATH.
)

echo [ACTION] Trying to search tailscale on the default location: C:\Program Files/Tailscale/
if not exist "C:\Program Files\Tailscale\tailscale.exe" (
    echo [WARN] can't found tailscale on the default location
    REM TODO: download and install tailscale silently
    REM download it from https://pkgs.tailscale.com/stable/tailscale-setup-latest.exe
    echo [ACTION] downloading tailscale installer
    powershell -Command "Invoke-WebRequest -Uri https://pkgs.tailscale.com/stable/tailscale-setup-latest.exe -OutFile tailscale-setup-latest.exe

)

echo [INFO] tailscale is installed on: ...

sc query tailscale | findstr /i "STATE" >nul 2>nul

if %errorlevel%==0 (
    echo [INFO] tailscale service is installed.
    sc query msys2_sshd | findstr /i "RUNNING" >nul 2>nul
    if %errorlevel%==0 (
        echo [INFO] tailscale service is already running.
    ) else (
        echo [INFO] tailscale service is not running.
        REM TODO: start tailscale service and ensure the service will automatically started on next boot
    )

    REM TODO: start to connecting the machine to tailnet while authenticate tailscale silently with --unattended argument
) else (
    echo [ERROR] tailscale service is missing, make sure to install the software properly
    exit /b 1
)

The script is very useful to me as I often need to re-create Windows in VM for a reason, but it's not ready-to-use and still work-in-progress. :)

I have another question that is not related to the title of this question but still related to Tailscale:

From the tailscale page:

Tailscale MSI properties, if set, are stored in the HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Tailscale registry key. The registry value type for all Tailscale MSI properties is REG_SZ.

If I have installed Tailscale and want to see what are the current values of these properties. How to print them with a Windows command line or PowerShell?


Solution

  • The main issue is the specification of the Microsoft Installer file with ./tailscale-setup-1.74.0-amd64.msi. The directory separator on Windows is \ and not / as on Linux/Mac as explained by the Microsoft documentation about Naming Files, Paths, and Namespaces. The character / is used on Windows for command line options.

    The error message gives the information that the specified MSI file could not be found in the current working directory. The current working directory is C:\mysys64\home\ryuu for cmd.exe processing the batch file. But the execution of msiexec.exe results in most cases in running this executable in an elevated environment of a local administrator which could cause a change of the current working directory as described for example in: Why does 'Run as administrator' change (sometimes) batch file's current directory? It is highly recommended for that reason specifying all files on the msiexec.exe command line with their fully qualified file names, which means drive + path + name + extension enclosed in " for working independent on the current working directory.


    There can be executed in a command prompt window:

    %SystemRoot%\System32\reg.exe QUERY HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Tailscale
    

    That outputs the group policy settings for Tailscale. It could be necessary to append /S if there are subkeys with registry values below the specified registry key. Run in a command prompt window reg /? and next reg query /? and read the output usage helps of this Windows command.

    If that command is used also in the batch file, consider the information on the Microsoft documentation pages WOW64 Implementation Details, File System Redirector and Registry Keys Affected by WOW64. The batch file could be processed on 64-bit Windows also by 32-bit %SystemRoot%\SysWOW64\cmd.exe instead of 64-bit %SystemRoot%\System32\cmd.exe.


    Some more hints for improving the batch code:

    1. The second line should be modified from setlocal to setlocal EnableExtensions DisableDelayedExpansion. For the reason read the chapter Issue 6: Batch file depends on environment defined outside in this answer.

    2. The condition if [%1] == [] goto :usage is syntax for COMMAND.COM of MS-DOS and Windows 95/98/ME with no support for argument string modifiers like %~1. Those operating systems are for sure not used anymore for running this batch file. There should be used the Windows Command Processor cmd.exe syntax: if "%~1" == "" goto :usage

    3. All executables with well known path should be referenced with the fully qualified file name for making the batch file independent on the environment variables PATHEXT and PATH as much as possible which means more fail-safe and secure and also faster processed with less file system accesses. There should be used %SystemRoot%\System32\where.exe instead of just where and %SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe instead of just powershell and %SystemRoot%\System32\sc.exe instead of just sc and %SystemRoot%\System32\findstr.exe instead of just findstr and %SystemRoot%\System32\msiexec.exe instead of just msiexec.

    4. Open a command prompt window, run if /? and read the output usage help explaining already on first page how to evaluate the exit code of a previously run command or executable. There can be read nothing about if %errorlevel% NEQ 0 or if %errorlevel%==0 as used in the batch file. The reason is that those alternative exit code evaluations are processed slower and do not work inside a command block beginning with ( and ending with matching ) as used in the batch file too. if %errorlevel% NEQ 0 should be replaced by if errorlevel 1 and if %errorlevel%==0 must be replaced by if not errorlevel 1. See the chapter Accessing the values of dynamic variables in Difference between Dynamic variables and Environment variables in CMD for a detailed explanation.

    Other related questions and answers on Stack Overflow: