How do I run a Web search in the user's default Web browser using their default search provider?


More than one customer has asked, "How do I run a Web search in the user's default Web browser using their default search provider?"

Nobody knows for sure.

Windows does define a mechanism for determining the user's default Web browser, or more specifically, default handler for the http protocol. But that's as far as it goes. There is no standard mechanism for invoking the user's default search provider. The concept of the default search provider is internal to the Web browser; Windows itself has no insight into that, any more than it knows which of your bank accounts is in danger of being overdrawn, which is a concept internal to your personal finance program.

But that doesn't stop people from trying. In particular, Process Explorer uses the following technique: It acts as if it's launching a URL, but instead of passing something like http://www.microsoft.com, it passes "? search string". That is, a quotation mark, a question mark, a space, and then the search parameters, and then a closing quotation mark.

Experimentation revealed that most Web browsers interpret this as a request to perform a search in the user's default search provider. (Not all Web browsers do this, however. For example, it doesn't work in Internet Explorer 6 because Internet Explorer 6 didn't even have the concept of a default search provider.)

Here's some code that tries to follow the above algorithm:

using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;

class Program
{
 [DllImport("shlwapi.dll", CharSet=CharSet.Unicode, PreserveSig=false)]
 static extern void AssocQueryString(
    int flags, int str, string assoc, string extra,
    [Out] StringBuilder buffer, ref int bufferSize);

 const int ASSOCF_ISPROTOCOL = 0x00001000;
 const int ASSOCSTR_COMMAND = 1;

 [DllImport("shell32.dll", CharSet=CharSet.Unicode, PreserveSig=false)]
 static extern void SHEvaluateSystemCommandTemplate(
    string template,
    [Out] out string application,
    [Out] out string commandLine,
    [Out] out string parameters);

 public static void Main(string[] args)
 {
  int bufferSize = 260;
  var buffer = new StringBuilder(bufferSize);
  AssocQueryString(ASSOCF_ISPROTOCOL, ASSOCSTR_COMMAND,
                   "http", "open", buffer, ref bufferSize);
  var template = buffer.ToString();

  Console.WriteLine("Template = {0}", template);

  string application, commandLine, parameters;
  SHEvaluateSystemCommandTemplate(template, out application,
                                  out commandLine, out parameters);

  Console.WriteLine("Application = {0}", application);
  Console.WriteLine("Parameters = {0}", parameters);

  parameters = parameters.Replace("%1", "\"? " + args[0] + "\"");

  Console.WriteLine("Parameters after replacement = {0}", parameters);

  Process.Start(application, parameters);
 }
}

Most of this program is style points.

First, we call Assoc­Query­String to get the answer to the question "If I wanted to open a URL that begins with http:, what command template should I use?" This will return something like

"C:\Program Files\Internet Explorer\iexplore.exe" %1

All we have to do is replace the %1 with "? search phrase", then run the resulting command line.

Now come the style points.

The SHEvaluate­System­Command­Template function conveniently splits split the command template into the pieces we need in order to pass them to Process.Start. The path to the excutable comes out as the application, the command line arguments come out as the parameters, and we don't use the commandLine part.

After splitting the command line into the executable and the parameters, we perform the %1 substitution on the parameters, and then we're ready to pass it all to Process.Start.

And there you have it. Note that there is no guarantee that this code will actually work, but in practice it works with most of the major Web browsers out there.

Comments (22)
  1. Joshua says:

    Watch this technique become more popular until it is the de facto standard.

    I'm pretty sure it works as follows: The command line invokes the same function that the URL bar does, and anything in the URL bar with a space in it must be a search query (URLs do not contain spaces) and search engines eat the ? if the browser didn't already.

  2. Márton says:

    On Windows 10, Firefox can hijack the searches you type into the Windows search box, and open with your default Firefox search engine instead of Bing. How do they do that?

  3. John Doe says:

    @Joshua, you really like to hear yourself talk, don't you?  I mean, to read yourself, whatever.  You still took 8 minutes to read and answer, I'd expect an instant, cohesive and relevant response at no more than 1 minute after the post.  As if you'd guess the post.  Now that would make you a man!

    Nonetheless, you're wrong.  Current browsers take the leading question mark quite seriously, such that you can paste a URL and search for it instead of navigating to it.  Also, the question mark works whether you search for something with or without spaces.

  4. George says:

    Wouldn't AssocQueryString+ASSOCSTR_EXECUTABLE save the need to call SHEvaluateSystemCommandTemplate? Or will it return a different value?

    BTW, is this how the start menu in Windows 7 implements "Search the Internet"?

  5. skSdnW says:

    Most browsers support ? on the command line because it is required by the search internet from start menu feature added in Vista, documented @ msdn.microsoft.com/.../bb757032 (The sample there uses ASSOCSTR_EXECUTABLE which I guess could end up leaving out things on the command line like /profile=foo and /private ?)

    One strange thing about the start menu internet search feature is that the the open verb is used to find the .exe but the NULL "verb" is used when it looks for the icon ( windowssucks.wordpress.com/.../to-open-or-null-that-is-the-verb )

  6. Joshua says:

    @John Doe: I'm not competing with anybody. I just happen to pick this blog up on the train usually a few seconds after its posted at 7:00am + 10 seconds. Looks like Mr. sdrawkcab name found a better answer though.

  7. Myria says:

    Now that the concept exists of a "default search provider", why not create a "search" verb for the http handler?

  8. Stephan says:

    This post got me in the mood to code, so here's a Linux equivalent written in Bourne shell script in case anyone has a use for it:

    blog.ssokolow.com/.../script-to-open-in-default-web-search-provider

  9. Lars says:

    @Stephan: Debian has this already, in the form of the sensible-browser command. And yes, it is customizable, like sensible-pager and sensible-editor.

  10. @Stephan says:

    nevermind, doesn't do the same thing...

  11. Wondering says:

    At times when reading some of the comments people make I really wonder where their 'knowledge' comes from. Search engines or browsers eat the '?' or most browsers support the '?' because it was for something added in Vista?????

    Really?

    Browsers support the '?' because it is part of the URL and it is to be passed to the host computer with the rest of the URL. I see it in RFC 1738, from late 1994, in section 3.3 if you care to look it up. So it needs to be passed because it is part of the URL and it is from way before Vista.

    What the browsers are implementing is what to do with a URL that is not a 'correctly' formed URL, and it sounds like most of them will pass it on to some (browser specific) default web site. And then the web site will have to some basic handling of what to do with that URL (which may not be formatted exactly like they want, but is close enough to something they can guess at).

    Oh and while URL's shouldn't normally have spaces in them it has been very common in the past to find spaces in URLs and have them handled correctly most of the time.

  12. skSdnW says:

    @Wondering: The '?' we are talking about is not supposed to be part of the URL. If you invoke mybrowser.exe "? foo" then only "foo" should be passed as part of the URL. mybrowser "? ?foo" on the other hand should pass the encoded version of "?foo" which in most cases ends up with the browser opening a tab with a URL that ends with "q=%3Ffoo"

  13. Ben Voigt says:

    @Wondering, we are talking about leading question mark, not the question mark that denotes the beginning of GET form fields.  With a leading question mark, there is no hostname, so "it is to be passed to the host computer with the rest of the URL" is meaningless.  (And I'm not including relative URLs... they get combined with the base URL earlier, so even if the question mark appeared at the beginning of a relative URL, it isn't a leading question mark when the absolute URL is determined.  Relative URLs aren't supported in the address bar.)

  14. cheong00 says:

    Actually, if you click the "Magnifier" icon on the address bar of IE11 (or press Ctrl-E shortcut) you'll see the address bar content change to "? " allow you to type search pharse behind. Therefore it ought to be intentional feature (at least for IE).

  15. Tester says:

    I know, little programs and all :-)

    But if you really use this code for anything serious, make sure you handle the fact where the "%1" is already defined with quotes in the template.

    Firefox, for example, defines the template as follows:

    "C:Program Files (x86)Mozilla Firefoxfirefox.exe" -osint -url "%1"

    So you need some extra smarts to not end up with a command line / parameter set, where the too many quotes.

  16. Kathy Odonnell says:

    " Nobody knows for sure.

    Windows does define a mechanism for determining the user's default Web browser, or more specifically, default handler for the http protocol. But that's as far as it goes. There is no standard mechanism for invoking the user's default search provider."

    Raymond, now that we know that his is wrong and that there is a documented way, could you please update the article to correct it and link to the documentation?

    [You're assuming that the user's default Web browser is equal to their default Start menu search provider. What if they're not? -Raymond]
  17. Nick says:

    @Kathy: I doubt it. After all, that's kind of the point of the "IE 6 won't do this" comment. Besides this reads better (I laughed on that line).

  18. Max says:

    @Kathy: It's not really standard, though, and it's not Windows' place to document it. It's de facto, because Windows implemented the functionality and invited browser makers to integrate with it, but there's no guarantee - and probably won't ever be, since Windows still has no concept of "default search provider". That's under the control of the browser makers, and it's up to them to guarantee and document a way of invoking default search handler, with all the warranties that comes with.

    It may sound like I'm just being pedantic here, but it's an incredibly important distinction - if Windows writes documentation saying "hey programmers, here's how you invoke your user's browser's default search handler", and if Raymond writes a blog post saying that's the official and documented way, then Microsoft is guaranteeing that that will work forever, in all browsers, and that if it doesn't work then you can call Microsoft support about it. That's simply not a guarantee Microsoft can make - this behavior is up to browser makers, and any one of them can change or remove it at any time.

    By documenting it, Microsoft has guaranteed that the "Search the Internet" function on the start menu will always send that style of query, forever, but it cannot guarantee that browser makers will accept that style of query forever.

  19. Voo says:

    @max That's overstating it. Just because Microsoft defines a public interface doesn't mean you can bug them about bugs in certain implementations.

    MS defines a strict interface for DX12 for example, but if NVidia gets it wrong Microsoft still won't accept support calls for their divers. Same here: MS certainly could define an interface for invoking the default search provider and if a browser doesn't follow it, bad luck.

    Not sure it's worth the hassle though

  20. ErikF says:

    @Max: Also, just because users can enter "? search query" in the location bar doesn't necessarily mean that you can do that on the command line. For example, URLs accessed programmatically might be interpreted more strictly than ones entered manually (or through Favourites.)

  21. @Voo: To be fair, NVidia's divers are pretty shallow.

  22. xpclient says:

    If only Windows had a Group Policy to prevent programs from automatically launching the default web browser, that is, open it only when the user manually opened it.

    [Group Policy isn't psychic. How does it know that any particular call to CreateProcess was automatic as opposed to due to a user manually opening it (whatever that means)? I guess what you could do is set your default Web browser to Notepad.exe. And then when you want to run Firefox, you manually click the Firefox shortcut. -Raymond]

Comments are closed.

Skip to main content