Am I missing an obvious alternative to a Windows Service? - c#

I'm working on a small piece of software which is designed for some special Windows based kiosk devices. It listens for certain keystrokes/commands using a driver, intercepts them and performs certain actions.
At the minute, I've got my Proof of Concept working great. I can either run it as a console application in the background, or I've also built it as a Windows Service. The Windows Service is really effective and is working well, but a colleague has hinted that it'd be good to be able to do tasks based on what user application/window is active - something I can't do (legitimately) from a Windows service because it can't enumerate user applications.
The obvious solution would be to simply run it in the background - no drama there, except these kiosks use a custom Windows shell (Deployed using Group Policy). Because of this, the normal explorer Run keys don't initialise. I'm now at a loss on how to make my software autorun in this scenario?
Alternatively, if someone has a workaround for enumerating active windows and such for a specific user from a Windows service I'd be interested in that. NB: I don't need to actually do anything TO the desktop, just read data.

Windows Vista and above won't let a service interact with desktop apps at all, part of the new focus on security in the OS. I have something similar (in spirit) that I developed for an application system, which enumerates windows looking for a specific legacy app then sends some messages to it (all very much above-board, no other way to automate the creaky old app). I just launch it as a system-tray app when people log on, using Group Policy. But I don't have the issue of a custom Windows shell that you're apparently dealing with. Good luck!
So, userinit (HKLM\Software\Microsoft\Windows NT\Current Version\Winlogon\) probably isn't a particularly bad place to do this, but there should be an alternative or two. It's actually a little silly (if you ask me) how many Autorun locations have cropped up in Windows over the years.
The following is largely copied from http://www.bleepingcomputer.com/tutorials/windows-program-automatic-startup-locations/, with an update or two. I figured it might be handy here, too, and who knows what will remain live on the web forever (or not)?
Other Autorun locations include the following in order:
Boot device drivers
Hardware related.
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services
Windows does some housecleaning then starts Winlogon, which starts the service control manager, which starts services and drivers.
Services
The SCM launches services and drivers that are marked with a Start value of 2.
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services
RunServicesOnce
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunServicesOnce
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunServicesOnce
RunServices
HKLM/.../RunOnce entries won't run until these finish starting.
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunServices
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunServices
** The logon prompt is shown, user logs on, then auto-start processing continues.
Notify runs programs in response to events, including logon, logoff, startup, shutdown, startscreensaver, stopscreensaver. Malware often uses this key to start itself.
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Notify
UserInit specifies programs that should be launched immediately after a user logs on, takes a comma-separated list of programs. The default userinit.exe program loads your profile. Also a common key for malware to use.
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\Userinit
Shell contains a comma-separated list of programs that userinit.exe will launch. The default shell is explorer.exe. First the program(s) in HKCU are launched, then the ones in HKLM.
HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\Shell
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\Shell
** The rest of the Autostart locations are processed now...
RunOnce (HKLM) Primarily intended for setup programs, deleted by the OS after the first run if the path is preceded by an exclamation point (!), else deleted before the program runs. These programs are started synchronously in an undefined order, so they must all complete before the HKLM/.../Run, HKCU/.../Run, HKCU/.../RunOnce and Startup folders can be loaded. These keys are ignored when booting in safe mode.
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnceEx
Run Most common startup locations for standard programs to autorun from, ignored in Safe Mode unless prefixed with an asterisk (*).
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
Startup Folder (All Users)
Win7 and up %ProgramData%\Microsoft\Windows\Start Menu
Win XP/2K C:\Documents and Settings\All Users\Start Menu\Programs\Startup
Startup Folder (Per User)
Win7 and up %USERPROFILE%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
Win XP/2K %USERPROFILE%\Start Menu\Programs\Startup
RunOnce (HKCU) intended primarily for setup programs, same semantics as the HKLM RunOnce key (above).
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce
Explorer Run generally used to run programs as per policy configuration.
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run
Load Key deprecated, not commonly used anymore.
HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows\load
AppInit_DLLs this registry value contains a list of dlls that will be loaded when user32.dll is loaded. Many programs load user32.dll, so anything listed here gets loaded into all of those programs, as well. Used by malware.
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows
ShellServiceObjectDelayLoad similar to the Run key, but points to a registered CLSID InProcServer value. Files listed under this key are automatically loaded by Explorer when the computer starts, early in the startup process.
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\ShellServiceObjectDelayLoad
SharedTaskScheduler Files listed here run automatically when you start Windows.
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\SharedTaskScheduler
Other potential autostart locations, depending on the OS:
c:\autoexec.bat
c:\config.sys
3 . %WINDIR%\wininit.ini - Usually used by setup programs to have a file run once and then get deleted.
%WINDIR%\winstart.bat
%WINDIR%\win.ini - [windows] "load"
%WINDIR%\win.ini - [windows] "run"
%WINDIR%\system.ini - [boot] "shell"
%WINDIR%\system.ini - [boot] "scrnsave.exe"
%WINDIR%\dosstart.bat - Used in Win95 or 98 when you select the "Restart in MS-DOS mode" in the shutdown menu.
%WINDIR%\system\autoexec.nt
%WINDIR%\system\config.nt

I've got the end result I want by adding my application to the UserInit registry key:
HKLM\Software\Microsoft\Windows NT\Current Version\Winlogon\
Userinit c:\windows\system32\userinit.exe,c:\myapp\myapp.exe
This works great, but does seem incredibly hacky and I'd love alternatives.

Using a Windows Service is the best option and since services are isolated in Session 0, you can have this service starts another exe upon user logon, by calling [CreateProcessAsUser][1]. In fact, the service executable can call itself with a parameter indicating that it is invoked as a user and therefore all User Interface parts (which normally won't work from Session 0), will be enabled.

Related

Running sub application in the normal mode when the base application is in the administrative mode

I have two application which is a main and a sub. both can also be opened separately and the main can also open the sub.Since the main application is in the administrative mode, the sub-application when opened from the main application is also opening in the same mode. Is there any possible way where can I open the sub-application in a normal but I need to have the base application running in the admin mode. The problem is I need to drag and drop files in the sub-application which cant be done when the application is in administrator mode.
Getting rid of Adminsitrative Privileges is surprisingly hard. It is nigh impossible to get rid of them, like starting a non-Elevated Process from a elevated one. It is a a vexing property of Windows.
There are ways but they usually involve unmanaged code (Windows API) and are not that stable.
It is possibly if you have the Application user/System Adminsitrator Specify a specific Windows User that he he maintains explicitly as one without Administrative Privileges. The way most non-elevated Services are started is by a explicit Windows User that is set in the Service Manager.
Most programmers eventualy settle to dodge this Problem entirely via an approach like this:
Have both Process A and B designed to always start non-Elevated (no Manifest or anything demand Elevation)
Modify Process A to detect that it is non-Elevated right now
Let Process A try to start a Elevated copy of itself via Runas with proper Options.
If the user is always Elevated (because the UAC is turned off or soemthing like that), it is out of your hands.
As I learned the hard way, there is also a chance that elevation might fail due to faulty Windows configuration. Again, this is out of your hands.
Of course there is the big question of why this is a Problem to begin with and if that is perhaps a XY Problem. Drag & Drop might have those limits. But do you have to use D&D for this? There are many ways to go about Interprocess Communicaiton. Most of them do not suffer such Limitations. D&D is just one of them.

C# - An approach for an automatic updater for a windows app

I have a windows app (written in C#...) that is installed on multiple remote workstations, the installation is being done by a MSI package.
An updated installation with changes to the program is being conducted from time to time, at this point, for each update, for each station we need to go to where the .MSI is located copy it and run it and only than start the app.
I would like that: whenever a user tries to start the app a background process will be initialized that will compare the installed version with the most recent version on the .msi location and if an update in needed will run the installation and than start the app.
The problem is that it can't be done from within the program since the program cannot be running when the installation/upgrade is taking place. Another consideration is that not all the stations operating at the same time so I can't schedule a timely upgrade, and it can't be done on stations boot since sometimes the updates needs to be done while the station is already operating(the station has several functions beside my app).
I have considered several approaches, it seems like a windows service could do the trick but I don't know if it could be "bound" to the initialize of the program and if it could suspend the program to do the necessary checks and updates and only than to restart the app.
I am open to all ideas so please don't feel obligated to my ideas...
at this point, for each update, for each station we need to go to where the .MSI
is located copy it and run it and only than start the app.
Fire the guy pretending to be a system administrator.
Unless you have done something odd in your installer - it should be doable with your standard software distribution package. Heck, I can roll out updates with active directory ONLY and no third party software as long as the MSI allows administrative no ui installs.
You try to fix a non-problem. Software distribution is a solved solution for the last 15 to 20 years. MSI was particularly created to handle this issue because other approaches demonstrated issues.
So, whoever pretends to be the administrator on your company needs to get his act together and be one. Do nothing (except making a good MSI) and let the admin do his job.
Everything else just creates a lot of problems (at least in the cost side). And it is totally not needed.
I'm updating my answer,
This is what we did....
Create the Installer / Package ( you can install for all users here)
Generate Bootstrapper (https://msdn.microsoft.com/en-us/library/ms165429.aspx
You can use this tool create bootstrapper (http://www.softpedia.com/get/Programming/Other-Programming-Files/Bootstrapper-Manifest-Generator.shtml)
Add dependencies and other conditions in bootstrapper
Set the URL for updates
This will solve your problem. I was too quick to answer but this how we did.
Thanks.
Some comments and answers about the assumptions in the question:
"I would like that: whenever a user tries to start the app a background process will be initialized that will compare the installed version with the most recent version on the .msi location and if an update in needed will run the installation and than start the app."
The only time this is likely to be a useful approach is when the MSI is at a company's web server. The web site can host a web api that you send your ProductCode, Version, Upgrade to and it reports whether there is an upgrade, patch etc, and a location to download it from. In a company domain, just use AD, as has been said.
"The problem is that it can't be done from within the program since the program cannot be running when the installation/upgrade is taking place."
Why? Windows Installer will show FilesInUse dialogs for the end user to close down the running app. So this situation is already dealt with, and I'm not sure where you see a problem.
"...and if it could suspend the program to do the necessary checks and updates and only than to restart the app."
This is exactly what Restart Manager is for. Integrate your app with RM and Windows Installer will allow you to close down the app (saving whatever data you need to recover) and then restart you afterwards so you can recover your data and the user sees a minimal interruption. One example:
http://www.codeproject.com/Articles/772868/Restart-Manager-Support-For-Windows-Application
So I think TomTom's point is valid - there is no need to re-invent what AD does, or worry about how to update programs that are running, or how to restart a program after an installer update because all these problems were solved years ago.

Need deployment strategy with auto-update on all users

I need a deployment method that do following thing:
Auto-update, like click-once;
Install on all users, like Visual Studio Setup projects.
without admistratives privileges. (except the first times for the requirements)
Can install VB Powerpacks.
The problems is that I'm making a winforms program, that might need to be updated anytime, and that our computers are use by many users (our company run 24hours/days). And we don't want to update my program manually on our 80 computers, for each users!
Click-once could be great if we can do an install for all users (but yes, I already find that it's not possible).
I'M STUCK! Please help.
We use a system where the shortcut to launch our application actually launches an auto-updater. The updater checks the server for any update dlls, and if it finds them, it copies them to the local machine. After that (or if it didn't find any updates), it then launches the application.
This will only work if you have some way to force everyone to log out every now and then. We get around that by having the application watch for a specific file to be updated (the exe itself), and alerting the user every 5 minutes until they relaunch.

How to allow users only interactive with my program?

I'm writing a software for a call-center. It's somewhat like a ATM program: user can only interactive with it, not with underlying Windows. It takes controls when user logs in to Windows, and when user exits, it logs off Windows.
How can I do that in .NET? A demo will be much appreciated.
Thank you.
Replace the Windows Shell.
By that I mean Explorer.exe, by means of editing the Windows Registry. What this does for you is instead of logging on and the system running Explorer.exe which consists of the Start Menu, Taskbar and other similar features you are familiar with, it only runs your program. There is no desktop, no context menu, no taskbar, or start menu. Thus, making your application "The Shell" or the new "Explorer.exe".
However, by doing this the user still has access to Control+Alt+Delete, so they would still be able to access the Windows Task Manager, which mind you can also be disabled via a simple Registry Key Entry.
This is the most pain free, easiest solution because you don't even have to worry about things such as disabling the WindowsKey or other annoyances.
The registry key to this is as follows:
SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon
The name of the value to modify is:
Shell
And you can simply enter the value to be the fully qualified path to your program's executable file. You will only want to do this under HKEY_CURRENT_USER and only for the account that is to run your shell program. So you will need two separate accounts.
Administrator account
This account will just be a normal password protected account that will be used to manage the system
Kiosk account
This account will be the account that is logged on at all times, which runs your custom shell (your application)
Additional Notes
To disable the Task Manager the registry path is as follows:
Software\Microsoft\Windows\CurrentVersion\Policies\System
The name of the value is:
DisableTaskMgr
This is a DWORD value which to enforce the policy must be set to '1'.
What I did was to use DirectX and just use full-screen and exclusive modes, which you can see a small example of here: http://www.directxtutorial.com/tutorial9/b-direct3dbasics/dx9B2.aspx.
This is more work, but it will allow you to do what you want.
Depending on what control you have, there are steps you can do with group policy to limit what people can do on the computer. You can look at how people set up a kiosk application on Windows for some ideas.
What you want to do is run the OS in "kiosk mode".
This entails using the Group Policy Management Console to apply the kiosk mode template - as part of this you register your application as the shell.
As such there is no taskbar, or explorer view to fall back on to. The only way to run the usual shell would be to connect a keyboard to the system - press ctl-alt-delete and run explorer from the taskmanager that pops up.
And you can disable even the standard task manager if users are going to have keyboard access to the console. You will want to implement some kind of launch explorer.exe interface otherwise the system might become a bit difficult to manage :P
You can set your applications window to be always on top and to cover the entire screen. If you exclude buttons that close the window the user must know that ALT+F4 closes the window in order to exit. This has been good enough for me those times I've needed it.

How to restart my application if Windows Update forces a reboot?

At the office, when I leave for the night I very rarely log off or reboot. I simply lock my workstation and go home, leaving all my development tools exactly how I left them.
If Windows-Update rolls through and reboots my machine in the middle of the night I'm only slightly peeved because when I log back in the next morning, any MS Office application, or Visual Studio instance I had running will have already automatically restarted, opening whatever file(s)/projects/solutions I may have been working on.
My question is: How can I make my Windows Forms applications (C#) do this? Is there some way for my application to "register" that it wants to be restarted if the system automatically reboots?
I think the RegisterApplicationRestart Win32 API function might be what you're after, it's part of the Restart Manager API.
If you have Windows Vista or Windows 7, you can use the Managed Restart and Recovery API. The links on that page also point to some useful blog entries
http://channel9.msdn.com/posts/DanielMoth/Windows-Vista-Restart-amp-Recovery-APIs-from-managed-code/
A simple way is to add an entry to the following registry key :
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce
Just create a value containing the path of your app (optionally including command line arguments). The app will be run at the next startup, then the value will be deleted.
Step 1: Figure out a way to differentiate a windows-triggered restart from a standard one. One solution would be to try preprocessing messages. They're probably different for a windows-triggered restart...or at least they are in Vista in some cases :/
Step 2: If you detect it's a windows-triggered restart, add a scheduled, one-time task.

Categories