LoadRunner下DLL的調用

                    LoadRunnerDLL的調用

                                                        ——落葉夏日cwj.007

場景介紹   

       最近在做類似於QQ的通信工具的性能測試時發現了一些問題,現總結出來與大家分享一下。希望大家在使用LoadRunner時不僅僅停在只是錄製/播放角本,而全面提升角本的編程技術,解決複雜場景。

       本次測試中碰到的問題是這樣的,在消息的傳送過程中遇到了DEC加密的過程,LoadRunner錄製到的全是加密的消息,比如我錄製了某一個用戶的登陸,發送消息,退出,但由於是加密的,只能單個用戶使用,但如果我想併發多少個用戶就存在很多問題,最直接的一個問題就是用戶名是加密的,密碼是加密的,當然你可以說讓程序那裏注掉加密的代碼進行明碼的測試,當然也是一種辦法。但程序組提出了要使用更真實的方法來模擬,這時就必需使用下面介紹的方法。

       一開始是直接把API移植到LoadRunner中來,不過由於加密算法異常複雜,有幾層循環,而角本是解釋執行的,進行一次加密運算可能需要好幾分鐘,當然在角本里可以把角本本身運行的時間去掉,但這樣做顯然沒有直接調用DLL來的效率高。由於程序組比較忙,所以無法提供DLL給測試,所以測試完成了DLL的編寫,並在LoadRunner中調用成功,高效的完成了用戶信息加密,參數關聯,成功的完成了測試。

動態鏈接庫的編寫
  在Visual C++6.0開發環境下,打開FileNewProject選項,可以選擇Win32 Dynamic-Link Library建立一個空的DLL工程。
  1 Win32 Dynamic-Link Library方式創建Non-MFC DLL動態鏈接庫

  每一個DLL必須有一個入口點,這就象我們用C編寫的應用程序一樣,必須有一個WINMAIN函數一樣。在Non-MFC DLLDllMain是一個缺省的入口函數,你不需要編寫自己的DLL入口函數,用這個缺省的入口函數就能使動態鏈接庫被調用時得到正確的初始化。如果應用程序的DLL需要分配額外的內存或資源時,或者說需要對每個進程或線程初始化和清除操作時,需要在相應的DLL工程的.CPP文件中對DllMain()函數按照下面的格式書寫。

 

BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
switch( ul_reason_for_call )
{
case DLL_PROCESS_ATTACH:
    break;
case DLL_THREAD_ATTACH:
    break;
case DLL_THREAD_DETACH:
    break;
case DLL_PROCESS_DETACH:
    break;

default:

    break;
}
return TRUE;
}

  

       參數中,hMoudle是動態庫被調用時所傳遞來的一個指向自己的句柄(實際上,它是指向_DGROUP段的一個選擇符)ul_reason_for_call是一個說明動態庫被調原因的標誌,當進程或線程裝入或卸載動態鏈接庫的時候,操作系統調用入口函數,並說明動態鏈接庫被調用的原因,它所有的可能值爲:DLL_PROCESS_ATTACH: 進程被調用、DLL_THREAD_ATTACH: 線程被調用、DLL_PROCESS_DETACH: 進程被停止、DLL_THREAD_DETACH: 線程被停止;lpReserved爲保留參數。到此爲止,DLL的入口函數已經寫了,剩下部分的實現也不難,你可以在DLL工程中加入你所想要輸出的函數或變量了。

  我們已經知道DLL是包含若干個函數的庫文件,應用程序使用DLL中的函數之前,應該先導出這些函數,以便供給應用程序使用。要導出這些函數有兩種方法,一是在定義函數時使用導出關鍵字_declspec(dllexport),另外一種方法是在創建DLL文件時使用模塊定義文件.Def。需要讀者注意的是在使用第一種方法的時候,不能使用DEF文件。下面通過兩個例子來說明如何使用這兩種方法創建DLL文件。

  1)使用導出函數關鍵字_declspec(dllexport)創建MyDll.dll,該動態鏈接庫中有兩個函數,分別用來實現得到兩個數的最大和最小數。在MyDll.hMyDLL.cpp文件中分別輸入如下原代碼:
 

//MyDLL.h
extern "C" _declspec(dllexport) int desinit(int mode);

extern "C" _declspec(dllexport) void desdone(void);

extern "C" _declspec(dllexport) void des_setkey(char *subkey, char *key);

extern "C" _declspec(dllexport) void endes(char *block, char *subkey);

extern "C" _declspec(dllexport) void dedes(char *block, char *subkey);
//MyDll.cpp
#include"MyDll.h"

//這裏我用了比較大小的函數代替了我要實現的函數

 int desinit(int a, int b)
{
if(a>=b)return a;
else
return b;
}
int desdone(int a, int b)
{
if(a>=b)return b;
else
return a;
}

該動態鏈接庫編譯成功後,打開MyDll工程中的debug目錄,可以看到MyDll.dllMyDll.lib兩個文件。LIB文件中包含DLL文件名和DLL文件中的函數名等,該LIB文件只是對應該DLL文件的"映像文件",與DLL文件中,LIB文件的長度要小的多,在進行隱式鏈接DLL時要用到它。讀者可能已經注意到在MyDll.h中有關鍵字"extern C",它可以使其他編程語言訪問你編寫的DLL中的函數。

LoadRunner調用動態鏈接庫

       上面完成動態鏈接庫開發後,下面就介紹動態鏈接庫如何被LoadRunner進行調用,其實也是很簡單的。在LoadRunner中的DLL調用有局部調用與全局調用,下面介紹局部調用。

首先把你編譯的DLL放在角本路徑下面,這裏是MyDll.dll,MyDll.lib.然後在Action中使用

lr_load_dll("MYDll.dll"),此函數可以把DLL加載進來,讓你調用DLL裏面的函數,而DLL中的運算是編譯級的,所以效率極高,代碼樣例如下:

#include "lrs.h"

Action()

{

       //

       int nRet = 6;

       char srckey[129];

       memset(srckey, 'a', 128);

       lr_message(lr_eval_string(srckey));

       lr_load_dll("MyDLL.dll");

       nRet = desinit(5,8);

       lr_message("比較的結果爲%d",nRet);

    return 0;

}

運行結果

       比較的結果爲8

 

       全局的動態鏈接庫的調用則需要修改mdrv.dat路徑在LoadRunner的安裝目錄下面(LoadRunner/dat directory);在裏面修改如例:

    [WinSock]

ExtPriorityType=protocol

WINNT_EXT_LIBS=wsrun32.dll

WIN95_EXT_LIBS=wsrun32.dll

LINUX_EXT_LIBS=liblrs.so

SOLARIS_EXT_LIBS=liblrs.so

HPUX_EXT_LIBS=liblrs.sl

AIX_EXT_LIBS=liblrs.so

LibCfgFunc=winsock_exten_conf

UtilityExt=lrun_api

ExtMessageQueue=0

ExtCmdLineOverwrite=-WinInet No

ExtCmdLineConc=-UsingWinInet No

WINNT_DLLS=user_dll1.dll, user_dll2.dll, ...

//最後一行是加載你需要的DLL

       這樣你就可以在LR中隨意的調用程序員寫的API函數,進行一些複雜的數據加密,準備的一些操作,進行復雜的測試。同時如果你覺的有大量高複雜的運算也可以放在DLL中進行封裝,以提高效率。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章