I have an application, written by me in C#.net 2.0 - when the application is opened, a timer will check every 3 seconds for x. If x happens, it shows a warning in a windows form.
Is there a possibility to install this timer and the windows form call in a windows-service? So that the timer ticks every time a system is up and shows the message then?
No, it is not possible to have a service display a form. This is by design, since a service is supposed to run without a user interface
You can have a regular application that communicates with your service and displays the warning, but I don't know how exactly this is done.
IMO, you don't need a service, just create a regular application without a main form that runs in the background, performs your check, and displays a warning when necessary. You can add that application to the Run section of HKLM or HKCU, so that it is always started when a user logs on to the system.
Windows Forms cannot be displayed from a Windows Service. A Service runs only in the background.
You can have a separate Windows application that communicates with the Windows service and display warnings, information, etc.
To do this, the service runs on the LocalSystem account, and you have to enable the property for the service to interact with the desktop.
Services are forbidden from interacting with the desktop, including displaying windows or forms. In windows 2003 and XP you could work around the issue by marking the service 'interactive' and this would allow the service to display on the user session, but as of Windows 2008 and Vista this is enforced and services can no longer interact in any fashion with the user.
When services need to display anything, the solution is to split the logic into two separate processes, one being the service and one being a normal user process. The user process runs launched by the user, in its session (it can be launched automatically at session start up) and it connects to the service via some IPC channel (shared memory, named pipes, sockets etc). The service can then display anything it wishes to the user by asking the user process half of the application to display what it needs to display.
As others have said, remember that a windows service is supposed to be a background, never-interacting-with-the-user program. Many services run even when the user is not logged on -- how would they go about displaying a form when there's no desktop for them to display it on?
That said, it shounds like you're trying to shoehorn something into a service that shouldn't be a service. If you want something that runs in the background and still interacts with the user, look into making a lightweight system try application. In fact... here's a helpful tutorial:
Lightweight System Tray Application (NotifyIcon Based)
Related
I need to display Message Box and Windows Forms through windows service by using c#. Anyone Please help me. Thanks in advance.
You cannot (easily) do this directly from the service's process. As descibed here, there is a way to create an interactive service, that is able to send/process windows messages and display windows.
But: Since Windows Vista, all services run in a separate user session, named "session 0". Thus, all windows displayed by services, are displayed in that session. It is theoretically possible (I have even done that once, just for fun), to switch to this session and view these windows, but this would hardly be of use in real life.
My advice would be to create a separate gui application (maybe one with a nice tray icon), that communicates with your service via e.g. TCP/IP or a database. This application can then handle any required user interaction and do the appropriate interaction with the service's process.
i am creating a window service. my requirement is to display window form from window NT service on particular interval. For testing purpose , i just want to display the form on service start:
protected override void OnStart(string[] args)
{
eventLog1.WriteEntry("In OnStart -before form show");
Messager_Form obj = new Messager_Form();
obj.Show();
// System.Diagnostics.Process.Start("calc.exe");
eventLog1.WriteEntry("In OnStart -after form show");
// timer1.Start();
}
it not working. Neither form is showing nor calc process is running. i have found some links
showing pop up , but most of them suggesting WCF. isn't it possible without wcf. can anybody show me the way to achieve this.
Cant be done*. In later Operating Systems that won't work as Windows Services are disallowed from interacting with the Desktop - instead UI presented by Windows Services is shown in Session 0, a special logon session which is not normally visible to the end user.
What you should instead do is write a separate Windows Forms application which is always running, but not always visible (possibly have that application run at startup and have an icon in the notification area) and communicates with the Windows Service using some form of IPC
When the Windows Service wishes to display some UI to the user it sends a message to the application, which in turns shows the desired UI to the end user.
*or at least it definitely shouldn't be done
I am just referring to the answer given in another link in StackOverflow
How to communicate with a windows service from an application that interacts with the desktop?
Answer is :
Be aware that if you are planning to eventually deploy on Windows Vista or Windows Server 2008, many ways that this can be done today will not work. This is because of the introduction of a new security feature called "Session 0 Isolation".
Most windows services have been moved to run in Session 0 now in order to properly isolate them from the rest of the system. An extension of this is that the first user to login to the system no longer is placed in Session #0, they are placed in Session 1. And hence, the isolation will break code that does certain types of communication between services and desktop applications.
The best way to write code today that will work on Vista and Server 2008 going forward when doing communication between services and applications is to use a proper cross-process API like RPC, Named Pipes, etc. Do not use SendMessage/PostMessage as that will fail under Session 0 Isolation.
http://www.microsoft.com/whdc/system/vista/services.mspx
Now, given your requirements, you are going to be in a bit of a pickle. For the cross-platform concerns, I'm not sure if Remoting would be supported. You may have to drop down and go all the way back to sockets: http://msdn.microsoft.com/en-us/library/system.net.sockets.aspx
Checking the "Interact with desktop" box will work on Windows NT, 2000, XP and 2003 but thanks to Session 0 Isolation that setting no longer works as you may expect in Windows Vista and beyond. You want to think very carefully before developing an interactive service...
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.
I know how I can create a Windows Service in C# but I have a series of variables that the user currently feeds into a text file and I wanted to control this process. So can I attach a Windows service to a Windows form application to control such things as installing the service, uninstalling the service, start and restart. Or is it better to have them completely separate and just use the form app to run system commands for install/uninstall and use the serviceController to start/restart?
Thanks
I suggest to make it completely separated.
It's probably better to keep them separate: have the form write a config file for the service, then either restart the service or have the service detect the changed file and reconfigure itself.
If the service interacts with the desktop, then you'll have to start worrying about what happens if they're running as different users, or if there isn't a logged-on user at all, or...
You can do it by allowing the service to interact with the desktop. It's an acceptable way of doing it, but saying that, I agree with dario-g!
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)