Created
May 25, 2025 18:16
-
-
Save Lucho00Cuba/156c9234175db6bcabc553e518f0fc0f to your computer and use it in GitHub Desktop.
PowerShell CLI to manage vmrest.exe as a background process with PID tracking and port proxy via netsh.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.SYNOPSIS | |
CLI utility to manage vmrest.exe as a background process without Windows service. | |
.DESCRIPTION | |
This script starts vmrest.exe in the background, tracks its PID, and sets up a port proxy | |
to expose the localhost-only API to the network using netsh. It supports start, stop, status, | |
and interactive config execution. Requires administrator privileges for portproxy. | |
.AUTHOR | |
Lucho00Cuba ([email protected]) | |
#> | |
param ( | |
[string]$Action, | |
[switch]$Help | |
) | |
function Show-Help { | |
@" | |
VMRest CLI - Manage vmrest.exe without a Windows service | |
Usage: | |
vmrest-cli.ps1 -Action <start|stop|status|config> [--help] | |
Actions: | |
start Launch vmrest.exe in background and save PID to vmrest.pid | |
stop Stop the running vmrest.exe process using the saved PID and remove proxy rule | |
status Check if vmrest.exe is running using the saved PID | |
config Launch vmrest.exe in a new PowerShell window (interactive) | |
--help Show this help message | |
"@ | Write-Output | |
} | |
function Check-AdminPrivileges { | |
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator") | |
if (-not $isAdmin) { | |
Write-Error "This script requires administrator privileges to manage portproxy rules." | |
exit 1 | |
} | |
} | |
if ($Help -or (-not $Action)) { | |
Show-Help | |
exit 0 | |
} | |
$validActions = @("start", "stop", "status", "config") | |
if (-not $validActions -contains $Action.ToLower()) { | |
Write-Error "Invalid action '$Action'." | |
Show-Help | |
exit 1 | |
} | |
$vmrestExePath = "C:\Program Files (x86)\VMware\VMware Workstation\vmrest.exe" | |
$vmrestCfg = "$env:USERPROFILE\vmrest.cfg" | |
$pidFile = "$env:USERPROFILE\vmrest.pid" | |
$proxyListenPort = 3001 | |
$vmrestPort = 3000 | |
function Test-PortListening($port) { | |
return (Get-NetTCPConnection -LocalAddress 127.0.0.1 -LocalPort $port -State Listen -ErrorAction SilentlyContinue) -ne $null | |
} | |
function Start-VMRest { | |
Check-AdminPrivileges | |
if (-not (Test-Path $vmrestCfg)) { | |
Write-Warning "Missing required configuration file: $vmrestCfg" | |
exit 1 | |
} | |
if (-not (Test-Path $vmrestExePath)) { | |
Write-Error "vmrest.exe not found at: $vmrestExePath" | |
exit 1 | |
} | |
if (Test-Path $pidFile) { | |
Write-Warning "PID file already exists. Is vmrest already running? Use -Action status or stop." | |
exit 1 | |
} | |
$proc = Start-Process -FilePath $vmrestExePath -ArgumentList "-p", "$vmrestPort" -WindowStyle Hidden -PassThru | |
$proc.Id | Out-File $pidFile -Encoding ascii | |
Write-Host "VMRest started in background with PID $($proc.Id) on port $vmrestPort" | |
Start-Sleep -Seconds 2 | |
if (-not (Test-PortListening -port $vmrestPort)) { | |
Write-Warning "vmrest is not listening on port $vmrestPort. Skipping proxy rule creation." | |
return | |
} | |
Write-Host "Creating port proxy from 0.0.0.0:$proxyListenPort to 127.0.0.1:$vmrestPort" | |
$existing = netsh interface portproxy show v4tov4 | Select-String ":$proxyListenPort\s+0.0.0.0" | |
if (-not $existing) { | |
netsh interface portproxy add v4tov4 listenport=$proxyListenPort listenaddress=0.0.0.0 connectport=$vmrestPort connectaddress=127.0.0.1 | Out-Null | |
} else { | |
Write-Host "Proxy rule already exists." | |
} | |
} | |
function Stop-VMRest { | |
Check-AdminPrivileges | |
if (-not (Test-Path $pidFile)) { | |
Write-Warning "PID file not found. Is vmrest running?" | |
exit 1 | |
} | |
$vmrestPid = Get-Content $pidFile | Select-Object -First 1 | |
try { | |
Stop-Process -Id $vmrestPid -Force | |
Write-Host "VMRest process with PID $vmrestPid stopped." | |
} catch { | |
Write-Warning "Failed to stop process with PID $vmrestPid. It may not be running." | |
} | |
Remove-Item $pidFile -Force | |
Write-Host "Removing port proxy rule for port $proxyListenPort" | |
$existing = netsh interface portproxy show v4tov4 | Select-String ":$proxyListenPort\s+0.0.0.0" | |
if ($existing) { | |
netsh interface portproxy delete v4tov4 listenport=$proxyListenPort listenaddress=0.0.0.0 | Out-Null | |
} else { | |
Write-Host "No proxy rule to remove." | |
} | |
} | |
function Status-VMRest { | |
if (-not (Test-Path $pidFile)) { | |
Write-Host "VMRest is not running." | |
exit 0 | |
} | |
$vmrestPid = Get-Content $pidFile | Select-Object -First 1 | |
$proc = Get-Process -Id $vmrestPid -ErrorAction SilentlyContinue | |
if ($proc) { | |
Write-Host "VMRest is running with PID $vmrestPid." | |
} else { | |
Write-Warning "PID file exists but no running process found with PID $vmrestPid." | |
} | |
} | |
function Config-VMRest { | |
if (-not (Test-Path $vmrestCfg)) { | |
Write-Warning "Missing required configuration file: $vmrestCfg" | |
exit 1 | |
} | |
if (-not (Test-Path $vmrestExePath)) { | |
Write-Error "VMRest executable not found at: $vmrestExePath" | |
exit 1 | |
} | |
Write-Host "Launching VMRest in a new PowerShell window..." | |
$exe = "`"$vmrestExePath`"" | |
$cfg = "`"$vmrestCfg`"" | |
$command = "& '$exe' -C $cfg; Write-Host ''; Read-Host 'Press Enter to close this window...'" | |
Start-Process -FilePath "powershell.exe" -ArgumentList "-Command", $command | |
} | |
switch ($Action.ToLower()) { | |
"start" { Start-VMRest } | |
"stop" { Stop-VMRest } | |
"status" { Status-VMRest } | |
"config" { Config-VMRest } | |
default { | |
Show-Help | |
exit 1 | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment