您的位置:首页 > 产品设计 > UI/UE

[C#] cmdarg_ui:“简单参数命令行程序”的通用图形界面

2012-06-19 17:29 495 查看
  我们有时需要写一些小工具,或者是需要写一些简短的测试程序,这时编写命令行程序会比较方便。但是命令行程序用起来不太方便,比如——
1.查看信息困难。有时候我们需要观察命令行程序的输出结果,但是在默认情况下,命令行程序执行完毕后会自动关闭窗口,来不及观察信息。这时可以采取“在程序中等待按键”、“手工打开命令提示符输入命令”、“在批处理中等待按键”、“批处理重定向”等方法,但是都比较麻烦。
2.命令参数困难。某些命令行程序需要参数,这时只有手工打开命令提示符输入命令。有时要键入文件的全限定名,那就更花功夫了。

  怎么解决以上难题呢?
  首先想到的是把那些小程序改写为图形界面程序,或者为命令行程序分别开发图形界面。但这两个方案的开发成本都太高了,这仅仅只是简短测试程序,很不值得。
  所以,我编写了一个通用的图形界面,专门解决这些命令行程序的使用问题。

一、设计

1.1 如何关联

  首先,怎么将图形界面与原来的命令行程序关联起来呢?
  传统的做法是使用配置文件,在配置文件中指定原来的命令行程序的文件名和路径等信息。但这样做配置起来比较麻烦,因为现在有大量的命令行程序,逐个逐个的修改配置文件就太麻烦了。
  于是我决定不使用配置文件,设计两种关联方式——根据自身文件名、根据命令行参数。

1.1.1 根据自身文件名(“*_ui.exe”)

  用法:假设某命令行程序的文件名为“filesize.exe”,那么将“cmdarg_ui.exe”复制到该目录下并改名为“filesize_ui.exe”,然后就可以利用“filesize_ui.exe”来操作“filesize.exe”了。
  优点:配置十分方便,复制、改名就行了,不需要切换窗口。而且可以为每一个命令行程序分别配置图形界面,方便以后随时双击打开。
  缺点:对于每一个命令行程序都需要配置一次。

1.1.2 根据命令行参数(鼠标拖曳)

  在很多时候只需要看一次就行了。为了看一次而建立“*_ui.exe”,随后又删掉“*_ui.exe”,那就有些啰嗦了。
  于是设计了另一种关联方式——根据命令行参数。

  用法:A)打开命令提示符,输入“cmdarg_ui.exe <空格> <命令行程序>”启动cmdarg_ui。
     B)在资源管理器中选择命令行程序,然后按住鼠标左键拖曳,将其放置在“cmdarg_ui.exe”的文件图标上,于是资源管理器会启动“cmdarg_ui.exe”,并将刚才拖曳的命令行程序作为参数。
  优点:操作十分简单,只需鼠标拖曳一下。
  缺点:每次启动时都需要拖曳。如果需要频繁使用时,建议还是使用上面的办法(复制、改名“*_ui.exe”)。

1.1.3 特例:“*_wui.exe”会显示命令行窗口,适用于等待按键的命令行程序

  在使用图形界面时,我们一般不希望再弹出命令行窗口。
  但是,某些命令行程序需要等待按键。而现在没有命令行窗口,会导致程序一直等待,不会结束。
  最简单的解决办法是让显示命令行窗口,然后按键使程序继续运行,直至结束。
  这时可以改名为“*_wui.exe”,会自动切换到“显示命令行窗口”模式。

1.2 命令行参数

  对于小工具和测试程序来说,很多是没有参数的,或者是参数格式很简单。例如只有一个输入参数,用于传递文件名。
  于是我设计了两种参数模式——
1.文件。使用文件对话框选择文件,确定后自动运行。
2.自定义。在文本框中手动填好参数,然后点击“运行”。

1.3 其他特性

  为了方便使用,还设计了这些功能——
接收文件:当文件拖曳到窗口上时,将该文件作为参数来调用命令行程序。因为在很多时候,文件拖曳比打开对话框用起来方便一些。
实时优先级:调用命令行程序时,自动将它的进程优先级设为实时。因为某些测试程序需要实时优先级,如果每次在任务管理器中配置的话就太麻烦了。

二、cmdarg_ui的代码

  编程语言为C#。开发工具是VS2005。

  界面如下——



  代码如下——

using System;
//using System.Collections.Generic;
//using System.ComponentModel;
//using System.Data;
using System.Drawing;
//using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.IO;

namespace cmdarg_ui
{
public partial class FrmCmdarg_ui : Form
{
/// <summary>
/// 命令行程序的文件名
/// </summary>
private string _FileExe;

public FrmCmdarg_ui()
{
InitializeComponent();
}

private void FrmCmdarg_ui_Load(object sender, EventArgs e)
{
_FileExe = string.Empty;

// 计算命令行程序的文件名——根据自身文件名
string sFile = Application.ExecutablePath;    // 全限定文件名
string sFileBase = Path.GetFileNameWithoutExtension(sFile);    // 文件基本名(无扩展名、无路径)
this.Text = sFileBase;    // 以基本名作为窗口标题
int n = sFileBase.LastIndexOf('_');    // 在基本名中查找下划线
if (n > 0)
{
// 存在下划线,文件名有效
// 解析后缀参数
for (int i = n + 1; i < sFileBase.Length; ++i)
{
char ch = char.ToUpper(sFileBase[i]);
switch (ch)
{
case 'W':
mnuRunNoWindow.Checked = false;
break;
}
}
// 计算命令行程序的文件名
_FileExe = sFile.Substring(0, sFile.LastIndexOf(Path.DirectorySeparatorChar) + 1 + n) + ".exe";
// 检查文件是否存在
if (!File.Exists(_FileExe)) _FileExe = string.Empty;
}

// 计算命令行程序的文件名——根据命令行参数
if (string.IsNullOrEmpty(_FileExe))
{
string[] lst = Environment.GetCommandLineArgs();
if (lst.Length >= 2)
{
_FileExe = lst[1];
// 检查文件是否存在
if (!File.Exists(_FileExe)) _FileExe = string.Empty;
}
}

if (string.IsNullOrEmpty(_FileExe))
{
// 文件名无效
btnRun.Enabled = false;
txtOut.Text = "Invalid file path!";
}
ttpMain.SetToolTip(btnRun, _FileExe);
mnuRunName.ToolTipText = _FileExe;
}

private void FrmCmdarg_ui_FormClosed(object sender, FormClosedEventArgs e)
{
//
}

private void btnRun_Click(object sender, EventArgs e)
{
string sAll;

if (string.IsNullOrEmpty(_FileExe)) return;    // 文件无效

// 参数
string sArg = txtFile.Text;
if (optCmd.Checked) sArg = txtCmd.Text;

// 执行
Process p = new Process();
p.StartInfo.FileName = _FileExe;
p.StartInfo.Arguments = sArg;
p.StartInfo.UseShellExecute = false;
//p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
//p.StartInfo.RedirectStandardError = true;
p.StartInfo.CreateNoWindow = mnuRunNoWindow.Checked;
Cursor = Cursors.WaitCursor;
try
{
p.Start();
if (mnuRunRealTime.Checked)
{
p.PriorityClass = ProcessPriorityClass.RealTime;
}
try
{
sAll = p.StandardOutput.ReadToEnd();
}
finally
{
p.Close();
}
}
catch (Exception ex)
{
sAll = ex.ToString();
}
finally
{
Cursor = Cursors.Default;
}

// 显示
txtOut.Text = sAll;
}

private void btnRunEx_Click(object sender, EventArgs e)
{
mnuRun.Show(btnRunEx, new Point(0, btnRunEx.Height));
}

/// <summary>
/// 更新文件
/// </summary>
/// <param name="sFile"></param>
private void updateFile(string sFile)
{
Debug.WriteLine(sFile);
if (string.IsNullOrEmpty(sFile)) return;

// 加上双引号,改善对长文件名的支持性
if ('\"' != sFile[0])
{
sFile = "\"" + sFile + "\"";
}

// 更新
txtFile.Text = sFile;
txtFile.SelectionStart = txtFile.Text.Length;    // 优先显示最后面的,便于识别文件名
if (mnuRunAutoFile.Checked)
{
btnRun_Click(btnRun, null);
}
}

private void btnFile_Click(object sender, EventArgs e)
{
if (dlgOpen.ShowDialog(this) == DialogResult.OK)
{
updateFile(dlgOpen.FileName);
}
}

private void FrmCmdarg_ui_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Link;
}

private void FrmCmdarg_ui_DragDrop(object sender, DragEventArgs e)
{
string[] lst = (string[])e.Data.GetData(DataFormats.FileDrop);
if (lst.Length > 0)
{
optFile.Checked = true;
updateFile(lst[0]);
}
}

private void mnuRunName_Click(object sender, EventArgs e)
{
Clipboard.SetText(_FileExe);
}
}
}


  其实原理很简单,利用Process类运行程序,并配置StartInfo.RedirectStandardOutput进行重定向,然后使用StandardOutput.ReadToEnd()获得所有输出信息。

三、测试程序的代码(filesize)

  为了检测参数传递与信息显示,编写了一个小测试程序,功能是显示文件的大小。

  编程语言为C语言。开发工具是VC6。

  代码如下——

#include <stdlib.h>
#include <stdio.h>
#include <tchar.h>

int _tmain(int argc, _TCHAR* argv[])
{
long fileSize = 0;
FILE* pFile;

// 检查参数个数
if (argc<2)
{
// 没有给出文件参数。提示语法
_tprintf(_T("filesize [filename]\n"));
return 1;
}

// 显示文件名
_tprintf(_T("file:\t%s\n"), argv[1]);

// 获取文件大小
pFile = _tfopen(argv[1], _T("rb"));
if ( pFile == NULL )
{
_tprintf(_T("[error] File open failed!\n"));
}
else
{
fseek(pFile, 0L, SEEK_END );    // 将指针定位到文件末尾
fileSize = ftell( pFile );    // 返回当前位置
fclose(pFile);
_tprintf(_T("size:\t%d\n"), fileSize);
}

return 0;
}


四、测试

4.1.1 测试filesize

  filesize具有一个文件名输入参数。所以我们主要测试文件参数。

  测试A——
将“filesize.exe”放在“test”文件夹。
复制“cmdarg_ui.exe”至“test”文件夹,并改名为“filesize_ui.exe”。
双击“filesize_ui.exe”启动图形界面。
“文件”单选框模式是已勾选的,这时点击右侧的“...”按钮弹出文件对话框,选择一个文件。便可发现成功的调用“filesize.exe”,并正确的返回了文件大小信息。
点击“自定义”单选框,然后在右侧文本框中输入参数,再点击“运行”。便可发现下面的文本框更新了,如果手工输入的参数不正确的话,“filesize.exe”会报告“[error] File open failed!”。
在资源管理器中选择一个文件,将其拖曳到本程序。可发现“文件”单选框自动被勾选了,成功的将该文件作为参数调用了“filesize.exe”。

  测试B——
在资源管理器中选择“filesize.exe”,然后按住鼠标左键拖曳,将其放置在“cmdarg_ui.exe”的文件图标上。于是“cmdarg_ui.exe”会启动,并关联“filesize.exe”。
“文件”单选框模式是已勾选的,这时点击右侧的“...”按钮弹出文件对话框,选择一个文件。便可发现成功的调用“filesize.exe”,并正确的返回了文件大小信息。
其他测试同上。

4.1.2 测试noifVC6s.exe

  noifVC6s.exe是我以前写的一个测试程序(/article/4862360.html),没有参数,它需要等待按键。

  测试C——
将“noifVC6s.exe”放在“test”文件夹。
复制“cmdarg_ui.exe”至“test”文件夹,并改名为“noifVC6s_wui.exe”。(注意这里是_wui)
双击“noifVC6s_wui.exe”启动图形界面。
界面启动后,点击“运行”按钮右侧的“V”按钮,可以观察到“无窗口”菜单项没有勾选。此时不需操作,点击空白地方关闭菜单。
因为“noifVC6s.exe”没有命令行参数,可以直接点“运行”按钮。弹出“noifVC6s_wui.exe”的命令行窗口,这时按两下空格键时期继续运行,运行结束可发现正确的返回了输出信息。

  测试D——
在资源管理器中选择“noifVC6s.exe”,然后按住鼠标左键拖曳,将其放置在“cmdarg_ui.exe”的文件图标上。于是“cmdarg_ui.exe”会启动,并关联“noifVC6s.exe”。
界面启动后,点击“运行”按钮右侧的“V”按钮,可以观察到“无窗口”菜单项已经勾选。这时应该点击“无窗口”菜单项,使其取消勾选。
因为“noifVC6s.exe”没有命令行参数,可以直接点“运行”按钮。弹出“noifVC6s_wui.exe”的命令行窗口,这时按两下空格键时期继续运行,运行结束可发现正确的返回了输出信息。



五、小结

  本程序能方便命令行程序的使用,而且配置使用非常简单。

  例如将它关联到“checksimd64_2010.exe”(/article/4862374.html),也是简单的复制、改名就行了,如图——



  以后编写命令行程序时,只需把这个程序放过去就行了,能极大的方便测试和使用。

(完)

源码下载——
http://files.cnblogs.com/zyl910/cmdarg_ui.rar
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: