找回密码
 加入
搜索
查看: 7901|回复: 16

[系统综合] 如何安全的关闭QQ(给它保存信息)

 火.. [复制链接]
发表于 2010-8-24 17:25:26 | 显示全部楼层 |阅读模式
希望就像是用它自己的退出功能一样,不要是ProcessClose。这样无法保存数据。
我试过RunWait(@ComSpec & ' /c taskkill /IM QQ.exe', @SystemDir, @SW_HIDE)
多次执行看不出什么效果,然后鼠标移到系统栏QQ图标上,图标就消失了。然而进程中仍然存在"QQ.exe"
晕了,想想关机时QQ可以无提示正常退出,可是用什么语句来模拟系统的关闭消息呢,就是说让QQ误以为系统要关机或重启了。
总之希望让QQ在保存数据的基础上退出,不知大家有没有好的方法或是思路……
发表于 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[0]
EndFunc ;==>_OpenProcess()

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

评分

参与人数 1金钱 +15 收起 理由
afan + 15

查看全部评分

 楼主| 发表于 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[0], "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[1][2]
        Local $x = 0
        For $i = 1 To $WinList[0][0]
        If WinGetProcess($WinList[$i][1], "") = $PId And $WinList[$i][0] <> ""Then
        ReDim $WindowTitle[$x+1][2]
        $WindowTitle[$x][0] = $WinList[$i][0]
        $WindowTitle[$x][1] = $WinList[$i][1]
        $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][1])
        Next
        If($Return==0) Then
        Return
        EndIf
        DllCall("User32.dll", "int", "PostMessage", "hwnd", $Return[0][1], "int", $WM_QUIT, "int", "", "int", "")
EndFunc
用在qq2010上,出现

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

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×
发表于 2010-8-24 20:07:13 | 显示全部楼层
有那么麻烦吗?
为什么我这样也能成功。即使最小化到任务栏
WinKill("QQ2010")
 楼主| 发表于 2010-8-24 20:31:44 | 显示全部楼层
有那么麻烦吗?
为什么我这样也能成功。即使最小化到任务栏
xsjtxy 发表于 2010-8-24 20:07


这相当于点击窗口关闭按钮,如果用户设置点关闭时最小化到系统栏,就……
发表于 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难度还是比较大的……

评分

参与人数 1金钱 +20 收起 理由
afan + 20

查看全部评分

 楼主| 发表于 2010-8-25 20:50:08 | 显示全部楼层
顶下,看到QQplus可以安全关闭QQ(至少它自己这样声称),看来找到合适的API和参数,是可以做到安全关闭的,只是我还没有找到。
发表于 2010-8-25 23:41:34 | 显示全部楼层
向QQ的关闭按钮发送一个鼠标点击,或许是一个可行的方法。
 楼主| 发表于 2010-8-26 09:09:58 | 显示全部楼层
向QQ的关闭按钮发送一个鼠标点击,或许是一个可行的方法。
itljl 发表于 2010-8-25 23:41


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

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

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

评分

参与人数 1金钱 +20 收起 理由
afan + 20

查看全部评分

发表于 2010-8-26 11:01:23 | 显示全部楼层
一般点某个菜单时是发送WM_COMMAND消息给某个窗口, 所以只要用Spy看下退出菜单的ID,模拟发送一下这个消息就可以了。

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

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

评分

参与人数 1金钱 +15 收起 理由
afan + 15

查看全部评分

发表于 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][0] > 0 then   
  For $i = 1 To $list[0][0]
   $x = WinGetPos($list[$i][1])
   If $x[2] = 132 And $x[3] = 261 Then
    $a = 0
    $b = 0
    WinMove($list[$i][1], "", $a, $b)
    WinSetState($list[$i][1], "", @SW_SHOW)
    $s = MouseGetPos()
    top($list[$i][1])
    MouseClick("left", $a + 20, $b + 210, 1, 0)
    MouseMove($s[0], $s[1], 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[3] - 20, 1, 0)
   WinMove("TM", "", $y[0],$y[1],$y[2],$y[3])
   MouseMove($s[0], $s[1], 0)   
  EndIf
  EndIf
WEnd 


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


Exit
EndFunc   ;==>mimi
func top($hdl);把窗口放到最前端.
    $hw=_WinAPI_GetForegroundWindow()
                If $hw<>$hdl  Then
                        _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

多谢帮忙,是个好的思路……
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-12-25 14:33 , Processed in 0.099080 second(s), 31 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表