c#窗口问题

zxjdai 2009-10-09 04:21:39
有一个在cmd命令行运行的程序,它的显示结果都在cmd窗口下显示。

本人想做一个c#程序,运行这个程序。

问题:c#中有没有这样的窗体控件,可以把cmd.exe等dos界面的程序包含到里面,就是说
能在c#窗体中显示这些程序的显示结果。

简单说就是,c#模拟一个cmd.exe程序,怎么写?有没有相关的控件

各位大虾请指点哦。

...全文
536 27 打赏 收藏 转发到动态 举报
写回复
用AI写文章
27 条回复
切换为时间正序
请发表友善的回复…
发表回复
N_ccw 2009-10-19
  • 打赏
  • 举报
回复
从C#窗体发送命令到CMD执行,再装执行结果返回在C#窗体显示
zxjdai 2009-10-18
  • 打赏
  • 举报
回复
设置窗口的大小通过下面的api函数解决

[DllImport("User32.dll",EntryPoint="SetWindowPos")]
public static extern bool SetWindowPos(IntPtr hWnd, int hWndInsertAfter,
int x, int y, int cx, int cy, int uFlags);


cmd屏蔽ctrl+c 通过下面的方法解决:完整的console程序代码,呵呵

WIN_API.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Drawing;

namespace CS_CMD
{
class WIN_API
{
//截获ctrl+c时需要用到的代理函数
public delegate bool ConsoleCtrlDelegate(int dwCtrlType);

[DllImport("User32.dll", EntryPoint = "FindWindow")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

[DllImport("user32.dll ", EntryPoint = "GetSystemMenu")]
public extern static IntPtr GetSystemMenu(IntPtr hWnd, IntPtr bRevert);

[DllImport("user32.dll ", EntryPoint = "RemoveMenu")]
public extern static int RemoveMenu(IntPtr hMenu, int nPos, int flags);

[DllImport("kernel32.dll")]
public static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate HandlerRoutine, bool Add);
}
}



runcmd.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Threading;
using System.Diagnostics;
using System.IO;
using System.Collections;
using System.Windows.Forms;
namespace CS_CMD
{
class RunCmd
{
//processList记录程序所开启的进程号(可以根据这些进程号,关闭进程)
private static List<int> processList = new List<int>();

//一个Ctrl + C的信号被接收,来自键盘或是来自GenerateConsoleCtrlEvent 函数
private const int CTRL_C_EVENT = 0;
//一个Ctrl + Break信号被接收,来自键盘或是来自GenerateConsoleCtrlEvent 函数
private const int CTRL_BREAK_EVENT = 1;
//当用户系统关闭console时,发出此信号
private const int CTRL_CLOSE_EVENT = 2;
//当用户退出系统时会发出信号给所有的Console程序。该信号不能显示是那个用户退出。
private const int CTRL_LOGOFF_EVENT = 5;
//当系统将要关闭时发出信号给所有Console程序。
private const int CTRL_SHUTDOWN_EVENT = 6;
private static bool is_Exit_Cmd = false;

/*
* run_Cmd函数调用cmd程序,重定向cmd的输入流
* 用于和用户的交互
*/
public static void run_Cmd()
{
Console.Title = "run_Cmd";
//为屏蔽ctrl+c,用API安装事件处理
WIN_API.ConsoleCtrlDelegate newDelegate = new WIN_API.ConsoleCtrlDelegate(HandlerRoutine);
bool bRet = WIN_API.SetConsoleCtrlHandler(newDelegate, true);

Process myProcess = new Process();
myProcess.StartInfo.FileName = "cmd.exe";
//设置/Q参数,关闭cmd的命令回应(即,不再重复显示所输入的命令)
myProcess.StartInfo.Arguments = "/Q";
myProcess.StartInfo.UseShellExecute = false;
//重定向输入流,实现交互功能
myProcess.StartInfo.RedirectStandardInput = true;
myProcess.Start();

//根据名字获取到Console程序的窗口句柄
IntPtr WINDOW_HANDLER = new IntPtr(0);
WINDOW_HANDLER = WIN_API.FindWindow(null, "run_Cmd");
//获得窗口的menu
IntPtr CLOSE_MENU = WIN_API.GetSystemMenu(WINDOW_HANDLER, IntPtr.Zero);
int SC_CLOSE = 0xF060;
//将窗口的关闭按钮设为不可用
WIN_API.RemoveMenu(CLOSE_MENU, SC_CLOSE, 0x0);

//将建立的进程号,记录下来,在析构函数中调用
processList.Add(myProcess.Id);

StreamWriter myStreamWriter = myProcess.StandardInput;

String inputText;
int numLines = 0;
do
{
inputText = Console.ReadLine();
if (is_Exit_Cmd==false)
{
if (!String.IsNullOrEmpty(inputText))
{
if (inputText.Trim()=="exit")
{
killProcess();
break;
}else
{
numLines++;
//将用户输入的命令交给cmd处理。
myStreamWriter.WriteLine(inputText);
// MyProcessOutPrint(myStreamReader);
}

}
}else
{
is_Exit_Cmd = false;
}
} while (/*inputText.Length != 0*/true);

// Write a report header to the console.

// End the input stream to the sort command.
// When the stream closes, the sort command
// writes the sorted text lines to the
// console.
myStreamWriter.Close();
// Wait for the sort process to write the sorted text lines.
myProcess.WaitForExit();
myProcess.Close();
}

/// <summary>
/// 处理消息的事件
/// </summary>
private static bool HandlerRoutine(int CtrlType)
{
if (CtrlType==CTRL_C_EVENT|CtrlType==CTRL_BREAK_EVENT|CtrlType==CTRL_CLOSE_EVENT|
CtrlType==CTRL_LOGOFF_EVENT|CtrlType==CTRL_SHUTDOWN_EVENT)
{
is_Exit_Cmd = true;
//MessageBox.Show("ctrl+c");
}


return true; //如果返回false 虽然能捕获ctrl+c,但是还是会退出cmd窗口。

}

private static void killProcess()
{
if (processList.Count > 0)
{
foreach (int i in processList)
{
Process.GetProcessById(i).Kill();
}
}

}
~RunCmd()
{
//对象消除时,杀掉其开启的相关进程
if (processList.Count > 0)
{
foreach (int i in processList)
{
Process.GetProcessById(i).Kill();
}
}

}

}
}


-------------------------------------------------
折腾了好几天,现在贴出来,和大家分享,谢谢各位热心的朋友。
vc815 2009-10-17
  • 打赏
  • 举报
回复
BC
ctwei86 2009-10-17
  • 打赏
  • 举报
回复
学习
kangde 2009-10-17
  • 打赏
  • 举报
回复
中文注释是我的
kangde 2009-10-17
  • 打赏
  • 举报
回复
屏蔽 ctrl c , 可以 ctrl c 后, 再创建 cmd 进程
十八道胡同 2009-10-17
  • 打赏
  • 举报
回复
2.怎样使cmd程序,屏蔽掉ctrl+c 的命令,就是当按下ctrl+c 时 不关闭cmd程序。求c#的解决方法

要屏蔽ctrl+c命令,要使用全局hook
十八道胡同 2009-10-17
  • 打赏
  • 举报
回复
15楼,微软的注释里怎么会有中文?
cja03 2009-10-16
  • 打赏
  • 举报
回复
1.虽然将窗体放入了panel中,但是不知道怎么设置这个cmd窗口相对于panel的位置和大小,那位大哥知道利用窗口句柄来设置子窗口和父窗口的大小关系的函数,请通告声,谢谢。
--------------------------------------------------------------------------------
private static extern bool MoveWindow(IntPtr hwnd, int x, int y, int cx, int cy, bool repaint);
详见帖子:http://topic.csdn.net/u/20090409/11/7125b137-e9f3-4575-8a03-976f23d01d76.html
zxjdai 2009-10-16
  • 打赏
  • 举报
回复
将cmd加入到panel中的问题已经解决:
这是我的解决方法,
首先需要写一个调用cmd的console小程序
 class TestClass
{
List<int> processList = new List<int>();
/*
* run_Cmd函数调用cmd程序,重定向cmd的输入流
* 用于和用户的交互
*/
public void run_Cmd()
{
//这行是重要的,设置窗口的名字。
Console.Title = "run_Cmd";
Process myProcess = new Process();
myProcess.StartInfo.FileName = "cmd.exe";
myProcess.StartInfo.UseShellExecute = false;
//重定向输入流,实现交互功能
myProcess.StartInfo.RedirectStandardInput = true;

myProcess.Start();

//将建立的进程号,记录下来,在析构函数中调用
processList.Add(myProcess.Id);

StreamWriter myStreamWriter = myProcess.StandardInput;

String inputText;
int numLines = 0;
do
{
inputText = Console.ReadLine();
//if (inputText.Trim()!=)
// {
// }
if (inputText.Length > 0)
{
numLines++;
//将用户输入的命令交给cmd处理。
myStreamWriter.WriteLine(inputText);
// MyProcessOutPrint(myStreamReader);
}
} while (/*inputText.Length != 0*/true);

// Write a report header to the console.

// End the input stream to the sort command.
// When the stream closes, the sort command
// writes the sorted text lines to the
// console.
myStreamWriter.Close();
// Wait for the sort process to write the sorted text lines.
myProcess.WaitForExit();
myProcess.Close();
}

~TestClass()
{
//对象消除时,杀掉其开启的相关进程
if (processList.Count > 0)
{
foreach (int i in processList)
{
Process.GetProcessById(i).Kill();
}
}

}

}

在main函数中调用这个方法,编译生成可执行文件CS_CMD.exe

然后建立住窗口程序,已添加一个Button和一个SpliteContainer。

代码如下:

public partial class Form1 : Form
{
//用来记录进程号
ArrayList processList = new ArrayList();
Process process_main = null;
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr SetParent(IntPtr child, IntPtr newParent);
[DllImport("User32.dll", EntryPoint = "FindWindow")]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("User32.dll", EntryPoint = "ShowWindow")] //
private static extern bool ShowWindow(IntPtr hWnd, int type);
public Form1()
{
InitializeComponent();
process_main=Process.GetCurrentProcess();
}

private void button1_Click(object sender, EventArgs e)
{
cmd();
}
public void cmd()
{
Process process = new Process();

//process = Process.Start(path+"snort.exe","-i2 -v");

process.StartInfo.FileName ="CS_CMD.exe";
//设置进程后台运行,实验隐藏窗口的功能
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.Start();

processList.Add(process.Id);

/* process = Process.Start("CS_CMD.exe");*/
//这儿需要使主程序,睡一段时间,才能得到正确的窗口句柄
//不知道问什么,可能是子进程,建立需要时间吧。高手请关注
Thread.Sleep(500);

IntPtr child_IntPrt = new IntPtr(0);
//根据窗体名,获得窗体句柄。
child_IntPrt = FindWindow(null, "run_Cmd");
if (!child_IntPrt.Equals(IntPtr.Zero))
{
//设置子窗体到panel中
SetParent(child_IntPrt, splitContainer1.Panel2.Handle);
//MessageBox.Show(child_IntPrt.ToString());
ShowWindow(child_IntPrt, 1);
}else
{
MessageBox.Show("窗体run_Cmd不存在");
}


}

private void Form1_Load(object sender, EventArgs e)
{

}

private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
//在窗体关闭时 销毁掉程序激活的进程
foreach (int i in processList)
{
try
{

Process.GetProcessById(i).Kill();
}

catch (System.Exception e1)
{
// MessageBox.Show(e1.ToString());

}
}
}
}


呵呵,终于解决了 一个小问题。

还两个问题就是,
1.虽然将窗体放入了panel中,但是不知道怎么设置这个cmd窗口相对于panel的位置和大小,那位大哥知道利用窗口句柄来设置子窗口和父窗口的大小关系的函数,请通告声,谢谢。
2.怎样使cmd程序,屏蔽掉ctrl+c 的命令,就是当按下ctrl+c 时 不关闭cmd程序。求c#的解决方法。
24K純帥 2009-10-15
  • 打赏
  • 举报
回复
直接调用啊。。process
zjh222 2009-10-14
  • 打赏
  • 举报
回复
楼上的强大
kangde 2009-10-14
  • 打赏
  • 举报
回复
continued

#region 强悍
/// <summary>
/// 创建 cmd.exe 进程
/// </summary>
/// <returns>如果创建成功, 返回 true, 否则返回 false</returns>
bool CreateCommandProcess()
{
this._outputBuffer = new StringBuilder(0x100);
this._commandProcess = new Process();
this._commandProcess.EnableRaisingEvents = true;
this._commandProcess.Exited += new EventHandler(this.OnProcessExited);
this._commandProcess.StartInfo.CreateNoWindow = true;
this._commandProcess.StartInfo.FileName = Environment.GetEnvironmentVariable("ComSpec");
this._commandProcess.StartInfo.Arguments = "/Q /E:ON /F:OFF /D";
this._commandProcess.StartInfo.UseShellExecute = false;
this._commandProcess.StartInfo.RedirectStandardInput = true;
this._commandProcess.StartInfo.RedirectStandardOutput = true;
this._commandProcess.StartInfo.RedirectStandardError = true;
this._commandProcess.StartInfo.WorkingDirectory = Environment.CurrentDirectory;
bool flag = this._commandProcess.Start();
if (flag)
{
this._outputThread = new Thread(new ThreadStart(this.CommandShellOutputReaderThread));
this._outputThread.Name = "Cmd.StdOut";
this._outputThread.IsBackground = true;
this._outputThread.Start();
this._errorThread = new Thread(new ThreadStart(this.CommandShellErrorReaderThread));
this._errorThread.Name = "Cmd.StdErr";
this._errorThread.IsBackground = true;
this._errorThread.Start();
System.Windows.Forms.Application.Idle += new EventHandler(this.OnApplicationIdle);
}
return flag;
}

/// <summary>
///
/// </summary>
void CleanCommandProcess()
{
System.Windows.Forms.Application.Idle -= new EventHandler(this.OnApplicationIdle);
if (this._commandProcess != null)
{
if (!this._commandProcess.HasExited)
{
try
{
this._commandProcess.Kill();
}
catch (Exception)
{
}
}
this._commandProcess = null;
}
this._isErrorMode = false;
this._errorThread = null;
this._outputThread = null;
}

void ClearCurrentCommand()
{
//base.BeginUpdate();
try
{
if (this.CommandStartIndex != this.TextLength)
{
this.Text = this.Text.Substring(0, this.CommandStartIndex);
base.SelectionStart = this.TextLength;
base.ScrollToCaret();
base.ClearUndo();
}
}
finally
{
this._inCommandEditMode = false;
//base.EndUpdate(true);
}
}

void CommandShellErrorReaderThread()
{
Process process = this._commandProcess;
do
{
char ch = (char)process.StandardError.Read();
this._isErrorMode = true;
if (ch != '\0')
{
lock (this._outputBuffer)
{
this._outputBuffer.Append(ch);
}
}
if (process.StandardError.Peek() == -1)
{
this._isErrorMode = false;
}
}
while (!process.HasExited);
this._isErrorMode = false;
}

void CommandShellOutputReaderThread()
{
Process process = this._commandProcess;
do
{
string str = process.StandardOutput.ReadLine();
while (this._isErrorMode)
{
Thread.Sleep(250);
}
lock (this._outputBuffer)
{
this._outputBuffer.Append(str);
this._outputBuffer.Append(Environment.NewLine);
}
}
while (!process.HasExited);
}

string GetHistoryCommand()
{
if (this._historyIndex < 0)
{
return null;
}
return (string)this._commandHistory[this._historyIndex];
}

bool MoveNextHistoryCommand()
{
if (this._historyIndex < (this._commandHistory.Count - 1))
{
this._historyIndex++;
return true;
}
return false;
}

bool MovePreviousHistoryCommand()
{
if (this._historyIndex > 0)
{
this._historyIndex--;
return true;
}
return false;
}

/// <summary>
/// 程序闲暇的时候, 从 cmd 进程的输出缓冲区中复制文字到本座
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void OnApplicationIdle(object sender, EventArgs e)
{
string text = null;
lock (this._outputBuffer)
{
if (this._outputBuffer.Length > 0)
{
text = this._outputBuffer.ToString();
this._outputBuffer.Length = 0;
}
}
if (!string.IsNullOrEmpty(text))
{
int num = text.LastIndexOf('\f');
if (num != -1)
{
base.Clear();
text = text.Substring(num + 1);
}
base.AppendText(text);
base.ClearUndo();
}
}

/// <summary>
/// cmd 进程关闭, 如果程序还没退出, 再次创建新的 cmd 进程
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void OnProcessExited(object sender, EventArgs e)
{
if (!this._isExiting)
{
this.CleanCommandProcess();
base.Clear();
this.CreateCommandProcess();
}
}

void SendCommand(string command, bool updateHistory)
{
string strA = command.Trim();
if ((string.Compare(strA, "exit", true) == 0) || (string.Compare(strA, "more", true) == 0))
{
this.ClearCurrentCommand();
}
else
{
if (updateHistory)
{
this.UpdateHistory(command);
}
this._inCommandEditMode = false;
base.AppendText(Environment.NewLine);
base.ClearUndo();
base.SelectionStart = this.TextLength;
base.ScrollToCaret();
this._inCommandEditMode = false;
this._commandProcess.StandardInput.WriteLine(command);
this._commandProcess.StandardInput.Flush();
}
}

void SetCurrentCommand(string command)
{
//base.BeginUpdate();
try
{
this.Text = this.Text.Substring(0, this.CommandStartIndex) + command;
base.SelectionStart = this.TextLength;
base.ScrollToCaret();
base.ClearUndo();
}
finally
{
this._inCommandEditMode = true;
//base.EndUpdate(true);
}
}

void SetFocus()
{
base.Focus();
}

void UpdateHistory(string command)
{
command = command.Trim();
if (command.Length != 0)
{
this._commandHistory.Add(command);
this._historyIndex = this._commandHistory.Count;
}
}
#endregion
}
kangde 2009-10-14
  • 打赏
  • 举报
回复
我来贡献一个真正的控制台控件, 大家赶紧收藏(这是偷的微软的)


public sealed class CommandPrompt : RichTextBox
{
#region 成员变数
ArrayList _commandHistory;
Process _commandProcess;
int _commandStartIndex;
Thread _errorThread;
Thread _outputThread;
int _historyIndex;
bool _inCommandEditMode;
bool _isErrorMode;
bool _isExiting;
StringBuilder _outputBuffer;
#endregion

/// <summary>
///
/// </summary>
public CommandPrompt()
{
this.BackColor = System.Drawing.SystemColors.WindowFrame;
this.ForeColor = System.Drawing.Color.Green;
base.DetectUrls = false;
this.Multiline = true;
base.HideSelection = false;
base.ScrollBars = RichTextBoxScrollBars.ForcedBoth;
base.WordWrap = false;
base.ShowSelectionMargin = true;
this._historyIndex = -1;
this._commandHistory = new ArrayList();
}

#region 属性
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public override string Text
{
get { return base.Text; }
set { base.Text = value; }
}

int CommandStartIndex
{
get
{
if (!this._inCommandEditMode)
{
this._commandStartIndex = this.TextLength;
}
return this._commandStartIndex;
}
}
#endregion

#region 重载
/// <summary>
///
/// </summary>
/// <param name="e"></param>
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
this.CreateCommandProcess();
base.BeginInvoke(new MethodInvoker(this.SetFocus));
}

/// <summary>
///
/// </summary>
/// <param name="m"></param>
/// <returns></returns>
protected override bool ProcessKeyMessage(ref Message m)
{
if (m.Msg != 0x100/*WM_KEYDOWN*/)
{
if (m.Msg == 0x102/*WM_CHAR*/)
{
switch (((Keys)((int)m.WParam)))
{
case Keys.Back:
if (base.SelectionStart > this.CommandStartIndex)
{
return base.ProcessKeyMessage(ref m);
}
return true;

case Keys.Tab:
case Keys.Return:
return true;
}
if (base.SelectionStart >= this.CommandStartIndex)
{
this._inCommandEditMode = true;
}
else
{
return true;
}
}
}
else
{
switch (((Keys)((int)m.WParam)))
{
case Keys.Back:
case Keys.Left:
if (base.SelectionStart > this.CommandStartIndex)
{
return base.ProcessKeyMessage(ref m);
}
return true;

case Keys.Tab:
case Keys.Prior:
case Keys.Next:
return true;

case Keys.Return:
{
if (base.SelectionStart < this.CommandStartIndex)
{
this.SelectionLength = 0;
base.SelectionStart = this.TextLength;
return base.ProcessKeyMessage(ref m);
}
string command = this.Text.Substring(this.CommandStartIndex);
this.SendCommand(command, true);
return true;
}
case Keys.Escape:
if (this._inCommandEditMode)
{
this.ClearCurrentCommand();
}
return true;

case Keys.End:
base.SelectionStart = this.TextLength;
return true;

case Keys.Home:
base.SelectionStart = this.CommandStartIndex;
return true;

case Keys.Up:
if (this.MovePreviousHistoryCommand())
{
this.SetCurrentCommand(this.GetHistoryCommand());
}
return true;

case Keys.Down:
if (this.MoveNextHistoryCommand())
{
this.SetCurrentCommand(this.GetHistoryCommand());
}
return true;
}
if (base.SelectionStart < this.CommandStartIndex)
{
return true;
}
}
return base.ProcessKeyMessage(ref m);
}

/// <summary>
///
/// </summary>
/// <param name="disposing"></param>
protected override void Dispose(bool disposing)
{
if (disposing)
{
this._isExiting = true;
this.CleanCommandProcess();
}
base.Dispose(disposing);
}
#endregion

zxjdai 2009-10-14
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 lerit 的回复:]
后台调用cmd执行结果(隐藏执行),前台将结果显示出来不就行啦
[/Quote]
这样的界面效果总是做不好啊,呵呵,还有就是,运行一些命令行的程序,比如说一些网络监听软件,
显示结果不能实时更改。
zxjdai 2009-10-14
  • 打赏
  • 举报
回复
是啊。有没有别的办法啊? 是不是这个句柄抓的不对啊?
lerit 2009-10-14
  • 打赏
  • 举报
回复
后台调用cmd执行结果(隐藏执行),前台将结果显示出来不就行啦
足球中国 2009-10-14
  • 打赏
  • 举报
回复
你已经做的不错了。感觉也就是这个了。SetParent
zxjdai 2009-10-14
  • 打赏
  • 举报
回复
我用了SetParent(),出现了这种情况,偶尔cmd窗口出现在程序的panel中,但是大部分时间是单独的弹出一个窗口。郁闷了:
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr SetParent(IntPtr child, IntPtr newParent);
public void cmd()
{
Process process = new Process();
process.StartInfo.FileName = "cmd.exe";
process.Start();
SetParent(process.Handle,this.Handle);
// SetParent(process.MainWindowHandle, new IntPtr(0));
process.Close();
}


各位看看怎么改改
fengling2001 2009-10-12
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 red_angelx 的回复:]
API SetParent
[/Quote]
将DOS窗口作为C#程序的一个子窗口

另一种思路,可以使用重定向,将结果直接映射到C#的窗体上
加载更多回复(6)

110,538

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧