Skip to content

Commit 7ba4906

Browse files
committed
fix(windows): preserve Unicode paths in terminal launch scripts
1 parent ef713af commit 7ba4906

2 files changed

Lines changed: 62 additions & 1 deletion

File tree

‎MCPForUnity/Editor/Services/Server/TerminalLauncher.cs‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,14 @@ public System.Diagnostics.ProcessStartInfo CreateTerminalProcessStartInfo(string
109109
string scriptsDir = Path.Combine(GetProjectRootPath(), "Library", "MCPForUnity", "TerminalScripts");
110110
Directory.CreateDirectory(scriptsDir);
111111
string scriptPath = Path.Combine(scriptsDir, "mcp-terminal.cmd");
112+
// Match cmd's code page to the script encoding before it reads non-ASCII paths.
112113
File.WriteAllText(
113114
scriptPath,
114115
"@echo off\r\n" +
116+
"chcp 65001 >nul\r\n" +
115117
"cls\r\n" +
116-
command + "\r\n");
118+
command + "\r\n",
119+
new System.Text.UTF8Encoding(false));
117120
return new System.Diagnostics.ProcessStartInfo
118121
{
119122
FileName = "cmd.exe",

‎TestProjects/UnityMCPTests/Assets/Tests/EditMode/Services/Server/TerminalLauncherTests.cs‎

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,64 @@ public void CreateTerminalProcessStartInfo_SpecialCharacters_HandlesGracefully()
154154
Assert.IsNotNull(startInfo);
155155
}
156156

157+
#if UNITY_EDITOR_WIN
158+
[TestCase(437)]
159+
[TestCase(936)]
160+
public void CreateTerminalProcessStartInfo_UnicodePaths_SurviveLegacyCodePage(int codePage)
161+
{
162+
string testDir = System.IO.Path.Combine(System.IO.Path.GetTempPath(),
163+
"mcp-terminal-" + Guid.NewGuid().ToString("N"), "南京项目 空格");
164+
System.IO.Directory.CreateDirectory(testDir);
165+
string pidPath = System.IO.Path.Combine(testDir, "mcp_http_8090.pid");
166+
string generatedScript = System.IO.Path.Combine(_launcher.GetProjectRootPath(),
167+
"Library", "MCPForUnity", "TerminalScripts", "mcp-terminal.cmd");
168+
byte[] originalScript = System.IO.File.Exists(generatedScript)
169+
? System.IO.File.ReadAllBytes(generatedScript) : null;
170+
171+
try
172+
{
173+
_launcher.CreateTerminalProcessStartInfo($"> \"{pidPath}\" echo 123");
174+
byte[] scriptBytes = System.IO.File.ReadAllBytes(generatedScript);
175+
Assert.IsFalse(scriptBytes.Length >= 3 && scriptBytes[0] == 0xef
176+
&& scriptBytes[1] == 0xbb && scriptBytes[2] == 0xbf,
177+
"cmd scripts must not contain a UTF-8 BOM");
178+
179+
// Execute the generated bytes in a Unicode directory without opening a terminal.
180+
string scriptPath = System.IO.Path.Combine(testDir, "mcp-terminal.cmd");
181+
System.IO.File.WriteAllBytes(scriptPath, scriptBytes);
182+
var startInfo = new System.Diagnostics.ProcessStartInfo
183+
{
184+
FileName = "cmd.exe",
185+
Arguments = $"/d /c chcp {codePage} >nul & call \"{scriptPath}\"",
186+
UseShellExecute = false,
187+
CreateNoWindow = true,
188+
RedirectStandardOutput = true,
189+
RedirectStandardError = true
190+
};
191+
using (var process = System.Diagnostics.Process.Start(startInfo))
192+
{
193+
if (!process.WaitForExit(10000))
194+
{
195+
process.Kill();
196+
Assert.Fail("Generated cmd script did not finish within 10 seconds");
197+
}
198+
Assert.AreEqual(0, process.ExitCode, process.StandardError.ReadToEnd());
199+
}
200+
201+
Assert.IsTrue(System.IO.File.Exists(pidPath), "The Unicode pidfile path must be preserved");
202+
Assert.AreEqual("123", System.IO.File.ReadAllText(pidPath).Trim());
203+
}
204+
finally
205+
{
206+
if (originalScript != null)
207+
System.IO.File.WriteAllBytes(generatedScript, originalScript);
208+
else if (System.IO.File.Exists(generatedScript))
209+
System.IO.File.Delete(generatedScript);
210+
System.IO.Directory.Delete(System.IO.Path.GetDirectoryName(testDir), true);
211+
}
212+
}
213+
#endif
214+
157215
#endregion
158216

159217
#region CreateHeadlessProcessStartInfo Tests

0 commit comments

Comments
 (0)