fix: 修复 Windows trans 编码与参数传递

This commit is contained in:
Codex
2026-07-10 13:31:26 +02:00
parent ad93490f4a
commit b6ac6f71f6
6 changed files with 108 additions and 4 deletions
+62 -4
View File
@@ -501,11 +501,11 @@ function parseWinRouteArgs(route: ParsedSshRoute, args: string[]): ParsedSshArgs
if (operation === "ps" || operation === "powershell" || operation === "powershell.exe") {
const commandArgs = args[1] === "--" ? args.slice(2) : args.slice(1);
if (commandArgs.length >= 2 && (commandArgs[0] === "-File" || commandArgs[0] === "-file")) {
const fileArgs = commandArgs.slice(1).map((a: string) => a.replace(/\\/g, "/")).join(" ");
const fileArgs = [commandArgs[1]?.replace(/\\/g, "/") ?? "", ...commandArgs.slice(2)];
return {
remoteCommand: buildWindowsPowerShellInvocation(buildWindowsPowerShellInlineLauncherScript("& " + fileArgs, route.workspace)),
remoteCommand: buildWindowsPowerShellInvocation(buildWindowsPowerShellArgvLauncherScript(fileArgs, route.workspace)),
requiresStdin: false,
invocationKind: "helper",
invocationKind: "argv",
};
}
if (commandArgs.length === 0) {
@@ -515,8 +515,15 @@ function parseWinRouteArgs(route: ParsedSshRoute, args: string[]): ParsedSshArgs
invocationKind: "helper",
};
}
if (commandArgs.length > 1) {
return {
remoteCommand: buildWindowsPowerShellInvocation(buildWindowsPowerShellArgvLauncherScript(commandArgs, route.workspace)),
requiresStdin: false,
invocationKind: "argv",
};
}
return {
remoteCommand: buildWindowsPowerShellInvocation(buildWindowsPowerShellInlineLauncherScript(commandArgs.join(" "), route.workspace)),
remoteCommand: buildWindowsPowerShellInvocation(buildWindowsPowerShellInlineLauncherScript(commandArgs[0] ?? "", route.workspace)),
requiresStdin: false,
invocationKind: "helper",
};
@@ -810,6 +817,7 @@ export function windowsPowerShellScriptPrelude(cwd: string | null): string {
"[Console]::InputEncoding = [System.Text.UTF8Encoding]::new()",
"[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new()",
"$OutputEncoding = [System.Text.UTF8Encoding]::new()",
"$PSDefaultParameterValues['Get-Content:Encoding'] = 'utf8'",
"$env:PYTHONUTF8 = '1'",
"$env:PYTHONIOENCODING = 'utf-8'",
...windowsPowerShellJsonSafetyPreludeLines,
@@ -822,6 +830,56 @@ function buildWindowsPowerShellInlineLauncherScript(command: string, cwd: string
return buildWindowsPowerShellScriptRunner(powerShellSingleQuote(command), cwd);
}
function buildWindowsPowerShellArgvLauncherScript(commandArgs: string[], cwd: string | null): string {
const command = commandArgs[0] ?? "";
if (command.trim().length === 0) throw new Error("ssh win ps requires a command before argv arguments");
const args = commandArgs.slice(1);
const payloadJsonB64 = Buffer.from(JSON.stringify({
command,
args,
nativeArguments: args.map(windowsNativeProcessArgument).join(" "),
}), "utf8").toString("base64");
const script = [
`$payloadJsonB64 = ${powerShellSingleQuote(payloadJsonB64)};`,
"$payload = ConvertFrom-Json -InputObject ([System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($payloadJsonB64)));",
"$command = [string]$payload.command;",
"$commandArgs = @();",
"if ($null -ne $payload.args) { foreach ($item in @($payload.args)) { $commandArgs += [string]$item } }",
"$resolvedCommand = Get-Command -Name $command -ErrorAction Stop;",
"if ($resolvedCommand.CommandType -eq 'Application') {",
" $startInfo = [Diagnostics.ProcessStartInfo]::new();",
" $startInfo.FileName = $resolvedCommand.Source;",
" $startInfo.Arguments = [string]$payload.nativeArguments;",
" $startInfo.WorkingDirectory = (Get-Location).ProviderPath;",
" $startInfo.UseShellExecute = $false;",
" $process = [Diagnostics.Process]::new(); $process.StartInfo = $startInfo;",
" if (-not $process.Start()) { throw ('failed to start native command: ' + $command) }",
" $process.WaitForExit(); $global:LASTEXITCODE = $process.ExitCode;",
"} else { & $command @commandArgs; }",
].join(" ");
return buildWindowsPowerShellScriptRunner(powerShellSingleQuote(script), cwd);
}
function windowsNativeProcessArgument(value: string): string {
if (value.length === 0) return '""';
let quoted = '"';
let backslashes = 0;
for (const character of value) {
if (character === "\\") {
backslashes += 1;
continue;
}
if (character === '"') {
quoted += "\\".repeat(backslashes * 2 + 1) + '"';
backslashes = 0;
continue;
}
quoted += "\\".repeat(backslashes) + character;
backslashes = 0;
}
return quoted + "\\".repeat(backslashes * 2) + '"';
}
function buildWindowsPowerShellStdinLauncherScript(cwd: string | null): string {
return buildWindowsPowerShellScriptRunner("[Console]::In.ReadToEnd()", cwd);
}