コマンドライン文字列の解析
- 単純に空白で区切ると、二重引用符で囲まれたパスが正しく分割できない
やりたいこと
入力
この文字列を
"C:\Program Files\Hoge\Fuga.exe" /opt1
出力
このように解析
| 要素 | 値 |
|---|---|
| 0 | C:\Program Files\Hoge\Fuga.exe |
| 1 | /opt1 |
解決策1:System.CommandLine.dll で解析
-
System.CommandLineをnugetで追加
using System.CommandLine.Parsing; // 拡張メソッドを使用するために必要
static string[] Parse_CommandLineDLL(string text)
{
return new Parser().Parse(text).Tokens.Select(token => token.Value).ToArray();
}
解決策2:Win32API で解析
static class NativeMethods
{
[DllImport("shell32.dll", SetLastError = true)]
public static extern IntPtr CommandLineToArgvW([MarshalAs(UnmanagedType.LPWStr)] string lpCmdLine, out int pNumArgs);
[DllImport("kernel32.dll")]
public static extern IntPtr LocalFree(IntPtr hMem);
}
static string[] Parse_Win32API(string text)
{
var argsPtr = NativeMethods.CommandLineToArgvW(text, out var argsNum);
if (argsPtr == IntPtr.Zero) throw new ArgumentException("Unable to split argument.", new Win32Exception());
try
{
return Enumerable
.Range(0, argsNum)
.Select(i => Marshal.PtrToStringUni(Marshal.ReadIntPtr(argsPtr, i * IntPtr.Size)))
.ToArray();
}
finally
{
NativeMethods.LocalFree(argsPtr);
}
}
解決策3:正規表現で解析
static string[] Parse_RegEx(string text)
{
return Regex.Matches(text, @"("".*?""|[^ ""]+)+").OfType<Match>()
.Select(m => m.Groups[0].Value)
.ToArray();
}
まとめ
| 解決策 | メリット | デメリット |
|---|---|---|
| 解決策1 |
MS公式 |
余計なライブラリが増えるnetstandard2.0ornet6が必要 |
| 解決策2 |
MS公式ライブラリ不要 |
Win32API |
| 解決策3 | ライブラリ不要 |