Project1
标题:
请教API中函数参数类型的问题(不知道是不是这个问题= =)
[打印本页]
作者:
fux2
时间:
2011-1-24 13:33
标题:
请教API中函数参数类型的问题(不知道是不是这个问题= =)
本帖最后由 fux2 于 2011-1-26 12:09 编辑
原句
@GetPID = Win32API.new("user32","GetWindowThreadProcessId",['L'],'L')
ppid = @GetPID.call(pid)
复制代码
不知道为何这里获得的ppid和VB中获取的不同,导致后面的工程无法继续,于是请假
是因为函数类型错误么?
[line]1[/line]
另请教一下这里为什么会得到一个非定值的错误返回值?
作者:
蕾米莉亚·斯卡雷特
时间:
2011-1-24 17:14
本帖最后由 蕾米莉亚·斯卡雷特 于 2011-1-24 19:09 编辑
DWORD GetWindowThreadProcessId(
HWND hWnd,
LPDWORD lpdwProcessId
);
确定没有写错?
Win32API.new("user32.dll", "GetWindowThreadProcessId", "lp", "l")
[line]2[/line]
如果想获得 Ruby 运行的 PID 的话, 可以直接使用 $$ 来获取.
p $$
作者:
苏小脉
时间:
2011-1-25 02:02
本帖最后由 苏小脉 于 2011-1-25 02:02 编辑
参数类型声明写错了,你只声明了一个 'L' 参数,但实际上 GetWindowThreadProcessId 接受两个参数,一个是窗口句柄,一个是保存进程标识的指针(可为 NULL)。API 是本地函数,不存在参数默认值这样的高层概念,VB 这玩意儿可能是在 API 上面抽象了一层,实现了可选参数的机制,所以才可以只传递第一个参数。如果对本地函数也这么做,结果就是未知的。Windows API 遵循标准调用约定(stdcall),参数是从右到左压入栈中的。对于动态链接库函数调用这样的未经优化的代码,如果你只传递了一个参数给接受两个参数的函数,那在栈内存中本该是第二个参数的位置就没有被实际压入任何数据,但却保留着上一次使用这个位置的内存后遗留下来的值,所以对于函数调用者来说是不可知的,而且是可变的,这取决于整个程序帧在什么内存地址被装载。最后 GetWindowThreadProcessId 获取到的两个参数都是错误的值。
应该是:
@GetPID = Win32API.new("user32","GetWindowThreadProcessId",['L', 'p'],'L')
ppid = @GetPID.call(pid, 0)
作者:
fux2
时间:
2011-1-25 10:50
回复
苏小脉
的帖子
多谢苏大人赐教,但是此方法获得的pid还是与VB有出入(本次是3700和3704)
以至于玩呗后面的hProcess = @OpenPro.call(2035711,0,pid)无法取得正确值
还求继续详解
作者:
苏小脉
时间:
2011-1-25 11:40
回复
fux2
的帖子
没明白你想做什么,GetWindowThreadProcessId 返回的是创建了指定窗口的线程的标识,不是进程标识。如果同时需要进程标识,那需要给第二个参数传递一个有效的缓冲区指针,该 API 函数检测到这个指针不是 NULL,就会把进程标识拷贝到指针指向的内存中。
作者:
fux2
时间:
2011-1-25 11:42
本帖最后由 fux2 于 2011-1-26 07:04 编辑
回复
苏小脉
的帖子
啊……
调用:
if findwindow("扫雷")
cheat(openpro(getpid(findwindow("扫雷"))))
end
复制代码
一共有如下方法
def findwindow(name)
buf = name * 1024
Win32API.new("kernel32", "MultiByteToWideChar", ['I', 'L', 'P', 'I', 'P', 'I'], 'I').call(65001, 0, "扫雷", -1, buf, 1024)
buf.strip!
isfind = @FindWindow.call(0, buf)
isfind == 0 ? false : isfind
end
def getpid(pid)
return nil if pid == 0
ppid = @GetPID.call(pid, 0)
return ppid
end
def openpro(pid)
p pid
return nil if pid == nil or pid == 0
hProcess = @OpenPro.call(2035711,0,pid)
hProcess == 0 ? false : hProcess
end
def cheat(hProcess)
return false if hProcess == nil
baseaddr = 16798561
@Writeaddr.call(hProcess,baseaddr,0x41,1,0)
end
复制代码
作者:
苏小脉
时间:
2011-1-25 23:24
回复
fux2
的帖子
虽然你没给出你是如何调用方法的,但从你的方法命名来推断,你大概是把 GetWindowThreadProcessId 返回的线程标识传给 OpenProcess 了?OpenProcess 需要的是进程标识,所以你应该给 GetWindowThreadProcessId 传递一个有效的缓冲区地址,这样进程标识就会被拷贝到这个缓冲区中,然后再把它传给 OpenProcess。
作者:
紫苏
时间:
2011-1-26 12:08
所以说你确实是把线程标识当作进程标识在用了嘛,正确做法:
buf = ' '
@GetPID.call(hwindow, buf)
pid = buf.unpack('I')[0]
复制代码
这个 pid 才是创建了 hwindow 所标识的窗口的进程 ID。
欢迎光临 Project1 (https://rpg.blue/)
Powered by Discuz! X3.1