这一周尝试着用C#写了两个后台程序,主程序用CreateProcess()传递命令行参数并创建进程。在实现的过程中,碰到了一个问题,命令行参数中如果带有空格该如何处理。一直认为,命令行中的空格用作参数的分隔符。如果参数内部有空格,该怎么办呢?譬如命令行的参数为“祝福 张学友 \Program Files\1 2 3.lrc”。
刚开始写后台程序时,没考虑到这个问题。后来ZWF在使用时问起,才注意到。经过商量,决定自己定义一个命令行格式,用|作为分隔符。将“祝福 张学友 \Program Files\1 2 3.lrc”改为“祝福|张学友|\Program Files\1 2 3.lrc”。在后台程序中,首先将所有的参数合并,然后再通过分隔符|解析各个字段,代码如下:
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
namespace ConsoleApplication1
{
class Program
{
static void Main( string [] args)
{
String temp = "" ;
string song, singer, path;
int head, tail;
// 合并命令行参数
for ( int i = 0 ; i < args.Length; i ++ )
{
MessageBox.Show(args[i]);
temp += args[i];
temp += " " ;
}
MessageBox.Show(temp);
try
{
// 解析合并后的命令行
head = temp.IndexOf( ' | ' , 0 );
song = temp.Substring( 0 , head);
MessageBox.Show(song);
head += 1 ;
tail = temp.IndexOf( ' | ' , head);
singer = temp.Substring(head, tail - head);
MessageBox.Show(singer);
path = temp.Substring(tail + 1 );
MessageBox.Show(path);
}
catch {}
}
}
}
主程序是用C++写的,代码如下:
{
TCHAR szCMD[MAX_PATH];
PROCESS_INFORMATION pi;
STARTUPINFO sii;
memset( & sii, 0 , sizeof (sii));
sii.cb = sizeof (sii);
sii.wShowWindow = SW_SHOW;
sii.dwFlags = STARTF_USESHOWWINDOW;
// 自定义格式的命令行参数
wcscpy(szCMD, L " 祝福|张学友|\\Program Files\\1 2 3.lrc " );
// 使用系统支持的命令行参数
// wcscpy(szCMD,L" 祝福 张学友 \"\\Program Files\\1 2 3.lrc\"");
CreateProcess(_T( " .\\ConsoleApplication1.exe " ), szCMD,
NULL, NULL, 0 , 0 , NULL, NULL, & sii, & pi);
return 0 ;
}
注意,wcscpy(szCMD, L" 祝福|张学友|\\Program Files\\1 2 3.lrc");中祝福前必须留一个空格,否则会导致后台程序接收的命令行不完整。关于这一点,请参考《C++和C#程序之间命令行参数传递和接收》,博主整理的非常细致。MSDN中有关C#命令行参数的说明,Main() 和命令行参数(C# 编程指南),其中提到了“与 C 和 C++ 不同,C#程序的名称不会被当作第一个命令行参数”。
虽然通过自定义命令行的方式,解决了命令行参数本身带有空格的问题,但总感觉有点怪。这是参数不多,如果参数多了怎么办?按理来说,命令行参数的解析规则不能这么简单。在MSDN中查了一下,有其具体的解析规则Parsing C Command-Line Arguments。其中第一个示例就是解决命令行参数中带有空格的问题,只要将该参数放在一对双引号内就可以了。所以,将“祝福 张学友 \Program Files\1 2 3.lrc”改成“ 祝福 张学友 \"\Program Files\1 2 3.lrc\"”即可。通过实验证明,这种方法可行,且简单方便。