如何等待SQLCMD提示符显示并捕获Password密码输入提示
问题原因
你无法捕获Password:提示是两个核心机制导致的:
- SQLCMD的密码输入提示默认写入标准错误流(stderr),你当前代码仅监听了标准输出流(stdout)的
OutputDataReceived事件,根本收不到这条内容。 BeginOutputReadLine/BeginErrorReadLine这类行读取API,会以换行符作为事件触发的分割标记,但SQLCMD输出Password:后不会追加换行符,会直接等待用户输入,就算你绑定了错误流的行读取事件,也会因为等不到换行符永远不触发回调。
解决步骤
1. 正确配置进程启动参数
启动SQLCMD时必须同时重定向三个标准流,关闭系统外壳执行模式:
ProcessStartInfo startInfo = new ProcessStartInfo() { FileName = "sqlcmd.exe", // 替换为你实际的启动参数,注意不要加-P传密码,否则不会触发密码提示 Arguments = "-S 你的数据库地址 -U 你的登录用户名", RedirectStandardInput = true, RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true }; Process process = new Process() { StartInfo = startInfo };
2. 替换行读取逻辑为原始流块读取
不要使用按行分割的读取API,直接对标准输出、标准错误流做异步块读取,实时匹配密码提示关键字:
StringBuilder outputCache = new StringBuilder(); StringBuilder errorCache = new StringBuilder(); bool passwordSubmitted = false; // 异步读取标准输出,保留原有的查询结果打印逻辑 _ = Task.Run(async () => { char[] readBuffer = new char[256]; using StreamReader stdoutReader = process.StandardOutput; int readCount; while ((readCount = await stdoutReader.ReadAsync(readBuffer, 0, readBuffer.Length)) > 0) { string contentChunk = new string(readBuffer, 0, readCount); outputCache.Append(contentChunk); Console.Write(contentChunk); } }); // 异步读取标准错误,匹配密码提示 _ = Task.Run(async () => { char[] readBuffer = new char[256]; using StreamReader stderrReader = process.StandardError; int readCount; while ((readCount = await stderrReader.ReadAsync(readBuffer, 0, readBuffer.Length)) > 0) { string contentChunk = new string(readBuffer, 0, readCount); errorCache.Append(contentChunk); Console.Error.Write(contentChunk); // 匹配到密码提示且未提交过密码时,写入密码 if (!passwordSubmitted && errorCache.ToString().Contains("Password:")) { passwordSubmitted = true; // 替换为你实际的数据库密码,写入后追加回车确认 await process.StandardInput.WriteLineAsync("你的数据库密码"); } } }); process.Start(); process.WaitForExit();
注意事项
- 启动参数中不要携带
-P密码参数,否则SQLCMD会直接登录,不会弹出密码输入提示。 - 如果你使用的是较旧版本的SQLCMD,重定向流后可能不输出提示,可以在启动参数中追加
-r1,强制SQLCMD将所有提示信息输出到stderr流。 - 密码提交完成后,后续通过
StandardInput写入SQL语句、读取查询返回结果的逻辑可以正常执行,不受流读取方式改动的影响。
内容的提问来源于stack exchange,提问作者MTS
相关产品推荐
相关产品推荐

