Solved

How to end Win2K screen saver, or make Win2K reboot when screen saver is on

Posted on 2004-10-22
324 Views
Last Modified: 2013-12-03
I have a 24x7x365 server application on a dedicated Win2K box.  I want my application to restart Windows at a pre-determined time every day (or by a remote command at any time).

I have the code to successfully reboot Windows 2000 using ExitWindowsEx() but this fails to completely shut down Win2K if the password-enabled screen saver is on.

Another acceptable solution would be to programmatically log back in, if that's possible.

If this stuff is easy to find, take it easy on me:  I'm on-site 200 miles from home and have to try to get home for dinner!

Rob---
0
Question by:RHenningsgard
    14 Comments
     
    LVL 86

    Expert Comment

    by:jkr
    You'd find the process that has a .scr extension and terminate it. See http://support.microsoft.com/kb/q175030/ ("How To Enumerate Applications Using Win32 APIs") on how to find it and http://support.microsoft.com/default.aspx?scid=KB;en-us;178893& ("How To Terminate an Application "Cleanly" in Win32") on how to terminate it.
    0
     
    LVL 86

    Expert Comment

    by:jkr
    BTW, have you tried 'InitiateSystemShutdown()'? This should work with a running screensaver (even a protected one) also. At least it did when I tried it last...
    0
     
    LVL 2

    Author Comment

    by:RHenningsgard
    Thanks!  I kind of thought that might be the approach to take.  I'm punting for today, just restarting my application instead of the reboot, so I can get home.  Will award points on this after I get a chance to implement it.
    0
     
    LVL 2

    Author Comment

    by:RHenningsgard
    Well, I got part-way there.  I can enumerate processes and find the screen saver and its process ID, but I can't get a window handle to the screen saver, to send it a WM_CLOSE message.  I tried using FindWindow to no avail.  Works on apps like NOTEPAD.EXE, but it returns a zero handle for the screen saver.

    [[later:  Maybe the problem is that I was running the screen saver from the properties dialog, using the "Test" button.  I'll try this tomorrow with the screen saver actually having timed out]]

    I also took a stab at using EnumWindows() to give me all of the existing window handles, and then GetWindowThreadProcessID to hopefully match up one of the window handles to the screen saver's process ID.  In this I was unsuccessful at getting anything but zeroes back from GetWindowThreadProcessID, so I must be doing something wrong there.

    Do you suppose the approach I'm taking will work, once I actually get my GetWindowThreadProcessID call working properly?

    Any other suggestions?

    Rob---
    0
     
    LVL 86

    Expert Comment

    by:jkr
    >>but I can't get a window handle to the screen saver, to send it a WM_CLOSE message

    Um, user 'TerminateProcess()' on the process handle and leave the window handle out :o)

          // Wait on the handle. If it signals, great. If it times out,
          // then you kill it.
          if(WaitForSingleObject(hProc, dwTimeout)!=WAIT_OBJECT_0)
             dwRet=(TerminateProcess(hProc,0)?TA_SUCCESS_KILL:TA_FAILED);
          else
             dwRet = TA_SUCCESS_CLEAN
    0
     
    LVL 2

    Author Comment

    by:RHenningsgard
    Several attempts with TerminateProcess did not succeed.  Is the ProcessID enumerated by Process32First/Next the process handle, or is there a level of indirection there I need to traverse to get the process handle?

    Also tried setting SystemParametersInfo(SPI_SETSCREENSAVEACTIVE,0) to no avail, despite it returning true.

    I even tried launching the screen saver using ShellExecute(), saving the HInstance handle, and passing that later to TerminateProcess.  No joy: The screen saver keeps merrily running along.

    Seems either I'm more inept than I thought, or programmatically shutting off the screen saver is tougher than I expected!

    I'm still open to suggestions.
    0
     
    LVL 86

    Expert Comment

    by:jkr
    >>Is the ProcessID enumerated by Process32First/Next the process handle

    The process ID is a process ID - to obtain a handle, you need to 'OpenProcess()', e.g.

       #define TA_FAILED 0
       #define TA_SUCCESS_CLEAN 1
       #define TA_SUCCESS_KILL 2

       DWORD WINAPI TerminateApp( DWORD dwPI )
       {
          HANDLE   hProc ;
          DWORD   dwRet ;

          // If we can't open the process with PROCESS_TERMINATE rights,
          // then we give up immediately.
          hProc = OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE,
             dwPID);

          if(hProc == NULL)
          {
             return TA_FAILED ;
          }


             dwRet=(TerminateProcess(hProc,0)?TA_SUCCESS_KILL:TA_FAILED);
          else
             dwRet = TA_SUCCESS_CLEAN ;

          CloseHandle(hProc) ;

          return dwRet ;
       }

    BTW, have you tried 'InitiateSystemShutdown()'?
    0
     
    LVL 2

    Author Comment

    by:RHenningsgard
    Hey jkr, (apparently nobody would bother to take you on for a question like this... you must be the EE authority on stuff like this!)

    Got to dash off to the customer site, so will not get to this until the morrow.  As you can tell, I am a newbie to most of the inter-process communications and controls in Windows, having programmed about 99.9% just individual applications.  I appreciate the education you're spooning out to me.

    <<The process ID is a process ID - to obtain a handle>>

    Yep, I figured that had to be the case.  Thanks for the OpenProcess() example.

    <<BTW, have you tried 'InitiateSystemShutdown()'?>>

    Sorry I didn't mention it:  That was the first suggestion I tried.  It doesn't shut down the screen saver.  Works fine if the system is logged in and running normally, so I assume I called it correctly.

    More to come...
    0
     
    LVL 2

    Author Comment

    by:RHenningsgard
    Hello again jkr,

    Well your suggestion works perfectly, unless the screen saver has the "[X]Password protected" option selected.  When that's the case, the password dialog pops up, and that's where the machine sits.

    I'm going to try stuffing the keyboard buffer with the machine's Admin password and <Enter>, and we'll see if that gets the last piece of this puzzle solved.  That solution would work for me fine, as every one of the dedicated computers running my application wil be set up with AutoAdminLogon=1 in the registry, thus always logged on in the Admin account with a clear-text password in the Registry.

    Will let you know in a bit how I make out.  I may also try terminating the WinLogon process, just to see what happens.  I will of course read any more suggestions you may have.
    0
     
    LVL 2

    Author Comment

    by:RHenningsgard
    Well, no go sending keystrokes to the screen-saver password dialog using keybd_event.  (Works everywhere else I can try it).  This is turning out to be more tricky than I imagined!

    If I don't succeed fairly soon, I'm going to have to abandon the effort and write my own screen-saver instead.

    0
     
    LVL 86

    Expert Comment

    by:jkr
    Is your app running under an admin account? If so, try to

       HANDLE           hToken;
       TOKEN_PRIVILEGES tp;

       if   (   !OpenProcessToken   (   GetCurrentProcess   (),
                                        TOKEN_ADJUST_PRIVILEGES,
                                        &hToken
                                    )
            )   return  (   FALSE);


       tp.PrivilegeCount    =   1;
       
       LookupPrivilegeValue (   NULL,
                                SE_DEBUG_NAME,
                                &tp.Privileges  [   0].Luid
                            );

       tp.Privileges    [   0].Attributes   =       bEnable
                                                ?   SE_PRIVILEGE_ENABLED
                                                :   0;

       AdjustTokenPrivileges    (   hToken,
                                    FALSE,
                                    &tp,
                                    sizeof  (   tp),
                                    NULL,
                                    NULL
                                );

    *before* calling 'TerminateProcess()'
    0
     
    LVL 2

    Author Comment

    by:RHenningsgard
    Well, "swing and a miss" on killing WINLOGON.EXE.  Heck, even Task Manager can't do it!

    I'm out of ideas.  JKR, you're going to get at least a major point split on this question for the great advice you've given me.  Do you have any other thoughts?
    0
     
    LVL 86

    Accepted Solution

    by:
    You cannot killl 'winlogon.exe', but with enabling SE_DEBUG_NAME like above, you should be able to kill the screeensaver.
    0
     
    LVL 2

    Author Comment

    by:RHenningsgard
    JKR, I am concluding that, apart from a serious hack, there's no way to have an executable program running on Windows log the desktop back in to a password-protected screen saver.  Your tips were good, and they added to my repertoire of tricks, so I'm awarding you the points.

    Rob---
    0

    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone. Privacy Policy Terms of Use

    Featured Post

    Highfive + Dolby Voice = No More Audio Complaints!

    Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

    Suggested Solutions

    As more and more people are shifting to the latest .Net frameworks, the windows presentation framework is gaining importance by the day. Many people are now turning to WPF controls to provide a rich user experience. I have been using WPF controls fo…
    Entering time in Microsoft Access can be difficult. An input mask often bothers users more than helping them and won't catch all typing errors. This article shows how to create a textbox for 24-hour time input with full validation politely catching …
    This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
    how to add IIS SMTP to handle application/Scanner relays into office 365.

    877 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    14 Experts available now in Live!

    Get 1:1 Help Now