189 lines
7.3 KiB
PowerShell
189 lines
7.3 KiB
PowerShell
# kfzgs-launcher.ps1 - 核价器启动脚本 (便携版)
|
|
# 用法:
|
|
# 协议模式: powershell -File kfzgs-launcher.ps1 -url "kfzgs://launch?dir=..."
|
|
# 服务模式: powershell -File kfzgs-launcher.ps1
|
|
param([string]$url = "")
|
|
|
|
$SERVICE_ID = "kfz-goods-pricing"
|
|
$HTTP_PORT = 5000
|
|
$SCRIPT_DIR = Split-Path $MyInvocation.MyCommand.Path -Parent
|
|
|
|
# 从同目录下的 config.json 读取 exe 路径,没有则用同目录下默认 exe
|
|
$CONFIG_FILE = Join-Path $SCRIPT_DIR "launcher-config.json"
|
|
$DEFAULT_EXE = Join-Path $SCRIPT_DIR "kfz-goods-pricing.exe"
|
|
|
|
function Load-Config {
|
|
if (Test-Path $CONFIG_FILE) {
|
|
try {
|
|
$config = Get-Content $CONFIG_FILE -Raw | ConvertFrom-Json
|
|
if ($config.exe_path) { return $config.exe_path }
|
|
} catch {}
|
|
}
|
|
return $DEFAULT_EXE
|
|
}
|
|
|
|
function Save-Config($exePath) {
|
|
@{ exe_path = $exePath; id = $SERVICE_ID; name = "核价器" } | ConvertTo-Json | Out-File $CONFIG_FILE -Encoding UTF8
|
|
}
|
|
|
|
$EXE_PATH = Load-Config
|
|
|
|
function Parse-KfzgsUrl($rawUrl) {
|
|
$decoded = [System.Uri]::UnescapeDataString($rawUrl)
|
|
$stripped = $decoded -replace "^kfzgs://", ""
|
|
$action = ""
|
|
$params = @{}
|
|
if ($stripped -match "^([^?]+)\?(.*)$") {
|
|
$action = $Matches[1]
|
|
$query = $Matches[2]
|
|
$query -split "&" | ForEach-Object {
|
|
$parts = $_ -split "=", 2
|
|
if ($parts.Count -eq 2) { $params[$parts[0]] = $parts[1] }
|
|
}
|
|
} elseif ($stripped -notmatch "[?]") {
|
|
$action = $stripped
|
|
}
|
|
return @{ action = $action; params = $params }
|
|
}
|
|
|
|
function Invoke-ProtocolHandler($rawUrl) {
|
|
$parsed = Parse-KfzgsUrl $rawUrl
|
|
$p = $parsed.params
|
|
if ($parsed.action -eq "launch") {
|
|
$dir = $p["dir"] -replace "/", "\"
|
|
$exeName = $p["exe"]
|
|
|
|
if ($exeName) {
|
|
if ($dir) {
|
|
if ($dir.EndsWith("\")) { $fullPath = "$dir$exeName" }
|
|
else { $fullPath = "$dir\$exeName" }
|
|
} else {
|
|
$fullPath = Join-Path $SCRIPT_DIR $exeName
|
|
}
|
|
} elseif ($dir -and $dir -match "\.exe$") {
|
|
if (Test-Path $dir) { $fullPath = $dir }
|
|
else { $fullPath = Join-Path $SCRIPT_DIR $dir }
|
|
} else { $fullPath = $EXE_PATH }
|
|
|
|
if ($fullPath -ne $EXE_PATH) {
|
|
Save-Config $fullPath
|
|
$script:EXE_PATH = $fullPath
|
|
}
|
|
|
|
if (Test-Path $fullPath) {
|
|
$parentDir = Split-Path $fullPath -Parent
|
|
Start-Process -FilePath $fullPath -WorkingDirectory $parentDir -WindowStyle Normal
|
|
}
|
|
}
|
|
}
|
|
|
|
function Start-ApiServer {
|
|
$listener = New-Object System.Net.HttpListener
|
|
$listener.Prefixes.Add("http://127.0.0.1:$HTTP_PORT/")
|
|
try { $listener.Start() } catch { exit 1 }
|
|
|
|
$services = @{}
|
|
$services[$SERVICE_ID] = @{
|
|
id = $SERVICE_ID
|
|
name = "核价器"
|
|
exe_path = $EXE_PATH
|
|
running = $false
|
|
}
|
|
|
|
while ($listener.IsListening) {
|
|
$context = $listener.GetContext()
|
|
$request = $context.Request
|
|
$response = $context.Response
|
|
|
|
if ($request.HttpMethod -eq "OPTIONS") {
|
|
$response.AddHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
|
|
$response.AddHeader("Access-Control-Allow-Headers", "Content-Type")
|
|
$response.StatusCode = 204
|
|
$response.Close()
|
|
continue
|
|
}
|
|
|
|
$path = $request.Url.AbsolutePath
|
|
$result = @{ code = 0; msg = "ok" }
|
|
|
|
try {
|
|
if ($path -eq "/api/services") {
|
|
if ($request.HttpMethod -eq "GET") {
|
|
$services[$SERVICE_ID]["exe_path"] = $EXE_PATH
|
|
$result["data"] = @($services.Values)
|
|
} elseif ($request.HttpMethod -eq "POST") {
|
|
$reader = New-Object System.IO.StreamReader($request.InputStream)
|
|
$body = $reader.ReadToEnd() | ConvertFrom-Json
|
|
if ($body.id -and $body.exe_path) {
|
|
$services[$body.id] = @{
|
|
id = $body.id
|
|
name = if ($body.name) { $body.name } else { $body.id }
|
|
exe_path = $body.exe_path
|
|
running = $false
|
|
}
|
|
Save-Config $body.exe_path
|
|
$script:EXE_PATH = $body.exe_path
|
|
$result["msg"] = "已注册: $($body.id)"
|
|
$result["data"] = $services[$body.id]
|
|
} else {
|
|
$result["code"] = 1
|
|
$result["msg"] = "缺少 id 或 exe_path"
|
|
}
|
|
}
|
|
}
|
|
elseif ($path -match "^/api/services/([^/]+)$" -and $request.HttpMethod -eq "GET") {
|
|
$sid = $Matches[1]
|
|
if ($services.ContainsKey($sid)) {
|
|
$result["data"] = $services[$sid]
|
|
} else {
|
|
$result["code"] = 1; $result["msg"] = "未找到"
|
|
}
|
|
}
|
|
elseif ($path -match "^/api/services/([^/]+)/start$" -and $request.HttpMethod -eq "POST") {
|
|
$sid = $Matches[1]
|
|
if ($services.ContainsKey($sid)) {
|
|
$svc = $services[$sid]
|
|
$exePath = if ($svc["exe_path"] -and (Test-Path $svc["exe_path"])) { $svc["exe_path"] } else { $EXE_PATH }
|
|
if (Test-Path $exePath) {
|
|
$parentDir = Split-Path $exePath -Parent
|
|
$proc = Start-Process -FilePath $exePath -WorkingDirectory $parentDir -WindowStyle Normal -PassThru
|
|
$svc["running"] = $true
|
|
$result["msg"] = "已启动"
|
|
$result["pid"] = $proc.Id
|
|
} else { $result["code"] = 1; $result["msg"] = "文件不存在: $exePath" }
|
|
} else { $result["code"] = 1; $result["msg"] = "未找到" }
|
|
}
|
|
elseif ($path -match "^/api/services/([^/]+)/stop$" -and $request.HttpMethod -eq "POST") {
|
|
$sid = $Matches[1]
|
|
if ($services.ContainsKey($sid)) {
|
|
$killed = $false
|
|
Get-CimInstance Win32_Process | Where-Object { $_.ExecutablePath -eq $services[$sid]["exe_path"] } | ForEach-Object {
|
|
Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue
|
|
$killed = $true
|
|
}
|
|
$services[$sid]["running"] = $false
|
|
$result["msg"] = if ($killed) { "已停止" } else { "未在运行" }
|
|
$result["killed"] = $killed
|
|
} else { $result["code"] = 1; $result["msg"] = "未找到" }
|
|
}
|
|
else { $result["code"] = 404; $result["msg"] = "未知接口" }
|
|
} catch {
|
|
$result["code"] = 1; $result["msg"] = $_.Exception.Message
|
|
}
|
|
|
|
$json = $result | ConvertTo-Json -Compress -Depth 3
|
|
$buffer = [System.Text.Encoding]::UTF8.GetBytes($json)
|
|
$response.AddHeader("Access-Control-Allow-Origin", "*")
|
|
$response.ContentType = "application/json; charset=utf-8"
|
|
$response.ContentLength64 = $buffer.Length
|
|
$response.OutputStream.Write($buffer, 0, $buffer.Length)
|
|
$response.Close()
|
|
}
|
|
}
|
|
|
|
if ($url -and $url -match "^kfzgs://") {
|
|
Invoke-ProtocolHandler $url
|
|
} else {
|
|
Start-ApiServer
|
|
}
|