Implications of Minimizing to System Tray - c#

I have an UI application that serves several functions (<800KB). I wanted to allow minimizing it to the system tray, and continue to decode data coming from the serial port and sending network messages.
Can I simply hide the main form and create a NotifyIcon in the system tray, or are there other considerations for system tray applications? Does the application use less resources while hidden? Or is it best to make a light version of the application for the system tray (with duplication of code)?
My application does what 2 different applications do (related functions). I'm trying to foresee the implications before I finish coding it.

I've written a couple apps that use NotifyIcon. Putting it in the notification area (system tray) isn't anything special. It's just not visible on the toolbar anymore.

IMO best way in your case is to make windows service that will decode data from serial port and send messages. And other winforms app that will only set preferences and watch service state, that one can go to tray. Maybe you don't really need this tray app, just windows service, you can set preferences trough config file and watch state trough EventLog.
Of course if is possible to run from windows service, eg. your serial port and network code doesn't need logged user or desktop.

Related

RequestAccessKindAsync from Desktop Bridge

I have Win32 desktop bridge application that uses background task to receive push notifications from WNS. I use UWP background task APIs over C++-WinRT
I'd like to be able to receive push notifications even when OS is in sleep so that it wakes up and the app handles push notification. By default OS does not wake up. It did only after manually changing settings value in System->Battery->See which apps are affecting your battery life->Click my app ->Uncheck Let Windows decide option (by default it is always checked) and check Allow the app to run background taks. Now I'd like to do this is manual work on code for better user experience.
RequestAccessKindAsync API allows to let user to change above setting value by showing popup notification to the user and I could do it without any problem in UWP C# sample app. But same code does not show pop notification from my desktop bridge over C++-WinRT. It simply returns false value for below code
auto result = co_await BackgroundExecutionManager::RequestAccessKindAsync(BackgroundAccessRequestKind::AlwaysAllowed,
L"App needs to use background to catch push notifications while device is in sleep");
Can anyone confirm that RequestAccessKindAsync API works from desktop bridge? If not then how I can make sure OS and the app will always be able to wake up from sleep when it receives push notification?
UPD: Raised request to enable this API from desktop brige here
This is a missing feature. When we designed this API a couple of releases ago we didn't consider desktop bridge apps would be calling it - but clearly there is a use case for supporting this. I have notified the team about this gap, but I'd also encourage you to log a feature request here: https://wpdev.uservoice.com/
Two possible workarounds:
(1) you could add a dummy/empty UWP foreground app to your desktop bridge app. You can then launch this on startup and request the background access from there. This will be a bit ugly, but you could make it look like a splash screen :-)
(2) you can instruct the user to go into the Settings app to set your app to always allowed. You can help them do that with a deep link to the battery save settings, but they will still need to manually flip the switch.

Balloon Tooltip using Windows Service C#

I want to open a balloon tooltip using windows service.
I can do it in Windows Forms. Is it possible using windows service ?
I have implemented this service before and used a named pipe. Basically you create two applications.
A windows service projects which acts as the Named Pipe Server
A winforms application with a tray icon, a balloon and a Named Pipe Client
The windows service pushes messages towards the clients that are connected, could be multiple users on the systems running the winforms app.
The winforms app listens to messages on the pipe. Once the message comes in you can make the balloon pop up.
Here is a cool test project: https://www.codeproject.com/Tips/492231/Csharp-Async-Named-Pipes
Happy coding!
Not directly. A windows service does not run in the user's session, it runs in its own special "Service Session". Tooltips that show up in that session don't show up on the users desktop.
The way to get around this normally is to have a 2nd program that starts with the user's login and is not visible in the taskbar. That program uses some form of IPC (for example WCF) to talk to the service, the service can then tell the helper program to show a notification as needed.

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 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.

NotifyIcon on startup

I trying to make a visible tray-icon of my program in windows startup, with the NotifyIcon component.
The program itself works great and the tray-icon showing up.
But, when i placing my program in computer startup, the tray icon not always showing up, while the program itself is running without any problems, and its main window is visible.
There is no custom code involved here, all code is auto-generated.
Running on Windows 7 Ultimate.
What can i do to make the tray icon to showing up in windows startup always?
in windows startup
If you mean you are running a OS boot time (e.g. by adding an entry to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run or with a service) then the process is running in a different session and has no access to the UI.
If you want a process to be run on OS startup and to be interactive you will need two applications: one to run on startup and expose some form of inter-0process communications (IPC), and two a UI application that uses the first applications IPC to communicate with it.
You also (depending on your target users) may need to consider cases where (1) no-one logs on to the system (e.g. a headless server), and (2) where multiple users login (e.g. remote desktop connections to a shared system).
In the past services could be configured to add items to the console user's UI, but this was blocked in Vista (as it opened up security holes).
You'll probably find it back in the hidden icons. On Win7 click the "Show hidden icons" arrow, click on Customize and override the behavior.

Categories

Resources