From 9d3191cbf1177009b47c183c564cf3df877824d4 Mon Sep 17 00:00:00 2001 From: Rohan Barar Date: Thu, 18 Jul 2024 18:27:07 +1000 Subject: [PATCH] Various changes to streamline Docker experience. --- bin/winapps | 55 ++++++++++----------- compose.yaml | 45 ++++++++++++------ docs/docker.md | 5 +- installer.sh | 127 +++++++++++++++++++++++++------------------------ 4 files changed, 123 insertions(+), 109 deletions(-) diff --git a/bin/winapps b/bin/winapps index a1399f1..90a9c5e 100755 --- a/bin/winapps +++ b/bin/winapps @@ -9,9 +9,9 @@ readonly CLEAR_TEXT="\033[0m" # Clear readonly EC_MISSING_CONFIG=1 readonly EC_MISSING_FREERDP=2 readonly EC_NOT_IN_GROUP=3 -readonly EC_VM_NOT_RUNNING=4 -readonly EC_VM_NO_IP=5 -readonly EC_VM_BAD_PORT=6 +readonly EC_NOT_RUNNING=4 +readonly EC_NO_IP=5 +readonly EC_BAD_PORT=6 readonly EC_UNSUPPORTED_APP=7 readonly EC_INVALID_FLAVOR=8 @@ -25,7 +25,7 @@ readonly CONFIG_PATH="${HOME}/.config/winapps/winapps.conf" readonly SCRIPT_DIR_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd)" # OTHER -readonly VM_NAME="RDPWindows" +readonly VM_NAME="RDPWindows" # FOR 'libvirt' ONLY readonly RDP_PORT=3389 readonly DOCKER_IP="127.0.0.1" # shellcheck disable=SC2155 # Silence warnings regarding masking return values through simultaneous declaration and assignment. @@ -71,20 +71,20 @@ function waThrowExit() { echo " sudo usermod -a -G libvirt $(whoami)" echo " sudo usermod -a -G kvm $(whoami)" ;; - "$EC_VM_NOT_RUNNING") - dprint "ERROR: VM NOT RUNNING. EXITING." - echo -e "${ERROR_TEXT}ERROR: VM NOT RUNNING.${CLEAR_TEXT}" - echo "Please ensure the Windows container/virtual machine is running." + "$EC_NOT_RUNNING") + dprint "ERROR: WINDOWS NOT RUNNING. EXITING." + echo -e "${ERROR_TEXT}ERROR: WINDOWS NOT RUNNING.${CLEAR_TEXT}" + echo "Please ensure Windows is running." ;; - "$EC_VM_NO_IP") - dprint "ERROR: VM UNREACHABLE. EXITING." - echo -e "${ERROR_TEXT}ERROR: VM UNREACHABLE.${CLEAR_TEXT}" - echo "Please ensure the Windows virtual machine is assigned an IP address." + "$EC_NO_IP") + dprint "ERROR: WINDOWS UNREACHABLE. EXITING." + echo -e "${ERROR_TEXT}ERROR: WINDOWS UNREACHABLE.${CLEAR_TEXT}" + echo "Please ensure Windows is assigned an IP address." ;; - "$EC_VM_BAD_PORT") + "$EC_BAD_PORT") dprint "ERROR: RDP PORT CLOSED. EXITING." echo -e "${ERROR_TEXT}ERROR: RDP PORT CLOSED.${CLEAR_TEXT}" - echo "Please ensure Remote Desktop is correctly configured on the Windows virtual machine." + echo "Please ensure Remote Desktop is correctly configured on Windows." ;; "$EC_UNSUPPORTED_APP") dprint "ERROR: APPLICATION NOT FOUND. EXITING." @@ -244,9 +244,9 @@ function waCheckGroupMembership() { } # Name: 'waCheckVMRunning' -# Role: Throw an error if the Windows VM is not running. +# Role: Throw an error if the Windows 'libvirt' VM is not running. function waCheckVMRunning() { - ! virsh list --state-running --name | grep -q "^${VM_NAME}$" && waThrowExit "$EC_VM_NOT_RUNNING" + ! virsh list --state-running --name | grep -q "^${VM_NAME}$" && waThrowExit "$EC_NOT_RUNNING" } # Name: 'waCheckContainerRunning' @@ -256,29 +256,30 @@ function waCheckContainerRunning() { local CONTAINER_STATE="" # Determine container state. - CONTAINER_STATE=$(docker ps --filter name="windows" --format '{{.Status}}') + CONTAINER_STATE=$(docker ps --filter name="WinApps" --format '{{.Status}}') CONTAINER_STATE=${CONTAINER_STATE,,} # Convert the string to lowercase. CONTAINER_STATE=${CONTAINER_STATE%% *} # Extract the first word. # Check container state. - [[ "$CONTAINER_STATE" != "up" ]] && waThrowExit "$EC_VM_NOT_RUNNING" + [[ "$CONTAINER_STATE" != "up" ]] && waThrowExit "$EC_NOT_RUNNING" } -# Name: 'waCheckVMContactable' -# Role: Assesses whether the Windows VM can be contacted. -function waCheckVMContactable() { +# Name: 'waCheckPortOpen' +# Role: Assesses whether the RDP port on Windows is open. +function waCheckPortOpen() { # Declare variables. local VM_MAC="" # Stores the MAC address of the Windows VM. - # Obtain Windows VM IP Address - if [ -z "$RDP_IP" ]; then + # Obtain Windows VM IP Address ('libvirt' ONLY) + # Note: 'RDP_IP' should not be empty if 'WAFLAVOR' is 'docker', since it is set to localhost before this function is called. + if [ -z "$RDP_IP" ] && [ "$WAFLAVOR" = "libvirt" ]; then VM_MAC=$(virsh domiflist "$VM_NAME" | grep -oE "([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})") # VM MAC address. RDP_IP=$(arp -n | grep "$VM_MAC" | grep -oE "([0-9]{1,3}\.){3}[0-9]{1,3}") # VM IP address. - [ -z "$RDP_IP" ] && waThrowExit "$EC_VM_NO_IP" + [ -z "$RDP_IP" ] && waThrowExit "$EC_NO_IP" fi # Check for an open RDP port. - timeout 5 nc -z "$RDP_IP" "$RDP_PORT" &>/dev/null || waThrowExit "$EC_VM_BAD_PORT" + timeout 5 nc -z "$RDP_IP" "$RDP_PORT" &>/dev/null || waThrowExit "$EC_BAD_PORT" } # Name: 'waRunCommand' @@ -290,7 +291,7 @@ function waRunCommand() { # Run option. if [ "$1" = "windows" ]; then - # Open Windows VM. + # Open Windows RDP session. dprint "WINDOWS" $FREERDP_COMMAND \ /d:"$RDP_DOMAIN" \ @@ -396,11 +397,11 @@ if [ "$WAFLAVOR" = "docker" ]; then elif [ "$WAFLAVOR" = "libvirt" ]; then waCheckGroupMembership waCheckVMRunning - waCheckVMContactable else waThrowExit "$EC_INVALID_FLAVOR" fi +waCheckPortOpen waRunCommand "$@" dprint "END" diff --git a/compose.yaml b/compose.yaml index 9599920..efe769a 100644 --- a/compose.yaml +++ b/compose.yaml @@ -1,23 +1,38 @@ -name: "winapps" +# For documentation, FAQ, additional configuration options and technical help, visit: https://github.com/dockur/windows +name: "winapps" # Docker Compose Project Name. volumes: - data: - + data: # Create Volume 'data' @ '/var/lib/docker/volumes/winapps_data/_data'. services: windows: - image: dockurr/windows - container_name: windows + image: dockurr/windows # https://hub.docker.com/r/dockurr/windows + container_name: WinApps # Created Docker VM Name. environment: + # Version of Windows to configure. For valid options, visit: + # https://github.com/dockur/windows?tab=readme-ov-file#how-do-i-select-the-windows-version + # https://github.com/dockur/windows?tab=readme-ov-file#how-do-i-install-a-custom-image VERSION: "tiny11" - RAM_SIZE: "4G" - CPU_CORES: "4" - privileged: true + RAM_SIZE: "4G" # RAM allocated to the Windows VM. + CPU_CORES: "4" # CPU cores allocated to the Windows VM. + DISK_SIZE: "64G" # Size of the primary hard disk. + #DISK2_SIZE: "32G" # Uncomment to add an additional hard disk to the Windows VM. Ensure it is mounted as a volume below. + #USERNAME: "Docker" # Uncomment to set a custom Windows username. The default is 'Docker'. + #PASSWORD: "" # Uncomment to set a password for the Windows user. There is no default password. + HOME: "${HOME}" # Set path to Linux user home folder. + privileged: true # Grant the Windows VM extended privileges. ports: - - 8006:8006 - - 3389:3389/tcp - - 3389:3389/udp - stop_grace_period: 2m - restart: on-failure + - 8006:8006 # Map '8006' on Linux host to '8006' on Windows VM --> For VNC Web Interface @ http://127.0.0.1:8006. + - 3389:3389/tcp # Map '3389' on Linux host to '3389' on Windows VM --> For Remote Desktop Protocol (RDP). + - 3389:3389/udp # Map '3389' on Linux host to '3389' on Windows VM --> For Remote Desktop Protocol (RDP). + stop_grace_period: 120s # Wait 120 seconds before sending SIGTERM when attempting to shut down the Windows VM. + restart: on-failure # Restart the Windows VM if the exit code indicates an error. volumes: - - data:/storage - - ./oem:/oem + - data:/storage # Mount volume 'data' to use as Windows 'C:' drive. + - ${HOME}:/shared # Mount Linux user home directory @ '\\host.lan\Data'. + #- /path/to/second/hard/disk:/storage2 # Uncomment to mount the second hard disk within the Windows VM. Ensure 'DISK2_SIZE' is specified above. + - ./oem:/oem # Enables automatic post-install execution of 'oem/install.bat', applying Windows registry modifications contained within 'oem/RDPApps.reg'. + #- /path/to/windows/install/media.iso:/custom.iso # Uncomment to use a custom Windows ISO. If specified, 'VERSION' (e.g. 'tiny11') will be ignored. + devices: + - /dev/kvm # Enable KVM. + #- /dev/sdX:/disk1 # Uncomment to mount a disk directly within the Windows VM (Note: 'disk1' will be mounted as the main drive). + #- /dev/sdY:/disk2 # Uncomment to mount a disk directly within the Windows VM (Note: 'disk2' and higher will be mounted as secondary drives). diff --git a/docs/docker.md b/docs/docker.md index 901c967..a8077ae 100644 --- a/docs/docker.md +++ b/docs/docker.md @@ -76,9 +76,6 @@ to run the VM in the background. After this, just open http://127.0.0.1:8006 in your web browser and wait for the Windows installation to finish. -> [!WARNING] -> Make sure to change the `RDP_IP` in your WinApps config to `127.0.0.1`. - Now you should be ready to go and try to connect to your VM with WinApps. For stopping the VM, just use: @@ -93,4 +90,4 @@ For starting again afterward, use: docker compose start ``` -(All compose commands have to be run from the directory where the `compose.yaml` is located.) +(All compose commands have to be run from the directory where `compose.yaml` is located.) diff --git a/installer.sh b/installer.sh index 1f39a6b..29a3f78 100755 --- a/installer.sh +++ b/installer.sh @@ -22,14 +22,14 @@ readonly EC_NO_CONFIG="4" # Absence of a valid WinApps configuration file readonly EC_MISSING_DEPS="5" # Missing dependencies. readonly EC_NO_SUDO="6" # Insufficient privilages to invoke superuser access. readonly EC_NOT_IN_GROUP="7" # Current user not in group 'libvirt' and/or 'kvm'. -readonly EC_VM_OFF="8" # Windows VM powered off. -readonly EC_VM_PAUSED="9" # Windows VM paused. -readonly EC_VM_ABSENT="10" # Windows VM does not exist. -readonly EC_CONTAINER_OFF="11" # Docker container is not running. -readonly EC_VM_NO_IP="12" # Windows VM does not have an IP address. -readonly EC_VM_BAD_PORT="13" # Windows VM is unreachable via RDP_PORT. -readonly EC_RDP_FAIL="14" # FreeRDP failed to establish a connection with the Windows VM. -readonly EC_APPQUERY_FAIL="15" # Failed to query the Windows VM for installed applications. +readonly EC_VM_OFF="8" # Windows 'libvirt' VM powered off. +readonly EC_VM_PAUSED="9" # Windows 'libvirt' VM paused. +readonly EC_VM_ABSENT="10" # Windows 'libvirt' VM does not exist. +readonly EC_CONTAINER_OFF="11" # Windows Docker container is not running. +readonly EC_NO_IP="12" # Windows does not have an IP address. +readonly EC_BAD_PORT="13" # Windows is unreachable via RDP_PORT. +readonly EC_RDP_FAIL="14" # FreeRDP failed to establish a connection with Windows. +readonly EC_APPQUERY_FAIL="15" # Failed to query Windows for installed applications. # PATHS # 'BIN' @@ -45,8 +45,8 @@ readonly SYS_APPDATA_PATH="/usr/local/share/winapps" # UNIX pat readonly USER_APPDATA_PATH="${HOME}/.local/share/winapps" # UNIX path to 'application data' directory for a '--user' WinApps installation. readonly USER_APPDATA_PATH_WIN='\\tsclient\home\.local\share\winapps' # WINDOWS path to 'application data' directory for a '--user' WinApps installation. # 'Installed Batch Script' -readonly BATCH_SCRIPT_PATH="${USER_APPDATA_PATH}/installed.bat" # UNIX path to a batch script used to search the Windows VM for applications. -readonly BATCH_SCRIPT_PATH_WIN="${USER_APPDATA_PATH_WIN}\\installed.bat" # WINDOWS path to a batch script used to search the Windows VM for applications. +readonly BATCH_SCRIPT_PATH="${USER_APPDATA_PATH}/installed.bat" # UNIX path to a batch script used to search Windows for applications. +readonly BATCH_SCRIPT_PATH_WIN="${USER_APPDATA_PATH_WIN}\\installed.bat" # WINDOWS path to a batch script used to search Windows for applications. # 'Installed File' readonly TMP_INST_FILE_PATH="${USER_APPDATA_PATH}/installed.tmp" # UNIX path to a temporary file containing the names of detected officially supported applications. readonly TMP_INST_FILE_PATH_WIN="${USER_APPDATA_PATH_WIN}\\installed.tmp" # WINDOWS path to a temporary file containing the names of detected officially supported applications. @@ -54,8 +54,8 @@ readonly INST_FILE_PATH="${USER_APPDATA_PATH}/installed" # UNIX readonly INST_FILE_PATH_WIN="${USER_APPDATA_PATH_WIN}\\installed" # WINDOWS path to a file containing the names of detected officially supported applications. # 'PowerShell Script' readonly PS_SCRIPT_PATH="./install/ExtractPrograms.ps1" # UNIX path to a PowerShell script used to store the names, executable paths and icons (base64) of detected applications. -readonly PS_SCRIPT_HOME_PATH="${USER_APPDATA_PATH}/ExtractPrograms.ps1" # UNIX path to a copy of the PowerShell script within the user's home directory to enable access by Windows VM. -readonly PS_SCRIPT_HOME_PATH_WIN="${USER_APPDATA_PATH_WIN}\\ExtractPrograms.ps1" # WINDOWS path to a copy of the PowerShell script within the user's home directory to enable access by Windows VM. +readonly PS_SCRIPT_HOME_PATH="${USER_APPDATA_PATH}/ExtractPrograms.ps1" # UNIX path to a copy of the PowerShell script within the user's home directory to enable access by Windows. +readonly PS_SCRIPT_HOME_PATH_WIN="${USER_APPDATA_PATH_WIN}\\ExtractPrograms.ps1" # WINDOWS path to a copy of the PowerShell script within the user's home directory to enable access by Windows. # 'Detected File' readonly DETECTED_FILE_PATH="${USER_APPDATA_PATH}/detected" # UNIX path to a file containing the output generated by the PowerShell script, formatted to define bash arrays. readonly DETECTED_FILE_PATH_WIN="${USER_APPDATA_PATH_WIN}\\detected" # WINDOWS path to a file containing the output generated by the PowerShell script, formatted to define bash arrays. @@ -68,11 +68,11 @@ readonly CONFIG_PATH="${HOME}/.config/winapps/winapps.conf" # UNIX path to the W readonly INQUIRER_PATH="./install/inquirer.sh" # UNIX path to the 'inquirer' script, which is used to produce selection menus. # REMOTE DESKTOP CONFIGURATION -readonly VM_NAME="RDPWindows" # Name of the Windows VM. -readonly RDP_PORT=3389 # Port used for RDP on the Windows VM. +readonly VM_NAME="RDPWindows" # Name of the Windows VM (FOR 'libvirt' ONLY). +readonly RDP_PORT=3389 # Port used for RDP on Windows. readonly DOCKER_IP="127.0.0.1" # Localhost. -readonly WINAPPS_CONFIG='RDP_USER="MyWindowsUser" -RDP_PASS="MyWindowsPassword" +readonly RDP_USER="" +RDP_PASS="" #RDP_DOMAIN="MYDOMAIN" #RDP_IP="192.168.123.111" #WAFLAVOR="docker" @@ -594,11 +594,11 @@ function waCheckDependencies() { echo -e "${ERROR_TEXT}ERROR:${CLEAR_TEXT} ${BOLD_TEXT}MISSING DEPENDENCIES.${CLEAR_TEXT}" # Display the error details. - echo -e "${INFO_TEXT}Please install 'Docker Desktop on Linux' to proceed.${CLEAR_TEXT}" + echo -e "${INFO_TEXT}Please install 'Docker Engine' to proceed.${CLEAR_TEXT}" # Display the suggested action(s). echo "--------------------------------------------------------------------------------" - echo "Please visit https://docs.docker.com/desktop/install/linux-install/ for more information." + echo "Please visit https://docs.docker.com/engine/install/ for more information." echo "--------------------------------------------------------------------------------" # Terminate the script. @@ -648,7 +648,7 @@ function waCheckGroupMembership() { } # Name: 'waCheckVMRunning' -# Role: Checks the state of the Windows VM to ensure it is running. +# Role: Checks the state of the Windows 'libvirt' VM to ensure it is running. function waCheckVMRunning() { # Print feedback. echo -n "Checking the status of the Windows VM... " @@ -722,13 +722,13 @@ function waCheckVMRunning() { # Role: Throw an error if the Docker container is not running. function waCheckContainerRunning() { # Print feedback. - echo -n "Checking the status of the Windows Docker container/virtual machine... " + echo -n "Checking container status... " # Declare variables. local CONTAINER_STATE="" # Determine container state. - CONTAINER_STATE=$(docker ps --filter name="windows" --format '{{.Status}}') + CONTAINER_STATE=$(docker ps --filter name="WinApps" --format '{{.Status}}') CONTAINER_STATE=${CONTAINER_STATE,,} # Convert the string to lowercase. CONTAINER_STATE=${CONTAINER_STATE%% *} # Extract the first word. @@ -738,14 +738,14 @@ function waCheckContainerRunning() { echo -e "${FAIL_TEXT}Failed!${CLEAR_TEXT}\n" # Display the error type. - echo -e "${ERROR_TEXT}ERROR:${CLEAR_TEXT} ${BOLD_TEXT}DOCKER VM NOT RUNNING.${CLEAR_TEXT}" + echo -e "${ERROR_TEXT}ERROR:${CLEAR_TEXT} ${BOLD_TEXT}DOCKER CONTAINER NOT RUNNING.${CLEAR_TEXT}" # Display the error details. - echo -e "${INFO_TEXT}The Windows Docker container/virtual machine is not running.${CLEAR_TEXT}" + echo -e "${INFO_TEXT}Windows is not running.${CLEAR_TEXT}" # Display the suggested action(s). echo "--------------------------------------------------------------------------------" - echo "Please ensure the Windows Docker container/virtual machine is powered on:" + echo "Please ensure Windows is powered on:" echo -e "${COMMAND_TEXT}docker compose start${CLEAR_TEXT}" echo "--------------------------------------------------------------------------------" @@ -757,17 +757,18 @@ function waCheckContainerRunning() { echo -e "${DONE_TEXT}Done!${CLEAR_TEXT}" } -# Name: 'waCheckVMContactable' -# Role: Assesses whether the Windows VM can be contacted (prior to attempting a remote desktop connection). -function waCheckVMContactable() { +# Name: 'waCheckPortOpen' +# Role: Assesses whether the RDP port on Windows is open. +function waCheckPortOpen() { # Print feedback. - echo -n "Attempting to contact the Windows VM... " + echo -n "Checking for an open RDP Port on Windows... " # Declare variables. local VM_MAC="" # Stores the MAC address of the Windows VM. - # Obtain Windows VM IP Address - if [ -z "$RDP_IP" ]; then + # Obtain Windows VM IP Address (FOR 'libvirt' ONLY) + # Note: 'RDP_IP' should not be empty if 'WAFLAVOR' is 'docker', since it is set to localhost before this function is called. + if [ -z "$RDP_IP" ] && [ "$WAFLAVOR" = "libvirt" ]; then VM_MAC=$(virsh domiflist "$VM_NAME" | grep -oE "([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})") # VM MAC address. RDP_IP=$(arp -n | grep "$VM_MAC" | grep -oE "([0-9]{1,3}\.){3}[0-9]{1,3}") # VM IP address. @@ -787,7 +788,7 @@ function waCheckVMContactable() { echo "--------------------------------------------------------------------------------" # Terminate the script. - return "$EC_VM_NO_IP" + return "$EC_NO_IP" fi fi @@ -800,15 +801,15 @@ function waCheckVMContactable() { echo -e "${ERROR_TEXT}ERROR:${CLEAR_TEXT} ${BOLD_TEXT}NETWORK CONFIGURATION ERROR.${CLEAR_TEXT}" # Display the error details. - echo -e "${INFO_TEXT}Failed to establish a connection with the Windows VM '${VM_NAME}' at '${RDP_IP}:${RDP_PORT}'.${CLEAR_TEXT}" + echo -e "${INFO_TEXT}Failed to establish a connection with Windows at '${RDP_IP}:${RDP_PORT}'.${CLEAR_TEXT}" # Display the suggested action(s). echo "--------------------------------------------------------------------------------" - echo "Please ensure Remote Desktop is configured on the Windows VM as per the WinApps README." + echo "Please ensure Remote Desktop is configured on Windows as per the WinApps README." echo "--------------------------------------------------------------------------------" # Terminate the script. - return "$EC_VM_BAD_PORT" + return "$EC_BAD_PORT" fi # Print feedback. @@ -816,10 +817,10 @@ function waCheckVMContactable() { } # Name: 'waCheckRDPAccess' -# Role: Tests if the Windows VM is accessible via remote desktop. +# Role: Tests if Windows is accessible via RDP. function waCheckRDPAccess() { # Print feedback. - echo -n "Attempting to establish a Remote Desktop connection with the Windows VM... " + echo -n "Attempting to establish a Remote Desktop connection with Windows... " # Declare variables. local FREERDP_LOG="" # Stores the path of the FreeRDP log file. @@ -836,7 +837,7 @@ function waCheckRDPAccess() { rm -f "$TEST_PATH" # This command should create a file on the host filesystem before terminating the RDP session. This command is silently executed as a background process. - # If the file is created, it means the Windows VM received the command via FreeRDP successfully and can read and write to the Linux home folder. + # If the file is created, it means Windows received the command via FreeRDP successfully and can read and write to the Linux home folder. # Note: The following final line is expected within the log, indicating successful execution of the 'tsdiscon' command and termination of the RDP session. # [INFO][com.freerdp.core] - [rdp_print_errinfo]: ERRINFO_LOGOFF_BY_USER (0x0000000C):The disconnection was initiated by the user logging off their session on the server. # shellcheck disable=SC2140,SC2027 # Disable warnings regarding unquoted strings. @@ -886,13 +887,13 @@ function waCheckRDPAccess() { echo -e "${ERROR_TEXT}ERROR:${CLEAR_TEXT} ${BOLD_TEXT}REMOTE DESKTOP PROTOCOL FAILURE.${CLEAR_TEXT}" # Display the error details. - echo -e "${INFO_TEXT}FreeRDP failed to establish a connection with the Windows VM.${CLEAR_TEXT}" + echo -e "${INFO_TEXT}FreeRDP failed to establish a connection with Windows.${CLEAR_TEXT}" # Display the suggested action(s). echo "--------------------------------------------------------------------------------" echo -e "Please view the log at ${COMMAND_TEXT}${FREERDP_LOG}${CLEAR_TEXT}." echo "Troubleshooting Tips:" - echo " - Ensure the user is logged out of the Windows VM prior to initiating the WinApps installation." + echo " - Ensure the user is logged out of Windows prior to initiating the WinApps installation." echo " - Ensure the credentials within the WinApps configuration file are correct." echo -e " - Utilise a new certificate by removing relevant certificate(s) in ${COMMAND_TEXT}${HOME}/.config/freerdp/server${CLEAR_TEXT}." echo " - If using 'libvirt', ensure the Windows VM is correctly named as specified within the README." @@ -913,7 +914,7 @@ function waCheckRDPAccess() { } # Name: 'waFindInstalled' -# Role: Identifies installed applications on the Windows VM. +# Role: Identifies installed applications on Windows. function waFindInstalled() { # Print feedback. echo -n "Checking for installed Windows applications... " @@ -933,7 +934,7 @@ function waFindInstalled() { rm -f "$BATCH_SCRIPT_PATH" "$TMP_INST_FILE_PATH" "$INST_FILE_PATH" "$PS_SCRIPT_HOME_PATH" "$DETECTED_FILE_PATH" # Copy PowerShell script to a directory within the user's home folder. - # This will enable the PowerShell script to be accessed and executed by the Windows VM. + # This will enable the PowerShell script to be accessed and executed by Windows. cp "$PS_SCRIPT_PATH" "$PS_SCRIPT_HOME_PATH" # Enumerate over each officially supported application. @@ -965,7 +966,7 @@ function waFindInstalled() { # Append a command to the batch script to terminate the remote desktop session once all previous commands are complete. echo "tsdiscon" >>"$BATCH_SCRIPT_PATH" - # Silently execute the batch script within the Windows VM in the background (Log Output To File) + # Silently execute the batch script within Windows in the background (Log Output To File) # Note: The following final line is expected within the log, indicating successful execution of the 'tsdiscon' command and termination of the RDP session. # [INFO][com.freerdp.core] - [rdp_print_errinfo]: ERRINFO_LOGOFF_BY_USER (0x0000000C):The disconnection was initiated by the user logging off their session on the server. # shellcheck disable=SC2140,SC2027 # Disable warnings regarding unquoted strings. @@ -1015,7 +1016,7 @@ function waFindInstalled() { echo -e "${ERROR_TEXT}ERROR:${CLEAR_TEXT} ${BOLD_TEXT}APPLICATION QUERY FAILURE.${CLEAR_TEXT}" # Display the error details. - echo -e "${INFO_TEXT}Failed to query Windows VM for installed applications.${CLEAR_TEXT}" + echo -e "${INFO_TEXT}Failed to query Windows for installed applications.${CLEAR_TEXT}" # Display the suggested action(s). echo "--------------------------------------------------------------------------------" @@ -1031,14 +1032,14 @@ function waFindInstalled() { } # Name: 'waConfigureWindows' -# Role: Create an application entry for launching Windows VM via Remote Desktop. +# Role: Create an application entry for launching Windows via Remote Desktop. function waConfigureWindows() { # Print feedback. - echo -n "Creating an application entry for Windows VM... " + echo -n "Creating an application entry for Windows... " # Declare variables. - local WIN_BASH="" # Stores the bash script to launch the Windows VM. - local WIN_DESKTOP="" # Stores the '.desktop' file to launch the Windows VM. + local WIN_BASH="" # Stores the bash script to launch a Windows RDP session. + local WIN_DESKTOP="" # Stores the '.desktop' file to launch a Windows RDP session. # Populate variables. WIN_BASH="\ @@ -1052,7 +1053,7 @@ Terminal=false Type=Application Icon=${APPDATA_PATH}/icons/windows.svg StartupWMClass=Microsoft Windows -Comment=Microsoft Windows VM" +Comment=Microsoft Windows RDP Session" # Copy the 'Windows' icon. $SUDO cp "./icons/windows.svg" "${APPDATA_PATH}/icons/windows.svg" @@ -1071,7 +1072,7 @@ Comment=Microsoft Windows VM" } # Name: 'waConfigureApp' -# Role: Create application entries for a given application installed on the Windows VM. +# Role: Create application entries for a given application installed on Windows. function waConfigureApp() { # Declare variables. local APP_ICON="" # Stores the path to the application icon. @@ -1120,12 +1121,12 @@ MimeType=${MIME_TYPES}" } # Name: 'waConfigureOfficiallySupported' -# Role: Create application entries for officially supported applications installed on the Windows VM. +# Role: Create application entries for officially supported applications installed on Windows. function waConfigureOfficiallySupported() { # Declare variables. - local OSA_LIST=() # Stores a list of all officially supported applications installed on the Windows VM. + local OSA_LIST=() # Stores a list of all officially supported applications installed on Windows. - # Read the list of officially supported applications that are installed on the Windows VM into an array, returning an empty array if no such files exist. + # Read the list of officially supported applications that are installed on Windows into an array, returning an empty array if no such files exist. # This will remove leading and trailing whitespace characters as well as ignore empty lines. readarray -t OSA_LIST < <(grep -v '^[[:space:]]*$' "$INST_FILE_PATH" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' 2>/dev/null || true) @@ -1152,18 +1153,18 @@ function waConfigureOfficiallySupported() { # Role: Allow the user to select which officially supported applications to configure. function waConfigureApps() { # Declare variables. - local OSA_LIST=() # Stores a list of all officially supported applications installed on the Windows VM. + local OSA_LIST=() # Stores a list of all officially supported applications installed on Windows. local APPS=() # Stores a list of both the simplified and full names of each installed officially supported application. local OPTIONS=() # Stores a list of options presented to the user. local APP_INSTALL="" # Stores the option selected by the user. local SELECTED_APPS=() # Stores the officially supported applications selected by the user. local TEMP_ARRAY=() # Temporary array used for sorting elements of an array. - # Read the list of officially supported applications that are installed on the Windows VM into an array, returning an empty array if no such files exist. + # Read the list of officially supported applications that are installed on Windows into an array, returning an empty array if no such files exist. # This will remove leading and trailing whitespace characters as well as ignore empty lines. readarray -t OSA_LIST < <(grep -v '^[[:space:]]*$' "$INST_FILE_PATH" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' 2>/dev/null || true) - # Loop over each officially supported application installed on the Windows VM. + # Loop over each officially supported application installed on Windows. for OSA in "${OSA_LIST[@]}"; do # Source 'Info' File Containing: # - The Application Name (FULL_NAME) @@ -1245,7 +1246,7 @@ function waConfigureDetectedApps() { if [ -f "$DETECTED_FILE_PATH" ]; then # On UNIX systems, lines are terminated with a newline character (\n). # On WINDOWS systems, lines are terminated with both a carriage return (\r) and a newline (\n) character. - # Remove all carriage returns (\r) within the 'detected' file, as the file was written by the Windows VM. + # Remove all carriage returns (\r) within the 'detected' file, as the file was written by Windows. sed -i 's/\r//g' "$DETECTED_FILE_PATH" # Import the detected application information: @@ -1321,7 +1322,7 @@ function waConfigureDetectedApps() { NAME=\"${PROGRAM_NAME}\" # Used for Descriptions and Window Class FULL_NAME=\"${PROGRAM_NAME}\" -# Executable within Windows VM +# Path to executable inside Windows WIN_EXECUTABLE=\"${EXES[$INDEX]}\" # GNOME Categories CATEGORIES=\"WinApps\" @@ -1379,7 +1380,7 @@ function waInstall() { # Set RDP_IP to localhost. RDP_IP="$DOCKER_IP" - # Check if the Windows Docker container/virtual machine is powered on. + # Check if Windows is powered on. waCheckContainerRunning elif [ "$WAFLAVOR" = "libvirt" ]; then # Check the group membership of the current user. @@ -1387,14 +1388,14 @@ function waInstall() { # Check if the Windows VM is powered on. waCheckVMRunning - - # Check if the Windows VM is contactable. - waCheckVMContactable else waThrowExit "$EC_INVALID_FLAVOR" fi - # Test RDP access to the Windows VM. + # Check if the RDP port on Windows is open. + waCheckPortOpen + + # Test RDP access to Windows. waCheckRDPAccess # Create required directories. @@ -1409,7 +1410,7 @@ function waInstall() { # Install the WinApps bash script. $SUDO cp "./bin/winapps" "${BIN_PATH}/winapps" - # Configure the Windows VM application launcher. + # Configure the Windows RDP session application launcher. waConfigureWindows if [ "$OPT_AOSA" -eq 1 ]; then