• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

用Delphi创建DLL在LoadRunner中使用

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

参考:

Creating a DLL with Delphi for LoadRunner

http://ptfrontline.wordpress.com/2010/04/13/creating-a-dll-with-delphi-for-loadrunner/

This article extends my previous post on Using a Custom DLL in LoadRunner and now shows by example how a DLL is actually created in Delphi and used from LoadRunner.

The DLL I’ll create here is a simple stub with a few basic functions and can serve as a template for any type of DLL that you want to create.

I’ll show how to avoid the most common problems of sending/retrieving strings to/from the DLL as well as how to handle the Unicode situation with D2009 and D2010 (LR is not Unicode enabled). 

Some of the things a LR DLL developer needs to remember are:

  • LR is Muti-Threaded and Multi-processed, make the DLL thread-safe
  • When using LoadGenerators the DLL must be distributed to several machines
  • When using Performance Center the lr_load_dll() function needs to be white-listed on every LoadGenerator. The file to manipulate is “C:\Program Files\HP\Load Generator\merc_asl\lrun_api.asl”
  • The DLL may be unloaded at any time, if the script fails/aborts (=> YOU must release allocated memory)
  • If eternal loops or lockups inside the DLL occur, the whole controller/loadgenerator is lost until rebooted (really bad when under PerfCenter)

Keeping the above in mind, also remember the following general rules

  • LR script makers make mistakes too by sending INVALID input to functions or using them in an unintended way. This means that you as a DLL developer NEED TO VERIFY the input params for every function call!
  • The DLL may be installed on a variety of windows platforms (Win2000->Win7) so make sure you check the OS Version if you are using Windows API calls that are version dependent
  • There is no guarantee that the DLL has Administrator privilidges!
  • The DLL is restricted to the same Win32 memory as the host process (2 Gig max allocation)

Creating the DLL in Delphi

Close all projects and then choose “FILE | OTHER …“, select “DELPHI PROJECTS” and then “Dynamic Link Library“. You should now have the following skeleton (excluding all comments):

1 library Project1;
2 uses
3   SysUtils,
4   Classes;
5 {$R *.res}
6 begin
7 end.

Now copy & paste the following instead of the above:

001 library MyDLL;
002   
003 uses
004   SysUtils, Classes, Windows,
005   VUManager in 'VUManager.pas';
006   
007 Const
008   { Version Constants }
009   DLLVer_Major                 = 1;
010   DLLVer_Minor                 = 0;
011   DLLVer_Copyright             = 'Copyright (C) by Celarius Oy';
012   
013   { DLL Errors - Negatives are errors }
014   ERR_None                     =  0;
015   ERR_Unknown                  = -1;
016   ERR_Unknown_Object           = -2;
017   ERR_Insufficient_Buffer      = -3;
018   
019 ////////////////////////////////////////////////////////////////////////////////
020   
021 Var
022   VUMgr : TVUManager;
023   
024 {$R *.res}
025   
026 ////////////////////////////////////////////////////////////////////////////////
027   
028 function dll_Initialize( VUserID: Cardinal ): Integer; stdcall;
029 // Initialize DLL, Adds the Vuser with the ID
030 //
031 // Returns
032 //    Integer    The Error code
033 begin
034      If VUMgr.AddVUser( VUserID ) then
035         Result := ERR_None
036      Else
037         Result := ERR_Unknown_Object;
038 end;
039   
040 ////////////////////////////////////////////////////////////////////////////////
041   
042 function dll_Finalize( VUserID: Cardinal ): Integer; stdcall;
043 // Finalize DLL, removes the VUser with the ID
044 //
045 // Returns
046 //    Integer    Error code
047 begin
048      If VUMgr.RemoveVUser( VUserID ) then
049         Result := ERR_None
050      Else
051         Result := ERR_Unknown_Object;
052 end;
053   
054 ////////////////////////////////////////////////////////////////////////////////
055   
056 function dll_GetVersion: Integer; stdcall;
057 // Get Library version
058 //
059 // Returns
060 //    Integer    Version Number
061 begin
062      Result := (DLLVer_Major SHL 16) + DLLVer_Minor;
063 end;
064   
065 ////////////////////////////////////////////////////////////////////////////////
066   
067 function dll_GetCopyright( DestStr: PAnsiChar; DestSize: Integer): Integer; stdcall;
068 // Get Library Copyright String
069 //
070 // Returns
071 //    Integer    Version Number
072 begin
073      if (DestSize>Length(DLLVer_Copyright)) then
074      Begin
075           StrCopy( DestStr, PAnsiChar(DLLVer_Copyright) );
076           Result := ERR_None;
077      End Else Result := ERR_Insufficient_Buffer;
078 end;
079   
080 ////////////////////////////////////////////////////////////////////////////////
081   
082 function dll_TrimStr(ID:Cardinal; SourceStr: PAnsiChar; DestStr: PAnsiChar; DestSize: Integer): Integer; stdcall;
083 // Trims a String (removes special chars in beginning/end)
084 //
085 // Returns
086 //    Integer    Error Code
087 Var
088    VU : TVirtualUser;
089    S  : AnsiString;
090 begin
091      { Find the Virtual User }
092      VU := VUMgr.FindVU(ID);
093      if Assigned(VU) then
094      Begin
095           S := VU.TrimString( SourceStr ); // process the string
096   
097           if (DestSize>Length(S)) then
098           Begin
099                StrCopy( DestStr, PAnsiChar(S) );
100                Result := ERR_None;
101           End Else Result := ERR_Insufficient_Buffer;
102   
103      End Else Result := ERR_Unknown_Object;
104 end;
105   
106 ////////////////////////////////////////////////////////////////////////////////
107   
108 { Export functions }
109 exports
110   { General Functions }
111   dll_Initialize       name 'dll_Initialize',
112   dll_Finalize         name 'dll_Finalize',
113   dll_GetVersion       name 'dll_GetVersion',
114   dll_GetCopyright     name 'dll_GetCopyright',
115   dll_TrimStr          name 'dll_TrimStr'
116   ;
117   
118 ////////////////////////////////////////////////////////////////////////////////
119   
120 procedure DLLEntryProc(EntryCode: integer);
121 //
122 // DLL Entry/Exit, Process and Thread Attach/Detach procedures }
123 //
124 Var
125    Buf           : Array[0..MAX_PATH] of Char;
126    LoaderProcess : String;
127    DLLPath       : String;
128 begin
129      Try
130         Case EntryCode of
131              { The DLL has just been loaded with LoadLibrary()               }
132              { either by the main process, or by a vuser - we do not know    }
133              { which one                                                     }
134              DLL_PROCESS_ATTACH:
135              Begin
136                   { Get the Path where the DLL is }
137                   GetModuleFileName(HInstance, buf, Length(buf)) ;
138                   DLLPath := ExtractFilePath(StrPas(buf));
139                   { Get the name of the module that loaded us }
140                   GetModuleFileName(HInstance, buf, Length(buf)) ;
141                   LoaderProcess := StrPas(buf);
142                   { Create handler }
143                   VUMgr:= TVUManager.Create( NIL );
144              End;
145   
146              { The Process Detached the DLL - Once per MMDRV Process }
147              { Application called Unload - Perform Cleanup }
148              DLL_PROCESS_DETACH:
149              Begin
150                   If Assigned(VUMgr) then FreeAndNil(VUMgr);
151              End;
152   
153              { A Thread has just loaded the DLL }
154              DLL_THREAD_ATTACH:
155              Begin
156                   { This occures when a VUser calls lr_load_dll() }
157              End;
158   
159              { A Thread has just unloaded the DLL }
160              DLL_THREAD_DETACH:
161              Begin
162                   { This occures when a VUser exits }
163              End;
164         End;
165      Except
166         // TODO: Write an Exception Handler
167         On E: Exception do ;
168      End;
169 end;
170   
171 ////////////////////////////////////////////////////////////////////////////////
172 //
173 // DLL Initialization - When DLL is loaded the first time by any process }
174 //
175 ////////////////////////////////////////////////////////////////////////////////
176 begin
177 {$IFDEF Debug}
178           { True means Delphi checks & reports memleaks }
179           ReportMemoryLeaksOnShutdown := True;
180 {$ENDIF}
181           { Make the Memory-Manager aware that this DLL is used in Thread-environments }
182           IsMultiThread := True;
183           VUMgr:= NIL;
184   
185           { If we have not already set te DLLProc, do it }
186           if NOT Assigned(DllProc) then
187           begin
188                DLLProc := @DLLEntryProc;         // install custom exit procedure
189                DLLEntryProc(DLL_PROCESS_ATTACH);
190           end;
191 end.

You can now save the project as “MyDLL” in a folder of your choice.

Now we’ll need to create the VUManager unit with “FILE | NEW UNIT” and save the new unit as “VUManager.pas” in the same directory as the rest of the Delphi files. Copy & Paste the following into the new unit.

001 unit VUManager;
002   
003 Interface
004   
005 Uses SysUtils, Classes, Windows;
006   
007 Type
008   { Forward Declarations }
009   TVirtualUser = class;
010   TVUManager = class;
011   
012 ////////////////////////////////////////////////////////////////////////////////
013   
014   TVirtualUser = class(TComponent)
015   private
016     { Private declarations }
017   protected
018     { Protected declarations }
019   public
020     { Public declarations }
021     VUserID               : Cardinal;
022     Constructor Create(AOwner:TComponent; ID:Cardinal); ReIntroduce;
023     Destructor Destroy; Override;
024     Function TrimString(InStr: AnsiString): AnsiString;
025   end;
026   
027 ////////////////////////////////////////////////////////////////////////////////
028   
029   TVUManager = class(TComponent)
030   private
031     { Private declarations }
032     fVirtualUsers          : TThreadList;
033   protected
034     { Protected declarations }
035   public
036     { Public declarations }
037     Constructor Create(AOwner:TComponent); Override;
038     Destructor Destroy; Override;
039     { Methods }
040     Function FindVU(ID:Cardinal):TVirtualUser;
041     Function AddVUser(ID: Cardinal): Boolean;
042     Function RemoveVUser(ID: Cardinal): Boolean;
043   end;
044   
045 ////////////////////////////////////////////////////////////////////////////////
046   
047 Implementation
048   
049 ////////////////////////////////////////////////////////////////////////////////
050   

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
Matlab slice方法和包络法绘制三维立体图发布时间:2022-07-18
下一篇:
matlab中画三维图形 - Dec-Fth发布时间:2022-07-18
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap