Traps

I have a service that I need to launch a forms application whenever a user logs in. This I have done, no problem, however if this user logs off using "switch user" instead of "log off", and then a new user logs in under a different account, my service will launch the application on the original user's desktop, instead of the new user's desktop. How can I fix this so that the application will launch on the correct desktop

In my OnStart() method for the service, I start a Management Event Watcher, checking for Win32_LogonSession. When the event fires, I launch my application using process.start.



Re: Visual C# General How to launch application from service on current user's desktop?

Traps

This sucks. In my testing, I guess that programs launched from a service, are launched under the same SessionID as services.exe. So basically who ever logins in first, launches services.exe which in turn initializes all the services installed on the computer.

Upon startup, Services.exe enumerates through all registry subkeys located under the HKEY_LOCAL_MACHINE\Services registry key in the protected registry, where each subkey represents a service. Services.exe then uses the information located in the subkeys to initialize each service, one at a time, and in the order specified in the registry.

Is there any way to change the session ID of a running application





Re: Visual C# General How to launch application from service on current user's desktop?

Peter Ritchie

A user doesn't log off when switched; you technically have muliple current uers asnd multiple desktops.




Re: Visual C# General How to launch application from service on current user's desktop?

Traps

Yeah, I understand they dont log off. The problem is that whatever desktop(sessionID) launched services.exe(that initialized and started all the services) is the desktop that receives my application when launched from process.start or via a thread from my own service. I need my service to be able to launch my application on any desktop, not just the original desktop that launched services.exe



Re: Visual C# General How to launch application from service on current user's desktop?

Peter Ritchie


It would depend on what user the service is running under. One user isn't generally able to run applications on the desktop of two different users. In Vista, I believe this isn't supported any more. Do you need to support Vista




Re: Visual C# General How to launch application from service on current user's desktop?

Traps

My service is running as local system. In vista, at this present time, I believe vista does support interaction with desktop, its just that all services run under sessionID 0 or something like that, so that the logged in user will never see the application running nor be able to interact with it. I guess technically if you can tell a program to run under a different sessionID, then you could make it work on vista as well.

I have seen video of a service interacting with desktop on vista. When launched, vista prompts the user if they want to view the desktop for the application that was launched. If user agrees, they are taken to that sessionID 0, and then see the application running........ Something like that anyway.....





Re: Visual C# General How to launch application from service on current user's desktop?

Peter Ritchie

You should probably have a read of Larry Osterman's blog Interacting with Services where he says "interactive services aren't guarenteed to work with Windows Vista". But he does go on to suggest using CreateProcessAsUser platform API to create a process on a users desktop. Are you using CreateProcessAsUser




Re: Visual C# General How to launch application from service on current user's desktop?

Traps

Hmmm, no I figured that would just launch the process under whatever sessionID started my service, using the credentials provided in the call to CreateProcessAsUser.

As far as the techniques. I was using Process.start, and have since changed that to run my process(yes a gui window) on a thread started from the my services OnStart method. I had to make the window modal, and it seems to work fine, although I dont know how safe this is.





Re: Visual C# General How to launch application from service on current user's desktop?

Traps

Hmm this looks very promising

SUMMARY

When a process is started by means of the CreateProcessAsUser function, the process will be started into a windowstation and desktop combination based on the value of lpDesktop in the STARTUPINFO structure parameter:
? If a windowstation and desktop combination is specified in the lpDesktop member, the system will try to start the process into that windowstation and desktop.
? If the lpDesktop member is initialized to NULL, the system will try to use the same windowstation and desktop as the calling process if the system is associated with the interactive windowstation.
? If the lpDesktop member is not initialized to NULL, the system will create a new windowstation and desktop that you cannot see.
? If the system is initialized with the empty string, "", it will either create a new windowstation and desktop that you cannot see, or if one has been created by means of a prior call by using the same access token, the existing windowstation and desktop will be used.




Re: Visual C# General How to launch application from service on current user's desktop?

Traps

I'm not too sure, but this might be what I need. All I'm trying to do is launch a program or a thread on the current interactive desktop. If I read this correctly, the function will fail, if the thread calling SetThreadDesktop has a window or hook. Sooooo, basically as it stands now, my current threadproc calls a form.showdialog() to display a modal form, which in the form load event, installs a hook. If I make the call to SetThreadDesktop, before I show the form, shouldnt it be successfull, and the subsequent call to show my modal form appear on the desktop that I specified

http://msdn2.microsoft.com/en-us/library/ms686250.aspx

SetThreadDesktop

Assigns the specified desktop to the calling thread. All subsequent operations on the desktop use the access rights granted to the desktop.

BOOL WINAPI SetThreadDesktop(
 HDESK hDesktop
);

Parameters

hDesktop
[in] Handle to the desktop to be assigned to the calling thread. This handle is returned by the CreateDesktop, GetThreadDesktop, OpenDesktop, or OpenInputDesktop function.

This desktop must be associated with the current window station for the process.

Return Value

If the function succeeds, the return value is nonzero.

If the function fails, the return value is zero. To get extended error information, call GetLastError.

Remarks

The SetThreadDesktop function will fail if the calling thread has any windows or hooks on its current desktop (unless the hDesktop parameter is a handle to the current desktop).

Warning There is a significant security risk for any service that opens a window on the interactive desktop. By opening a desktop window, a service makes itself vulnerable to attack from the logged-on user, whose application could send malicious messages to the service's desktop window and affect its ability to function.





Re: Visual C# General How to launch application from service on current user's desktop?

Traps

First problem. How do I get the handle to the current interactive desktop I know I use OpenDesktop, but how do I get the "Pointer to null-terminated string specifying the name of the desktop to be opened" As indicated for the LPTSTR lpszDesktop parameter

OpenDesktop

Opens the specified desktop object.

HDESK WINAPI OpenDesktop(
 LPTSTR lpszDesktop,
 DWORD dwFlags,
 BOOL fInherit,
 ACCESS_MASK dwDesiredAccess
);

Parameters

lpszDesktop
[in] Pointer to null-terminated string specifying the name of the desktop to be opened. Desktop names are case-insensitive.

This desktop must belong to the current window station.

dwFlags
[in] This parameter can be zero or the following value.
Value Meaning
DF_ALLOWOTHERACCOUNTHOOK
0x0001
Allows processes running in other accounts on the desktop to set hooks in this process.
fInherit
[in] If this value is TRUE, processes created by this process will inherit the handle. Otherwise, the processes do not inherit this handle.
dwDesiredAccess
[in] Access to the desktop. For a list of access rights, see Desktop Security and Access Rights.

Return Value

If the function succeeds, the return value is a handle to the opened desktop. When you are finished using the handle, call the CloseDesktop function to close it.

If the function fails, the return value is NULL. To get extended error information, call GetLastError.





Re: Visual C# General How to launch application from service on current user's desktop?

Traps

Man all this desktop stuff is pretty cool. I like how easy it is to simply create another desktop, and switch to it, or switch to an existing desktop. Anyways, I think maybe this might be my solution. Using OpenInputDesktop. If I understand this right, this will return the handle for the current interactive desktop, or in Microsoft's terms, the desktop that receives user input.

OpenInputDesktop

Opens the desktop that receives user input.

HDESK WINAPI OpenInputDesktop(
 DWORD dwFlags,
 BOOL fInherit,
 ACCESS_MASK dwDesiredAccess
);

Parameters

dwFlags
[in] This parameter can be zero or the following value.
Value Meaning
DF_ALLOWOTHERACCOUNTHOOK
0x0001
Allows processes running in other accounts on the desktop to set hooks in this process.
fInherit
[in] If this value is TRUE, processes created by this process will inherit the handle. Otherwise, the processes do not inherit this handle.
dwDesiredAccess
[in] Access to the desktop. For a list of access rights, see Desktop Security and Access Rights.

Return Value

If the function succeeds, the return value is a handle to the desktop that receives user input. When you are finished using the handle, call the CloseDesktop function to close it.

If the function fails, the return value is NULL. To get extended error information, call GetLastError.

Remarks

The calling process must have an associated window station, either assigned by the system at process creation time or set by SetProcessWindowStation. The window station associated with the calling process must be capable of receiving input.

An application can use the SwitchDesktop function to change the input desktop.

If the dwDesiredAccess parameter specifies the READ_CONTROL, WRITE_DAC, or WRITE_OWNER standard access rights, you must also request the DESKTOP_READOBJECTS and DESKTOP_WRITEOBJECTS access rights.





Re: Visual C# General How to launch application from service on current user's desktop?

Traps

I'm trying to have a thread run on the current interactive desktop. I am doing this so that I can launch a thread with a GUI from a service on whatever desktop is currently active. I may switch this over to launch a process instead of a thread, but thats irrelavent at this time

My test code for Form1 containing 1 button named button1

Code Snippet

using System;

using System.Windows.Forms;

using System.Runtime.InteropServices;

using System.Threading;

namespace DeleteMe

{

publicpartialclassForm1 : Form

{

public Form1()

{

InitializeComponent();

}

[DllImport("user32.dll")]

privatestaticexternbool SetThreadDesktop(IntPtr hDesktop);

[DllImport("user32.dll")]

privatestaticexternIntPtr OpenInputDesktop(uint dwFlags, bool fInherit, int dwDesiredAccess);

privatevoid button1_Click(object sender, EventArgs e)

{

Thread t = newThread(newThreadStart(Thread_ShadowKS));

t.Priority = ThreadPriority.AboveNormal;

t.Start();

}

privatevoid Thread_ShadowKS()

{

IntPtr x = OpenInputDesktop(0, true, 0);

MessageBox.Show(x.ToString());

bool Success = SetThreadDesktop(x);

MessageBox.Show(Success.ToString());

}

}

}

Each time the button is clicked, the first MessageBox shows a number. This number changes everytime the button is clicked. The second MessageBox always returns false, which indicates the thread was not assigned to the desktop.

I'm not confident on my API declares, especially dwDesiredAccess. Perhaps this has something to do with it.

Anyone have some suggestions





Re: Visual C# General How to launch application from service on current user's desktop?

Traps

Oh ***, I just realized the flaw in my code. If a thread has a window or hook running when calling SetTHreadDesktop, it will fail. So I got rid of the first message box, and stepped through the code. This time when I made the call to SetThreadDesktop, it returned a true, however the second messagebox did not appear on my desktop. Any suggestions as to why the 2nd message box did not show



Re: Visual C# General How to launch application from service on current user's desktop?

Traps

Ok it worked. I passed the value 0x0000037f to dwDesiredAccess which gives all access. The handle for the desktop returned is 0. Which is the sessionID that my current desktop is running The 2nd messagebox appeared

Thank you Peter Ritchie.