是否可以在 C# 2.0 中的 Windows 窗体或用户控件中嵌入 DOS 控制台?
我们有一个旧版 DOS 产品,我的 Windows 应用程序必须与之交互,并且要求旧版产品的实例应在 Windows 应用程序中运行。
目前,我正在使用 user32.dll 来定位 DOS 产品正在运行的窗口,最小化然后最大化窗口,然后在窗口中输入字符。这并不是一个很好的解决方案,因为这意味着我的应用程序必须将窗口名称存储在应用程序设置中,并且要求用户在使用交互功能之前返回到 DOS 应用程序的正确页面。
编辑:更多信息
旧版应用程序需要对用户可见,但不能在单独的窗口中显示。
我已经尝试过 TimothyP 的答案,它工作得很好,但是是否有可能实现相同的功能,但 DOS 窗口可视化地嵌入到 Windows 窗体或用户控件中,而不是弹出在它自己的窗口中?最好采用 ShowDialog() 方式,这样用户在处于“传统模式”时就无法与应用程序交互。
可以使用 Process 类重定向控制台/dos 应用程序的标准输入/输出。它可能看起来像这样:
var processStartInfo = new ProcessStartInfo("someoldapp.exe", "-p someparameters");
processStartInfo.UseShellExecute = false;
processStartInfo.ErrorDialog = false;
processStartInfo.RedirectStandardError = true;
processStartInfo.RedirectStandardInput = true;
processStartInfo.RedirectStandardOutput = true;
processStartInfo.CreateNoWindow = true;
Process process = new Process();
process.StartInfo = processStartInfo;
bool processStarted = process.Start();
StreamWriter inputWriter = process.StandardInput;
StreamReader outputReader = process.StandardOutput;
StreamReader errorReader = process.StandardError;
process.WaitForExit();
您现在可以使用流与应用程序交互。 通过将 processStartInfo.CreateNoWindow 设置为 true,原始应用程序将被隐藏。
我希望这有帮助。
您可以使用 CreateProcess 函数以及 STARTUPINFO 参数的 hStdInput、Output 和 Error 成员,这将允许您拦截应用程序的标准输入和输出。
是的,这并不难做到。我刚刚创建了一个用户控件。 我不包括 WindowLongIndex、WindowStyles 和 SetWindowPosFlags 枚举的定义,您可以在互联网上轻松找到它们。
public partial class FormConsole : UserControl
{
private IntPtr consoleHandle = IntPtr.Zero;
public FormConsole()
{
InitializeComponent();
Disposed += OnDispose;
}
private void OnDispose(object? sender, EventArgs e)
{
if (consoleHandle != IntPtr.Zero)
{
FreeConsole();
}
}
private void FormConsole_Load(object sender, EventArgs e)
{
AllocConsole();
consoleHandle = GetConsoleWindow();
SetWindowLong(consoleHandle, WindowLongIndex.GWL_STYLE, WindowStyles.WS_CHILD | WindowStyles.WS_VISIBLE);
SetParent(consoleHandle, Handle);
SetWindowPos(consoleHandle, IntPtr.Zero, 0, 0, Width, Height, 0);
Console.Clear();
}
private void FormConsole_Resize(object sender, EventArgs e)
{
if (consoleHandle != IntPtr.Zero)
{
SetWindowPos(consoleHandle, IntPtr.Zero, 0, 0, Width, Height, 0);
}
}
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool AllocConsole();
[DllImport("kernel32.dll")]
private static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, WindowLongIndex index, WindowStyles newLong);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll", SetLastError = true)]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
private static extern bool FreeConsole();
}