From 12dee36bdc2c8fdb792e0cc0de8d5de29b940bca Mon Sep 17 00:00:00 2001 From: eylenburg <84839316+eylenburg@users.noreply.github.com> Date: Fri, 20 Jun 2025 11:06:01 +0100 Subject: [PATCH 1/9] Wait a bit before running command if Windows is not booted --- bin/winapps | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/bin/winapps b/bin/winapps index 0941ad9..69e15fc 100755 --- a/bin/winapps +++ b/bin/winapps @@ -55,6 +55,7 @@ MULTI_FLAG="" # OTHER FREERDP_PID=-1 +NEEDED_BOOT=false ### TRAPS ### # Catch SIGINT (CTRL+C) to call 'waCleanUp'. @@ -412,6 +413,8 @@ function waCheckContainerRunning() { local TIME_ELAPSED=0 local TIME_LIMIT=60 local TIME_INTERVAL=5 + local MAX_WAIT_TIME=120 + local WAIT_ELAPSED=0 # Determine the state of the container. CONTAINER_STATE=$("$WAFLAVOR" inspect --format='{{.State.Status}}' "$CONTAINER_NAME") @@ -431,6 +434,7 @@ function waCheckContainerRunning() { dprint "WINDOWS CREATED. BOOTING WINDOWS." notify-send --expire-time=4000 --icon="dialog-info" --app-name="WinApps" --urgency="low" "WinApps" "Booting Windows." $COMPOSE_COMMAND --file "$COMPOSE_PATH" start &>/dev/null + NEEDED_BOOT=true ;; "restarting") dprint "WINDOWS RESTARTING. WAITING." @@ -441,6 +445,7 @@ function waCheckContainerRunning() { EXIT_STATUS=0 dprint "WINDOWS RESTARTED." notify-send --expire-time=4000 --icon="dialog-info" --app-name="WinApps" --urgency="low" "WinApps" "Restarted Windows." + NEEDED_BOOT=true break fi sleep $TIME_INTERVAL @@ -456,11 +461,13 @@ function waCheckContainerRunning() { dprint "WINDOWS SHUT OFF. BOOTING WINDOWS." notify-send --expire-time=4000 --icon="dialog-info" --app-name="WinApps" --urgency="low" "WinApps" "Booting Windows." $COMPOSE_COMMAND --file "$COMPOSE_PATH" start &>/dev/null + NEEDED_BOOT=true ;; "dead") dprint "WINDOWS DEAD. RECREATING WINDOWS CONTAINER." notify-send --expire-time=4000 --icon="dialog-info" --app-name="WinApps" --urgency="low" "WinApps" "Re-creating and booting Windows." $COMPOSE_COMMAND --file "$COMPOSE_PATH" down &>/dev/null && $COMPOSE_COMMAND --file "$COMPOSE_PATH" up -d &>/dev/null + NEEDED_BOOT=true ;; "unknown") EXIT_STATUS=$EC_UNKNOWN @@ -469,6 +476,43 @@ function waCheckContainerRunning() { # Handle non-zero exit statuses. [ "$EXIT_STATUS" -ne 0 ] && waThrowExit "$EXIT_STATUS" + + # Wait for container to be fully ready + if [[ "$CONTAINER_STATE" == "created" || "$CONTAINER_STATE" == "exited" || "$CONTAINER_STATE" == "dead" ]]; then + dprint "WAITING FOR CONTAINER TO BE FULLY READY..." + notify-send --expire-time=4000 --icon="dialog-info" --app-name="WinApps" --urgency="low" "WinApps" "Waiting for Windows to be ready..." + + while (( WAIT_ELAPSED < MAX_WAIT_TIME )); do + # Check if container is running + if [[ $("$WAFLAVOR" inspect --format='{{.State.Status}}' "$CONTAINER_NAME") == "running" ]]; then + # Try to connect to RDP port to verify it's ready + if timeout 1 bash -c ">/dev/tcp/$RDP_IP/$RDP_PORT" 2>/dev/null; then + dprint "CONTAINER IS READY" + notify-send --expire-time=4000 --icon="dialog-info" --app-name="WinApps" --urgency="low" "WinApps" "Windows is ready." + # Add a delay after Windows is ready + if [ "$NEEDED_BOOT" = "true" ]; then + sleep 10 + fi + break + fi + fi + + sleep 5 + WAIT_ELAPSED=$((WAIT_ELAPSED + 5)) + + # Show progress every 30 seconds + if (( WAIT_ELAPSED % 30 == 0 )); then + notify-send --expire-time=4000 --icon="dialog-info" --app-name="WinApps" --urgency="low" "WinApps" "Still waiting for Windows to be ready... ($((WAIT_ELAPSED/60)) minutes elapsed)" + fi + done + + # If we timed out waiting for the container + if (( WAIT_ELAPSED >= MAX_WAIT_TIME )); then + dprint "TIMEOUT WAITING FOR CONTAINER TO BE READY" + notify-send --expire-time=4000 --icon="dialog-info" --app-name="WinApps" --urgency="low" "WinApps" "Timeout waiting for Windows to be ready. Please try again." + waThrowExit $EC_FAIL_START + fi + fi } # Name: 'waCheckPortOpen' @@ -698,7 +742,12 @@ else fi waCheckPortOpen -waRunCommand "$@" +if [ "$NEEDED_BOOT" = "true" ]; then + sleep 10 + waRunCommand "$@" +else + waRunCommand "$@" +fi if [[ "$AUTOPAUSE" == "on" ]]; then waCheckIdle From 8b8e50aeaf47f3bd3a08a32a44fc69b8f04a3934 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 20 Jun 2025 10:14:57 +0000 Subject: [PATCH 2/9] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- bin/winapps | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bin/winapps b/bin/winapps index 69e15fc..c4815ca 100755 --- a/bin/winapps +++ b/bin/winapps @@ -481,7 +481,7 @@ function waCheckContainerRunning() { if [[ "$CONTAINER_STATE" == "created" || "$CONTAINER_STATE" == "exited" || "$CONTAINER_STATE" == "dead" ]]; then dprint "WAITING FOR CONTAINER TO BE FULLY READY..." notify-send --expire-time=4000 --icon="dialog-info" --app-name="WinApps" --urgency="low" "WinApps" "Waiting for Windows to be ready..." - + while (( WAIT_ELAPSED < MAX_WAIT_TIME )); do # Check if container is running if [[ $("$WAFLAVOR" inspect --format='{{.State.Status}}' "$CONTAINER_NAME") == "running" ]]; then @@ -496,16 +496,16 @@ function waCheckContainerRunning() { break fi fi - + sleep 5 WAIT_ELAPSED=$((WAIT_ELAPSED + 5)) - + # Show progress every 30 seconds if (( WAIT_ELAPSED % 30 == 0 )); then notify-send --expire-time=4000 --icon="dialog-info" --app-name="WinApps" --urgency="low" "WinApps" "Still waiting for Windows to be ready... ($((WAIT_ELAPSED/60)) minutes elapsed)" fi done - + # If we timed out waiting for the container if (( WAIT_ELAPSED >= MAX_WAIT_TIME )); then dprint "TIMEOUT WAITING FOR CONTAINER TO BE READY" From 3e84f5efdfb154143d34d0db41af072ac5b9171a Mon Sep 17 00:00:00 2001 From: eylenburg <84839316+eylenburg@users.noreply.github.com> Date: Mon, 23 Jun 2025 12:16:44 +0100 Subject: [PATCH 3/9] Update winapps --- bin/winapps | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/bin/winapps b/bin/winapps index 966b6c4..860f456 100755 --- a/bin/winapps +++ b/bin/winapps @@ -50,6 +50,7 @@ RDP_SCALE=100 AUTOPAUSE="off" AUTOPAUSE_TIME="300" DEBUG="true" +BOOT_MAX_WAIT_TIME=120 # OTHER FREERDP_PID=-1 @@ -408,7 +409,6 @@ function waCheckContainerRunning() { local TIME_ELAPSED=0 local TIME_LIMIT=60 local TIME_INTERVAL=5 - local MAX_WAIT_TIME=120 local WAIT_ELAPSED=0 # Determine the state of the container. @@ -477,7 +477,7 @@ function waCheckContainerRunning() { dprint "WAITING FOR CONTAINER TO BE FULLY READY..." notify-send --expire-time=4000 --icon="dialog-info" --app-name="WinApps" --urgency="low" "WinApps" "Waiting for Windows to be ready..." - while (( WAIT_ELAPSED < MAX_WAIT_TIME )); do + while (( WAIT_ELAPSED < BOOT_MAX_WAIT_TIME )); do # Check if container is running if [[ $("$WAFLAVOR" inspect --format='{{.State.Status}}' "$CONTAINER_NAME") == "running" ]]; then # Try to connect to RDP port to verify it's ready @@ -502,7 +502,7 @@ function waCheckContainerRunning() { done # If we timed out waiting for the container - if (( WAIT_ELAPSED >= MAX_WAIT_TIME )); then + if (( WAIT_ELAPSED >= BOOT_MAX_WAIT_TIME )); then dprint "TIMEOUT WAITING FOR CONTAINER TO BE READY" notify-send --expire-time=4000 --icon="dialog-info" --app-name="WinApps" --urgency="low" "WinApps" "Timeout waiting for Windows to be ready. Please try again." waThrowExit $EC_FAIL_START @@ -719,12 +719,7 @@ else fi waCheckPortOpen -if [ "$NEEDED_BOOT" = "true" ]; then - sleep 10 - waRunCommand "$@" -else - waRunCommand "$@" -fi +waRunCommand "$@" if [[ "$AUTOPAUSE" == "on" ]]; then waCheckIdle From 8ea5c2e07998f8d0b2cf34409d0907138fc5d66e Mon Sep 17 00:00:00 2001 From: eylenburg <84839316+eylenburg@users.noreply.github.com> Date: Mon, 23 Jun 2025 12:18:10 +0100 Subject: [PATCH 4/9] Update winapps --- bin/winapps | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/winapps b/bin/winapps index 860f456..d6667a4 100755 --- a/bin/winapps +++ b/bin/winapps @@ -50,7 +50,7 @@ RDP_SCALE=100 AUTOPAUSE="off" AUTOPAUSE_TIME="300" DEBUG="true" -BOOT_MAX_WAIT_TIME=120 +BOOT_TIMEOUT=120 # OTHER FREERDP_PID=-1 @@ -477,7 +477,7 @@ function waCheckContainerRunning() { dprint "WAITING FOR CONTAINER TO BE FULLY READY..." notify-send --expire-time=4000 --icon="dialog-info" --app-name="WinApps" --urgency="low" "WinApps" "Waiting for Windows to be ready..." - while (( WAIT_ELAPSED < BOOT_MAX_WAIT_TIME )); do + while (( WAIT_ELAPSED < BOOT_TIMEOUT )); do # Check if container is running if [[ $("$WAFLAVOR" inspect --format='{{.State.Status}}' "$CONTAINER_NAME") == "running" ]]; then # Try to connect to RDP port to verify it's ready @@ -502,7 +502,7 @@ function waCheckContainerRunning() { done # If we timed out waiting for the container - if (( WAIT_ELAPSED >= BOOT_MAX_WAIT_TIME )); then + if (( WAIT_ELAPSED >= BOOT_TIMEOUT )); then dprint "TIMEOUT WAITING FOR CONTAINER TO BE READY" notify-send --expire-time=4000 --icon="dialog-info" --app-name="WinApps" --urgency="low" "WinApps" "Timeout waiting for Windows to be ready. Please try again." waThrowExit $EC_FAIL_START From 17a511230c1a2473d06b486d5020acab001f36fa Mon Sep 17 00:00:00 2001 From: eylenburg <84839316+eylenburg@users.noreply.github.com> Date: Mon, 23 Jun 2025 12:19:56 +0100 Subject: [PATCH 5/9] Update README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index b7ed96b..89e4188 100644 --- a/README.md +++ b/README.md @@ -469,6 +469,12 @@ RDP_TIMEOUT="30" # DEFAULT VALUE: '60' APP_SCAN_TIMEOUT="60" +# WINDOWS BOOT +# - The maximum time (in seconds) to wait for the Windows VM to boot if it is not running, before attempting to launch an application. +# - Only relevant for Docker and Podman containers. +# DEFAULT VALUE: '120' +BOOT_TIMEOUT="120" + ``` > [!IMPORTANT] From d250907a3c23ccada42045b3c7ea4424ae23a4fc Mon Sep 17 00:00:00 2001 From: eylenburg <84839316+eylenburg@users.noreply.github.com> Date: Wed, 2 Jul 2025 13:54:45 +0100 Subject: [PATCH 6/9] Update winapps --- bin/winapps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/winapps b/bin/winapps index d6667a4..5003696 100755 --- a/bin/winapps +++ b/bin/winapps @@ -473,7 +473,7 @@ function waCheckContainerRunning() { [ "$EXIT_STATUS" -ne 0 ] && waThrowExit "$EXIT_STATUS" # Wait for container to be fully ready - if [[ "$CONTAINER_STATE" == "created" || "$CONTAINER_STATE" == "exited" || "$CONTAINER_STATE" == "dead" ]]; then + if [[ "$CONTAINER_STATE" == "created" || "$CONTAINER_STATE" == "exited" || "$CONTAINER_STATE" == "dead" || "$CONTAINER_STATE" == "restarting" ]]; then dprint "WAITING FOR CONTAINER TO BE FULLY READY..." notify-send --expire-time=4000 --icon="dialog-info" --app-name="WinApps" --urgency="low" "WinApps" "Waiting for Windows to be ready..." From abf4c7ae6622ae961c656f49bb4cd8a345b95b30 Mon Sep 17 00:00:00 2001 From: eylenburg <84839316+eylenburg@users.noreply.github.com> Date: Wed, 2 Jul 2025 14:02:43 +0100 Subject: [PATCH 7/9] Update winapps --- bin/winapps | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/bin/winapps b/bin/winapps index 5003696..ee5645f 100755 --- a/bin/winapps +++ b/bin/winapps @@ -409,7 +409,6 @@ function waCheckContainerRunning() { local TIME_ELAPSED=0 local TIME_LIMIT=60 local TIME_INTERVAL=5 - local WAIT_ELAPSED=0 # Determine the state of the container. CONTAINER_STATE=$("$WAFLAVOR" inspect --format='{{.State.Status}}' "$CONTAINER_NAME") @@ -477,7 +476,9 @@ function waCheckContainerRunning() { dprint "WAITING FOR CONTAINER TO BE FULLY READY..." notify-send --expire-time=4000 --icon="dialog-info" --app-name="WinApps" --urgency="low" "WinApps" "Waiting for Windows to be ready..." - while (( WAIT_ELAPSED < BOOT_TIMEOUT )); do + TIME_ELAPSED=0 + + while (( TIME_ELAPSED < BOOT_TIMEOUT )); do # Check if container is running if [[ $("$WAFLAVOR" inspect --format='{{.State.Status}}' "$CONTAINER_NAME") == "running" ]]; then # Try to connect to RDP port to verify it's ready @@ -493,16 +494,16 @@ function waCheckContainerRunning() { fi sleep 5 - WAIT_ELAPSED=$((WAIT_ELAPSED + 5)) + TIME_ELAPSED=$((TIME_ELAPSED + 5)) # Show progress every 30 seconds - if (( WAIT_ELAPSED % 30 == 0 )); then - notify-send --expire-time=4000 --icon="dialog-info" --app-name="WinApps" --urgency="low" "WinApps" "Still waiting for Windows to be ready... ($((WAIT_ELAPSED/60)) minutes elapsed)" + if (( TIME_ELAPSED % 30 == 0 )); then + notify-send --expire-time=4000 --icon="dialog-info" --app-name="WinApps" --urgency="low" "WinApps" "Still waiting for Windows to be ready... ($TIME_ELAPSED seconds elapsed)" fi done # If we timed out waiting for the container - if (( WAIT_ELAPSED >= BOOT_TIMEOUT )); then + if (( TIME_ELAPSED >= BOOT_TIMEOUT )); then dprint "TIMEOUT WAITING FOR CONTAINER TO BE READY" notify-send --expire-time=4000 --icon="dialog-info" --app-name="WinApps" --urgency="low" "WinApps" "Timeout waiting for Windows to be ready. Please try again." waThrowExit $EC_FAIL_START From ee967296a62f55a0e857f947763af0663fed46bf Mon Sep 17 00:00:00 2001 From: eylenburg <84839316+eylenburg@users.noreply.github.com> Date: Wed, 2 Jul 2025 14:37:13 +0100 Subject: [PATCH 8/9] Update winapps --- bin/winapps | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/bin/winapps b/bin/winapps index ee5645f..f7a5c0e 100755 --- a/bin/winapps +++ b/bin/winapps @@ -325,6 +325,7 @@ function waCheckVMRunning() { if (virsh list --state-shutoff --name | xargs | grep -wq "$VM_NAME"); then dprint "WINDOWS SHUT OFF. BOOTING WINDOWS." notify-send --expire-time=4000 --icon="dialog-info" --app-name="WinApps" --urgency="low" "WinApps" "Booting Windows." + NEEDED_BOOT=true virsh start "$VM_NAME" &>/dev/null || EXIT_STATUS=$EC_FAIL_START if (virsh list --state-paused --name | xargs | grep -wq "$VM_NAME"); then dprint "WINDOWS PAUSED. RESUMING WINDOWS." @@ -346,6 +347,7 @@ function waCheckVMRunning() { dprint "WINDOWS SHUT OFF. BOOTING WINDOWS." notify-send --expire-time=4000 --icon="dialog-info" --app-name="WinApps" --urgency="low" "WinApps" "Booting Windows." virsh start "$VM_NAME" &>/dev/null || EXIT_STATUS=$EC_FAIL_START + NEEDED_BOOT=true break fi sleep $TIME_INTERVAL @@ -359,6 +361,7 @@ function waCheckVMRunning() { dprint "WINDOWS DESTROYED. BOOTING WINDOWS." notify-send --expire-time=4000 --icon="dialog-info" --app-name="WinApps" --urgency="low" "WinApps" "Booting Windows." virsh start "$VM_NAME" &>/dev/null || EXIT_STATUS=$EC_FAIL_START + NEEDED_BOOT=true fi elif (virsh domstate "$VM_NAME" | xargs | grep -wq "dying"); then dprint "WINDOWS DYING. WAITING." @@ -374,6 +377,7 @@ function waCheckVMRunning() { dprint "WINDOWS DESTROYED. BOOTING WINDOWS." notify-send --expire-time=4000 --icon="dialog-info" --app-name="WinApps" --urgency="low" "WinApps" "Booting Windows." virsh start "$VM_NAME" &>/dev/null || EXIT_STATUS=$EC_FAIL_START + NEEDED_BOOT=true fi break elif (virsh list --state-shutoff --name | xargs | grep -wq "$VM_NAME"); then @@ -381,6 +385,7 @@ function waCheckVMRunning() { dprint "WINDOWS SHUT OFF. BOOTING WINDOWS." notify-send --expire-time=4000 --icon="dialog-info" --app-name="WinApps" --urgency="low" "WinApps" "Booting Windows." virsh start "$VM_NAME" &>/dev/null || EXIT_STATUS=$EC_FAIL_START + NEEDED_BOOT=true break fi sleep $TIME_INTERVAL @@ -397,6 +402,45 @@ function waCheckVMRunning() { # Handle non-zero exit statuses. [ "$EXIT_STATUS" -ne 0 ] && waThrowExit "$EXIT_STATUS" + + # Wait for VM to be fully ready + if [[ "$NEEDED_BOOT" == "true" ]]; then + dprint "WAITING FOR VM TO BE FULLY READY..." + notify-send --expire-time=4000 --icon="dialog-info" --app-name="WinApps" --urgency="low" "WinApps" "Waiting for Windows to be ready..." + + TIME_ELAPSED=0 + + while (( TIME_ELAPSED < BOOT_TIMEOUT )); do + # Check if VM is running + if (virsh list --state-running --name | xargs | grep -wq "$VM_NAME"); then + # Try to connect to RDP port to verify it's ready + if timeout 1 bash -c ">/dev/tcp/$RDP_IP/$RDP_PORT" 2>/dev/null; then + dprint "VM IS READY" + notify-send --expire-time=4000 --icon="dialog-info" --app-name="WinApps" --urgency="low" "WinApps" "Windows is ready." + # Add a delay after Windows is ready + if [ "$NEEDED_BOOT" = "true" ]; then + sleep 10 + fi + break + fi + fi + + sleep 5 + TIME_ELAPSED=$((TIME_ELAPSED + 5)) + + # Show progress every 30 seconds + if (( TIME_ELAPSED % 30 == 0 )); then + notify-send --expire-time=4000 --icon="dialog-info" --app-name="WinApps" --urgency="low" "WinApps" "Still waiting for Windows to be ready... ($TIME_ELAPSED seconds elapsed)" + fi + done + + # If we timed out waiting for the VM + if (( TIME_ELAPSED >= BOOT_TIMEOUT )); then + dprint "TIMEOUT WAITING FOR VM TO BE READY" + notify-send --expire-time=4000 --icon="dialog-info" --app-name="WinApps" --urgency="low" "WinApps" "Timeout waiting for Windows to be ready. Please try again." + waThrowExit $EC_FAIL_START + fi + fi } # Name: 'waCheckContainerRunning' From 8e0ef40b1f5794ab88d0f656817081ac691aa616 Mon Sep 17 00:00:00 2001 From: eylenburg <84839316+eylenburg@users.noreply.github.com> Date: Tue, 22 Jul 2025 14:32:12 +0100 Subject: [PATCH 9/9] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 3eb3b97..431518c 100644 --- a/README.md +++ b/README.md @@ -471,7 +471,6 @@ APP_SCAN_TIMEOUT="60" # WINDOWS BOOT # - The maximum time (in seconds) to wait for the Windows VM to boot if it is not running, before attempting to launch an application. -# - Only relevant for Docker and Podman containers. # DEFAULT VALUE: '120' BOOT_TIMEOUT="120"