@import url(http://www.tkk7.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);
本次通過loadRunner錄制SQL Server介紹一下如何測試一個sql語句或存儲過程的執行性能。
主要分如下幾個步驟完成:
第一步、測試準備
第二步、配置ODBC數據源
第三步、錄制SQL語句在Sql Server查詢分析器中的運行過程
第四步、優化錄制腳本,設置事務
第五步、改變查詢數量級查看SQL語句的性能
第六步、在controller中運行腳本
下面開始具體的介紹:
測試準備階段我們首先要確認測試數據庫服務器:我們可以在本地安裝SQL SERVER數據庫服務端及客戶端,也可以確定一臺裝好的SQL SERVER服務器。
接下來,準備測試數據:對數據庫測試時我們要考慮的不是SQL語句是否能夠正確執行,而是在某數量級的情況下SQL語句的執行效率及數據庫服務的運行情況,所以我們分別準備不同數量級的測試數據,即根據實際的業務情況預估數據庫中的記錄數,在本次講解中我們不考慮業務邏輯也不考慮數據表之間的關系,我們只建立一張表,并向此表中加入不同數量級的數據,如分別加入1000條、10000條、50000條、100000條數據查看某SQL語句的執行效率。
在查詢分析器中運行如下腳本:
--創建測試數據庫
create database loadrunner_test;
use loadrunner_test
--創建測試數據表
create table test_table
(username varchar(50),sex int,age int,address varchar(100),post int)
--通過一段程序插入不同數量級的記錄,具體的語法在這里就不多說了
declare @i int
set @i=0
while @i<1000 //循環1000次,可以根據測試數據情況改變插入條數
begin
BEGIN TRAN T1
insert into test_table (username,sex,age,address,post) values ('戶瑞海'+cast(@i as varchar),@i-1,@i+1,'北京市和平里'+cast(@i as varchar)+'號',123456);
IF @@ERROR <> 0
begin
rollback;
select @@error
end
else
begin
commit;
set @i = @i+1
end
end
|
好了,執行完上述語句后,建立的數據表中已經有1000條記錄了,下面進行第二步的操作,配置ODBC數據源,為了能讓loadrunner能夠通過ODBC協議連接到我們建立的SQL SERVER數據路,我們需要在本機上建立ODBC數據源,建立方法如下:
控制面板—性能和維護—管理工具—數據源(ODBC)--添加,在列表中選擇SQL SERVER點擊完成,根據向導輸入數據源名稱,鏈接的服務器,下一步,輸入鏈接數據庫的用戶名和密碼,更改鏈接的數據庫,完成ODBC的配置,如果配置正確的話,在最后一步點擊“測試數據源”,會彈出測試成功的提示。
配置好ODBC數據源后就要錄制SQL語句在查詢分析器中的執行過程了:
1、 打開loadrunner,選擇ODBC協議
2、 在start recording中的application type 選擇win32 application;program to record中錄入SQL SERVER查詢分析器的路徑“..\安裝目錄\isqlw.exe”
3、 開始錄制,首先通過查詢分析器登錄SQL SERVER,在打開的查詢分析器窗口中輸入要測試的SQL語句,如“select * from test_table;”
4、 在查詢分析器中執行該語句,執行完成后,結束錄制
好了,現在就可以看到loadrunner生成的腳本了(由于腳本過長,在這里就不粘貼了,有需要的朋友可以加我QQ,我把腳本發給你們),通過這些語句,我們可以看出,登錄數據庫的過程、執行SQL語句的過程。
接下來,我們來優化腳本,我們分別為數據庫登錄部分和執行SQL語句的部分加一個事物,在增加一個double的變量獲取事務執行時間,簡單內容如下:
Action()
{ double trans_time; //定義一個double型變量用來保存事務執行時間
lr_start_transaction("sqserver_login"); //設置登錄事務的開始
lrd_init(&InitInfo, DBTypeVersion); //初始化鏈接(下面的都是loadrunner生成的腳本了,大家可以通過幫助查到每個函數的意思)
lrd_open_context(&Ctx1, LRD_DBTYPE_ODBC, 0, 0, 0);
lrd_db_option(Ctx1, OT_ODBC_OV_ODBC3, 0, 0);
lrd_alloc_connection(&Con1, LRD_DBTYPE_ODBC, Ctx1, 0 /*Unused*/, 0);
………………
trans_time=lr_get_transaction_duration( "sqserver_login" ); //獲得登錄數據庫的時間
lr_output_message("sqserver_login事務耗時 %f 秒", trans_time); //輸出該時間
lr_end_transaction("sqserver_login", LR_AUTO); //結束登錄事務
lr_start_transaction("start_select");//開始查詢事務
lrd_cancel(0, Csr2, 0 /*Unused*/, 0);
lrd_stmt(Csr2, "select * from test_table;\r\n", -1, 1, 0 /*None*/, 0);//此句為執行的SQL
lrd_bind_cols(Csr2, BCInfo_D42, 0);
lrd_fetch(Csr2, -10, 1, 0, PrintRow24, 0);
……………..
trans_time=lr_get_transaction_duration( "start_select" ); //獲得該SQL的執行時間
lr_output_message("start_select事務耗時 %f 秒", trans_time); //輸出該時間
lr_end_transaction("start_select", LR_AUTO); //結束查詢事務
|
優化后,在執行上述腳本后,就可以得到登錄到數據庫的時間及運行select * from test_table這條語句的時間了,當然我們也可以根據實際情況對該條語句進行參數化,可以測試多條語句的執行時間,也可以將該語句改為調用存儲過程的語句來測試存儲過程的運行時間。
接下來把該腳本在controller中運行,設置虛擬用戶數,設置集合點,這些操作我就不說了,但是值得注意的是,沒有Mercury 授權的SQL SERVER用戶license,在運行該腳本時回報錯,提示“You do not have a license for this Vuser type.
Please contact Mercury Interactive to renew your license.”我們公司窮啊買不起loadrunner,所以我也無法繼續試驗,希望有license朋友們監控一下運行結果!
最起碼在VUGen中運行該腳本我們可以得到任意一個SQL語句及存儲過程的執行時間,如果我們測試的B/S結構的程序,我們也可以通過HTML協議錄制的腳本在CONTROLLER中監控SQL SERVER服務器的性能情況,這樣兩方面結合起來就可以對數據庫性能做一個完整的監控了。
本人對LOADRUNNER也是在摸索中,如果文章有寫的不對,或理解錯誤的地方請指出,不甚感激。(以上言論僅代表作者的個人觀點,不代表51Testing觀點)
/*需要的表結構如下
CREATE TABLE `test_data` (
`order_id` BIGINT UNSIGNED NOT NULL COMMENT 'Order numbers. Must be unique.',
`status` BOOL NOT NULL DEFAULT '0' COMMENT 'Whether data has been used or not. A value of 0 means FALSE.',
`date_used` DATETIME NULL COMMENT 'Date/time that the data was used.',
UNIQUE (
`order_id`
)
) ENGINE = innodb COMMENT = 'LoadRunner test data';
*/
Action()
{
int rc;
int db_connection; // 數據庫連接
int query_result; // 查詢結果集 MYSQL_RES
char** result_row; // 查詢的數據衕
char *server = "localhost";
char *user = "root";
char *password = "123456";
char *database = "test";
int port = 3306;
int unix_socket = NULL;
int flags = 0;
// 找到libmysql.dll的所在位置.
rc = lr_load_dll("C:\\Program Files\\MySQL\\MySQL Server 5.1\\bin\\libmysql.dll");
if (rc != 0) {
lr_error_message("Could not load libmysql.dll");
lr_abort();
}
// 創建MySQL對象
db_connection = mysql_init(NULL);
if (db_connection == NULL) {
lr_error_message("Insufficient memory");
lr_abort();
}
// 連接到MySQL數據庫
rc = mysql_real_connect(db_connection, server, user, password, database, port, unix_socket, flags);
if (rc == NULL) {
lr_error_message("%s", mysql_error(db_connection));
mysql_close(db_connection);
lr_abort();
}
// 向數據庫插入數據
// 此處的 {ORDER_ID} 是一個參數,簡單測試時可以用一個常數代替
lr_save_string (lr_eval_string("INSERT INTO test_data (order_id) VALUES ({ORDER_ID})"),"paramInsertQuery");
rc = mysql_query(db_connection, lr_eval_string("{paramInsertQuery}"));
if (rc != 0) {
lr_error_message("%s", mysql_error(db_connection));
mysql_close(db_connection);
lr_abort();
}
// 從數據庫讀取一個數據并顯示
rc = mysql_query(db_connection, "SELECT order_id FROM test_data WHERE status IS FALSE LIMIT 1");
if (rc != 0) {
lr_error_message("%s", mysql_error(db_connection));
mysql_close(db_connection);
lr_abort();
}
query_result = mysql_use_result(db_connection);
if (query_result == NULL) {
lr_error_message("%s", mysql_error(db_connection));
mysql_free_result(query_result);
mysql_close(db_connection);
lr_abort();
}
// 如果結果集包含多行數據,需要多次調用 mysql_fetch_row 直到返回NULL
result_row = (char **)mysql_fetch_row(query_result);
if (result_row == NULL) {
lr_error_message("Did not expect the result set to be empty");
mysql_free_result(query_result);
mysql_close(db_connection);
lr_abort();
}
// 保存參數,用于刪除這行數據
lr_save_string(result_row[0], "paramOrderID");
lr_output_message("Order ID is: %s", lr_eval_string("{paramOrderID}"));
mysql_free_result(query_result);
// 在事務里更新一行數據,需要用InnoDB引擎
rc = mysql_query(db_connection, "BEGIN"); //啟動事務
if (rc != 0) {
lr_error_message("%s", mysql_error(db_connection));
mysql_close(db_connection);
lr_abort();
}
// 使用 "FOR UPDATE" 鎖住要更新的數據行
rc = mysql_query(db_connection, "SELECT order_id FROM test_data WHERE status IS FALSE LIMIT 1 FOR UPDATE");
if (rc != 0) {
lr_error_message("%s", mysql_error(db_connection));
mysql_close(db_connection);
lr_abort();
}
query_result = mysql_use_result(db_connection);
if (query_result == NULL) {
lr_error_message("%s", mysql_error(db_connection));
mysql_free_result(query_result);
mysql_close(db_connection);
lr_abort();
}
result_row = (char **)mysql_fetch_row(query_result);
if (result_row == NULL) {
lr_error_message("沒有查詢到結果");
mysql_free_result(query_result);
mysql_close(db_connection);
lr_abort();
}
lr_save_string(result_row[0], "paramOrderID");
lr_output_message("Order ID is: %s", lr_eval_string("{paramOrderID}"));
mysql_free_result(query_result);
lr_save_string(lr_eval_string("UPDATE test_data SET status=TRUE, date_used=NOW() WHERE order_id='{paramOrderID}'"),"paramUpdateQuery");
rc = mysql_query(db_connection, lr_eval_string("{paramUpdateQuery}"));
if (rc != 0) {
lr_error_message("%s", mysql_error(db_connection));
mysql_close(db_connection);
lr_abort();
}
rc = mysql_query(db_connection, "COMMIT"); // 提交事務
if (rc != 0) {
lr_error_message("%s", mysql_error(db_connection));
mysql_close(db_connection);
lr_abort();
}
// 再次查找數據,應該為空了,因為前面的事務更新了標志
rc = mysql_query(db_connection, "SELECT order_id FROM test_data WHERE status IS FALSE LIMIT 1");
if (rc != 0) {
lr_error_message("%s", mysql_error(db_connection));
mysql_close(db_connection);
lr_abort();
}
query_result = mysql_use_result(db_connection);
if (query_result == NULL) {
lr_error_message("%s", mysql_error(db_connection));
mysql_free_result(query_result);
mysql_close(db_connection);
lr_abort();
}
result_row = (char **)mysql_fetch_row(query_result);
if (result_row == NULL) {
lr_output_message("Result set is empty as expected");
mysql_free_result(query_result);
} else {
lr_error_message("Did not expect the result set to contain any rows");
mysql_free_result(query_result);
mysql_close(db_connection);
lr_abort();
}
// 刪除數據
lr_save_string(lr_eval_string("DELETE FROM test_data WHERE order_id = '{paramOrderID}'"),"paramDeleteQuery");
rc = mysql_query(db_connection, lr_eval_string("{paramDeleteQuery}"));
if (rc != 0) {
lr_error_message("%s", mysql_error(db_connection));
mysql_close(db_connection);
lr_abort();
}
// 釋放MySQL資源
mysql_close(db_connection);
return 0;
}
本文章來源于西盟軟件站【www.zmke.com】詳細地址:http://www.zmke.com/article/175/data/2009/2009070819880.html
(轉)LoadRunner測試過程中調用dll文件的制作與使用
上一篇 / 下一篇 2009-01-17 16:35:36 / 個人分類:LoadRunner
在Windows操作系統中使用DLL有很多優點,最主要的一點是多個應用程序、甚至是不同語言編寫的應用程序可以共享一個DLL文件,真正實現了資源"共享",大大縮小了應用程序的執行代碼,更加有效的利用了內存;使用DLL的另一個優點是DLL文件作為一個單獨的程序模塊,封裝性、獨立性好,在軟件需要升級的時候,開發人員只需要修改相應的DLL文件就可以了,而且,當DLL中的函數改變后,只要不是參數的改變,程序代碼并不需要重新編譯。這在編程時十分有用,大大提高了軟件開發和維護的效率。
在LR下也可以直接調用動態鏈接庫文件,針對一些使用LR腳本編寫比較煩瑣的方法可以考慮此方法(比如各種加解密算法的實現,數據庫的操作等),并能夠使測試腳本簡單明了。鑒于此,本人初次嘗試了如何制作DLL文件并在LR中使用。
1、dll文件的制作
在Visual C++6.0開發環境下,打開File-New-Project選項,可以選擇Win32 Dynamic-Link Library來創建一個名為dllfortest的空的dll工程(這只是方法之一)。
在該項目中新建一個dllfortest.h和dllfortest.cpp文件,文件的內容如下:
//dllfortest.h
extern "C" _declspec(dllexport) int Max(int a, int b, int c);
extern "C" _declspec(dllexport) int Min(int a, int b, int c);
//dllfortest.cpp 包含一個計算三個整數中最大值和最小值的方法
#include"dllfortest.h"
int Max(int a, int b, int c)
{
int Res;
Res = (a>b? a:b)>c? (a>b? a:b):c;
return Res;
}
int Min(int a, int b, int c)
{
int Res;
Res = (a>b? b:a)>c? c:(a>b? b:a);
return Res;
}
該動態鏈接庫編譯成功后,打開dllfortest工程目錄下的debug目錄下,可以看到生成了一個dllfortest.dll文件,這就是我們想要的文件。
2、dll文件在LR中的調用
打開LR VU Generator,選擇C Vuser協議(或其他支持C的協議),進入編輯界面。Action部分如下所示:
Action()
{
lr_load_dll("dllfortest.dll");
lr_message("Max Result is %d",Max(100,200,67));
lr_message("Min Result is %d",Min(55,97,63));
return 0;
}
將dllfortest.dll文件復制到腳本所在的目錄(如果不復制的話,lr_load_dll的參數應該寫成dll文件的絕對路徑),如果編譯沒有報錯的話,就可以直接運行了。
運行結果如下:
Virtual User scrīpt started
Starting action vuser_init.
Ending action vuser_init.
Running Vuser...
Starting iteration 1.
Starting action Action.
Max Result is 200
Min Result is 55
Ending action Action.
Ending iteration 1.
Ending Vuser...
Starting action vuser_end.
Ending action vuser_end.
Vuser Terminated.
如果在腳本中用到了DLL文件中并不存在的方法名時,編譯也能通過,但是運行時LR會報錯,提示不存在該方法
比如我們在腳本中添加一句:
lr_message("Min Result is %d",Sum(55,97,63)); //Sum方法并不存在
運行時錯誤信息如下:
Action.c(7): Error: C interpreter run time error: Action.c (7): Error -- Unresolved symbol : Sum.
Action.c(7): Notify: CCI trace: Compiled_code(0): Action()
.
這個例子并沒有體現出DLL文件調用的優點,因為調用的方法在LR中用C直接就可以完成,但涉及到LR中完不成的任務時,或許dll文件的作用就體現出來了
example:
LoadRunner提供了功能強大的API集合,足夠應付大多數性能測試的需求。但在某些情況下,這些API仍然有覆蓋不到的地方。例如,我們有一個WEB應用,該應用有一個頁面輸入用戶的信息,為了安全起見,用戶輸入的信息在提交之前都要先進行加密處理,加密處理通過本地的COM組件實現。
對這個要求而言,LoadRunner的現有API不能提供直接支持,因為LoadRunner在錄制腳本時只錄制數據交互,因此,COM的加密處理過程是不能錄制下來的。在LoadRunner的腳本中,可能只有類似以下的語句描述了這個過程:
…………
web_url("userinfo",
"URL=http://testweb/userinfo.aspx",
"TargetFrame=",
"Resource=0",
"Referer=",
LAST);
web_submit_form("login ",
"Snapshot=t4.inf",
ITEMDATA,
"Name=username", "Value=4e92Sh6d394g", ENDITEM,
"Name=password", "Value=932A2hf34U18", ENDITEM,
LAST);
…………
從腳本可以看到,輸入的數據是加密后的數據,但LR沒有錄制到加密過程。
假設加密函數所在的DLL名為security.dll,用于加密的函數名為encode,則一種可能的對腳本的修改方法如下代碼所示。
…………
char *encode_username, *encode_password, *orgin_username, *orgin_password;
char* uservalue, passvalue;
int ret;
……
web_url("userinfo",
"URL=http://testweb/userinfo.aspx",
"TargetFrame=",
"Resource=0",
"Referer=",
LAST);
orgin_username = lr_eval_string(“{ username }”); //獲取參數的值
orgin_password = lr_eval_string(“{ password }”);
ret = lr_load_dll(“security.dll”); //加載DLL庫
encode(origin_username, encode_username); //調用encode函數
encode(origin_password, encode_password);
sprintf(uservalue, “Value=%s”, encode_username);
sprintf(passvalue, “value=%s”, encode_password);
web_submit_form("login ",
"Snapshot=t4.inf",
ITEMDATA,
"Name=username", uservalue, ENDITEM,
"Name=password", passvalue, ENDITEM,
LAST);
注意:有些腳本錄制需要相應的patch的支持,如錄制DotNet編寫的應用程序你需要把lr78安裝盤\ Patches\Trap_for_.net_patch文件夾中trpfnc32.32dll拷貝到loadrunner\bin路徑下,才能正常工作。
場景介紹
最近在做類似于QQ的通信工具的性能測試時發現了一些問題,現總結出來與大家分享一下。希望大家在使用LoadRunner時不僅僅停在只是錄制/播放腳本,而全面提升腳本的編程技術,解決復雜場景。
本次測試中碰到的問題是這樣的,在消息的傳送過程中遇到了DEC加密的過程,LoadRunner錄制到的全是加密的消息,比如我錄制了某一個用戶的登陸,發送消息,退出,但由于是加密的,只能單個用戶使用,但如果我想并發多少個用戶就存在很多問題,最直接的一個問題就是用戶名是加密的,密碼是加密的,當然你可以說讓程序那里注掉加密的代碼進行明碼的測試,當然也是一種辦法。但程序組提出了要使用更真實的方法來模擬,這時就必需使用下面介紹的方法。
一開始是直接把API移植到LoadRunner中來,不過由于加密算法異常復雜,有幾層循環,而腳本是解釋執行的,進行一次加密運算可能需要好幾分鐘,當然在腳本里可以把腳本本身運行的時間去掉,但這樣做顯然沒有直接調用DLL來的效率高。由于程序組比較忙,所以無法提供DLL給測試,所以測試組完成了DLL的編寫,并在LoadRunner中調用成功,高效的完成了用戶信息加密,參數關聯,成功的完成了測試。
動態鏈接庫的編寫
在Visual C++6.0開發環境下,打開FileNewProject選項,可以選擇Win32 Dynamic-Link Library建立一個空的DLL工程。
Win32 Dynamic-Link Library方式創建Non-MFC DLL動態鏈接庫
每一個DLL必須有一個入口點,這就象我們用C編寫的應用程序一樣,必須有一個WINMAIN函數一樣。在Non-MFC DLL中DllMain是一個缺省的入口函數,你不需要編寫自己的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.h和MyDLL.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.dll、MyDll.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中進行封裝,以提高效率。
|