Why do forms fail in Windows Services - windows-services

I understand that Window's Services have no desktop, and can't access any of the user's desktops directly (indeed, they can run when there is no desktop loaded). Why is it though that launching a form in a Window's Service causes an error?

A service should run without any user interaction, so there is no need for a form. If a service has to wait around for user feedback then it probably isn't going to be doing what it is supposed to.

You have to understand three related concepts: sessions, windows stations and desktops. But because there's a one-to-one relationships between sessions and stations, we can broadly ignore stations for this discussion. A session contains a station (winSta0 being the only interactive station) and stations contain one or more desktops.
Now session architecture differs according to Windows version. For NT <= 5 (XP/2003 and everything before them) services execute in session 0 along with the interactive user's apps. This is why you can configure services to interact with the desktop in these Windows NT versions - they are in the same session. For NT >= 6 (Vista, Server 2008 going forwards), services exists in session 0 but the interactive desktop is in another session. This is what's known as "service hardening", and is basically a security fix.
So since session 0 apps cannot get at the interactive console, it makes no sense for them to attempt to display a user interface of any kind.
Just to make this more confusing, Vista has a temporary kludge to cater for this situation: if an app in session 0 tries to create a dialog, Windows will trap this and present a warning to the user so they switch to a (I presume temporary) desktop where they can interact with the dialog. However this measure is explicitly temporary and you cannot rely upon it being in future Windows releases. I've seen this working in native code, but I suspect you are in managed code and the runtime is being smart enough to catch your behaviour and deliver a metaphorical slap to the hindquarters :-).

Ummm... what and whose desktop is that form going to appear on, exactly? A 'desktop' is an operating system concept: each window handle is owned by a specific desktop within a window station belonging to a single (interactive) user. The process within which the service is executing isn't going to find the user's visible desktop in its window station. For a rather dry reference, look at MSDN.
Actually, it's even nastier. You might be able to configure permissions for the service to be able to create a desktop -- but then nobody will see it! Alternatively, you could grant the process the rights to switch desktops, and confuse the heck out of the user!

There's a setting you must enable in order to allow your Windows Service to access certain folders directly (like desktop) or show forms (including MessageBox pop-ups): "Allow service to interact with desktop"
To see this, right click on My Computer => Manage => Services and Applications => Services. Double-click on a service to access its properties. On the "Log On" tab there is a checkbox for this setting.
Here is an article for how to set it programmatically in C#
[Edit] As Stephen Martin points out in the comments: this is only valid advice for pre-Vista versions of Windows.

Because if nobody is going to see the Form, nobody is going to dismiss it - running a modal dialog is a recipe for a hang - so you want it to complain loudly when this happens rather than sit there quietly until you kill the process (or look at a stack trace to determine what'd going on). (The other obvious problem is, who is going to pick the DialogResult if there is more than one possibility?) You want to know when this is happening. (Assert dialogs that dont throw if they cant show anything are a fun way of making people mad.).
In other words, because you want to know when things are confused enough in your code that a dialog is being shown within a service context.
(I'm assuming you're using Windows Forms on .NET, eve though you didnt tag it as such)
(If you have correctly configured things such that the service is allowed to interact with the desktop, you won't get an Exception)

When a Windows Service is started it is assigned to a Window Station and Desktop according to well documented, though somewhat obscure rules. As mentioned elsewhere it is not assigned to the interactive desktop (unless it is set to interact with the desktop on a pre-Vista OS) but it definitely runs in a desktop.
It is a common misconception that services cannot use UI elements. In fact many services (such as SQL Server) have in the past used hidden windows and windows messages for thread synchronization and work distribution purposes. There is no reason that a Form cannot be shown in a service. If you are getting an error it is due to something you are doing with the form or some component that is on the form. The most likely issues have to do with whether or not you need an STA thread for your form or are you creating a message pump for your form or something similar.
While you certainly can use a form in a Windows Service you almost certainly shouldn't. There will be threading issues, cross apartment call issues, possible blocking UI issues, etc. There are a very few situations where using a window in a service is a good choice but there is a better way, with no UI, in 99.99% of all cases.

Because at the time when the operating system needs to paint the window there is nothing to draw the form on.

Related

renderer and main process communication in electron - the right way

I'm a newbie to both Web tech and Electron! I'm trying to build a desktop app with many windows and fields - including lookup/searches and retrieving data from a DB.
I believe I have most of what I need to get the job done except how to handle the communication between windows. I.e. I need a dialog that displays a table of customers where the user selects a customer to return the data to the calling window. So I pass the search string to the lookup dialog which displays the customer list and in the dialog the user picks the customer and returns the primary key to the calling window (which will display the customer information).
I have found several ways to do this on the web. But I can't imagine that I need to keep a list of all the windows (about 90) and include a listener for each in the main.js (main process) to allow communication between the windows. There must be a better way!! Is there a simple way to setup a universal routine to process communication????
If you're opening 90 windows you're going about this the wrong way. With Electron, every window runs in its own process. This means your app is going to have nearly 100 processes running which is going to be very slow on most machines.
Electron is a platform that brings web apps to the desktop. In a web app, if you want to show 90 windows you'd show them as HTML layers in a single browser window.
I have discovered several ways to open windows and add my html, css, and javascript to each of the windows. I also have discovered a way to create a global var in the main process and have the other windows to retrieve the information from the global var. So I guess I have avoided my concern of having to keep a list of the windows. Still I'm struggling with Electron - almost nothing is straight forward. Or maybe I should say - very little matches my experience with desktop programming languages.
Johnf

JclAppInstances between service and desktop

I'm using the following code in an application that automatically detects when it is run whether it is running as a service or desktop application and behaves appropriately for the situation.
JclAppInst.JclAppInstances('<application descriptive label>').CheckSingleInstance;
The code is embedded into an initialization block at the bottom of a unit that contains code responsibility for acknowledging the service status and displaying key desktop information so I know this unit is included in both modes of operation. The CheckSingleInstance call works perfectly in desktop mode making sure that only one instance is run but doesn't seem to be able to detect if the application is currently running as a service.
Unfortunately I can't work out why the JclAppInstances would be affected by the difference. Both instances are running from the same folder but are operating as different users (ie service user differs from desktop user) but my understanding is different users should work.
Does anyone know whether it is possible to do this with the JclAppInstances and if so what my problem is?
It seems quite clear that the JclAppInstances class doesn't support the required functionality and any solution based on using this Jedi component should refer to the following StackOverflow answer instead.
one instance of app per Computer, how?

URL Stop using Delphi service

I want to have background service written in Delphi 7, that stops a specific URL from being loaded by any browser. Is this possible?
Can anyone point me in a direction?
Thanks in advance.
Shane
There are two approaches of which the second one is technically the best:
Write a DLL that you inject into all processes and if these processes are for a browser you have to intercept and filter all traffic, e.g. using Windows sockets
Write a Layered service provider that works a bit like a firewall (at a lower level in the OS)
I've worked in internet filtering software and I can tell you both are big undertakings.
We initially took the first approach, then switched to the other because it's technically better. [And we never finished that transition because the company folded ;-(]
We did not write our own LSP (it's a big job in itself) but used the products from Komodia. Although they write for C, the people were very helpful answering our questions about porting to Delphi.
But as I said earlier, this is BIG: you have to deal with 32 and 64 bit code, http versus https, protecting services from being stopped, etc. Any non-programming solution that you can find is better (although easy to circumvent).
If you still want to program: prepare for 1 man-year of coding using LSP.
A service, no, I don't think so. But you can edit the 'hosts' file so that the domain of the url points to 127.0.0.1. You can make a service that 'guards' this file, although the service itself must have elevated rights to be able to edit it, and of course, the service itself can be killed as well, if the user has the rights to do so.
Anyway, if you manage to edit the file, the browser will not be able to find the server by domain name. Of course, urls with an IP address cannot be blocked this way and neither can you block specific urls, only the entire domain.
But in general, this is not something to solve using a custom service, but in the firewall on either the PC or the router.
For Internet Explorer, you can write a Browser Helper Object that IE itself loads and passes browser events to. The BHO can then accept/reject URLS on a per-request basis as needed.

Windows Service or Tray/NotifyIcon?

I want to write an app that will, given some network input, simulate mouse movements, clicks, and keyboard input. How and Why i want to do that is a different discussion :-) What I'd like to hear from SO is what would be the preferable model for an app/service like this?
Should I make a windows service that
sits in the background running as
system?
or should I make a tray app that
sits in the tray listening and
manipulating the user's input?
I haven't started working on it, so some of the things I'd imagine would trip me up would have to do with the service not having an interactive session, and/or permissions.
Anything I should anticipate or keep in mind?
If you intend to run your code on Vista and Windows 7, a Windows service isn't going to be enough because they can't interact with user desktops anymore. If you're going to be manipulating user input, you'll need a program running in the user's session.
One alternative is to write a service for monitoring the network events, start the client when a user logs in, and use IPC to communicate between the two.
EDIT: NetworkService should suffice for service privileges.
As Aaron suggested, have a Windows service monitoring the network.
As for the IPC to the process in the user session, you can use WCF, and a named pipe is probably the best transport, but you need to design it the right way round in order to get across the session boundary. Make the Service process the WCF service, with a duplex contract: the user session process calls the service to register and then events are passed back to the user session process on the callback contract. See this question for an explanation of the issues.
Aaron gave all the arguments why you can't do without the tray app, but why add the complexity of a service communicating with the app through IPC ?
A service is useful when you need to have code running even when no user is logged in. This isn't the case here, right ?
Unless you have to manipulate the input of multiple users logged in at the same time, I would go with only the tray app doing both tasks of monitoring network events and manipulating user input, it's way simpler to me.

Does anyone know about issues between Citrix and Delphi 2007 applications? (And perhaps other development languages?)

The situation is simple. I've created a complex Delphi application which uses several different techniques. The main application is a WIN32 module but a few parts are developed as .NET assemblies. It also communicates with a web service or retrieves data from a specific website. It keeps most of it's user-data inside an MS Access database with some additional settings inside the Registry. In-memory, all data is converted inside an XML document, which is occasionally saved to disk as backup in case the system crashes. (Thus allowing the user to recover his data.) There's also some data in XML files for read-only purposes. The application also executes other applications and wants for those to finish. All in al, it's a pretty complex application.
We don't support Citrix with this application, although a few users do use this application on a Citrix server. (Basically, it allows those users to be more mobile.) But even though we keep telling them that we don't support Citrix, those customers are trying to push us to help them with some occasional problems that they tend to have.
The main problem seems to be an occasional random exception that seems to pop up on Citrix systems. Never at the same location and often it looks related to some memory problems. We've p[lenty of error reports already and there are just too many different errors. So I know solving all those will be complex.
So I would like to go a bit more generic and just want to know about the possible issues a Delphi (2007) can have when it's run on a Citrix system. Especially when this application is not designed to be Citrix-aware in any way. We don't want to support Citrix officially but it would be nice if we can help those customers. Not that they're going to pay us more, but still...
So does anyone know some common issues a Delphi application can have on a Citrix system?
Does anyone know about common issues with Citrix in general?
Is there some Silver Bullet or Golden Hammer solution somewhere for Citrix problems?
Btw. My knowledge about Citrix is limited to this Wikipedia entry and this website... And a bit I've Googled...
There were some issues in the past with Published Delphi Applications on Citrix having no icon in the taskbar. I think this was resolved by the MainFormOnTaskbar (available in D2007 and higher). Apart from that there's not much difference between Terminal Server and Citrix (from the Application's perspective), the most important things you need to account for are:
Users are NEVER administrator on a Terminal or Citrix Server, so they no rights in the Local Machine part of the registry, the C drive, Program Folder and so on.
It must be possible for multiple users on the same system to start your application concurrently.
Certain folders such as the Windows folder are redirected to prevent possible application issues, this is also means that API's like GetWindowsFolder do not return the real windows folder but the redirected one. Note that this behaviour can be disabled by setting a particular flag in the PE header (see delphi-and-terminal-server-aware).
Sometimes multiple servers are used in a farm which means your application can run on any of these servers, the user is redirected to the least busy server at login (load balancing). Thefore do not use any local database to store things.
If you use an external database or middleware or application server note that multiple users will connect with the same computername and ip address (certain Citrix versions can use Virtual IP addresses to address this).
Many of our customers use our Delphi applications on Citrix. Generally speaking, it works fine. We had printing problems with older versions of Delphi, but this was fixed in a more recent version of Delphi (certainly more recent than Delphi 2007). However, because you are now running under terminal services, there are certain things which will not work, with or without Citrix. For example, you cannot make a local connection to older versions of InterBase, which use a named pipe without the GLOBAL modifier. Using DoubleBuffered would also be a really bad idea. And so on. My suggestion is to look for advice concerning Win32 apps and Terminal Services, rather than looking for advice on Delphi and Citrix in particular. The one issue which is particular to Citrix that I'm aware of is that you can't count on having a C drive available. Hopefully you haven't hard-coded any drive letters into your code, but if you have you can get in trouble.
Generally speaking, your application needs to be compatible with MS Terminal Services in order to work with XenApp. My understanding is that .NET applications are Terminal Services-compatible, and so by extension should also work in a Citrix environment. Obviously, as you're suffering some problems, it's not quite that simple, however.
There's a testing and verification kit available from http://community.citrix.com/citrixready that you may find helpful. I would imagine the Test Kit and Virtual Lab tools will be of most use to you. The kit is free to use, but requires sign-up.
Security can be an issue. If sensitive folders are not "sandboxed" (See Remko's discussion about redirection), the user can break out of your app and run things that they shouldn't. You should probe your app to see what happens when they "shell out" of your app. Common attack points are CHM Help, any content that uses IE to display HTML, and File Open/Save dialogs.
ex: If you show .chm help, the user can right-click within a help topic, View Source. That typically opens Notepad. From there, they can navigate the directory structure. If they are not properly contained, they may be able to do some mischief.
ex: If they normally don't have a way to run Internet Explorer, and your app has a clickable URL in the about box or a "visit our web site" in the Help menu, voila! they have access to the web browser. If unrestrained, they can open a command shell by navigating to the windows directory.

Resources