C# Windows Forms GUI - Monitor Windows Startup - c#

I have a C# Windows Forms interactive app and a related C# windows service.
On the particular machines where these are deployed, the login and app startup are automatic. The interactive app always starts well before the service. The app has a status indicator to show when it has connected to the service, but these machines are slow and it takes 45-60 seconds for my service to finally get started. During this time, there is nothing happening on the screen.
I should point out that my service starts quickly... it's the dependent (and other) services that are taking some time to start.
I would like to have some sort of indication of the windows startup progress displayed while the application is waiting for the service. I was thinking of showing a progress bar showing something like started_automatic_services/automatic_services. Is there some other more appropriate method?

One possibility would be to use a WMI event query to monitor the services starting up, which would allow you at least to give an idea of progress
Starting services:
Service 1 started
Service 2 started etc.
The MSDN sample Subscribing to and Consuming Management Events should be enough to get you going, as it specifically illustrates querying services for state changes.

Why not use a tray icon? An image that represents a 'broken' or uninitialized connection to your service would be the initial one used, and once the service comes up you can change that to a 'normal' or 'all is well' icon. Some AV software clients do that.
You could also use the same icon with an overlay, maybe a small hourglass on the lower right corner or something like that, and then remove it.
Maybe showing a progress bar every single time the user boots could be rather intrusive and annoying.

Related

Start TrayIcon from service

I have a C# service (.NET 4.6.2) that polls an online API. Tied to that is also a tray icon. The service is supposed to keep the tray icon running, and the icon is supposed to keep the service running.
If the service has to restart the tray icon for any reason, then it does, but the icon doesn't come back. I am trying to solve that because the users think that if the icon isn't there that it isn't working. When they restart the application and get the icon back, it runs through this:
Process process = Process.GetCurrentProcess();
var dupl = (Process.GetProcessesByName(process.ProcessName));
if (dupl.Length > 1)
{
foreach (var p in dupl)
{
if (p.Id != process.Id)
p.Kill();
}
}
to make sure there is only a single copy at any one time. I realize that services aren't supposed to access the UI directly, but isn't there an indirect method? Can I do it by passing my call through another DLL or something?
I have looked into this quite a bit and find so many resources that end up being outdated. Even this one from last year, which seemed promising doesn't work.
How to create process as user with arguments
This service is deployed on computers from Windows 32bit to Windows 10. There is not always a user logged in, but let's assume for simplicity's sake that there is and I can error handle the rest later.
Indeed, your service is not supposed to interact with a user and if you find an article that sports a hack on how to do it anyway, it's bound to fail sooner or later.
The correct way to do it is to have two applications. A service and a user interface. The service runs as a service. The user interface app is started as the user (maybe from their autostart). Then those two applications communicate via some kind of IPC, maybe sockets or pipes. The user interface can display a tray icon and display status messages it gets from the service or it can send commands to the service that it gets from the user via for example the tray icons context menu.
So do not try to fake a solution. It will not work properly, because it's not supposed to work properly. Build two applications.

Proper way to handle Windows Service Tray App / NotifyIcon startup

For the record, I want to point out two things:
I know how to create a Windows Service, I know how to create Tray applications and how to communicate with my Windows Service
I have read countless articles on this subject, almost all of them suggest hacks, putting applications in the Startup menu, (old) interactive desktop services, startup scripts etc. I also found very resources for the subject dated after 2010 (aka light years in the world of technology)
What I'm looking for is the proper way to make sure that when my service is installed, every user gets a nice icon in his tray whenever he/she logs on to his/her computer. This is slightly more complex than it seems, and most of the hackish solutions won't work anyway (not that I'd want to use them anyway).
What I want to achieve is twofold. I want to know how to:
Start the Tray application WITHOUT modifying any user settings. This means not adding anything to the user startup, not modifying the registry, no startup-scripts or whatever. My company doesn't have fixed seats in almost all of its departments. Any user can log on to nearly every workstation at every time. Ideally the Tray application would be launched from the service detecting a user logging on or the shell being started, and then spawning an instance of the tray application for that user.
I'm also looking for a way to handle the startup of the service. For example, when I start up the service and multiple users are logged on to a single machine (which is entirely possible), the service should spawn a tray application instance for each of the users with an interactive logon. This is especially important should the service need to recover. The same goes for when the service is stopped or restarted.
Just to give you an idea, the application I'm writing consists out of a Windows Service, a Tray application that gives feedback to users via notifications and allows them to start op a configuration program that also contains additional information for them, and finally said configuration program that communicates with the service via named pipes. It's all very simple.

How to set permissions on a Windows Service

So I created a Windows Service using C# and created an installer in Visual Studio for it. It's set up to run manually as I don't want it running all the time. I then have another application (C# WPF) that should have an option to turn the service on and off (the service itself creates a web service that in turn communicates back to my WPF application). This works fine in Windows XP, but testing it on a Windows 7 machine, it won't start. Surprisingly it does throw an exception and crash, it just does nothing. I believe this is a permissions problem. If I go to the services control panel using the same Windows 7 account, I'm not able to start or stop the service either.
So my question is, is there a way to set my service so that regular user accounts can start and stop it? And is there a way to set my installer to do this automatically.
I don't want my WPF application to have run as administrator!
Whilst I believe that it is possible to secure a service so that regular users can start and stop it, I do not recommend doing so. This will create a lot of complication and is a potential cause for confusion. I always prefer to keep things simple, especially when it comes to installation and security.
So, if we can't let the user start and stop the service we probably need to let the service run all the time. Since you don't want the service to be active all the time I suggest you give the service its own internal Running flag. When this is set true, the service is active and does busy things, otherwise the service remains idle. You can use your preferred IPC mechanism (sockets, named pipes, WCF etc.) to allow the user to toggle this switch.
Windows 8 has a feature to allow services to start on demand, basically in response to some kind of trigger. But for Windows 7, your only real option is to set it to start automatically on startup. You could set it to start delayed, so that its not adding to the time it takes windows to start.
Regular users cannot start and stop services.
EDIT: Reading the link in the comment above it sounds to me as that is a blanket ability for users to start and stop services. I think the question here is about how to do this for a particular service.
Also, while it may be possible to set the service to run as that particular user, it really means it only works for that particular user and other users on the work station would not be able to use the application as they'd not be able to start or stop the service, assuming that the service running as a user implies that the user may control it, which may not be the case.
Also in reading the comments and other answer, I'm left to wonder if the service can be used by any user which can run the application. That is, if user A logs on to the work station and starts this app (and thus the service), locks it and walks away, what happens when use B logs on and tries to run the same service? Can the service support multiple users at the same time, or will funny things begin to happen if the service is utlized by the application running multiple times.
This really sounds like what is desired is for a background to be started when the application starts. This thread (or threads) would do the work of the service, and by their nature would end when the application ends. Of course more detail in the question would help give a better answer.
Of course if it is appropriate as a service, I see no reason not to have a service with a worker thread that sleeps, and another timer thread that acts as a producer that checks if there's work to do.

How can I get the MainWindowHandle of a Windows 7 application running as user <foo> from within a service running as Local System?

I've created a service that runs as the Local System user. This service launches and monitors a Silverlight Out-of-browser application using native interop and the CreateProcessAsUser() method (to run it as the currently logged-in user, rather than Local System). I'm able to get a handle on the spawned Process and do things like Kill() it, however, I've become aware that the service is unable to get a handle to the main window of the child application because the child application is running as a different user. I'm running on Windows 7.
My end goal is to respond properly to when the Process stops responding (i.e. Process.Responding == false) so that I can kill the application and restart it. However, Process.Responding requires a handle to the main window of the process (Process.MainWindowHandle, to be exact), however, in this scenario, Process.MainWindowHandle always returns 0.
I'm stumped here. Is there any way for one user to get a window handle to a process running as another user in Win 7?
Thanks in advance for any and all help.
No, that's not possible. Windows Services are completely isolated from user-mode applications for security reasons. If you could get the handle to a window, you could manipulate and otherwise interact with that window, leaving open a huge security vulnerability.
More information is available here:
How can a Windows Service start a process when a Timer event is raised?
How can I run an EXE program from a Windows Service using C#?
windows service (allow service to interact with desktop)
Need suggestion on replacing Windows Service by invisible WinForm Application
Strictly speaking, what you're using the Windows Service for in the first place is bad design. It shouldn't be creating or launching any user-mode processes, or interacting with the user in any way. Remember that services run even when there is no user logged in! Thus, they shouldn't be starting applications.
A better solution is a simple background application, set to launch automatically when the user logs in. This background application could then launch the Silverlight application, monitor its state, and interact with it as necessary, because both would be running under the context of the same local user account. The effect is similar to a service, but without any of the drawbacks of isolation. The easiest way to do this in Visual Studio is to create a WinForms application (or possibly a WPF application, I have less experience in that area) that simply doesn't show any forms/windows.

Desktop notifier with no visible form to user

I want to make a application that runs with no form interaction with user and only specific person can run a form and change config setting. The application is desktop reminder which runs every 4 months and shows up a notification.
I don't have any idea how to start it. Please guide me with some good suggestions.
If you have an application that needs to notify the user once every 4 months, its a bit overhead to have it running all the time.
Use the Task Scheduler in Windows, to schedule this command to run (once per day, or every week) check if the condition is met. If not silently exit.
You can effectively create a windows Service and then configure it to allow it interact with the desktop through the Services administration console.
However, for security reasons in W2008 Server (and I assume that more or less it will be the same with W7 or even Vista, you'll have to try it) this behaves differently, and services that interact with the desktop are not allowed. Actually, I remember that when I created and showed a Window I got a notification and when clicking on it the desktop switched to another one with my window. Still, no issue with XP, I've done it.

Categories

Resources