|
最近针对loadrunner做功能扩展,其中一个环节是:尽力正常点击stop停止,如经过处理无法停止,则干净终止loadrunner进程。
loadrunner手册有命令行方式启动wlrun.exe进程的方式,但没有停止wlrun.exe的方式。本方法用win32实现友好停止Loadrunner场景。
窗口层次关系可以用spy++察看 .
测试程序的方法,启动一个loadrunner运行场景。
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <errno.h>
#include <locale.h>
#include <windows.h>
#include <vdmdbg.h>
typedef struct
{
DWORD dwID ;
DWORD dwThread ;
} TERMINFO ;
BOOL CALLBACK TerminateAppEnum( HWND hwnd, LPARAM lParam ) ;
DWORD WINAPI TerminateApp( DWORD dwPID, DWORD dwTimeout )
{
HANDLE hProc ;
DWORD dwRet ;
// If we can't open the process with PROCESS_TERMINATE rights,
// then we give up immediately.
hProc = OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE,
dwPID);
if(hProc == NULL)
{
return FALSE ;
}
// TerminateAppEnum() posts WM_CLOSE to all windows whose PID
// matches your process's.
EnumWindows((WNDENUMPROC)TerminateAppEnum, (LPARAM) dwPID) ;
// Wait on the handle. If it signals, great. If it times out,
// then you kill it.
if(WaitForSingleObject(hProc, dwTimeout)!=WAIT_OBJECT_0)
dwRet=(TerminateProcess(hProc,0)?TRUE:FALSE);
else
dwRet = TRUE ;
CloseHandle(hProc) ;
return dwRet ;
}
BOOL CALLBACK TerminateAppEnum( HWND hwnd, LPARAM lParam )
{
DWORD dwID ;
GetWindowThreadProcessId(hwnd, &dwID) ;
if(dwID == (DWORD)lParam)
{
PostMessage(hwnd, WM_CLOSE, 0, 0) ;
}
return TRUE ;
}
//MyEnumWindow 函数本身只能枚举最top-level的窗口。
//嵌套的窗口自己枚举
//这里用spy++观察层次结构
//模拟用户鼠标操作停止loadrunner的过程
BOOL CALLBACK MyEnumWindow(HWND hWnd, LPARAM lParam)
{
char sz_text[MAX_PATH]={0};
int len =0;
char * p_title = NULL;
int ret;
HWND child_hWnd=NULL,dialog_hWnd=NULL,next_hWnd=NULL;
int i=0;
BOOL isFound = FALSE;
int try_time=10;
WINDOWINFO winInfo;
DWORD dwID ;
p_title=(char*)lParam;
len= GetWindowText(hWnd, sz_text, sizeof(sz_text)/sizeof(sz_text[0]));
if (strstr(sz_text,"LoadRunner"))
printf("%s\r\n",sz_text);
child_hWnd = hWnd;
if(strstr(sz_text,p_title))
{
while(1)
{
//获取子窗口
child_hWnd=GetWindow(child_hWnd, GW_CHILD);
//恶意关闭loadrunner时,窗口是否为存在?防止死循环。
if(child_hWnd!=NULL)
{
len= GetWindowText(child_hWnd, sz_text, sizeof(sz_text)/sizeof(sz_text[0]));
if (!strcmp(sz_text,"&Start Scenario"))
{
//获取兄弟窗口
next_hWnd=GetWindow(child_hWnd, GW_HWNDNEXT);
len= GetWindowText(next_hWnd,sz_text, sizeof(sz_text)/sizeof(sz_text[0]));
if (!strcmp(sz_text,"S&top") )
{
//找到停止的窗口
isFound =TRUE;
break;
}
}
}
else //child_hWnd!=NULL
{
break;
}
} //while
if (FALSE ==isFound )
{
//失败退出
printf("not found S&top!\r\n");
return TRUE;
}
//尝试投递try_time次。
//for(i=0;i < try_time; i++)
while(1)
{
//SendMessage(next_hWnd, BM_CLICK,0, 0);
PostMessage(next_hWnd, BM_CLICK,0, 0); // 这里不能用SendMessage,否则阻塞进程
dialog_hWnd = FindWindow("#32770", "LoadRunner Controller");
if (!dialog_hWnd)
{
printf("Find dialog error. ret=%d\r\n",GetLastError());
}
else
{
//if (IsWindowVisible(dialog_hWnd))
//{
len= GetWindowText(dialog_hWnd, sz_text, sizeof(sz_text)/sizeof(sz_text[0]));
printf("GetWindowText return %s\r\n",sz_text);
//查找对话框上按纽
child_hWnd = FindWindowEx(dialog_hWnd,0,"Button","确定");
if (!child_hWnd)
{
printf("确定 button ret=%d\r\n",GetLastError());
continue;
}
SendMessage(child_hWnd, BM_CLICK,0, 0);
ret = GetLastError();
if (ret)
{
printf("button error. ret=%d\r\n",ret);
}
else
{
printf("正常停止loadrunner!\r\n");
}
//经过如上处理后
printf("destroywindows\r\n");
Sleep(10);
//强行关闭loadrunner相关进程
GetWindowThreadProcessId(hWnd, &dwID) ;
TerminateApp(dwID,10);
return FALSE;
//}
} //(!prev_hWnd)
}//for
}
return TRUE;
}
int stop_loadrunner()
{
char sz_title[]="Mercury LoadRunner Controller ";
// char sz_title[]="S&top";
if (EnumWindows(MyEnumWindow,(long) sz_title) )
printf("failed,errno=%d",GetLastError());
}
void main()
{
stop_loadrunner();
} |
|