Skip to content

Instantly share code, notes, and snippets.

@Lucho00Cuba
Created May 25, 2025 18:16
Show Gist options
  • Save Lucho00Cuba/156c9234175db6bcabc553e518f0fc0f to your computer and use it in GitHub Desktop.
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.
<#
.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