Link to home
Start Free TrialLog in
Avatar of tdubroff
tdubroff

asked on

Boot Windows98, hide desktop, launch application?

Does anyone know a way, or can anyone refer me to information on how to boot Windows98 to directly enter my GUI application, completely hiding the desktop from ever being seen?
ASKER CERTIFIED SOLUTION
Avatar of feenix
feenix
Flag of Finland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of tdubroff
tdubroff

ASKER

Feenix, I did a quick test with winword.exe.  Figured that it would load right into Word, but instead it said there was an error and that I should reinstall Windows!  I'll do another test tomorrow with my executable, but do you know the reason this is happening?
I haven't gotten that kind of an error ever. Did you remember to put the whole path to the ini file? E.g. C:\dir\program.exe? Otherwise it won't work and it might give you that kind of an error.
I put the whole path in.  I'll test with a new executable shortly.
COOL THAT WORKED!

I used an MFC-based app with MFC dlls statically linked and it worked fine.  

I've also added an _onexit function that logs the user off when the app is closed.  However, what I'd really like to do is allow an admin to get to the desktop on app exit, but anybody else gets logged off.

Can you offer more help?
As far as I know, the desktop cannot be started from a program, so if you set the shell to your own program, you have to change the value and boot to get the normal desktop back.
I figured I'd post this here as well, so that if people use the search engine they'd get an update.  Also, thanks for your help feenix and hopefully this will also help you.

"Boot Windows into your own application first, then goto desktop"

I recently inherited a project in which a PC running Windows98 executes
an application which controls various hardware components in a system.
This system, including the controlling PC, is delivered directly to end
users.  The PC exists only to run the controller application and house
a database that stores information on how the system is used.  End users
need not - and should not - have access to the database, file system, or
anything which may affect the way the PC is to be used in the system.

When I inherited the project, a shortcut to the controller application was
placed in the Startup folder.  So after Windows loaded the desktop and
explorer (start button, desktop icons, etc visible) the controller
application started.  The problem with this is that end users may still
access the PC normally by simply clicking on the start button and then
gaining access to anything in the computer.

To provide a better modicum of protection to the PC's file contents, I
made the PC boot directly into the controller application, skipping
the usual Windows Shell (no start button, no system tray, no desktop icons,
no executables visible in the Task Manager).  I also edited the application
so that when the end user quit from the application the PC was shutdown.  
However, when a maintainer quits from the application the familiar Windows
desktop is loaded.

I pieced together how to do all this from https://www.experts-exchange.com as
well as Dino Espisito's book, 'Programming the Windows Shell'.  Both
items are great resources for the person starting to learn how to
program in/with Windows.  I realize the solution presented is not perfect;
any computer-savvy end user could easily bypass the controller application
if they really wanted to.  So, if you have information which would improve
on the security setup, please email me at tdubroff@cris.com.

Several people on experts-exchange suggested editing the system.ini
file to boot directly into the controller application.  If you replace
shell=explorer.exe with shell=controllerapp.exe then the desired effect
is gained; Windows will boot directly into the application without the
start button, system tray, or any desktop icons visible.  The problem with
this method is that it does not allow for the loading of the normal desktop
if a maintainer is using the system.  Even the normal programatic ways of
restarting the Windows shell do not work; simply ShellExecute-ing
explorer.exe and systray.exe only cause a Windows Explorer view to pop up.

Another clue that this is not the right way to do this, is that when a
critical update for Windows (lets say) is downloaded, the user is often
prompted to restart the machine.  Why restart the machine?  Because when
a PC is already booted up and running, several system files have already
been loaded into memory and cannot be changed.  A sharing violation will
occur if the attempt is made to change any of these files.  However, when
a PC is restarted there is a short time period where these system files
are not yet being accessed and software running during this time can go
ahead and modify these files.  It is this time period where the controller
application is executed.

How did I do this?  Well one way appeared to be editing the system.ini
file.  However, I just discussed why this was not feasable.  Also, editing
the system.ini file is surely not the way Microsoft performs critical
updates.  Editing the system.ini file only allows for explorer.exe to
be replaced by a single other piece of software (some other *.exe).  
But it could very well happen, and it often does happen, that multiple
executables need to be run before the Windows Shell really gets into the
swing of things.  So, how to designate that certain software should run
before the normal desktop is loaded?  The solution is to use the Registry.  

Inside HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion exist two subkeys entitled Run and RunOnce.  It turns out that the Windows boot-up process executes any values contained within these keys before or during the Shell bootup.  Under the Run subkey, systray.exe is found.  This is the executable that is responsible for initializing the system tray and
displaying the start button.  Because the controller application needs to
execute before the start button is made visible, I did not place it as a
value inside the Run subkey.

Instead, I used the RunOnce subkey.  In Dino Espisito's book he shows that
during bootup, Windows executes the values inside the RunOnce subkey in an optimal time period just after all the normal Windows services are started but before any registered programs are completed and before the contents of the Run subkey are executed.  The only hickup in using the RunOnce subkey is that after the value is executed, the entry is deleted, thus making the entry run once and only once.  The Run subkey does not have this feature. Any item in the Run subkey will execute everytime Windows is booted up.

So here's where I got a little bit tricky.  I placed the following value
in the RunOnce subkey:

      ControllerApp      "c:\controller\controller.exe"

I then changed the controller application code to set this key every
time an end user closed the controller application.  Also when an end
user closed the application I called the Windows API function ExitWindowsEx() which causes the PC to shutdown.  Shutting down the PC of course prevents it from running any other applications inside RunOnce, or Run for that matter.

Here is a snippet of the code I'm talking about:

      int ControllerApp::ExitInstance()
      {
          if (!g_UserIsMaintainer) {

              // Add the RunOnce registry value for this application
            CString subkey = "Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce";
            CString keyValue1 = "ControllerApp";
            CString keyValue2 = "c:\\controller\\controller.exe";

            HKEY  hKey;
            RegOpenKeyEx(HKEY_LOCAL_MACHINE, subkey, 0, KEY_SET_VALUE, &hKey);
            RegSetValueEx(hKey, keyValue1, 0, REG_SZ, (BYTE*) keyValue2.GetBuffer(0), keyValue2.GetLength()+1);
            RegCloseKey(hKey);

              // Turn off the PC
            ExitWindowsEx(EWX_SHUTDOWN,0);
          }
          return CWinApp::ExitInstance();
      }

To make very clear, if the user is a maintainer of the system, the controller
application is not reinstatiated under the RunOnce subkey and the PC is not
shutdown (maintainer's must be able to get to the desktop).

Why didn't I just simply replace the controller application in the RunOnce
subkey every time the controller application was started, regardless of end
user or maintainer?  Actually, that's how I started out.  But the infinite loop
I had created showed me the error of my ways.  Windows will execute each item in the RunOnce subkey and then remove that item and continue on to the next item to execute.  My controller application itself kept adding a new value, so when the application finished for a maintainer (no call to ExitWindowsEx()), Windows lo and behold found another value under RunOnce, my app again!

What I have described up until now is perfect if the application is only ever
used by end users.  The PC will boot up finding the controller application
in RunOnce and it will execute it.  When the end user is done with the system, the application will reinstantiate the RunOnce subkey and shutdown the PC.  If on the other hand, a maintainer boots up the PC and quits the application, the RunOnce subkey will not contain the call to the controller application.  

This is bad news.  This means that the next time an end user logs in, the
controller application won't automatically start and furthermore the normal
Windows Shell, start button included, will boot up - waiting for the end
user to presumably wreak havoc or at least put a call into customer support.

The final solution then is to put a helper application under the Run subkey,
which when executed reinstantiates the controller application under the
RunOnce subkey.  Note that if a value already exists under a key it will
simply be replaced, not duplicated.  Therefore the Run key will contain the
following:

      ReinstateController      "c:\controller\reinstate.exe"

So, if a maintainer exits the controller application, Windows will eventually
execute the helper application because it is placed in the Run subkey.
The helper makes sure that the next time the PC is booted the controller
application will start up again.

I hope this helps people in similar circumstances.

-Ted