Windows平台DLL开发及LoadRunner调用
关于压力测试工具,目前使用比较多的还是Apache JMeter和loadrunner,loadrunner因为是商业化软件,在稳定性、辅助工具、报告生成、图形用户界面等方面相对更出色更友好一些,尤其是扩展性;
在某些特定场景下需要通过扩展脚本实现特定功能,例如base64编/解码、加解密运算等,此时可以直接将代码嵌入脚本,也可以封装成动态库,对于常用脚本封装更利于维护复用。在windows下就是封装DLL;
DLL(Dynamic Link Library)是Windows平台下的动态链接库文件,是windows系统的核心技术。
本文中以Base64编解码为例演示一个DLL库的开发调用过程。
从使用者角度看,DLL由入口函数(entry point)和导出表两部分组成,其中入口函数声明如下:
点击查看代码
extern "C" BOOL WINAPI DllMain(
HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpReserved ) // reserved
{
// Perform actions based on the reason for calling.
switch( fdwReason )
{
case DLL_PROCESS_ATTACH:
// Initialize once for each new process.
// Return FALSE to fail DLL load.
break;
case DLL_THREAD_ATTACH:
// Do thread-specific initialization.
break;
case DLL_THREAD_DETACH:
// Do thread-specific cleanup.
break;
case DLL_PROCESS_DETACH:
// Perform any necessary cleanup.
break;
}
return TRUE; // Successful DLL_PROCESS_ATTACH.
}
extern "C"关键字告诉编译器,按照C语言规范进行编译,防止导出函数C无法调用。
与Linux下的.so默认导出所有成员不同,DLL默认所有成员为“私有”,只有声明导出的成员才能被外部调用。按照MSDN说法,可以通过以下两种方式导出成员:
这里的示例为了测试方便直接在LoadRunner11中调用,输出函数直接调用LoadRunner内置函数;
点击查看代码
#include "D:\Loadrunner11\include\lrun.h"
#include "stdafx.h"
#include "base64.h"
/**
* 自定义导出函数
*/
extern "C" {
int __declspec(dllexport) Run (char *userName, char *pass)
{
int src_len = strlen(pass);
int dst_len = Base64encode_len(src_len);
char* dst = (char*)malloc(dst_len);
lr_output_message("pass:%s, src_len:%d, dst_len:%d", pass, src_len, dst_len);
int encoded_len = Base64encode(dst, pass, src_len);
//size_t len = 0;
//char* dst = base64_encode(src_msg, sizeof(src_msg), len);
lr_output_message( "We are on iteration: %s, userName: %s, Passwd: %s", lr_eval_string("{iter}" ), (char*)userName, dst);
//base64解码
int decode_len1 = Base64decode_len(dst);
//int Base64decode(char *bufplain, const char *bufcoded)
char *decoded1 = (char*)malloc(decode_len1);
if(decoded1 == NULL){
infos("内存分配失败");
return 0;
}
memset(decoded1, 0, decode_len1);
Base64decode(decoded1, dst);
lr_output_message("Secret:%s", decoded1);
free(dst);
free(decoded1);
return 0;
}
}
点击查看代码
vuser_init()
{
lr_load_dll("E:/LRWorkSpace/testdll/testHPlr/testHPlr.dll");
return 0;
}
在Action中调用DLL接口做业务:
点击查看代码
Action()
{
char *user_name = "Michael Sylvester Gardenzio Stallone(西尔维斯特·史泰龙)";
char *pwd = "ppnn13%dkstFeb.1st";
int src_len = strlen(pwd);
int dst_len = Base64encode_len(src_len);
char * encode_pwd = (char*)malloc(sizeof(char) * dst_len);
//调用1
Init(user_name, pwd);
lr_output_message("Src length: [%d], Target length: [%d]\n", src_len, dst_len);
//调用2
Base64encode(encode_pwd, pwd, src_len);
lr_log_message("base64:[%s]", encode_pwd);
free(encode_pwd);//attention
return 0;
}
此处C函数声明和C++和Java面向对象语言不同(面向对象时只要释放对象实例即可),有一个技巧,申请的内存需要考虑释放,所以C函数大概有以下声明方式:
1、两步调用,由调用者提供所有内存空间
int base64_len(const char *input_plain);
void base64(const char input_plain, char output_eoncoded)
由于输出长度不确定,所以先调用base64_len预计算长度,然后根据长度分配output_eoncoded内存空间
注意事项
测试过程中发现,Loadrunner变量声明需要在函数开始处,在函数中部声明变量会提示:
Action.c (14): illegal statement termination
Action.c (14): skippingchar' Action.c (14): undeclared identifiert'
另外通过malloc/calloc或new在运行期间分配的空间需要手动释放,通过char[100]方式在编译期分配的空间无需释放,所以在已知大小的情况下用此方式更安全简洁。
[参考链接]
https://msdn.microsoft.com/en-us/library/z4zxe9k8.aspx
本文来自博客园,作者:七彩代码,转载请注明原文链接:https://www.cnblogs.com/bitlife/articles/dll_for_loadrunner.html

浙公网安备 33010602011771号