獲取可執行文件的名稱。當我從註冊表得到一個完整的命令行字符串,或其他地方,例如:從完整的命令行
mycommand -p -o c:\file\1.txt -r output
或
"c:\program files\dir\executable.exe" -options -o1 -o2
我怎麼能輕鬆地之間的分裂可執行文件和參數?
感謝
獲取可執行文件的名稱。當我從註冊表得到一個完整的命令行字符串,或其他地方,例如:從完整的命令行
mycommand -p -o c:\file\1.txt -r output
或
"c:\program files\dir\executable.exe" -options -o1 -o2
我怎麼能輕鬆地之間的分裂可執行文件和參數?
感謝
Windows命令行解析是相當靠不住的,因爲它是由C運行時庫完成的(你可以檢查代碼在Visual Studio中的東西安裝目錄像
你的機器上的實際路徑可能會有所不同,當然。而且,如果您沒有使用Visual Studio安裝C運行時源代碼,它將不會是他們的。
我相信這樣的,因爲它是從DOS繼承的,所以它是相當的這些混沌的「邏輯」。
的基本語法是這樣的:
A命令行是由空格分隔1個或多個字的序列。
每個字是1或多個以下的序列:BARE_WORD,QUOTED_WORD或ESCAPE_SEQUENCE。單詞由空白或命令行結尾終止。
甲BARE_WORD比反斜槓( '\')其它1個或多個字符,雙引號(序列' 「 ')或空白。
甲QUOTED_WORD由LEAD_IN_QUOTE引入(」' 「),接着是零個或多個以下:
並由LEAD_OUT_QUOTE('「')終止。導入和導出報價從引用的單詞中刪除。
一個ESCAPE_SEQUENCE是下列結構之一:
這就是它。
命令行中的第一個單詞是命令名稱(例如,可執行文件的名稱/路徑)。嚴格地說,解析命令名稱應該比其他詞語更簡單,因爲它必須表示有效的NTFS文件名稱。然而,這不一定是真實的,取決於誰組成命令行。
下面是一些示例C#代碼,應該以與Windows操作系統相同的方式解析任何給定的命令行,儘管我應該注意,這有而不是經過了全面測試。
方法Parse()
返回IEnumerable<string>
,其中第一個元素是命令/程序名稱,其餘部分是組成參數的單詞。
class CommandLineParser
{
char[] cmd; // source buffer
StringBuilder buf; // output buffer
int i; // current position within the source buffer
public CommandLineParser()
{
cmd = null;
buf = null;
i = -1;
return;
}
public IEnumerable<string> Parse(string commandLine)
{
cmd = commandLine.ToCharArray();
buf = new StringBuilder();
i = 0;
while (i < cmd.Length)
{
char ch = cmd[i];
if (char.IsWhiteSpace(ch)) { throw new InvalidOperationException(); }
else if (ch == '\\') { ParseEscapeSequence(); }
else if (ch == '"') { ParseQuotedWord(); }
else { ParseBareWord(); }
if (i >= cmd.Length || char.IsWhiteSpace(cmd[i]))
{
string arg = buf.ToString();
yield return arg;
buf.Length = 0;
ConsumeWhitespace();
}
}
}
/// <summary>
/// Parse a quoted word
/// </summary>
private void ParseQuotedWord()
{
// scan over the lead-in quotation mark w/o adding it to the buffer
++i;
// scan the contents of the quoted word into the buffer
while (i < cmd.Length && cmd[i] != '"')
{
char ch = cmd[i];
if (ch == '\\') { ParseEscapeSequence(); }
else { buf.Append(ch); ++i; }
}
// scan over the lead-out quotation mark w/o adding it to the buffer
if (i < cmd.Length)
{
++i;
}
return;
}
/// <summary>
/// Parse a bareword
/// </summary>
private void ParseBareWord()
{
while (i < cmd.Length)
{
char ch = cmd[i];
if (char.IsWhiteSpace(ch)) break; // whitespace terminates a bareword
else if (ch == '"') break; // lead-in quote starts a quoted word
else if (ch == '\\') break; // escape sequence terminates the bareword
buf.Append(ch); // otherwise, keep reading this word
++i;
}
return;
}
/// <summary>
/// Parse an escape sequence of one or more backslashes followed an an optional trailing quotation mark
/// </summary>
private void ParseEscapeSequence()
{
//---------------------------------------------------------------------------------------------------------
// The rule is that:
//
// * An even number of backslashes followed by a quotation mark ('"') means that
// - the backslashes are escaped, so half that many get injected into the buffer, and
// - the quotation mark is a lead-in/lead-out quotation mark that marks the start of a quoted word
// which does not get added to the buffer.
//
// * An odd number of backslashes followed by a quotation mark ('"') means that
// - the backslashes are escaped, so half that many get injected into the buffer, and
// - the quotation mark is escaped. It's a literal quotation mark that also gets injected into the buffer
//
// * Any number of backslashes that aren't followed by a quotation mark ('"') have no special meaning:
// all of them get added to the buffer as-sis.
//
//---------------------------------------------------------------------------------------------------------
//
// scan in the backslashes
//
int p = i; // start of the escape sequence
while (i < cmd.Length && cmd[i] == '\\')
{
buf.Append('\\');
++i;
}
//
// if the backslash sequence is followed by a quotation mark, it's an escape sequence
//
if (i < cmd.Length && cmd[i] == '"')
{
int n = (i - p); // find the number of backslashes seen
int quotient = n >> 1; // n divide 2 (5 div 2 = 2 , 6 div 2 = 3)
int remainder = n & 1; // n modulo 2 (5 mod 2 = 1 , 6 mod 2 = 0)
buf.Length -= (quotient + remainder); // remove the unwanted backslashes
if (remainder != 0)
{
// the trailing quotation mark is an escaped, literal quotation mark
// add it to the buffer and increment the pointer
buf.Append('"');
++i;
}
}
return;
}
/// <summary>
/// Consume inter-argument whitespace
/// </summary>
private void ConsumeWhitespace()
{
while (i < cmd.Length && char.IsWhiteSpace(cmd[i]))
{
++i;
}
return;
}
}
class Program
{
static void Main()
{
CommandLineParser parser = new CommandLineParser();
string commandLine = RetrieveUnparsedCommandLine();
int i = 0;
IEnumerable<string> args = parser.Parse(commandLine);
Console.WriteLine("-------------------");
foreach (string arg in args)
{
string template = i > 0 ? "argv[0:#0]" : "command";
string label = string.Format(template , i++);
Console.WriteLine("{0}: {1}" , label , arg);
}
Console.WriteLine("-------------------------");
return;
}
static string RetrieveUnparsedCommandLine()
{
// get the raw command line. Source might be registry, config file, whatever
string commandLine = Environment.CommandLine;
return commandLine;
}
}
祝你好運。
由於其中包含了可能有效的命令行輸入的字符串:
static string[] SplitArgs(string input)
{
var args = new List<string>();
var parts = input.Split(' ');
for (int ii = 0; ii < parts.Length; ++ii)
{
// if it starts with a quote, search to the end
// NB: this does not handle the case of --x="hello world"
// an arguments post processor is required in that case
if (parts[ii].StartsWith("\""))
{
var builder = new StringBuilder(parts[ii].Substring(0));
while (ii + 1 < parts.Length
&& !parts[++ii].EndsWith("\""))
{
builder.Append(' ');
}
// if we made it here before the end of the string
// it is the end of a quoted argument
if (ii < parts.Length)
builder.Append(parts[ii].Substring(0, parts[ii].Length - 1));
args.Add(builder.ToString());
}
else
args.Add(part[ii]);
}
return args.ToArray();
}
對不起,但我需要一個通用的方法來做到這一點,我的應用程序不是一個ConsoleApplication – 2012-02-13 19:18:25
你可以展開你的意思,它是一個WinForms,WPF等?或者它是一個給定一個字符串或一個字符串數組的庫? – user7116 2012-02-13 19:20:40
我從用戶,文件中獲取字符串,這是完整的命令行,我需要區分可執行文件和參數。 – 2012-02-13 19:22:47