辣椒龙 发表于 2010-8-24 17:25:26

如何安全的关闭QQ(给它保存信息)

希望就像是用它自己的退出功能一样,不要是ProcessClose。这样无法保存数据。
我试过RunWait(@ComSpec & ' /c taskkill /IM QQ.exe', @SystemDir, @SW_HIDE)
多次执行看不出什么效果,然后鼠标移到系统栏QQ图标上,图标就消失了。然而进程中仍然存在"QQ.exe"
晕了,想想关机时QQ可以无提示正常退出,可是用什么语句来模拟系统的关闭消息呢,就是说让QQ误以为系统要关机或重启了。
总之希望让QQ在保存数据的基础上退出,不知大家有没有好的方法或是思路……

itljl 发表于 2010-8-24 17:29:35

试一下

Func _OpenProcess($iProcessId, $iAccess, $iInherit = 0)
Local $hProcess

$iProcessId = ProcessExists($iProcessId)
$hProcess = DllCall("Kernel32.dll", "hWnd", "OpenProcess", _
"dword", $iAccess, "int", $iInherit, "int", $iProcessId)
Return $hProcess
EndFunc ;==>_OpenProcess()

Func _TerminateProcess($hProcess, $iExitCode)
Local $iResult
$iResult = DllCall("Kernel32.dll", "int", "TerminateProcess", _
"hWnd", $hProcess, "uint", $iExitCode)
Return $iResult <> 0
EndFunc ;==>_TerminateProcess()

辣椒龙 发表于 2010-8-24 17:46:45

感谢帮助。下面是我的尝试。
$sProcess = "QQ.exe"
$ProcessPid = ProcessExists($sProcess)
$ProcHandle = DllCall("kernel32.dll", "hwnd", "OpenProcess", "dword", 0x10000000, "int", 0, "dword", $ProcessPid)
$ProcTerminate = DllCall("kernel32.dll", "int", "TerminateProcess", "hwnd", $ProcHandle, "uint",0)
可中止,但图标还在,而且我测试用这种方法关闭别的软件,它不会保存数据。还请问是不是调用的参数应该调整?

辣椒龙 发表于 2010-8-24 19:50:25

搜索一番,又有发现。这个可能更接近答案ProcessQuit("QQ.exe")

Func ProcessGetWindows($PId)
        $PId = ProcessExists($PId)
        If $PId = 0 Then
        SetError(1)
        Else
        Local $WinList = WinList()
        Local $WindowTitle
        Local $x = 0
        For $i = 1 To $WinList
        If WinGetProcess($WinList[$i], "") = $PId And $WinList[$i] <> ""Then
        ReDim $WindowTitle[$x+1]
        $WindowTitle[$x] = $WinList[$i]
        $WindowTitle[$x] = $WinList[$i]
        $x += 1
        EndIf
        Next
        Return $WindowTitle
        EndIf
EndFunc

Func ProcessQuit($filename)
        $Return=0
        $a = ProcessList($filename)
        For $i = 1 To UBound($a) - 1
        $Return = ProcessGetWindows($a[$i])
        Next
        If($Return==0) Then
        Return
        EndIf
        DllCall("User32.dll", "int", "PostMessage", "hwnd", $Return, "int", $WM_QUIT, "int", "", "int", "")
EndFunc用在qq2010上,出现

看来我不用ProcessClose这样的猛招,QQ还要跳起来喊疼。真是麻烦了。继续寻找答案……

xsjtxy 发表于 2010-8-24 20:07:13

有那么麻烦吗?
为什么我这样也能成功。即使最小化到任务栏
WinKill("QQ2010")

辣椒龙 发表于 2010-8-24 20:31:44

有那么麻烦吗?
为什么我这样也能成功。即使最小化到任务栏
xsjtxy 发表于 2010-8-24 20:07 http://www.autoitx.com/images/common/back.gif

这相当于点击窗口关闭按钮,如果用户设置点关闭时最小化到系统栏,就……

xsjtxy 发表于 2010-8-24 20:51:06

回复 6# 辣椒龙


    额。果然

辣椒龙 发表于 2010-8-24 20:53:37

看了一些文章,把我的理解整理一下。
发送WM_CLOSE消息,表示关闭窗口,相当于你点右上角关闭按钮,对于一些程序,可能会弹出是否保存之类的询问。也就是说该程序截获了这个消息,根据用户的选择来决定是取消还是继续处理关闭程序事件 或者做一些保存工作。后两者会引发WM_DESTROY
发送WM_DESTROY消息,引发上面说到的事件,习惯上在这个事件中释放资源等等,然后再引发WM_QUIT。当然程序也可能设计为不引发WM_QUIT,而用它的方式处理。
发送WM_QUIT消息,直接结束消息循环,退出程序。
看来这个机制会收到程序设计的严重影响,我也不知道QQ怎么处理这一系列事件。唯一可以肯定地是WM_CLOSE肯定拦截了。所以第一次关闭QQ窗口会问你最小化还是关闭。

看来从这个方向来安全关闭QQ难度还是比较大的……

辣椒龙 发表于 2010-8-25 20:50:08

顶下,看到QQplus可以安全关闭QQ(至少它自己这样声称),看来找到合适的API和参数,是可以做到安全关闭的,只是我还没有找到。

itljl 发表于 2010-8-25 23:41:34

向QQ的关闭按钮发送一个鼠标点击,或许是一个可行的方法。

辣椒龙 发表于 2010-8-26 09:09:58

向QQ的关闭按钮发送一个鼠标点击,或许是一个可行的方法。
itljl 发表于 2010-8-25 23:41 http://www.autoitx.com/images/common/back.gif

不知道楼上兄弟说的是哪一个按钮,如果是这个恐怕不行。
用户如果设置点关闭就最小化,点按钮也起不到预期作用了。

jhun 发表于 2010-8-26 10:37:21

最终还是败了,因为获取文本和图标的位置的顺序不一致,所以我无法通过文本来确定QQ的图标顺序,不过也算是条思路吧#include <GUIToolbar.au3>
      Local $hTb = ControlGetHandle('', '', 'ToolbarWindow321')
      For $i = 0 To _GUICtrlToolbar_ButtonCount($hTb) - 1
                                _GUICtrlToolbar_ClickButton($hTb,$i,"right",1)
                                Sleep(1000)
      Next这段代码会在每个状态栏图标上面右击,鼠标我设置跟随的,这样再相对移动一下就可以点到退出了
能力有限,不能有效的帮助LZ,见谅

weiym 发表于 2010-8-26 11:01:23

一般点某个菜单时是发送WM_COMMAND消息给某个窗口, 所以只要用Spy看下退出菜单的ID,模拟发送一下这个消息就可以了。

QQ比较特殊,界面用的是DirectUI技术,所以它的菜单也是自己用窗口模拟的,所以点菜单时没有消息通讯,没法模拟。

可能只能通过破解的技术才能做到了,比如暂时修改它的配置类型为关闭时退出,然后发送WM_CLOSE消息,再改回配置

sanmoking 发表于 2010-8-26 12:24:07

本帖最后由 sanmoking 于 2010-8-26 14:57 编辑

直接调出退出面板,然后点击退出,
另外发现那个退出面板需要用户曾经点击过才会出现,所以当发现有tm窗口却没有那个退出面板的话,模拟用户手动点一下.直到所有的tm,qq退出...
该代码唯一的缺陷就是,如果点击的位置前面有个更高权限的置顶窗口就会是点击失效.....我已经尽力了.top()



HotKeySet("`", "mimi")
Func mimi()
While WinExists("TM") or ProcessExists("TM.EXE")
      $num = 0
$list = WinList("TXMenuWindow")
if $list > 0 then   
For $i = 1 To $list
   $x = WinGetPos($list[$i])
   If $x = 132 And $x = 261 Then
    $a = 0
    $b = 0
    WinMove($list[$i], "", $a, $b)
    WinSetState($list[$i], "", @SW_SHOW)
    $s = MouseGetPos()
    top($list[$i])
    MouseClick("left", $a + 20, $b + 210, 1, 0)
    MouseMove($s, $s, 0)
    $num = $num + 1
    Sleep(100)
    ContinueLoop(2)
   EndIf
Next
If $num = 0 Then
   $y = WinGetPos("TM")
   WinMove("TM", "", 0, 0)
   WinSetState("TM", "", @SW_SHOW)
   $x = WinGetPos("TM")
   $s = MouseGetPos()
   top(WinGetHandle ("TM"))
   MouseClick("left", 20, $x - 20, 1, 0)
   WinMove("TM", "", $y,$y,$y,$y)
   MouseMove($s, $s, 0)   
EndIf
EndIf
WEnd


While WinExists("QQ") or ProcessExists("QQ.EXE")
$num = 0
$list = WinList("TXMenuWindow")
if $list > 0 then
For $i = 1 To $list
   $x = WinGetPos($list[$i])
   If $x = 147 And $x = 288 Then
    $a = 0
    $b = 0
    WinMove($list[$i], "", $a, $b)
    WinSetState($list[$i], "", @SW_SHOW)
    $s = MouseGetPos()
    top($list[$i])
    MouseClick("left", $a + 20, $b + 230, 1, 0)
    MouseMove($s, $s, 0)
    $num = $num + 1
    Sleep(100)
    ContinueLoop(2)
   EndIf
Next
If $num = 0 Then
   $y = WinGetPos("QQ")
   WinMove("QQ", "", 0, 0)
   WinSetState("QQ", "", @SW_SHOW)
   $x = WinGetPos("QQ")
   $s = MouseGetPos()
   top(WinGetHandle ("TM"))
   MouseClick("left", 20, $x - 20, 1, 0)
   WinMove("QQ", "", $y,$y,$y,$y)
   MouseMove($s, $s, 0)   
EndIf
EndIf
WEnd


Exit
EndFunc   ;==>mimi
func top($hdl);把窗口放到最前端.
    $hw=_WinAPI_GetForegroundWindow()
                If $hw<>$hdlThen
                        _WinAPI_SetWindowPos($hw, -2, 0, 0, 0, 0, 3)
                EndIf
                _WinAPI_SetWindowPos($hdl, -1, 0, 0, 0, 0, 3)
EndFunc

辣椒龙 发表于 2010-8-26 13:48:30

最终还是败了,因为获取文本和图标的位置的顺序不一致,所以我无法通过文本来确定QQ的图标顺序,不过也算是 ...
jhun 发表于 2010-8-26 10:37 http://www.autoitx.com/images/common/back.gif
多谢帮忙,是个好的思路……
页: [1] 2
查看完整版本: 如何安全的关闭QQ(给它保存信息)