diff --git a/ILSpy/NativeMethods.cs b/ILSpy/NativeMethods.cs
index 1513d66ae..9487743d6 100644
--- a/ILSpy/NativeMethods.cs
+++ b/ILSpy/NativeMethods.cs
@@ -19,6 +19,7 @@
using System;
using System.Text;
using System.Runtime.InteropServices;
+using System.ComponentModel;
namespace ICSharpCode.ILSpy
{
@@ -50,8 +51,102 @@ namespace ICSharpCode.ILSpy
[DllImport("user32.dll", CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool SetForegroundWindow(IntPtr hWnd);
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass")]
+ [DllImport("shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
+ static extern unsafe char** CommandLineToArgvW([MarshalAs(UnmanagedType.LPWStr)] string lpCmdLine, out int pNumArgs);
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass")]
+ [DllImport("kernel32.dll")]
+ static extern IntPtr LocalFree(IntPtr hMem);
+
+ #region CommandLine <-> Argument Array
+ ///
+ /// Decodes a command line into an array of arguments according to the CommandLineToArgvW rules.
+ ///
+ ///
+ /// Command line parsing rules:
+ /// - 2n backslashes followed by a quotation mark produce n backslashes, and the quotation mark is considered to be the end of the argument.
+ /// - (2n) + 1 backslashes followed by a quotation mark again produce n backslashes followed by a quotation mark.
+ /// - n backslashes not followed by a quotation mark simply produce n backslashes.
+ ///
+ public static unsafe string[] CommandLineToArgumentArray(string commandLine)
+ {
+ if (string.IsNullOrEmpty(commandLine))
+ return new string[0];
+ int numberOfArgs;
+ char** arr = CommandLineToArgvW(commandLine, out numberOfArgs);
+ if (arr == null)
+ throw new Win32Exception();
+ try {
+ string[] result = new string[numberOfArgs];
+ for (int i = 0; i < numberOfArgs; i++) {
+ result[i] = new string(arr[i]);
+ }
+ return result;
+ } finally {
+ // Free memory obtained by CommandLineToArgW.
+ LocalFree(new IntPtr(arr));
+ }
+ }
+
+ static readonly char[] charsNeedingQuoting = { ' ', '\t', '\n', '\v', '"' };
+
+ ///
+ /// Escapes a set of arguments according to the CommandLineToArgvW rules.
+ ///
+ ///
+ /// Command line parsing rules:
+ /// - 2n backslashes followed by a quotation mark produce n backslashes, and the quotation mark is considered to be the end of the argument.
+ /// - (2n) + 1 backslashes followed by a quotation mark again produce n backslashes followed by a quotation mark.
+ /// - n backslashes not followed by a quotation mark simply produce n backslashes.
+ ///
+ public static string ArgumentArrayToCommandLine(params string[] arguments)
+ {
+ if (arguments == null)
+ return null;
+ StringBuilder b = new StringBuilder();
+ for (int i = 0; i < arguments.Length; i++) {
+ if (i > 0)
+ b.Append(' ');
+ AppendArgument(b, arguments[i]);
+ }
+ return b.ToString();
+ }
+
+ static void AppendArgument(StringBuilder b, string arg)
+ {
+ if (arg == null) {
+ return;
+ }
+
+ if (arg.Length > 0 && arg.IndexOfAny(charsNeedingQuoting) < 0) {
+ b.Append(arg);
+ } else {
+ b.Append('"');
+ for (int j = 0; ; j++) {
+ int backslashCount = 0;
+ while (j < arg.Length && arg[j] == '\\') {
+ backslashCount++;
+ j++;
+ }
+ if (j == arg.Length) {
+ b.Append('\\', backslashCount * 2);
+ break;
+ } else if (arg[j] == '"') {
+ b.Append('\\', backslashCount * 2 + 1);
+ b.Append('"');
+ } else {
+ b.Append('\\', backslashCount);
+ b.Append(arg[j]);
+ }
+ }
+ b.Append('"');
+ }
+ }
+ #endregion
}
-
+
[return: MarshalAs(UnmanagedType.Bool)]
delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
diff --git a/ILSpy/Search/SearchPane.cs b/ILSpy/Search/SearchPane.cs
index c71e0193e..9d9dea18f 100644
--- a/ILSpy/Search/SearchPane.cs
+++ b/ILSpy/Search/SearchPane.cs
@@ -200,7 +200,7 @@ namespace ICSharpCode.ILSpy
{
this.dispatcher = Dispatcher.CurrentDispatcher;
this.assemblies = assemblies;
- this.searchTerm = searchTerm.Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries);
+ this.searchTerm = NativeMethods.CommandLineToArgumentArray(searchTerm);
this.language = language;
this.searchMode = searchMode;