I have searched everywhere and tried just about everything and I am starting to think this is not possible.
I have a service running in Session 0 (win7) as SYSTEM.I need to launch an external application. If I simply launch the external application as SYSTEM, the application launches and I can see the GUI (if I click over to Session 0 using UI0Detect). In addition to me being able to see it, my service that launched the application can actually take a screen shot of the GUI and send it back to my servers. - at this point all is good.
The issue - there are cases where the external application is not allowed to run under the SYSTEM context. In these cases I must launch as a different user. I have another service running as an actual user in Session 0. I then launch the external application as this other user. The external application is launched in Session 0, and I specify WinSta0\Default to ensure that the application GUI launches on the same desktop that my SYSTEM service can see. When this happens UI0Detect pops up giving me the impression that i will click over and see my window. When I get over to session 0 or when my service attempts a screen shot, there is just a small black box. It's almost like only the SYSTEM account can render windows in session 0 - is this true? anyone know if user accounts running in session 0 are able to render a GUI?
I am not looking for code on how to launch an application from session 0 to an active user desktop. That is well documented. What I need to know is how to pull off the reverse (sort of). I need to launch a GUI in session 0 from an account other than SYSTEM.
From MSDN: "If the service type specifies SERVICE_INTERACTIVE_PROCESS, the service must run in the LocalSystem account."
So there is no supported way to do what you're trying to do. However, it might be possible to get it to work by getting the service that runs as SYSTEM to change the permissions on the desktop (and perhaps the window station) in question. Keep in mind that sharing a desktop in this way means that if the application or the user account in question is compromised, it may be able to compromise the system account.
Alternatively, you could try creating a new desktop in session 0 (with appropriate permissions) and launching the application there. I'm not sure if the interactive user would be able to see this desktop, but you could take a screenshot by launching another application in the same desktop (and preferably in the same user context) to take the screenshot on your behalf.
Related
I want to run a VLC with a video file.
I had written the following code in VS and run it under IIS Express. Under IIS Express everything is fine and I am able to see the video as well as audio.
But when I am publishing it to local IIS, I am able to see VLC.exe in task manager and able to hear the audio but not able to see VLC player.
Code Snippet
public bool LaunchVlC(string choice)
{
System.Diagnostics.Process VLC = new System.Diagnostics.Process();
VLC.StartInfo.FileName = #"F:\VLC\vlc.exe";
VLC.StartInfo.Arguments = "-vvv " + choice;
VLC.Start();
return true;
}
I have done IIS Admin Service run under local system account and allowed service to interact with desktop. Still not able to see the video.
As already indicated by 'Lex Li' in the comment section, if processes(your application in local IIS) running in session 0 request for the UI, the UI is not displayed in the user session. From the user perspective, the application appears to be hung, when in actual fact it is performing quite normally, and patiently waiting for a user response that the user cannot see!
In Windows Vista and above, Session 0 is created for services and user-mode drivers. Session 1 is created for the first user who logs in. Applications for this user run in Session 1.
Consider the following example – if a service belonging to an application generates a UI element in Session 0 – for example a dialog box waiting for the user to click “OK” or “Cancel”, the application is now waiting on the service, and the UI is not displayed in the user session. From the user perspective, the application appears to be hung, when in actual fact it is performing quite normally, and patiently waiting for a user response that the user cannot see!
As you can imagine – this presents a problem for users, administrators and developers. However, there are some quick mitigating factors to consider.
If the application’s service uses a UI, a built-in mitigation (in Windows Vista and above) allows the user to interact with the Session 0 UI in a special desktop. This will make the UI specific to the application available and not the entire Session 0 desktop.
If the application creates globally named objects, then use the Windows XP compatibility mode to ensure that the application will continue to work with the Session 0 services.
When testing applications for compatibility with Windows Vista and above, consider the following test scenarios:
Test and verify the application on Windows XP in a Terminal Server mode or a Fast User Switching (FUS) mode. If the application works properly on Windows XP in these scenarios, then it is very likely to work under Windows Vista.
Verify that the application functions properly after applying the Window XP compatibility mode, which contains mitigation for some of the Session 0 issues.
Test the driver (in Windows Vista and above) to ensure that it runs properly. If that is not possible, test the driver in Windows XP with FUS enabled and multiple users logged on. If the driver works correctly for second and subsequent logged-on users, it is not likely to be affected by the Session 0 changes (in Windows Vista and above). The only issues that this test does not detect are those related to the absence of the video driver in Session 0 (in Windows Vista and above).
Finally, you can leverage the following Windows Vista and above capability solutions:
Use client or server mechanisms such as remote procedure call (RPC) or named pipes to communicate between services and applications.
Use the WTSSendMessage function to create a simple message box on the user’s desktop. This allows the service to give the user a notification and request a simple response.
For more complex UI, use the CreateProcessAsUser function to create a process in the user’s session.
Explicitly choose either the Local\ or Global\ namespace for any named objects, such as events or mapped memory, which the service makes available.
And that will do it for a quick look at how Session 0 isolation affects Application Compatibility in Windows Vista and above.
NOTE : Copied from Application Compatibility – Session 0 Isolation; check this link for more information.
I have a windows service which gets the screenshots. But its creating only black screens. I know this happens because of session 0 isolation. I searched on internet and couldnt find any approved solution for this problem any working ideas will be really good.
1- Is there a way to change the session of a windows service and get the desktop screen of another user's session like session 1, session 2?
2- Is there a way to start a console application which runs in an another session other than session 0 from a windows service?
a windows service is designed to run also when there are no users connected, it works like a server process always up and listening, or up and doing something, or idle.
I think what you need is a client application which runs inside every logged user' session and eventually does the job then, if needed, communicates with the service to carry some job done.
I am saying here that instead of having the windows service running in another session than 0 you can create a small executable (probably with no UI at all) that starts up from the start up folder of all users at every user login. such application is then running inside the proper session and has access to it, it can get the screenshot then either store it somewhere itself or call some end points in your Windows Service (running always in session 0) and make the service to elaborate the screenshot taken from the client application of it.
this is the way I would do it, not trying some "magic" to tell Vista and 7 to start a service inside a session of a user that in the end is not logged in yet when the system starts.
Is there a way to change the session of a windows service and get the desktop screen of another user's session like session 1, session 2?
No.
Is there a way to start a console application which runs in an another session other than session 0 from a windows service?
This can be done but it's messy. It involves impersonation of the logged on user, manipulation of user tokens, and launching a process into a different session with CreateProcessAsUser(). This article describes what is needed.
As an aside, you don't want a console application because that will splat a console window on your screenshot. You just want a standard Windows app (using the GUI subsystem) but one that does not show any visible windows.
At the moment we have .NET WinService started under LocalService user at windows start. The service launch another WinForms Application using Process.Start().
But there are several problems in this solution:
We don't wait for an interactive user logon and the Application falls because it tries and fails to initialize DirectX device.
Application launched under LocalService perfectly interacts with user desktop in Windows XP. But it doesn't work in Windows 7 because of there are different graphic stations for each user in win7.
Sometimes we need to run application with current interactive logon user rights.
Does anybody know how to wait for user interactive logon in the service and start WinForms Application with these user rights?
I think this helps to solve all problems.
You will need a separate client app. Check out this document, page 6: http://msdn.microsoft.com/en-us/windows/hardware/gg463353.aspx.
For your monitoring/restart scenario look at CreateProcessAsUser as mentioned in the document. You will almost certainly need to have your client app coordinate with the service for this, and it's still pushing a square peg into a round hole.
I would try using a combination of the answers above.
To solve #1
At user logon, launch the Winforms application using autostart in registry or startup folder. Make it notify the service that it was started successfully.
To make sure that the Winform app is started successfully after user log on:
Have your service that checks if application is started running in the background as you have now but don't let it do the initial startup.
Instead just let it register when user logs on, should be possible to do by listening to OnSessionChange.
Set a delay for X number of seconds to allow the login/startup process finish before it starts checking for a running application (ok maybe not the best solution).
If the service discovers that the application is not started or crashes, restart it from the service using the method Mark points out, CreateProcessAsUser.
Is it possible that this just isn't the right approach for what you're trying to do? It seems possible that you'd be better off putting the monitoring logic or whatever has the uptime requirements into the service so that it's "always on" so to speak. Then you would be left with UI logic in the WinForms app, which could be open or closed with no ill effect.
At my company we have a product which pretty much interacts with everything you can imagine... registry, databases, devices, etc... it is composed of many parts but the entire application is launched by a single executable (start.exe) which is responsbile for launching everything else - this is all legacy code and run under a USER account.
Currently this is launched as a STARTUP item (or by double-clicking on the desktop icon) in Windows, meaning when the user logins into the USER account the application (start.exe) automatically kicks off, under this account it has all the permissions it needs to run and everything has been fine for years...
Now comes the change - I have written a service (Serv.exe) that is running as LocalSystem - this service is responsible for updating the various software components of our product and works as follows:
- when the product detects an update it signals the LocalSystem service (Serv.exe) and then terminates itself
- Serv.exe will then perform all the updating
Now, after everything is done, the product (via start.exe) needs to be launched again automatically ... and this is where I need some advice ... what is the best way to restart the product (start.exe)?
Right now I use the LocalSystem Service (Serv.exe) and impersonate the USER account as follows:
- CreateEnvironmentBlock for the USER
- CreateProcessAsUser(start.exe) as the USER with the corresponding EnvBlock
- DestroyEnvironmentBlock
But is this really 100% equivalent to double-clicking on the icon in the USER account context? I need to ensure that everything is identical when it is either launched on STARTUP of USER or by Impersonation from Serv.exe (LocalSystem) - is there a risk involved? Will I still have the same rights/abilities with all databases? registry? device interaction? etc..
By loading the EnvBlock I seem to get everything I need but ... is this not a good way to do it...?
Kind of hoping for some guidance and advice from the pro's out there ...
Any help or hints would be much appreciated.
Thanks,
Update: Here is a post named: Launching an interactive process from Windows Service in Windows Vista and later. Which is exactly what you are looking for. It starts with:
The first thing you should do about it is that; don't do it. There are many limitations and bad implications and restrictions involved.
So first test if your current solution works. That depend on what the process is doing. If it is not involving user interaction. Or manipulating the current user session. Then you don't need this complex solution. If you need it, than good luck!
Before update: Its not 100% equivalent. Except authorization there are, in windows, sessions and, in each session, there are desktops. The process that is lunched from the service will run on the service session and desktop ( if the service has it). Depending on what the start.exe does, it may be important or not.
Look at the SetTokenInformation function.
Instead of launching the application directly as a "startup item" you could start a "launcher.exe" that then would launch your application. The service could then signal "launcher.exe" that another instance of the application should start after an update. Using this method you can't use the service to update "launcher.exe", but this executable should be very simple and hopefully not require any updates. Using this method would avoid all the pitfalls of trying to start an interactive application from a service.
We have to run a process from a windows service and get a screenshot from it.
We tried the BitBlt and PrintWindow Win32 calls, but both give blank (black) bitmaps.
If we run our code from a normal user process, it works just fine.
Is this something that is even possible? Or could there be another method to try?
Things we tried:
Windows service running as Local System, runs process as Local System -> screenshot fails
Windows service running as Administrator, runs process as Administrator -> screenshot fails.
Windows application running as user XYZ, runs a process as XYZ -> screenshot works with both BitBlt or PrintWindow.
Tried checking "Allow service to interact with desktop" from Local System
We also noticed that PrintWindow works better for our case, it works if the window is behind another window.
For other requirements, both the parent and child processes must be under the same user. We can't really use impersonation from one process to another.
Currently i can't find the corresponding links, but the problem is, that a windows service runs in another session than a normal user application.
In XP this was not fully true. Here are all services started in Session 0 and the first user who logs into the system will also run in Session 0. So in that case, tricks like Allow service to interact with desktop work. But if you fast switch to another user he gets the Session 1 and has no chance to interact with the service directly. This is also true if you connect through RDP to a server version (like 2003 or 2008). These logins will also start in a session higher than 0.
Last but not least there is another drawback by using the interaction with the desktop:
If you enable this option and your service is running under the (default) SYSTEM account it won't be able to create a network connection anymore.
The correct way to get a custom GUI that works with a service is to separate them into two processes and do some kind of IPC (inter process communication). So the service will startup when the machine comes up and a GUI application will be started in the user session. In that case the GUI can create a screenshot, send it to the service and the service can do with it, whatever you like.
Have you tried to run as Local System with the "Allow service to interact with desktop" checked?
I don't think this is possible.
We had to change our scenario where our application wasn't started from a service, but was a standard windows program that has a NotifyIcon in the corner.
If someone still finds a real answer, let me know.
It works using Local System with the "Allow service to interact with desktop"
You can set it programatically using this sample code:
http://www.vbforums.com/showthread.php?t=367177 (it's vb.net but very simple)