OSK at winlogon (before logon) *and* on user desktop (after logon)

By: Frank Rysanek of FCC prumyslove systemy s.r.o. [rysanek (AT) fccps.cz]

Intro

In embedded / industrial PC hardware, on machines with touch screen only (no keyboard), you often face a requirement to have the Windows standard "On Screen Keyboard" available all the time, both "at winlogon" (when no particular user is logged in) and after logon, i.e. on a particular user's desktop.

Credits / past references / first efforts

Everybody's obvious first guess would be to run OSK.EXE using a shortcut from the "Startup" folder in the start menu, or from HKLM/Software/Microsoft/Windows/CurrentVersion/Run. That however doesn't work quite right - it runs OSK only after a particular user logs in. If you need to use OSK to log in as a particular user in the first place, this is a dead end.

Surfing the web, you can find a handful of references that point you all vaguely in the same way: you need to run OSK as a service, and it has to be a service that's allowed to "interact with desktop". And the usual suggested way of doing it is through "gpedit.msc" (Group Policies) -> "Computer Configuration" -> "Windows Settings" -> "Scripts", double-click "Startup", "Show Files", create a batch file (say osk.bat) containing just "C:\Windows\System32\osk.exe", back to the "Start Properties" dialog, and finally "Add" the batch file... And then you also have to enable "synchronous" script startup in "Computer Configuration" -> "Administrative Templates" -> "System" -> "Scripts".

Give credit where credit is due - here's a particular reference.

Thanks a lot for that hint, it got me started. It works to the extent that indeed the OnScreen Keyboard does become available within 5-10 seconds after the WinLogon dialog appears.

Early dead ends

The one problem may be, that as soon as some user logs in, the window of OSK.EXE becomes hidden (unavailable). The instance of OSK.EXE that was launched via the system startup script runs under the "SYSTEM" user (a requirement for desktop-interactive services) and has attached to the "WinLogon desktop", which is a different desktop than the one instantiated for the newly logged in user.

So, if you want to have OSK also available for the user who's already logged in, your obvious guess would be to run OSK.EXE using a shortcut from the "Startup" folder in the start menu, or from HKLM/Software/Microsoft/Windows/CurrentVersion/Run. Guess what: it doesn't work! :-) This time the trouble is, that there is a pre-existing instance of OSK.EXE running "in the background" on the WinLogon desktop (now hidden), and a new instance for your particular desktop refuses to start up.

This can be verified by killing the pre-existing instance of OSK.EXE via the task manager. Once you kill the old one, another one starts up just fine for your logged-in desktop. So you could just insert a batch file into the Startup menu or HKLM...Run, that would first kill the old instance using taskkill, and then start a new one, which would automatically bind to the current desktop. But there's another caveat: how do you re-start the global instance running under "SYSTEM" on the WinLogon desktop, when you need to log out, in order for another user to log in again? Logout scripts are possible via gpedit.msc, but those run still under the user who's just about to log out, and a user logout is not the same as a total system shutdown. => another dead end...

NSSM to the rescue: a somewhat improved launch method of "OSK as a service"

While I was googling around for something to "run an arbitrary app as a service", I first discovered the venerable NT/W2k resource kit addon called "srvany". It's not very clever (doesn't re-start the app "running as a service" if it dies), and it's a bit cumbersome to install (cmdline command + a manual mod via regedit).

And the very next thing I discovered was NSSM - a much needed replacement for srvany. It takes a single cmdline spell to install (create an NT service and insert a link to the target app) and it keeps respawning the target app if it dies. Which is useful in two important ways: it saves a user who accidentally closes OSK at the WinLogon desktop, and it helps to mainain OSK visible after logon. How come? Read on.

Installation instructions: Download NSSM, unpack nssm.exe from the ZIP file and drop it someplace into the shell path, maybe preferably into C:\Windows\System32\ as that's where such system utils tend to live. Next, open a Windows command prompt window and type

nssm install "On Screen Keyboard" C:\Windows\System32\OSK.EXE

It should respond with
Service "On Screen Keyboard" installed successfully!

Next, go to the "services" control panel (Start -> Run -> services.msc), find "On Screen Keyboard", open its properties and enable "interaction with desktop" (needed for OSK, which is a GUI application). All you need to do next is start the service right there, or maybe reboot the system, if you want to check that it really does work automagically starting from a cold boot :-)

Once you log in, obviously the instance of OSK originally launched via NSSM becomes invisible. So the first thing you probably do, without giving it much thought, is kill that stale instance of OSK.EXE. Voila, OSK becomes visible right away! Heh, wait, does this make any sense? When the (now hidden) instance of OSK dies, NSSM (the actual NT service) notices that and respawns OSK.EXE. OSK is again respawned under the "SYSTEM" user, but it does bind to the currently active desktop! :-) But... uh oh. No good. This is interesting. Both your keyboard AND the OSK work fine for the Windows command prompt window. But, the keystrokes never make it into GUI applications, such as the Notepad, or the Start menu "Run" text box. This is so sad... if it wasn't for this ugly glitch, you could really do with that single "taskkill" at logon, because at logoff, the current instance of OSK is automatically killed, and NSSM respawns it to the WinLogon desktop automagically... so very sad.

So you CAN NOT just put "taskkill /F /IM OSK.EXE" into the Startup folder or gpedit.msc logon script, and get the OSK "persistent across logon". You do need to stop the MSSN "On Screen Keyboard" super-service explicitly at logon, run an explicit OSK.EXE under the current user, and re-start the "On Screen Keyboard" service again at logoff, but only after killing OSK.EXE. You have to set up the following two scripts for user logon+logoff via gpedit.msc (-> "User Configuration" -> "Windows Settings" -> "Scripts"), which will be common to all your users:

At logon, suggested script name = osk_logon.bat :

C:\Windows\system32\sc stop "On Screen Keyboard"
C:\WINDOWS\system32\osk.exe

At logoff, suggested script name = osk_logoff.bat :

C:\WINDOWS\system32\taskkill /F /IM osk.exe
C:\Windows\system32\sc start "On Screen Keyboard"

In addition, as the "current user" instance of OSK.EXE doesn't respawn automatically, the users should have some chance to run OSK using their mouse, e.g. using a shortcut on the desktop, or in the start menu, or from a dedicated app running full screen.

Remaining unresolved issues

If you have unprivileged users (users who aren't granted admin privileges), you will have a problem stopping the service from a "logged in user" context. All your users must have admin privileges for this solution to work. If there's an easy way out of this via some selective permission settings on restricted user accounts, please let me know...

You cannot have multiple users logged in in parallel, just switching from one user session to another. The logon/logoff scripts don't get run when "switching users", the "global instance" of OSK (run as a service) wouldn't be available at WinLogon when just switching users, and your users wouldn't be able to log on (to finish the switch). Unfortunately, the start menu item "switch users" (a part of the Logoff dialog) cannot be disabled selectively. You can only disable the whole "log off" item from the Start menu and add an alternative shortcut to the "logoff" command. For the same reason, it's advisable to disable automatic fallback to the WinLogon screen (screensaver password protection), so that your users don't get locked out.
Other than that, it would be possible to add an "OSK respawn shortcut" to the desktop of every user, for the purpose of switching users - but that alone doesn't save you from the WinLogon lock-out.
If there is some way to run a script/program before AND after switching to another user session, please let me know...

Obviously none of this sorcery would be needed, if OSK itself was a proper accessibility helper, inherently persistent on the desktop and switching desktops on the fly... shouldn't be that much of a problem for the big OS authoring company, right?