fix: 修复 Windows trans 编码与参数传递
This commit is contained in:
+62
-4
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user