Service with the ServiceNotification option - c#

In Windows Vista and up, services can no longer access the GUI. However, after writing a simple mechanism to pass messages from my service to a helper GUI application, I found the following overload for System.Windows.Forms.MessageBox.Show, where the "MessageBoxOptions" parameter caught my eye:
public static DialogResult Show(
string text,
string caption,
MessageBoxButtons buttons,
MessageBoxIcon icon,
MessageBoxDefaultButton defaultButton,
MessageBoxOptions options
)
Looking at the enum more closely, one of the valid options is MessageBoxOptions.ServiceNotification, which states on MSDN that:
The message box is displayed on the active desktop. The caller is a
service notifying the user of an event. The function displays a
message box on the current active desktop, even if there is no user
logged on to the computer.
Does this mean that by passing the MessageBox.Show() method this option, my service can actually handle displaying a simple message from the service without having to use a helper application in Vista, Windows 7, and up?

MESSAGEBOXOPTIONS ENUM DEMYSTIFIED - Applicable for XP
Starting with Windows Vista and above, user interfaces generated by Windows services can’t be seen. And even worst, your service could be stuck waiting for some user input that the user cannot give as she does not see anything
From here
To display MessageBox in windows service, you need to send WTSSendMessage message. It will show up DialogBox in Session 0 special desktop.

Yes, what you're proposing will work, but do you really want to do that? Remember that by default MessageBox.Show() is a blocking operation. Generally it's a really bad practice to have services waiting on UI operations.
The answer to your question is: "yes, but please don't."

Your Service can display a MessageBox using Show method only if you have started "Interactive Service Detection" service. To start this Service type "services.msc" in the Run Window.

Related

Why can't a windows service created in C# detect that a screen saver is currently running?

As part of some work I need to get done for Windows 10, I have written a code in C# that essentially detects every minute whether a PC is in screen saver mode or not, and it writes to a table in MySQL the relevant status ("PC in use" if the screen saver is off, "available PC" if the screen saver is on).
I did this using (full link if required - https://www.codeproject.com/Articles/17067/Controlling-The-Screen-Saver-With-C):
// Returns TRUE if the screen saver is actually running
public static bool GetScreenSaverRunning( )
{
bool isRunning = false;
SystemParametersInfo( SPI_GETSCREENSAVERRUNNING, 0,
ref isRunning, 0 );
return isRunning;
}
The code works flawlessly in console application mode (I made a loop to test it out over a minute with a check up on screen save status every 10 seconds), this means in MySQL the status was set correctly every time, depending on the screen save status at the moment of the check up.
The problem occurs when I use this code for a windows service. The service is installed correctly, the log on tab is set on Local System (I also tried with the logged in user instead, same results) and I allow the service to interact with the desktop, just in case, but the difference here is that no matter if the PC enters screen save or not, it always returns false on GetScreenSaverRunning(), thus setting the status of the PC in MySQL as "PC in use", even if the screen saver is on at the moment of check up.
I get the sense that the problem isn't in the code itself, since it works without any issues as a console application, but perhaps something behind the scenes. I tried to search here and on many other websites, haven't found anything related to such a problem.
Does anyone have any idea at all what might be the issue? Any help and/or suggestions will be greatly appreciated!
Thank you in advance.
(I could post the code if required, but it is pretty much straight forward and the main part of it, controlling the screen save detection, is taken from the website mentioned above, afterwards it's a simple if (GetScreenSaverRunning() == true) )
Ever since Vista, Services are barred from a Interactive Session. Even if they run under the same rights, they do not get a interactive Session. I would guess that is getting in the way here.
While you can overwrite this behavior in the Service settings, this is not adviseable for new code. Consider making this a Background Task started by the Task Sheduler instead.
Because the windows service runs in different session then the windows logon. You can't interact with the desktop related services unless you run the windows service in win logon session. There used to be an option in Windows service manager where you can set the properties to "Interact with desktop session" but I don't think that ever worked.
There's a work around to run the windows service using the win logo session.
See this helper class that can get the current logged on user session and interact with the desktop services. https://github.com/murrayju/CreateProcessAsUser/blob/master/ProcessExtensions/ProcessExtensions.cs

Windows 10 Feedback Task for my App

Similar to this question which invokes the Windows 10 store to allow a user to write a review or rate an app, I'd also like to be able to invoke the Windows 10 Feedback app and allow users to provide feedback there.
I cannot seem to find much information on:
How this works in general. Can any old app use this service? (I
notice it just kind of shows whatever apps I have running)
How to invoke the Windows Feedback app with my package id
In short - not that I can see.
Other apps are invoked via protocol activation. I haven't seen this documented for the feedback app though so I have to err on the side of 'we haven't made this available yet' (I'm still checking though)
Here's an overall guide to the process http://blog.jerrynixon.com/2012/10/walkthrough-using-windows-8-custom.html?m=1
When I look in the registry under HKEY_CLASSES_ROOT\Extensions\ContractId\Windows.Protocol I see (shortened a tad)
[HKEY_CLASSES_ROOT\Extensions\ContractId\Windows.Protocol\PackageId\Microsoft.WindowsFeedback...\ActivatableClassId\App.AppX7eaybq6p4x7d4jgd6w6jk7r5dg6yhmbf.mca\CustomProperties]
"Name"="windows-feedback"
So - give that a try via launching windows-feedback
If I do Windows Key-R (run): windows-feedback://
it works fine so this should work:
var uri = new Uri(#"windows-feedback://");
var success = await Windows.System.Launcher.LaunchUriAsync(uri);
if (success)
{
// URI launched
}
else
{
// URI launch failed
}
Update
I've done some searching and it seems the magic parameter there is
windows-feedback:?contextid=522
That launches the NFL feedback for example. This is a predetermined number - I'm not sure how one gets on this list though.

Send a string to IE and IE execute the string but not have IE appears or the Console screen appear

I don't know if it is possible to do this in Windows Console Application (C#) but I really need something like this for my project.
I would like to send a string (or URL link) to the IE and have IE execute that string. However, since this string is static; what it does is just turn a machine ON and OFF via internet. So, in this case I have no interest in seeing the IE to popup/display nor the black screen console to appears when the application got executed.
I know in Console Application C# we can do something like this
Process.Start("iexplore.exe", #"http://myserver.com");
However, when I run the above line, the IE popup and so does the black screen console.
Is there a way to not have IE popup and the screen console to not popup, too?
Thanks.
I think you are going about this the wrong way. IE is merely a portal to web requests. Just make the web request call directly. using something like the new Web API or HttpWebRequest
As to making the console not pop up, maybe you should be creating a Windows Service instead of a console application? We would need more details on the end user. If this is more of an automated action, then a service would work. If it is something the user clicks on, then why is displaying the console a bad thing? Typically, when you click on something you expect some sort of visual representation. But, here is a SO that answers this question already
Try ProcessStartInfo. This will hide the console app, but I'm not positive about it hiding IE.
ProcessStartInfo psi = new ProcessStartInfo("iexplore.exe", #"http://myserver.com");
psi.WindowStyle = ProcessWindowStyle.Hidden;
Process.Start(psi);

Exit(Quit) implementation

In my windows phone7(Silverlight) Application I have to display a message box asking, the user to confirm(Yes/No) before exit from the application [on device back button click].
The problem is I have to use a custom messagebox(using a popup) to get user confirmation, and I have no way to get exit from the application.(No method found which will exit the application like dispose() or close()).
if I didn't have to use a custom messagebox, the on the Device back key press event "OnBackKeyPress" I would have use the following logic and done my work
MessageBoxResult res = MessageBox.Show("Do you want to Exit?", "Exit", MessageBoxButton.OKCancel);
if (res == MessageBoxResult.OK)
{
if (NavigationService.CanGoBack)
{
while (NavigationService.RemoveBackEntry() != null)
{
NavigationService.RemoveBackEntry();
}
}
}
else
{
e.Cancel = true;
}
The problem is I need to use the custom messagebox and done this work. Same problem arise if need to implement a button to exit the application with out using the device back button.
I found in several posts suggesting to throw an exception and make this done. Following are some of them
http://mobile.dzone.com/articles/windows-phone-mango-sample-3
http://imaginativeuniversal.com/blog/post/2010/08/22/How-to-Quit-a-WP7-Silverlight-Application.aspx
I don't think that this is a good practice and also not sure if the windows market place will certify this way. Would like to hear the thoughts of once who have experienced this issue, and any suggestion to Achieve this(Terminate the application). Thanks inadvance....!!!!
If you want to submit to the Marketplace you've got a couple of problems because of the following certification requirements:
5.2.4.2 Pressing the Back button from the first screen of an application must close the application.
5.2.2 A Windows Phone application is closed and terminated by the OS when the user navigates away from the application. When an application is started after being closed, its launch time must meet the requirements in Section 5.2.1 – Launch Time
5.2.3 A Windows Phone application is deactivated when the user presses the Start button or if the device timeout causes the lock screen to engage. A Windows Phone application is also deactivated with it invokes a Launcher or Chooser API.
This is a couple instances where you simply can't display a message box.
And technically using an exception to termniate the app is a violation:
5.1.2 The application must handle exceptions raised by the .NET Framework and not close unexpectedly. During the certification process, the application is monitored for unexpected closure. An application that closes unexpectedly fails certification. The application must continue to run and remain responsive to user input after the exception is handled.
As a developer, part of your job is communicating to users about requirements that are unrealistic or unreasonable.
Sorry, no way to do this. Before mango update you could Clear the back stack, then programmatically trigger the Back button. but as of SDK 7.1 (wp7.5) we can no longer do this.
My recommendation is to create a custom Exception type ApplicationXExitException and throw that to exit the app. The reason for the custom type is so that when you pull your exception logs from the marketplace, you'll know the ones that were indeed unintended exceptions crashing the app, vs your exception to intentionally exit the app.
You can hook an event raising after your custom messagebox closes. Event arguments will keep information about user's choice. Depending on that you will decide whether to exit app or not.

CreateProcessAsUser() not showing CreateWindow of running Process [C#]

My system has 2 accounts (USER and ADMIN) and a service (Service.exe) running under LocalSystem.
The user logs into the USER account, the LocalService can then launch a process (CreateProcessAsUser(...)) as the ADMIN user.
The process the Service runs (Tool.exe) is a legacy C++ application that performs a job and also displays information to the user by using CreateWindow(...), but when launching it by the Service the Window does not show...
When the process is created by the Service I first load the Profile & Environment of the ADMIN user so that the correct context is used ...
(was still hoping the Window would display to USER)
Now, initialy I thought this would cause a problem as ADMIN is running the process so why would the CreateWindow(...) output in the USER desktop, so I tried with a simple command-line test.exe app and when launched as ADMIN the Command Prompt window appeared - so why does that work fine where-as the CreateWindow(...) doesn't display correctly?
Any clues on how I can get the STATUS (using CreateWindow in Tool.exe) running under ADMIN to show in the USER logged-on session?
Can I use the ENVIRONMENT somehow, I tried the following thinking it might work but didn't:
startInfo.lpDesktop = #"WinSta0\Default";
startInfo.dwFlags = STARTF_USESHOWWINDOW;
startInfo.wShowWindow = SW_SHOW;
The Window is created as follows (in Tool.exe):
HWND hwnd = CreateWindow
(
"Tool",
"Tool WINDOW",
WS_POPUP | WS_VISIBLE,
0,0,uWidth,uHeight,
NULL,
NULL,
hInstance,
Text
);
Is the lpDesktop wrong (not exactly sure how this works)?
I know how crazy this sounds - I just would rather not have to launch another ToolDisplay.exe as USER which communicates with Tool.exe as ADMIN as a display when the Tool.exe used to handle everything on its own - so checking to see if there isn't some nice way to handle this...
Any help would be much appreciated...
Thanks,
[Simplified Question:]
My system has 2 accounts (USER and ADMIN), the user is always logged on as USER but at some specific times a process (Tool.exe) is launched under the ADMIN account (by a LocalSystem Service using CreateProcessAsUser(...)), almost everything works fine except for the fact that the process (Tool.exe) is supposed to display status to the user using CreateWindow(...).
When Tool.exe is running (as ADMIN) and the user is logged-on as USER the window is not shown (obviously)...
Is there a way to show the window of Tool.exe running under ADMIN to the user logged-on as USER?
Any help would be much appreciated...
Thanks,
Just in case you want a window / GUI spawned by a service to be visible,
Go to-> run prompt -> services.msc -> go to your service's property, check "Allow service to interact with desktop".
Then restart your service.
Note that in Vista, the prompt will NOT be visible even after above. This is due to sessions issue. However there is a service which helps support prompts from services (I think it is Interactive Services Detection service).

Categories

Resources