views:

387

answers:

3

I'm currently using ShellExecute "open" to open a URL in the user's browser, but running into a bit of trouble in Win7 and Vista because the program runs elevated as a service.

When ShellExecute opens the browser, it seems to read the "Local Admin" profile instead of the user's. So for example, if the user at the keyboard has Firefox as his default browser, it may open IE (which is the admin's default).

I know that the "runas" verb can be used to elevate, but how do you do it the other way around? Is there a way to open a URL in the default browser on a standard user's desktop from a service?

+4  A: 

ShellExecute will execute the program in the context of the same session and same user as the process you are running.

If you'd like to use a different session or user token you can use the CreateProcessAsUser Win32 API.

There are several ways to obtain a user token, for example you can call the Win32 API:

Brian R. Bondy
CreateProcessAsUser() doesn't allow you to pass a URL the way ShellExectute() does. I've tried ImpersonateLoggedOnUser, but no luck.
Disco
You can pass a command line argument of the URL, and execute the browser of choice. You can look in the registry to see what the default browser is if you want too.
Brian R. Bondy
You could also try ImpersonateLoggedOnUser with ShellExecute, I'm not 100% sure if it will work on not though http://msdn.microsoft.com/en-us/library/aa378612(VS.85).aspx
Brian R. Bondy
Thanks. I tried impersonation, but no luck. The browser from the registry is proving difficult, too. I've marked this as "answered". I'm going to continue to work on it based on what you've said, but I don't have a definitive answer just yet. Thanks again.
Disco
Same Problem here: impersonification for ShellExecuteEx does not work within a service. But CreateProcessAsUser does (with some tricks) - but unfortunately the browser is not brought to the front on some platforms (2008r2) like with ShellExec.
fmuecke
@fmuecke: try minimize / restore
Brian R. Bondy
@fmuecke: that's not that easy. I only have a process handle of the process I startet - which needs not to be the process of the browser (e.g. browser is already open, execution helper is used, etc.). So determining the hwnd of the browser browser is not a safe and easy thing here.
fmuecke
A: 

Aaron Margosis has a seven-step native code example at http://blogs.msdn.com/aaron_margosis/archive/2009/06/06/faq-how-do-i-start-a-program-as-the-desktop-user-from-an-elevated-app.aspx. Won't help you from your service if that is what you have - I agree your service shouldn't be trying to launch an app as the logged in user, especially since there might not be one.

Kate Gregory
+1  A: 

After a while of testing, the best way to determine the default browser is the following:

NOTE: It is strange but it's true... It has nothing to say that an application is the default application for some file type or web protocol like 'http'. What matters to determine the default web browser is just what is registered in the start menu entry (see reg key below). So forget all the HKCR\http, HKCU\Software\Classes\http, HKLM\Software\Classes\http and their friends.

  1. read from "HKEY_CURRENT_USER\Software\Clients\StartMenuInternet"
  2. read command line from "HKEY_LOCAL_MACHINE\Software\Clients\StartMenuInternet\\shell\open\command"
  3. truncate the command line after ".exe"

Of course you need to impersonate as the logged on user first.

If this solution does not work (like with w2k), use the handler for the http protocol.

To actually start the default browser from a service we use an extra process which is within the service using the logged on user-context. This process starts the above commandline (using ShellExecute on platforms >= Vista). Be sure to use same integrity level (medium) as a default user (else IE won't work because it uses DDE).

HTH.

fmuecke
Cool thanks for that info!
Vinzenz