想做一个获取qq聊天内容的程序,在网上查资料,发现了一个博客,上面讲了很多,但是我把代码写好,编译完成,但是执行的时候就会崩溃,不知道那得问题,求大神指教,博客上有代码,网址如下:“http://www.vckbase.com/index.php/wv/651”
代码如下:
#include <iostream>
#include <windows.h>
#include <oleacc.h>
#include "atlbase.h"
#include <winable.h>
#include "comutil.h"
#pragma comment(lib,"comsupp.lib")
#pragma comment(lib,"oleacc.lib")
BOOL FindChild (IAccessible* paccParent,
char* szName, char* szRole,
char* szClass,
IAccessible** paccChild,
VARIANT* pvarChild);
UINT GetObjectState(IAccessible* pacc,
VARIANT* pvarChild,
LPTSTR lpszState,
UINT cchState);
void GetObjectName(IAccessible* paccChild, VARIANT* varChild, char szObjName[], int s);
void GetObjectRole(IAccessible* paccChild, VARIANT* varChild, char szObjRole[], int s);
void GetObjectClass(IAccessible* paccChild,char szObjClass[], int s);
int main()
{
IAccessible* paccControl = NULL;//输入框的 IAccessible 接口
VARIANT varControl; //子ID。
HWND hWndMainWindow;
IAccessible *paccMainWindow = NULL;
HRESULT hr;
//得到标题为"运行"的窗口的句柄
if(NULL == (hWndMainWindow = FindWindow(NULL, "运行")))
{
MessageBox(NULL, "没有发现窗口!", "错误", MB_OK);
}
else
{
//通过窗口句柄得到窗口的 IAccessible 接口指针。
HINSTANCE hInst = ::LoadLibrary( _T("OLEACC.DLL") );
LPFNACCESSIBLEOBJECTFROMWINDOW pfAccessibleObjectFromWindow =
(LPFNACCESSIBLEOBJECTFROMWINDOW)::GetProcAddress(hInst,_T("AccessibleObjectFromWindow"));
if(S_OK == (hr = pfAccessibleObjectFromWindow(
hWndMainWindow,
OBJID_WINDOW,
IID_IAccessible,
(void**)&
paccMainWindow)))
{
//……我们可以通过这个指针paccMainWindow进行操作。
//paccMainWindow->Release();
//在文本输入框输入"regedit"
printf("paccMainWindow:%d\n",paccMainWindow);
if(1 == FindChild (paccMainWindow, "打开(O):",
"可编辑文字",
"Edit",
&paccControl,
&varControl))
{
//在这里修改文本编辑框的值
printf("xiu gai wenben nei rong\n");
hr = paccControl->put_accValue(varControl,CComBSTR("regedit"));
printf("xiu gai cheng gong\n");
paccControl->Release();
VariantClear(&varControl);
}
// 找到确定按钮,并执行默认动作。
if(1 == FindChild (paccMainWindow,
"确定",
"按下按钮",
"Button",
&paccControl,
&varControl))
{
//这里执行按钮的默认动作,即"按下这个按钮"
hr = paccControl->accDoDefaultAction(varControl);
paccControl->Release();
VariantClear(&varControl);
}
}
}
return 0;
}
BOOL FindChild (IAccessible* paccParent,
char* szName, char* szRole,
char* szClass,
IAccessible** paccChild,
VARIANT* pvarChild)
{
HRESULT hr;
long numChildren;
unsigned long numFetched;
VARIANT varChild;
int index;
IAccessible* pCAcc = NULL;
IEnumVARIANT* pEnum = NULL;
IDispatch* pDisp = NULL;
BOOL found = false;
char szObjName[256], szObjRole[256], szObjClass[256], szObjState[256];
//得到父亲支持的IEnumVARIANT接口
if(paccParent==NULL)
{
printf("paccParent is NULL");
return false;
}
printf("enter findall\n");
hr = paccParent->QueryInterface(IID_IEnumVARIANT,(void**)&pEnum);
if(pEnum)
pEnum -> Reset();
//取得父亲拥有的可访问的子的数目
paccParent -> get_accChildCount(&numChildren);
printf("numChildren:%d\n",numChildren);
//搜索并比较每一个子ID,找到名字、角色、类与输入相一致的。
for(index = 1; index <= numChildren && !found; index++)
{
printf("%d\n",index);
pCAcc = NULL;
// 如果支持IEnumVARIANT接口,得到下一个子ID
//以及其对应的 IDispatch 接口
printf("pEnum:%d\n",pEnum);
if (pEnum)
{
//VariantInit(&varChild);
printf("varChild:%d\n",varChild);
hr = pEnum -> Next(1, &varChild, &numFetched);
if(hr==S_OK)
printf("S_OK\n");
printf("varChild:%d\n",varChild);
}
else
{
//如果一个父亲不支持IEnumVARIANT接口,子ID就是它的序号
varChild.vt = VT_I4;
varChild.lVal = index;
}
// 找到此子ID对应的 IDispatch 接口
if (varChild.vt == VT_I4)
{
//通过子ID序号得到对应的 IDispatch 接口
pDisp = NULL;
printf("pDisp:%d\n",pDisp);
hr = paccParent ->get_accChild(varChild,&pDisp);
if(hr==S_OK)
printf("S_OK\n");
else if(hr==S_FALSE)
printf("S_FALSE\n");
else if(hr==E_INVALIDARG)
printf("E_INVALIDARG\n");
printf("pDisp:%d\n",pDisp);
}
else
//如果父支持IEnumVARIANT接口可以直接得到子IDispatch 接口
pDisp = varChild.pdispVal;
// 通过 IDispatch 接口得到子的 IAccessible 接口 pCAcc
if (pDisp)
{
printf("pCAcc:%d\n",pCAcc);
hr = pDisp->QueryInterface(IID_IAccessible, (void**)&pCAcc);
printf("pCAcc:%d\n",pCAcc);
hr = pDisp->Release();
}
// Get information about the child
if(pCAcc)
{
//如果子支持IAccessible 接口,那么子ID就是CHILDID_SELF
printf("*paccChild = pCAcc;\n");
VariantInit(&varChild);
varChild.vt = VT_I4;
varChild.lVal = CHILDID_SELF;
*paccChild = pCAcc;
}
else
{
//如果子不支持IAccessible 接口
printf("*paccChild = paccParent;\n");
*paccChild = paccParent;
}
//跳过了有不可访问状态的元素
GetObjectState(*paccChild,
&varChild,
szObjState,
sizeof(szObjState));
if(NULL != strstr(szObjState, "unavailable"))
{
if(pCAcc)
pCAcc->Release();
continue;
}
//通过get_accName得到Nam
GetObjectName(*paccChild, &varChild, szObjName, sizeof(szObjName));
//通过get_accRole得到Role
GetObjectRole(*paccChild, &varChild, szObjRole, sizeof(szObjRole));
//通过WindowFromAccessibleObject和GetClassName得到Class
GetObjectClass(*paccChild, szObjClass, sizeof(szObjClass));
//以上实现代码比较简单,大家自己看代码吧。
//如果这些参数与输入相符或输入为NULL
if ((NULL==szName ||
0==strcmp(szName, szObjName))&&
(NULL==szRole ||
0==strcmp(szRole, szObjRole)) &&
(NULL==szClass ||
0==strcmp(szClass, szObjClass)))
{
found = true;
*pvarChild = varChild;
break;
}
if(!found && pCAcc)
{
// 以这次得到的子接口为父递归调用
printf("findall again");
found = FindChild(pCAcc,
szName,
szRole,
szClass,
paccChild,
pvarChild);
if(*paccChild != pCAcc)
pCAcc->Release();
}
}//End for
// Clean up
if(pEnum)
pEnum -> Release();
printf("exit findall\n");
return found;
}
// UI元素的状态也表示成整型形式。因为一个状态可以有多个值,
//例如可选的、可做焦点的,该整数是反映这些值的位的或操作结果。
//将这些或数转换成相应的用逗号分割的状态字符串。
UINT GetObjectState(IAccessible* pacc,
VARIANT* pvarChild,
LPTSTR lpszState,
UINT cchState)
{
HRESULT hr;
VARIANT varRetVal;
*lpszState = 0;
VariantInit(&varRetVal);
hr = pacc->get_accState(*pvarChild, &varRetVal);
if (!SUCCEEDED(hr))
return(0);
DWORD dwStateBit;
int cChars = 0;
if (varRetVal.vt == VT_I4)
{
// 根据返回的状态值生成以逗号连接的字符串。
for (dwStateBit = STATE_SYSTEM_UNAVAILABLE;
dwStateBit < STATE_SYSTEM_ALERT_HIGH;
dwStateBit <<= 1)
{
if (varRetVal.lVal & dwStateBit)
{
cChars += GetStateText(dwStateBit,
lpszState + cChars,
cchState - cChars);
*(lpszState + cChars++) = ',';
}
}
if(cChars > 1)
*(lpszState + cChars - 1) = '\0';
}
else if (varRetVal.vt == VT_BSTR)
{
WideCharToMultiByte(CP_ACP,
0,
varRetVal.bstrVal,
-1,
lpszState,
cchState,
NULL,
NULL);
}
VariantClear(&varRetVal);
return(lstrlen(lpszState));
}
void GetObjectName(IAccessible* paccChild, VARIANT* varChild, char szObjName[], int s)
{
printf("getname\n");
BSTR buf;
printf("paccChild:%d\n",paccChild);
paccChild->get_accName(*varChild,&buf);
printf("%s\n",buf);
szObjName=_com_util::ConvertBSTRToString(buf);
SysFreeString(buf);
}
void GetObjectRole(IAccessible* paccChild, VARIANT* varChild, char szObjRole[], int s)
{
printf("getrole\n");
VARIANT buf;
paccChild->get_accRole(*varChild,&buf);
buf.vt=VT_I2;
szObjRole=(char*)buf.bstrVal;
}
void GetObjectClass(IAccessible* paccChild,char szObjClass[], int s)
{
printf("getclass\n");
HWND hwnd;
LPSTR buf;
WindowFromAccessibleObject(paccChild,&hwnd);
GetClassName(hwnd,buf,s);
szObjClass=buf;
printf("getclass end\n");
}
但是代码执行到for循环的第二次的时候在 hr = paccParent ->get_accChild(varChild,&pDisp);处就会崩溃,而且pDisp的值始终为0,不知道为什么,对了这个程序我就是用的网址里的源码,把他的代码补完整了,基本功能就是实现将运行窗口的编辑框内容变为注册表的名字,并打开注册表程序。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)