第一个给出正确完整代码的给100分! 
    
如何在关机时使得dos程序正常关掉?我是vb初学者,参考资料编了个程序实现了dos程序界面windows化,既使用了winexec来调用一个dos程序(有窗体),但问题出现在关机,重启和注销时,一到这个时候就会弹出windows无法自动关闭此程序的对话框,我又重编试图拦截关机消息,但总是不成功,请问这种程序怎样实现?
 
 回复人: wxy_xiaoyu(☆然也☆╭∩╮(︶︿︶)╭∩╮) ( ) 信誉:115  2003-03-29 01:58:00  得分:0 
   你的 DOS 程序有窗口么?
有的话,在关机,重启和注销前先用 FINDWINDOW 找到它的窗口,然后用 SENDMESSAGE 发送 WM_CLOSE 消息给他关闭.
在发送消息后加一点延时以等待其关闭Top 
 
 回复人: JennyVenus() ( ) 信誉:101  2003-03-29 05:00:00  得分:0   如果WINDOWS不能关闭那个窗口,WM_CLOSE照样不能关闭那个窗口,发送多少个也是白搭。最多出现等待结束程序那个窗口,这时只要给那个立即结束按钮发送回车事件就行了,或者按照我刚刚写的这个,我的程序只针对一个窗口,同样,对于多个窗口只需要enumwindows得到每一个类似的窗口就行了Option Explicit
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function TerminateProcess Lib "kernel32" (ByVal hProcess As Long, ByVal uExitCode As Long) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Const PROCESS_TERMINATE = &H1''用于结束外部进程,hCloseWnd 是要结束的程序的主窗口的 HWND
Public Function TerminateProcessByHWND(ByVal hCloseWnd As Long) As Boolean
    Dim hProcessID  As Long
    Dim hProcess    As Long
On Error GoTo PROC_EXIT
    If hCloseWnd = 0 Then GoTo PROC_EXIT
    If GetWindowThreadProcessId(hCloseWnd, hProcessID) = 0 Then GoTo PROC_EXIT
    hProcess = OpenProcess(PROCESS_TERMINATE, False, hProcessID)
    If hProcess = 0 Then GoTo PROC_EXIT
    If TerminateProcess(hProcess, 0&) = 0 Then GoTo PROC_EXIT
    TerminateProcessByHWND = True
PROC_EXIT:
    If Err.Number <> 0 Then
        Debug.Print Err.Description
        Err.Clear
    End If
End FunctionPrivate Sub Command1_Click()
    Shell "command.com", vbNormalFocus
    Command1.Enabled = False
    Dim s As Double
    s = Timer
    Do
        DoEvents
    Loop While Timer - s < 5
    Dim l As Long
    l = FindWindow("ConsoleWindowClass", vbNullString)
    TerminateProcessByHWND l
    Command1.Enabled = True
End SubTop 
  回复人: imagex(非理性人) ( ) 信誉:100  2003-03-29 18:09:00  得分:0 
   我说的那个程序和command.com不一样,只要你去关它,它就弹出“windows 无法自动关闭此程序,建议使用‘退出‘ 命令退出“,所以关机时也一样会谈出这个对话框。
 

解决方案 »

  1.   

    是我的错误,以前错怪你了,你的猜测是正确的,收到关机消息的确有顺序,而且一旦前面的被阻塞了,后面的就无法继续了,下面是我刚组合完毕的程序,如果这个程序在任何dos窗口运行之前就运行,能够关闭任何dos窗口,使得关机/注销顺利进行,反之不行。
    所以我又添加了一个timer函数,在timer中用另外一个程序关闭这个窗口,调试成功,有新的问题再次联系。测试方法如下
    先打开两个dos窗口
    运行project1.exe
    再打开两个dos窗口
    注销,dos窗口先打开的直接被关闭,后打开的出现立即结束窗口后被关闭,速度取决于timer的设定测试环境: xp, vb6代码如下'窗体
    Option ExplicitPrivate Sub Form_Load()
        Me.AutoRedraw = True
        oldwinproc = GetWindowLong(Me.hwnd, GWL_WNDPROC)
        SetWindowLong Me.hwnd, GWL_WNDPROC, AddressOf OnMenu
    End Sub
    Private Sub Form_Unload(Cancel As Integer)
        SetWindowLong Me.hwnd, GWL_WNDPROC, oldwinproc
    End SubPrivate Sub Timer1_Timer()
        CloseConsole1
    End Sub'模块
    Option ExplicitPublic Const WM_SYSCOMMAND = &H112
    Public Const WM_QUERYENDSESSION = &H11
    Public Const PROCESS_TERMINATE = &H1
    Public Const GWL_WNDPROC = (-4)
    Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
    Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Public Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
    Public Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
    Public Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
    Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
    Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
    Private Declare Function TerminateProcess Lib "kernel32" (ByVal hProcess As Long, ByVal uExitCode As Long) As Long
    Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
    Public Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
    Public Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
    Public oldwinproc As Long
    Public g__caption As String
    Public g__hwnd As Long
    '查询是否关机并且关闭dos窗口
    Public Function OnMenu(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
        Select Case wMsg
            Case WM_QUERYENDSESSION
                Form1.WindowState = 0
                Form1.Cls
                Form1.Print "系统要关机了"
                CloseConsole
            Case WM_SYSCOMMAND
            Case Else
        End Select
        OnMenu = CallWindowProc(oldwinproc, hwnd, wMsg, wParam, lParam)
    End Function
    '枚举并且关闭
    Public Function CloseConsole() As Long
        EnumWindows AddressOf EnumProc, 0
        CloseConsole = 1
    End Function'枚举回调函数
    Public Function EnumProc(ByVal hwnd As Long, ByVal lParam As Long) As Long
        Dim s As String * 255
        Dim s1 As String
        Dim i As Integer
        GetClassName hwnd, s, 255
        For i = 1 To 255
            If Mid(s, i, 1) <> Chr(0) Then
                s1 = s1 & Mid(s, i, 1)
            Else
                Exit For
            End If
        Next i
        If s1 = "ConsoleWindowClass" Then
            GetWindowText hwnd, s, 255
            TerminateProcessByHWND hwnd
            Form1.Print s
            Form1.Print hwnd
        End If
        EnumProc = 1
    End Function'关闭任何普通应用程序的窗口
    Public Function TerminateProcessByHWND(ByVal hCloseWnd As Long) As Boolean
        Dim hProcessID  As Long
        Dim hProcess    As Long
    On Error GoTo PROC_EXIT
        If hCloseWnd = 0 Then GoTo PROC_EXIT
        If GetWindowThreadProcessId(hCloseWnd, hProcessID) = 0 Then GoTo PROC_EXIT
        hProcess = OpenProcess(PROCESS_TERMINATE, False, hProcessID)
        If hProcess = 0 Then GoTo PROC_EXIT
        If TerminateProcess(hProcess, 0&) = 0 Then GoTo PROC_EXIT
        TerminateProcessByHWND = True
    PROC_EXIT:
        If Err.Number <> 0 Then
            Debug.Print Err.Description
            Err.Clear
        End If
    End Function'定时查询是否有无法结束的dos窗口
    Public Function CloseConsole1() As Long
        Dim console As Long
        console = FindWindow("ConsoleWindowClass", vbNullString)    '查找是否有dos窗口
        Dim s As String * 255
        g__caption = ""
        Dim i As Integer
        If console Then
            GetWindowText console, s, 255
            For i = 1 To 255
                If Mid(s, i, 1) <> Chr(0) Then
                    g__caption = g__caption & Mid(s, i, 1)
                Else
                    Exit For
                End If
            Next i
            'Debug.Print g__caption
            g__hwnd = console
            EnumWindows AddressOf EnumProc1, 0
        End If
        CloseConsole1 = 1
    End Function
    '枚举是否出现立即结束的窗口
    Public Function EnumProc1(ByVal hwnd As Long, ByVal lParam As Long) As Long
        Dim s As String * 255
        Dim s1 As String
        Dim i As Integer
        GetClassName hwnd, s, 255
        For i = 1 To 255
            If Mid(s, i, 1) <> Chr(0) Then
                s1 = s1 & Mid(s, i, 1)
            Else
                Exit For
            End If
        Next i
        If s1 = "#32770" Then
            s1 = ""
            GetWindowText hwnd, s, 255
            For i = 1 To 255
                If Mid(s, i, 1) <> Chr(0) Then
                    s1 = s1 & Mid(s, i, 1)
                Else
                    Exit For
                End If
            Next i
            If s1 = "结束程序 - " & g__caption Then
                TerminateProcessByHWND hwnd
                TerminateProcessByHWND g__hwnd
            End If
        End If
        EnumProc1 = 1
    End Function