我尝试用vb做一个定时关闭系统的程序,但在计算机锁定的情况下调用ExitWindowsEx函数不管用,请高手赐教怎样才能解除计算机锁定,或绕过锁定,谢谢各位了!

解决方案 »

  1.   

    "锁定"就是在win2000下同时按下ctrl,alt,del键后"锁定计算机"
    需求前面有介绍,我想做一个定时关闭计算机的vb程序,但在计算机锁定的情况下调用API函数ExitWindowsEx不管用,所以想在程序中加入解除锁定计算机的代码,再调用该函数.
    或者还有什么方法能使现在计算机被锁定的情况下自动关机.
      

  2.   

    没有现成的2000系统,不知道那样锁定能不能触发。如果锁定状态下可以触发的话可以用一个计时!要是还不成的话,可以用shell调用 shutdown  在xp下shutdown 任何时候都可以的。
      

  3.   

    If a program uses the ExitWindowsEx function with the EWX_FORCE bit to log off a user or to shut down the computer when the computer is locked, the program may not log off the user or shut down the computer, and a blank screen that is the same color as the desktop color is displayed. The same problem occurs if you use the Shutdown.exe program to remotely shut down the computer when the computer is locked. Note that the Shutdown.exe program is included with the Windows 2000 Resource Kit. Cause
    This problem can occur because the Winlogon process does not handle either the user log off or the computer shut down requests correctly when the computer is locked. This problem also occurs with the Shutdown.exe program because this program uses the ExitWindowsEx function. Resolution
    To resolve this problem, obtain the latest service pack for Windows 2000. For additional information, click the following article number to view the article in the Microsoft Knowledge Base: Q260910 How to Obtain the Latest Windows 2000 Service Pack 
    The English-language version of this fix should have the following file attributes or later: 
       Date        Time      Version        Size     File name
       ----------------------------------------------------------
       3/12/2001  02:41p    5.0.2195.3357  331,536   Msgina.dll 
       3/12/2001  2:40 PM   5.0.2195.3357  178,448   Winlogon.exe Status
    Microsoft has confirmed that this is a problem in the Microsoft products that are listed at the beginning of this article. This problem was first corrected in Windows 2000 Service Pack 3.
      

  4.   

    This problem was first corrected in Windows 2000 Service Pack 3.
    ==================================
    意思是说在2K的SP3里已经解决了这个问题了
    现在大家都用SP4了,应该没问题了吧?
    楼主的2K打补丁了吗?
      

  5.   

    回 hitbird(Leo) :
    我用过shutdown了,它的所有命令好像都实现不了win2000关机功能,其中"-f","-t"只能实现注销,"-r"能实现重启.
      

  6.   

    回crycoming(瞎编):
    我的win2000都打了最新的sp5的补丁了,应该不是我机子问题.
    大家还有什么好办法吗?
      

  7.   

    '相关的API声明请自己补齐
    'NT下调用关机涵数前需先调用的安全机制涵数子过程
    Public Sub AdjustToken()
     Dim hdlProcessHandle As Long
     Dim hdlTokenHandle As Long
     Dim tmpLuid As LUID
     Dim tkp As TOKEN_PRIVILEGES
     Dim tkpNewButIgnored As TOKEN_PRIVILEGES
     Dim lBufferNeeded As Long
      
     hdlProcessHandle = GetCurrentProcess()
     OpenProcessToken hdlProcessHandle, (TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY), hdlTokenHandle' Get the LUID for shutdown privilege.
     LookupPrivilegeValue "", "SeShutdownPrivilege", tmpLuid
     tkp.PrivilegeCount = 1 ' One privilege to set
     tkp.Privileges(0).pLuid = tmpLuid
     tkp.Privileges(0).Attributes = SE_PRIVILEGE_ENABLED' Enable the shutdown privilege in the access token of this process.
     AdjustTokenPrivileges hdlTokenHandle, False, tkp, Len(tkpNewButIgnored), tkpNewButIgnored, lBufferNeeded
    End Sub
      

  8.   

    Public Declare Function ExitWindowsEx Lib "user32" (ByVal uFlags As Long, ByVal dwReserved As Long) As LongPublic Const EWX_SHUTDOWN = 1
    Public Const EWX_FORCE = 4
    Public Const EWX_REBOOT = 2
    Public Const EWX_LOGOFF = 0按照文章的意思应当是用EWX_FORCE参数, 你大概是用了EWX_SHUTDOWN吧
      

  9.   

    AdjustToken安全机制涵数子过程我也调用了,在计算机锁定的情况下,用EWX_FORCE参数可以实现注销,EWX_LOGOFF 不能实现注销,EWX_SHUTDOWN 不能实现关机,EWX_REBOOT不能实现重启,代码如下:
    我用了定时器控件
    Private Sub Timer1_Timer()
    Dim T As String
        T = Text1(0).Text & ":" & Text1(1).Text & ":" & Text1(2).Text
        If T = Right(Now, 8) Then
                AdjustTokenPrivilegesForNT
                ExitWindowsEx EWX_REBOOT, 0 '这里替换参数即可
        End If
    End Sub不知谁用过阿达自动关机,听说用vb做的,它在计算机锁定的情况下能实现关机,我想学学,所以发了这个帖子,但到现在还没有得到一个满意的答复.
    请高手出面指教,我是穷途末路了!
      

  10.   

    用EWX_FORCE参数可以实现注销,EWX_LOGOFF 不能实现注销,EWX_SHUTDOWN 不能实现关机,EWX_REBOOT不能实现重启
    ==============================
    EWX_FORCE参数并不执行具体操作,它只是强调了操作的强制性...例如:
    ExitWindowsEx EWX_SHUTDOWN or EWX_FORCE, 0 表示强制关机
    ExitWindowsEx EWX_LOGOFF or EWX_FORCE, 0 表示强制注销等等...具体操作由与EWX_FORCE一起的另外一个参数决定...
    AdjustTokenPrivilegesForNT
    ===================================
    建议使用上面zlt982001(乐天)兄的方法代替 AdjustTokenPrivilegesForNT试试看...
    另外,你用的是上面系统???你的用户名在系统里有什么权限?????
      

  11.   

    回lsftest()兄:
    在调用AdjustTokenPrivilegesForNT子函数后,在计算机锁定的情况下,我尝试你介绍的方法:‘程序没反应,计算机还是锁定状态
    AdjustTokenPrivilegesForNT
    ExitWindowsEx EWX_SHUTDOWN or EWX_FORCE, 0  ‘程序有反应,计算机实现注销(按道理应该是强制关机才对阿??????)
    AdjustTokenPrivilegesForNT
    ExitWindowsEx EWX_SHUTDOWN and EWX_FORCE, 0    另为我是超级管理员用的是administrator用户,win2000打了sp5补丁,在权限上没有问题!请问高手们,这作何解释?????????????????????
      

  12.   

    Option Explicit
          Private Const EWX_LogOff As Long = 0
          Private Const EWX_SHUTDOWN As Long = 1
          Private Const EWX_REBOOT As Long = 2
          Private Const EWX_FORCE As Long = 4
          Private Const EWX_POWEROFF As Long = 8      'The ExitWindowsEx function either logs off, shuts down, or shuts
          'down and restarts the system.
          Private Declare Function ExitWindowsEx Lib "user32" _
             (ByVal dwOptions As Long, _
              ByVal dwReserved As Long) As Long      'The GetLastError function returns the calling thread's last-error
          'code value. The last-error code is maintained on a per-thread basis.
          'Multiple threads do not overwrite each other's last-error code.
          Private Declare Function GetLastError Lib "kernel32" () As Long      Private Const mlngWindows95 = 0
          Private Const mlngWindowsNT = 1      Public glngWhichWindows32 As Long      'The GetVersion function returns the operating system in use.
          Private Declare Function GetVersion Lib "kernel32" () As Long      Private Type LUID
             UsedPart As Long
             IgnoredForNowHigh32BitPart As Long
          End Type      Private Type LUID_AND_ATTRIBUTES
             TheLuid As LUID
             Attributes As Long
          End Type      Private Type TOKEN_PRIVILEGES
             PrivilegeCount As Long
             TheLuid As LUID
             Attributes As Long
          End Type      'The GetCurrentProcess function returns a pseudohandle for the
          'current process.
          Private Declare Function GetCurrentProcess Lib "kernel32" () As Long      'The OpenProcessToken function opens the access token associated with
          'a process.
          Private Declare Function OpenProcessToken Lib "advapi32" _
             (ByVal ProcessHandle As Long, _
              ByVal DesiredAccess As Long, _
              TokenHandle As Long) As Long      'The LookupPrivilegeValue function retrieves the locally unique
          'identifier (LUID) used on a specified system to locally represent
          'the specified privilege name.
          Private Declare Function LookupPrivilegeValue Lib "advapi32" _
             Alias "LookupPrivilegeValueA" _
             (ByVal lpSystemName As String, _
              ByVal lpName As String, _
              lpLuid As LUID) As Long      'The AdjustTokenPrivileges function enables or disables privileges
          'in the specified access token. Enabling or disabling privileges
          'in an access token requires TOKEN_ADJUST_PRIVILEGES access.
          Private Declare Function AdjustTokenPrivileges Lib "advapi32" _
             (ByVal TokenHandle As Long, _
              ByVal DisableAllPrivileges As Long, _
              NewState As TOKEN_PRIVILEGES, _
              ByVal BufferLength As Long, _
              PreviousState As TOKEN_PRIVILEGES, _
              ReturnLength As Long) As Long      Private Declare Sub SetLastError Lib "kernel32" _
             (ByVal dwErrCode As Long)      Private Sub AdjustToken()      '********************************************************************
          '* This procedure sets the proper privileges to allow a log off or a
          '* shut down to occur under Windows NT.
          '********************************************************************         Const TOKEN_ADJUST_PRIVILEGES = &H20
             Const TOKEN_QUERY = &H8
             Const SE_PRIVILEGE_ENABLED = &H2         Dim hdlProcessHandle As Long
             Dim hdlTokenHandle As Long
             Dim tmpLuid As LUID
             Dim tkp As TOKEN_PRIVILEGES
             Dim tkpNewButIgnored As TOKEN_PRIVILEGES
             Dim lBufferNeeded As Long         'Set the error code of the last thread to zero using the
             'SetLast Error function. Do this so that the GetLastError
             'function does not return a value other than zero for no
             'apparent reason.
             SetLastError 0         'Use the GetCurrentProcess function to set the hdlProcessHandle
             'variable.
             hdlProcessHandle = GetCurrentProcess()         If GetLastError <> 0 Then
                MsgBox "GetCurrentProcess error==" & GetLastError
             End If         OpenProcessToken hdlProcessHandle, _
                (TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY), hdlTokenHandle         If GetLastError <> 0 Then
                MsgBox "OpenProcessToken error==" & GetLastError
             End If         'Get the LUID for shutdown privilege
             LookupPrivilegeValue "", "SeShutdownPrivilege", tmpLuid         If GetLastError <> 0 Then
                MsgBox "LookupPrivilegeValue error==" & GetLastError
             End If         tkp.PrivilegeCount = 1    ' One privilege to set
             tkp.TheLuid = tmpLuid
             tkp.Attributes = SE_PRIVILEGE_ENABLED         'Enable the shutdown privilege in the access token of this process
             AdjustTokenPrivileges hdlTokenHandle, _
                                   False, _
                                   tkp, _
                                   Len(tkpNewButIgnored), _
                                   tkpNewButIgnored, _
                                   lBufferNeeded         If GetLastError <> 0 Then
                MsgBox "AdjustTokenPrivileges error==" & GetLastError
             End If      End Sub      Private Sub cmdLogoff_Click()         ExitWindowsEx (EWX_LogOff), &HFFFF
             MsgBox "ExitWindowsEx's GetLastError " & GetLastError      End Sub      Private Sub cmdForceLogoff_Click()         ExitWindowsEx (EWX_LogOff Or EWX_FORCE), &HFFFF
             MsgBox "ExitWindowsEx's GetLastError " & GetLastError      End Sub      Private Sub cmdShutdown_Click()         If glngWhichWindows32 = mlngWindowsNT Then
                AdjustToken
                MsgBox "Post-AdjustToken GetLastError " & GetLastError
             End If         ExitWindowsEx (EWX_SHUTDOWN), &HFFFF
             MsgBox "ExitWindowsEx's GetLastError " & GetLastError      End Sub      Private Sub cmdForceShutdown_Click()
             If glngWhichWindows32 = mlngWindowsNT Then
                AdjustToken
                MsgBox "Post-AdjustToken GetLastError " & GetLastError
             End If      ExitWindowsEx (EWX_SHUTDOWN Or EWX_FORCE), &HFFFF
          MsgBox "ExitWindowsEx's GetLastError " & GetLastError      End Sub      Private Sub Form_Load()
          '********************************************************************
          '* When the project starts, check the operating system used by
          '* calling the GetVersion function.
          '********************************************************************
             Dim lngVersion As Long         lngVersion = GetVersion()         If ((lngVersion And &H80000000) = 0) Then
                glngWhichWindows32 = mlngWindowsNT
                MsgBox "Running Windows NT or Windows 2000"
             Else
                glngWhichWindows32 = mlngWindows95
                MsgBox "Running Windows 95/98/Me"
             End If      End Sub
      

  13.   

    '以下代码在xp待机锁定情况下测试通过,timer设为20秒:
    Option Explicit
         Private Const EWX_LogOff As Long = 0
         Private Const EWX_SHUTDOWN As Long = 1
         Private Const EWX_REBOOT As Long = 2
         Private Const EWX_FORCE As Long = 4
         Private Const EWX_POWEROFF As Long = 8
         
         'ExitWindowsEx函数可以退出登录、关机或者重新启动系统
         Private Declare Function ExitWindowsEx Lib "user32" _
         (ByVal dwOptions As Long, _
         ByVal dwReserved As Long) As Long
         
         'GetLastError函数返回本线程的最后一次错误代码。错误代码是按照线程
         '储存的,多线程也不会覆盖其他线程的错误代码。
         Private Declare Function GetLastError Lib "kernel32" () As Long
         
         Private Const mlngWindows95 = 0
         Private Const mlngWindowsNT = 1
         
         Public glngWhichWindows32 As Long
         
         ' GetVersion返回操作系统的版本。
         Private Declare Function GetVersion Lib "kernel32" () As Long
         
         Private Type LUID
         UsedPart As Long
         IgnoredForNowHigh32BitPart As Long
         End Type
         
         Private Type LUID_AND_ATTRIBUTES
         TheLuid As LUID
         Attributes As Long
         End Type
         
         Private Type TOKEN_PRIVILEGES
         PrivilegeCount As Long
         TheLuid As LUID
         Attributes As Long
         End Type
         
         'GetCurrentProcess函数返回当前进程的一个句柄。
         Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
         
         'OpenProcessToken函数打开一个进程的访问代号。
         Private Declare Function OpenProcessToken Lib "advapi32" _
         (ByVal ProcessHandle As Long, _
         ByVal DesiredAccess As Long, _
         TokenHandle As Long) As Long
         
         'LookupPrivilegeValue函数获得本地唯一的标示符(LUID),用于在特定的系统中
         '表示特定的优先权。
         Private Declare Function LookupPrivilegeValue Lib "advapi32" _
         Alias "LookupPrivilegeValueA" _
         (ByVal lpSystemName As String, _
         ByVal lpName As String, _
         lpLuid As LUID) As Long
         
         'AdjustTokenPrivileges函数使能或者禁用指定访问记号的优先权。
         '使能或者禁用优先权需要TOKEN_ADJUST_PRIVILEGES访问权限。
         Private Declare Function AdjustTokenPrivileges Lib "advapi32" _
         (ByVal TokenHandle As Long, _
         ByVal DisableAllPrivileges As Long, _
         NewState As TOKEN_PRIVILEGES, _
         ByVal BufferLength As Long, _
         PreviousState As TOKEN_PRIVILEGES, _
         ReturnLength As Long) As Long
         
         Private Declare Sub SetLastError Lib "kernel32" _
         (ByVal dwErrCode As Long)
         
         Private Sub AdjustToken()
         
         '********************************************************************
         '* 这个过程设置正确的优先权,以允许在Windows NT下关机或者重新启动。
         '********************************************************************
         
         Const TOKEN_ADJUST_PRIVILEGES = &H20
         Const TOKEN_QUERY = &H8
         Const SE_PRIVILEGE_ENABLED = &H2
         
         Dim hdlProcessHandle As Long
         Dim hdlTokenHandle As Long
         Dim tmpLuid As LUID
         Dim tkp As TOKEN_PRIVILEGES
         Dim tkpNewButIgnored As TOKEN_PRIVILEGES
         Dim lBufferNeeded As Long
         
         '使用SetLastError函数设置错误代码为0。
         '这样做,GetLastError函数如果没有错误会返回0
         SetLastError 0
         
         ' GetCurrentProcess函数设置 hdlProcessHandle变量
         hdlProcessHandle = GetCurrentProcess()
         
         If GetLastError <> 0 Then
         MsgBox "GetCurrentProcess error==" & GetLastError
         End If
         
         OpenProcessToken hdlProcessHandle, _
         (TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY), hdlTokenHandle
         
         If GetLastError <> 0 Then
         MsgBox "OpenProcessToken error==" & GetLastError
         End If
         
         ' 获得关机优先权的LUID
         LookupPrivilegeValue "", "SeShutdownPrivilege", tmpLuid
         
         If GetLastError <> 0 Then
         MsgBox "LookupPrivilegeValue error==" & GetLastError
         End If
         
         tkp.PrivilegeCount = 1 ' 设置一个优先权
         tkp.TheLuid = tmpLuid
         tkp.Attributes = SE_PRIVILEGE_ENABLED
         
         ' 对当前进程使能关机优先权
         AdjustTokenPrivileges hdlTokenHandle, _
         False, _
         tkp, _
         Len(tkpNewButIgnored), _
         tkpNewButIgnored, _
         lBufferNeeded
         
         If GetLastError <> 0 Then
         MsgBox "AdjustTokenPrivileges error==" & GetLastError
         End If
         
         End Sub
        Private Sub Form_Load()
         '********************************************************************
         '* 当项目启动时,调用GetVersion检查操作系统。
         '********************************************************************
         Dim lngVersion As Long
         
         lngVersion = GetVersion()
         
         If ((lngVersion And &H80000000) = 0) Then
         glngWhichWindows32 = mlngWindowsNT
         'MsgBox "在Windows NT或Windows 2000下运行"
         Else
         glngWhichWindows32 = mlngWindows95
         'MsgBox "在Windows 95/98/Me下运行"
         End If
         
         End Sub
    Private Sub Timer1_Timer()
    If glngWhichWindows32 = mlngWindowsNT Then
         AdjustToken
         'MsgBox "调用AdjustToken后的GetLastError " & GetLastError
         End If
         
         ExitWindowsEx (EWX_POWEROFF Or EWX_FORCE), 0
         'MsgBox "ExitWindowsEx's GetLastError " & GetLastError
    End Sub'天下文章一大抄,上面是从以前收集的代码堆里砍出来的,可能有不少多余的东西,楼主自己删吧...
      

  14.   

    结贴了,谢谢大家踊跃发言,程序我已经测试通过了,特别感谢crycoming(瞎编)和lsftest,和其他所有发言提供建议的朋友!