From 15b4176afba8ad10284033cd6841b14b1df3c91a Mon Sep 17 00:00:00 2001 From: root Date: Sat, 6 Dec 2025 04:34:47 +0000 Subject: [PATCH 1/4] =?UTF-8?q?=E6=94=AF=E6=8C=81window?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/release.yml | 13 +++- README.md | 27 ++++++++ README_CN.md | 27 ++++++++ codex-wrapper/main.go | 31 ++++++--- install.bat | 114 ++++++++++++++++++++++++++++++++++ install.ps1 | 66 ++++++++++++++++++++ 6 files changed, 268 insertions(+), 10 deletions(-) create mode 100644 install.bat create mode 100644 install.ps1 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 262f01b..f767e65 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -47,6 +47,10 @@ jobs: goarch: amd64 - goos: darwin goarch: arm64 + - goos: windows + goarch: amd64 + - goos: windows + goarch: arm64 steps: - name: Checkout code @@ -58,6 +62,7 @@ jobs: go-version: '1.21' - name: Build binary + id: build working-directory: codex-wrapper env: GOOS: ${{ matrix.goos }} @@ -66,14 +71,18 @@ jobs: run: | VERSION=${GITHUB_REF#refs/tags/} OUTPUT_NAME=codex-wrapper-${{ matrix.goos }}-${{ matrix.goarch }} + if [ "${{ matrix.goos }}" = "windows" ]; then + OUTPUT_NAME="${OUTPUT_NAME}.exe" + fi go build -ldflags="-s -w -X main.version=${VERSION}" -o ${OUTPUT_NAME} . chmod +x ${OUTPUT_NAME} + echo "artifact_path=codex-wrapper/${OUTPUT_NAME}" >> $GITHUB_OUTPUT - name: Upload artifact uses: actions/upload-artifact@v4 with: name: codex-wrapper-${{ matrix.goos }}-${{ matrix.goarch }} - path: codex-wrapper/codex-wrapper-${{ matrix.goos }}-${{ matrix.goarch }} + path: ${{ steps.build.outputs.artifact_path }} release: name: Create Release @@ -92,7 +101,7 @@ jobs: run: | mkdir -p release find artifacts -type f -name "codex-wrapper-*" -exec mv {} release/ \; - cp install.sh release/ + cp install.sh install.ps1 install.bat release/ ls -la release/ - name: Create Release diff --git a/README.md b/README.md index 8ad17f6..417a8d8 100644 --- a/README.md +++ b/README.md @@ -238,6 +238,33 @@ python3 install.py --module dev bash install.sh ``` +#### Windows + +Windows installs place `codex-wrapper.exe` in `%USERPROFILE%\bin`. + +```powershell +# PowerShell (recommended) +powershell -ExecutionPolicy Bypass -File install.ps1 + +# Batch (cmd) +install.bat +``` + +**Add to PATH** (if installer doesn't detect it): + +```powershell +# PowerShell - persistent for current user +[Environment]::SetEnvironmentVariable('PATH', "$HOME\bin;" + [Environment]::GetEnvironmentVariable('PATH','User'), 'User') + +# PowerShell - current session only +$Env:PATH = "$HOME\bin;$Env:PATH" +``` + +```batch +REM cmd.exe - persistent for current user +setx PATH "%USERPROFILE%\bin;%PATH%" +``` + --- ## Workflow Selection Guide diff --git a/README_CN.md b/README_CN.md index 1196fe0..961fb70 100644 --- a/README_CN.md +++ b/README_CN.md @@ -235,6 +235,33 @@ python3 install.py --module dev bash install.sh ``` +#### Windows 系统 + +Windows 系统会将 `codex-wrapper.exe` 安装到 `%USERPROFILE%\bin`。 + +```powershell +# PowerShell(推荐) +powershell -ExecutionPolicy Bypass -File install.ps1 + +# 批处理(cmd) +install.bat +``` + +**添加到 PATH**(如果安装程序未自动检测): + +```powershell +# PowerShell - 永久添加(当前用户) +[Environment]::SetEnvironmentVariable('PATH', "$HOME\bin;" + [Environment]::GetEnvironmentVariable('PATH','User'), 'User') + +# PowerShell - 仅当前会话 +$Env:PATH = "$HOME\bin;$Env:PATH" +``` + +```batch +REM cmd.exe - 永久添加(当前用户) +setx PATH "%USERPROFILE%\bin;%PATH%" +``` + --- ## 工作流选择指南 diff --git a/codex-wrapper/main.go b/codex-wrapper/main.go index 5edee6f..920191e 100644 --- a/codex-wrapper/main.go +++ b/codex-wrapper/main.go @@ -11,6 +11,7 @@ import ( "os" "os/exec" "os/signal" + "runtime" "sort" "strconv" "strings" @@ -925,21 +926,30 @@ func (b *tailBuffer) String() string { func forwardSignals(ctx context.Context, cmd *exec.Cmd, logErrorFn func(string)) { sigCh := make(chan os.Signal, 1) - signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM) + signals := []os.Signal{syscall.SIGINT} + if runtime.GOOS != "windows" { + signals = append(signals, syscall.SIGTERM) + } + signal.Notify(sigCh, signals...) go func() { defer signal.Stop(sigCh) select { case sig := <-sigCh: logErrorFn(fmt.Sprintf("Received signal: %v", sig)) - if cmd.Process != nil { - cmd.Process.Signal(syscall.SIGTERM) - time.AfterFunc(time.Duration(forceKillDelay)*time.Second, func() { - if cmd.Process != nil { - cmd.Process.Kill() - } - }) + if cmd.Process == nil { + return } + if runtime.GOOS == "windows" { + _ = cmd.Process.Kill() + return + } + _ = cmd.Process.Signal(syscall.SIGTERM) + time.AfterFunc(time.Duration(forceKillDelay)*time.Second, func() { + if cmd.Process != nil { + _ = cmd.Process.Kill() + } + }) case <-ctx.Done(): } }() @@ -962,6 +972,11 @@ func terminateProcess(cmd *exec.Cmd) *time.Timer { return nil } + if runtime.GOOS == "windows" { + _ = cmd.Process.Kill() + return nil + } + _ = cmd.Process.Signal(syscall.SIGTERM) return time.AfterFunc(time.Duration(forceKillDelay)*time.Second, func() { diff --git a/install.bat b/install.bat new file mode 100644 index 0000000..0f3f888 --- /dev/null +++ b/install.bat @@ -0,0 +1,114 @@ +@echo off +setlocal enabledelayedexpansion + +set "EXIT_CODE=0" +set "REPO=cexll/myclaude" +set "VERSION=latest" +set "OS=windows" + +call :detect_arch +if errorlevel 1 goto :fail + +set "BINARY_NAME=codex-wrapper-%OS%-%ARCH%.exe" +set "URL=https://github.com/%REPO%/releases/%VERSION%/download/%BINARY_NAME%" +set "TEMP_FILE=%TEMP%\codex-wrapper-%ARCH%-%RANDOM%.exe" +set "DEST_DIR=%USERPROFILE%\bin" +set "DEST=%DEST_DIR%\codex-wrapper.exe" + +echo Downloading codex-wrapper for %ARCH% ... +echo %URL% +call :download +if errorlevel 1 goto :fail + +if not exist "%TEMP_FILE%" ( + echo ERROR: download failed to produce "%TEMP_FILE%". + goto :fail +) + +echo Installing to "%DEST%" ... +if not exist "%DEST_DIR%" ( + mkdir "%DEST_DIR%" >nul 2>nul || goto :fail +) + +move /y "%TEMP_FILE%" "%DEST%" >nul 2>nul +if errorlevel 1 ( + echo ERROR: unable to place file in "%DEST%". + goto :fail +) + +"%DEST%" --version >nul 2>nul +if errorlevel 1 ( + echo ERROR: installation verification failed. + goto :fail +) + +echo. +echo codex-wrapper installed successfully at: +echo %DEST% + +set "PATH_CHECK=;%PATH%;" +echo !PATH_CHECK! | findstr /I /C:";%DEST_DIR%;" >nul +if errorlevel 1 ( + echo. + echo %DEST_DIR% is not in your PATH. + echo Add it for the current user with: + echo setx PATH "%%USERPROFILE%%\bin;%%PATH%%" + echo Then restart your terminal to use codex-wrapper globally. +) + +goto :cleanup + +:detect_arch +set "ARCH=%PROCESSOR_ARCHITECTURE%" +if defined PROCESSOR_ARCHITEW6432 set "ARCH=%PROCESSOR_ARCHITEW6432%" + +if /I "%ARCH%"=="AMD64" ( + set "ARCH=amd64" + exit /b 0 +) else if /I "%ARCH%"=="ARM64" ( + set "ARCH=arm64" + exit /b 0 +) else ( + echo ERROR: unsupported architecture "%ARCH%". 64-bit Windows on AMD64 or ARM64 is required. + set "EXIT_CODE=1" + exit /b 1 +) + +:download +where curl >nul 2>nul +if %errorlevel%==0 ( + echo Using curl ... + curl -fL --retry 3 --connect-timeout 10 "%URL%" -o "%TEMP_FILE%" + if errorlevel 1 ( + echo ERROR: curl download failed. + set "EXIT_CODE=1" + exit /b 1 + ) + exit /b 0 +) + +where powershell >nul 2>nul +if %errorlevel%==0 ( + echo Using PowerShell ... + powershell -NoLogo -NoProfile -Command " $ErrorActionPreference='Stop'; try { [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor 3072 -bor 768 -bor 192 } catch {} ; $wc = New-Object System.Net.WebClient; $wc.DownloadFile('%URL%','%TEMP_FILE%') " + if errorlevel 1 ( + echo ERROR: PowerShell download failed. + set "EXIT_CODE=1" + exit /b 1 + ) + exit /b 0 +) + +echo ERROR: neither curl nor PowerShell is available to download the installer. +set "EXIT_CODE=1" +exit /b 1 + +:fail +echo Installation failed. +set "EXIT_CODE=1" +goto :cleanup + +:cleanup +if exist "%TEMP_FILE%" del /f /q "%TEMP_FILE%" >nul 2>nul +set "CODE=%EXIT_CODE%" +endlocal & exit /b %CODE% diff --git a/install.ps1 b/install.ps1 new file mode 100644 index 0000000..9bc488d --- /dev/null +++ b/install.ps1 @@ -0,0 +1,66 @@ +[CmdletBinding()] +param() + +$ErrorActionPreference = 'Stop' +$ProgressPreference = 'Continue' +$tempFile = $null + +function Get-Architecture { + $arch = if ($env:PROCESSOR_ARCHITEW6432) { $env:PROCESSOR_ARCHITEW6432 } else { $env:PROCESSOR_ARCHITECTURE } + switch ($arch.ToLower()) { + 'amd64' { 'amd64' } + 'x86' { throw 'Unsupported architecture: x86 (64-bit Windows is required).' } + 'arm64' { 'arm64' } + 'aarch64' { 'arm64' } + default { throw "Unsupported architecture: $arch" } + } +} + +function Write-Step { + param([string] $Status, [int] $Percent) + Write-Progress -Activity 'Installing codex-wrapper' -Status $Status -PercentComplete $Percent + Write-Host $Status +} + +try { + Write-Step 'Detecting CPU architecture...' 5 + $arch = Get-Architecture + $url = "https://github.com/cexll/myclaude/releases/latest/download/codex-wrapper-windows-$arch.exe" + + $tempFile = Join-Path ([IO.Path]::GetTempPath()) "codex-wrapper-$arch.exe" + $homeBin = Join-Path $HOME 'bin' + $destination = Join-Path $homeBin 'codex-wrapper.exe' + + [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12 + + Write-Step "Downloading codex-wrapper from $url ..." 25 + Invoke-WebRequest -Uri $url -OutFile $tempFile -UseBasicParsing -ErrorAction Stop + + Write-Step "Installing to $destination ..." 65 + New-Item -ItemType Directory -Path $homeBin -Force | Out-Null + Move-Item -LiteralPath $tempFile -Destination $destination -Force + + Write-Step 'Verifying installation...' 90 + & $destination --version | Out-Null + + Write-Step 'codex-wrapper installed successfully.' 100 + Write-Progress -Activity 'Installing codex-wrapper' -Completed -Status 'Done' + Write-Host "Installed to $destination" + + $normalizedBin = ($homeBin.TrimEnd('\') -replace '/','\').ToLower() + $pathEntries = ($env:PATH -split ';') | Where-Object { $_ } | ForEach-Object { ($_ -replace '/','\').TrimEnd('\').ToLower() } + if (-not ($pathEntries -contains $normalizedBin)) { + Write-Warning "$homeBin is not in your PATH." + Write-Host 'Add it permanently with:' + Write-Host " [Environment]::SetEnvironmentVariable('PATH', '$homeBin;' + [Environment]::GetEnvironmentVariable('PATH','User'), 'User')" + Write-Host 'Then restart your shell to pick up the updated PATH.' + } +} catch { + Write-Progress -Activity 'Installing codex-wrapper' -Completed -Status 'Failed' + Write-Error "Installation failed: $($_.Exception.Message)" + exit 1 +} finally { + if ($tempFile -and (Test-Path $tempFile)) { + Remove-Item -LiteralPath $tempFile -Force -ErrorAction SilentlyContinue + } +} From 90f9a131fe73937a33802565416fb3bbd5b015bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E6=96=87=E5=BD=AC?= <1473157698@qq.com> Date: Sat, 6 Dec 2025 23:40:24 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E6=94=AF=E6=8C=81windows=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E7=9A=84=E5=AE=89=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- install.ps1 | 66 ----------------------------------------------------- install.py | 2 ++ 2 files changed, 2 insertions(+), 66 deletions(-) delete mode 100644 install.ps1 diff --git a/install.ps1 b/install.ps1 deleted file mode 100644 index 9bc488d..0000000 --- a/install.ps1 +++ /dev/null @@ -1,66 +0,0 @@ -[CmdletBinding()] -param() - -$ErrorActionPreference = 'Stop' -$ProgressPreference = 'Continue' -$tempFile = $null - -function Get-Architecture { - $arch = if ($env:PROCESSOR_ARCHITEW6432) { $env:PROCESSOR_ARCHITEW6432 } else { $env:PROCESSOR_ARCHITECTURE } - switch ($arch.ToLower()) { - 'amd64' { 'amd64' } - 'x86' { throw 'Unsupported architecture: x86 (64-bit Windows is required).' } - 'arm64' { 'arm64' } - 'aarch64' { 'arm64' } - default { throw "Unsupported architecture: $arch" } - } -} - -function Write-Step { - param([string] $Status, [int] $Percent) - Write-Progress -Activity 'Installing codex-wrapper' -Status $Status -PercentComplete $Percent - Write-Host $Status -} - -try { - Write-Step 'Detecting CPU architecture...' 5 - $arch = Get-Architecture - $url = "https://github.com/cexll/myclaude/releases/latest/download/codex-wrapper-windows-$arch.exe" - - $tempFile = Join-Path ([IO.Path]::GetTempPath()) "codex-wrapper-$arch.exe" - $homeBin = Join-Path $HOME 'bin' - $destination = Join-Path $homeBin 'codex-wrapper.exe' - - [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12 - - Write-Step "Downloading codex-wrapper from $url ..." 25 - Invoke-WebRequest -Uri $url -OutFile $tempFile -UseBasicParsing -ErrorAction Stop - - Write-Step "Installing to $destination ..." 65 - New-Item -ItemType Directory -Path $homeBin -Force | Out-Null - Move-Item -LiteralPath $tempFile -Destination $destination -Force - - Write-Step 'Verifying installation...' 90 - & $destination --version | Out-Null - - Write-Step 'codex-wrapper installed successfully.' 100 - Write-Progress -Activity 'Installing codex-wrapper' -Completed -Status 'Done' - Write-Host "Installed to $destination" - - $normalizedBin = ($homeBin.TrimEnd('\') -replace '/','\').ToLower() - $pathEntries = ($env:PATH -split ';') | Where-Object { $_ } | ForEach-Object { ($_ -replace '/','\').TrimEnd('\').ToLower() } - if (-not ($pathEntries -contains $normalizedBin)) { - Write-Warning "$homeBin is not in your PATH." - Write-Host 'Add it permanently with:' - Write-Host " [Environment]::SetEnvironmentVariable('PATH', '$homeBin;' + [Environment]::GetEnvironmentVariable('PATH','User'), 'User')" - Write-Host 'Then restart your shell to pick up the updated PATH.' - } -} catch { - Write-Progress -Activity 'Installing codex-wrapper' -Completed -Status 'Failed' - Write-Error "Installation failed: $($_.Exception.Message)" - exit 1 -} finally { - if ($tempFile -and (Test-Path $tempFile)) { - Remove-Item -LiteralPath $tempFile -Force -ErrorAction SilentlyContinue - } -} diff --git a/install.py b/install.py index 281b06c..65f1a22 100644 --- a/install.py +++ b/install.py @@ -285,6 +285,8 @@ def op_run_command(op: Dict[str, Any], ctx: Dict[str, Any]) -> None: env[key] = value.replace("${install_dir}", str(ctx["install_dir"])) command = op.get("command", "") + if sys.platform == "win32" and command.strip() == "bash install.sh": + command = "cmd /c install.bat" result = subprocess.run( command, shell=True, From 22987b5f741e1ba5f67151f1162713f453963597 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E6=96=87=E5=BD=AC?= <1473157698@qq.com> Date: Sat, 6 Dec 2025 23:47:57 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=89=93=E5=8C=85?= =?UTF-8?q?=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f767e65..3f5ea3f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -101,7 +101,7 @@ jobs: run: | mkdir -p release find artifacts -type f -name "codex-wrapper-*" -exec mv {} release/ \; - cp install.sh install.ps1 install.bat release/ + cp install.sh install.bat release/ ls -la release/ - name: Create Release From 95408e7fa7aa36255ad28a5d69eeafb8029c0348 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E6=96=87=E5=BD=AC?= <1473157698@qq.com> Date: Sun, 7 Dec 2025 01:43:47 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E4=BF=AE=E6=94=B9windows=E5=AE=89=E8=A3=85?= =?UTF-8?q?=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- README_CN.md | 2 +- install.bat | 65 +++++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 59 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 417a8d8..05f47e1 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ This system leverages a **dual-agent architecture**: - Codex excels at focused code generation and execution - Together they provide better results than either alone -## Quick Start +## Quick Start(Please execute in Powershell on Windows) ```bash git clone https://github.com/cexll/myclaude.git diff --git a/README_CN.md b/README_CN.md index 961fb70..0d74d05 100644 --- a/README_CN.md +++ b/README_CN.md @@ -20,7 +20,7 @@ - Codex 擅长专注的代码生成和执行 - 两者结合效果优于单独使用 -## 快速开始 +## 快速开始(windows上请在Powershell中执行) ```bash git clone https://github.com/cexll/myclaude.git diff --git a/install.bat b/install.bat index 0f3f888..3640009 100644 --- a/install.bat +++ b/install.bat @@ -46,15 +46,64 @@ echo. echo codex-wrapper installed successfully at: echo %DEST% -set "PATH_CHECK=;%PATH%;" -echo !PATH_CHECK! | findstr /I /C:";%DEST_DIR%;" >nul -if errorlevel 1 ( - echo. - echo %DEST_DIR% is not in your PATH. - echo Add it for the current user with: - echo setx PATH "%%USERPROFILE%%\bin;%%PATH%%" - echo Then restart your terminal to use codex-wrapper globally. +rem Automatically ensure %USERPROFILE%\bin is in the USER (HKCU) PATH +rem 1) Read current user PATH from registry (REG_SZ or REG_EXPAND_SZ) +set "USER_PATH_RAW=" +set "USER_PATH_TYPE=" +for /f "tokens=1,2,*" %%A in ('reg query "HKCU\Environment" /v Path 2^>nul ^| findstr /I /R "^ *Path *REG_"') do ( + set "USER_PATH_TYPE=%%B" + set "USER_PATH_RAW=%%C" ) +rem Trim leading spaces from USER_PATH_RAW +for /f "tokens=* delims= " %%D in ("!USER_PATH_RAW!") do set "USER_PATH_RAW=%%D" + +rem Normalize DEST_DIR by removing a trailing backslash if present +if "!DEST_DIR:~-1!"=="\" set "DEST_DIR=!DEST_DIR:~0,-1!" + +rem Build search tokens (expanded and literal) +set "PCT=%%" +set "SEARCH_EXP=;!DEST_DIR!;" +set "SEARCH_EXP2=;!DEST_DIR!\;" +set "SEARCH_LIT=;!PCT!USERPROFILE!PCT!\bin;" +set "SEARCH_LIT2=;!PCT!USERPROFILE!PCT!\bin\;" + +rem Prepare user PATH variants for containment tests +set "CHECK_RAW=;!USER_PATH_RAW!;" +set "USER_PATH_EXP=!USER_PATH_RAW!" +if defined USER_PATH_EXP call set "USER_PATH_EXP=%%USER_PATH_EXP%%" +set "CHECK_EXP=;!USER_PATH_EXP!;" + +rem Check if already present in user PATH (literal or expanded, with/without trailing backslash) +set "ALREADY_IN_USERPATH=0" +echo !CHECK_RAW! | findstr /I /C:"!SEARCH_LIT!" /C:"!SEARCH_LIT2!" >nul && set "ALREADY_IN_USERPATH=1" +if "!ALREADY_IN_USERPATH!"=="0" ( + echo !CHECK_EXP! | findstr /I /C:"!SEARCH_EXP!" /C:"!SEARCH_EXP2!" >nul && set "ALREADY_IN_USERPATH=1" +) + +if "!ALREADY_IN_USERPATH!"=="1" ( + echo User PATH already includes %%USERPROFILE%%\bin. +) else ( + rem Not present: append to user PATH using setx without duplicating system PATH + if defined USER_PATH_RAW ( + set "USER_PATH_NEW=!USER_PATH_RAW!" + if not "!USER_PATH_NEW:~-1!"==";" set "USER_PATH_NEW=!USER_PATH_NEW!;" + set "USER_PATH_NEW=!USER_PATH_NEW!!PCT!USERPROFILE!PCT!\bin" + ) else ( + set "USER_PATH_NEW=!PCT!USERPROFILE!PCT!\bin" + ) + rem Persist update to HKCU\Environment\Path (user scope) + setx PATH "!USER_PATH_NEW!" >nul + if errorlevel 1 ( + echo WARNING: Failed to append %%USERPROFILE%%\bin to your user PATH. + ) else ( + echo Added %%USERPROFILE%%\bin to your user PATH. + ) +) + +rem Update current session PATH so codex-wrapper is immediately available +set "CURPATH=;%PATH%;" +echo !CURPATH! | findstr /I /C:"!SEARCH_EXP!" /C:"!SEARCH_EXP2!" /C:"!SEARCH_LIT!" /C:"!SEARCH_LIT2!" >nul +if errorlevel 1 set "PATH=!DEST_DIR!;!PATH!" goto :cleanup