我要自动运行一个程序,然后自动关闭这个程序.
在98中,我使用Shell调用程序,然后取得句柄,最近关闭,并没有问题.但在2000或XP中,每次用shell调用程序后返回的进程ID都是不对的,根本无法取得句柄.代码如下.
Const SYNCHRONIZE = &H100000
Const INFINITE = &HFFFFFFFF
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function TerminateProcess Lib "kernel32" (ByVal hProcess As Long, ByVal uExitCode As Long) As LongPrivate Sub Command1_Click()
    Dim pId As Long, pHnd As Long     
    pId = Shell("Command.com", vbNormalFocus) 
    pHnd = OpenProcess(SYNCHRONIZE, 0, pId) ' 取得句柄
 
    Call TerminateProcess(pHnd, 0)
    Call CloseHandle(pHnd)
End Sub
------
我使用其它API函数获取到这个已经打开的程序的句柄及进程ID,发现使用Shell返回的PID是错误的.不知是怎么回事.

解决方案 »

  1.   

    我试了一下,发现Shell得到的句柄还是正确的!
    但是窗体没有被关闭,进程也还在,我是在2000下试的
    好象这两句没起作用:
        Call TerminateProcess(pHnd, 0)
        Call CloseHandle(pHnd)
      

  2.   

    对的,应该不是Shell的问题。
    因为在win2000中,已用cmd.exe代替了16位的command.com,Shell返回的PID与win2000任务管理器中的PID是相同的,还是找别的原因吧。
      

  3.   

    但我作用Findwindow或EnumWindows得到这个程序的句柄,和用Shell得到的句柄并不一样啊.而在98下却是正常的.
      

  4.   

    我知道为什么不能关闭了.问题出在
     pHnd = OpenProcess(SYNCHRONIZE, 0, pId) ' 取得句柄这句,我找到另一个例子,将其参数改了后,就可以关闭了,不知哪位知道这两个参数的各个值的意义呢,我估计应该是对进程操作的权限,因为2000或XP对权限控制得比较严,而98则没什么控制.
    pHnd = OpenProcess(1&, -1&, pId)
      

  5.   

    Option ExplicitPrivate Declare Function CreateProcess Lib "kernel32" Alias "CreateProcessA" (ByVal lpApplicationName As String, ByVal lpCommandLine As String, lpProcessAttributes As Any, lpThreadAttributes As Any, ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, lpEnvironment As Any, ByVal lpCurrentDriectory As String, lpStartupInfo As STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) As Long
    Private Declare Function TerminateProcess Lib "kernel32" (ByVal hProcess As Long, ByVal uExitCode As Long) As Long
    Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As LongPrivate Type STARTUPINFO
        cb As Long
        lpReserved As String
        lpDesktop As String
        lpTitle As String
        dwX As Long
        dwY As Long
        dwXSize As Long
        dwYSize As Long
        dwXCountChars As Long
        dwYCountChars As Long
        dwFillAttribute As Long
        dwFlags As Long
        wShowWindow As Integer
        cbReserved2 As Integer
        lpReserved2 As Long
        hStdInput As Long
        hStdOutput As Long
        hStdError As Long
    End TypePrivate Type PROCESS_INFORMATION
        hProcess As Long
        hThread As Long
        dwProcessId As Long
        dwThreadId As Long
    End TypePrivate Const SW_SHOW = 5
    Private Const STARTF_USESHOWWINDOW = &H1Dim hProcess As LongPrivate Sub Command1_Click()
        Dim stProcessInfo As PROCESS_INFORMATION
        Dim stStartInfo As STARTUPINFO
        stStartInfo.cb = LenB(stStartInfo)
        stStartInfo.wShowWindow = SW_SHOW
        stStartInfo.dwFlags = STARTF_USESHOWWINDOW
        
        Dim strExe As String
        strExe = "notepad.exe"
        
        If False = CreateProcess(ByVal vbNullString, ByVal strExe, ByVal 0, ByVal 0, False, ByVal 0, ByVal 0, ByVal vbNullString, stStartInfo, stProcessInfo) Then
            MsgBox "启动进程失败!"
            Exit Sub
        Else
            CloseHandle stProcessInfo.hThread
            hProcess = stProcessInfo.hProcess
        End If
        
    End SubPrivate Sub Command2_Click()
        If hProcess <> 0 Then
            TerminateProcess hProcess, -1
            CloseHandle hProcess
            hProcess = 0
        End If
    End SubPrivate Sub Form_Unload(Cancel As Integer)
        If hProcess <> 0 Then
            CloseHandle hProcess
            hProcess = 0
        End If
    End Sub
      

  6.   

    不要用Shell,要用CreateProcess。
      

  7.   

    如果楼主非要使用Shell,再OpenProcess的话。
    OpenProcess(PROCESS_TERMINATE, 0, pId)
    才对。
      

  8.   

    多谢 goodname008(卢培培,充电中......) ( ) 信誉:169 ----
    另外,有一个问题还想请教,我打开了cmd.exe命令窗口后,如何才能模拟键盘输入一些字符串(例如命令)?我使用SendKey ,但似乎只有偶然一两次会输入到命令窗.不知可否使用SendMessage这些API函数传送呢,如何使用?
    ----如解答,另外加分,谢谢!
      

  9.   

    //另外,有一个问题还想请教,我打开了cmd.exe命令窗口后,如何才能模拟键盘输入一些字符串(例如命令)?参考:
    http://www.china-askpro.com/msg2/qa48.shtml
      

  10.   

    好的办法应该是用管道。在CreateProcess函数中有一个STARTIPINFO结构的参数,该结构里有三个这样的成员:
    HANDLE hStdInput;
    HANDLE hStdOutput;
    HANDLE hStdError;
    这是启动控制台程序时需要的标准输入输出(这也是我建议用CreateProcess函数的一小方面)。用相应的管道函数将读写句柄传给这三个值,然后往管道里写数据就是了。
    这种事情确实用VC做比较好,不过VB也是能做的。
    楼主参考一下这里:
    http://www.codeguru.com/Cpp/misc/misc/article.php/c277
      

  11.   

    可惜我的英文太差,对管道技术也从未涉猎,不过的确长了不少见识,特别多谢 goodname008(卢培培,充电中......) !!