Zen Cent
The article has been collected, written too well, back up a copy of the
Author: http://www.cnblogs.com/shangdawei/p/4058452.html
Introduction
believe that some computer knowledge of friends should have heard of the "DLL." In particular, those who have used Windows operating systems should have had a "tragic" experience of reloading the system many times-no matter how careful, no driver damage, no virus intrusion, still using (installed) a period of time software, found that Windows systems are becoming larger, more and more slow operation, There were times when the software could not be used, leading to the eventual need to re-install the system. This situation is often caused by a large number of installation and conflict of DLL files. This explains the lack of DLLs, on the other hand, it also shows the importance of DLLs, so that we can not eliminate its use.
DLL (dynamic link library) is simply a compiled code module that can be executed by a call. DLLs are an early product of Windows systems. The primary purpose at that time was to reduce the use of memory by the application. Only when a function or procedure needs to be used is it called from the hard disk into memory, and once no program calls the DLL, it is purged from memory. Light said that the entire Windows system, including hundreds of DLL files, some of the functions of DLL files are more professional (such as network, database driver) can not even install. If all of these features are included in an application (application program), Windows will be an EXE file of hundreds of m size. This simple example makes it easy to explain the role of DLLs, while the performance penalty of invoking DLLs becomes negligible.
Multiple applications call the same DLL with only one copy of the code in memory. Rather than statically compiled programs, each must be loaded as a whole. When a DLL is loaded, it is mapped to the address space of the process, while dynamic linking using the DLL does not copy the library code, but only the entry point and interface of the function.
At the same time the DLL can also bring the benefits of sharing. Different software developed by a company may require some common functions/procedures that may be directly used by some internally developed DLLs; Some common functions can be directly used by Windows standard DLLs, which we often say windows The API is a function/process contained in several common DLL files in Windows, in theory (if not involving the author's copyright), knowing the Declaration and function of a DLL (input parameters and return values of the function definition), we can use it directly without knowing its implementation (algorithm or compilation).
If a DLL in the function/process algorithm has been updated, the bug has been fixed, the entire DLL file will be upgraded. In general, to ensure backward compatibility, the invocation declaration and return result should remain unchanged. But in fact, even with the same DLL, it is difficult to ensure that a call execution is completely intact as the functionality improves. This is even worse when using DLLs developed by others. For example, in a drawing program, I used an older version of the DLL package from a well-known graphics software vendor, and all of my calls were executed according to the old version of the statement that he published. Suppose the user installs a new software for the software, causing some DLLs to be updated, if these DLLs have been changed, the direct result is that my software is no longer stable or even can not run! Do not underestimate this situation, in fact it is very common, such as windows to fix bugs and upgrade process, it is constantly changing the DLLs it contains. Often the new version of the DLL is not a simple addition to the function/process, but instead of replacing or even cancel the original declaration, we can no longer guarantee that all programs are running normally.
DLL In addition to the above mentioned to improve the utilization of computer resources, increase development efficiency, hide implementation details, but also can contain data and various resources. For example, the development of a multi-language version of the software, you can use a DLL to rely on language-dependent functions and resources, and then let users around the installation of different DLLs to obtain support for the local character set. Another example of a software must be graphics, icons and other resources, can also be placed directly in the DLL file unified installation management. Create a DLL
Before I do that, I think you should know a concept: the routine declares a pointer variable, and the calling function/procedure is actually a pointer to the execution code of the function/procedure.
Let's first try to build a DLL file with Delphi. This DLL contains a standard directory delete (contains subdirectories and files) functions.
Building DLLs
It is easy to build a DLL through Delphi. New project, select the DLL Wizard, and then generate a very simple unit. The unit does not start with the program as a general engineering document, but begins with the library.
The project unit defaults to two units of sysutils and classes. You can add a function/procedure code before the Begin ... end section directly after the uses of the unit, or you can add a unit containing code to the project, and the cell will be automatically uses.
Next is the code that writes the DLL routines. If you are referencing a routine in a cell, you need to add an export suffix by declaring it. If it is written directly in the library unit, then you do not have to write export.
The final step is to add the exports section to the uses section and the function definition above the BEGIN statement of the library unit, and enumerate the name of the routine that needs to be elicited. Note that only the name, which does not contain the procedure or function keyword, does not require parameters, return values, and suffixes.
There are three forms of syntax after the exports statement (routines refer to specific functions/procedures):
Exports routine name;
Exports routine name index value;
Exports the name of the new routine name;
The index value and the new name make it easier for other programs to determine the function address, or you can not specify that if the index keyword is not used, Delphi will automatically assign the index number starting with 1 in the order after exports. Exports can be followed by several routines, separated by commas.
Compile, build the final DLL file.
Format to be aware of
To ensure that the generated DLLs are correctly compatible with languages such as C + +, the following points need to be noted:
Try to use a simple type or pointer as the type of parameter and return value. The simple Type here refers to the simple type of C + +, so the string string type is best converted to a pchar character pointer. DLL routines that use string directly are not problematic to invoke in Delphi-developed programs (there is data that requires adding SHAREMEM as the first unit to ensure correctness), but it is not guaranteed that parameters are passed correctly if they are invoked using C + + or other language-developed programs;
Although the process is permissible, it is best to be used to all functions. The process returns the true/false of the correct execution;
For parameters such as const (read only), out (write only) and so on, in order to ensure the compatibility of the call, it is best to use the default (default Var, can read and write address);
Use the stdcall to declare the suffix to ensure proper exception handling. A 16-bit DLL cannot handle an exception this way, so it has to be at the outermost of the routine with try ... Except the exception is handled;
The far suffix is generally not used unless you want to maintain compatibility with 16-bit.
Sample code
DLL Engineering Unit:
library FileOperate;
Uses
SysUtils,
Classes,
uDirectory in ‘uDirectory.pas‘;
{$R *.res}
Exports
DeleteDir;
Begin
End. Function function implementation unit:
unit uDirectory;
Interface
Uses
Classes, SysUtils;
function DeleteDir( DirName : Pchar ) : boolean; export; stdcall;
implementation
function DeleteDir( DirName : Pchar ) : boolean;
Var
FindFile : TSearchRec;
S: string;
Begin
s := DirName;
if copy( s, length( s ), 1 ) <> ‘/‘ then
s := s + ‘/‘;
if DirectoryExists( s ) then
Begin
if FindFirst( s + ‘*.*‘, faAnyFile, FindFile ) = 0 then
Begin
Repeat
if FindFile.Attr <> faDirectory then
Begin
//Delete file
DeleteFile( s + FindFile.Name );
end else begin
//Directories nest themselves
if ( FindFile.Name <> ‘.‘ ) and ( FindFile.Name <> ‘..‘ ) then
DeleteDir( Pchar( s + FindFile.Name ) );
End;
until FindNext( FindFile ) <> 0;
FindCLose( FindFile );
End;
End;
Result := RemoveDir( s );
End;
End.
Initialize and dispose of resources
There are several ways to initialize in Delphi. One is the use of unit initalization and finalization these two subsections (Do not know "unit section"?) You should first go to the evil complement of Delphi syntax) to initialize the variables in this unit. Note that although the DLL has only one copy in memory, the routine is subordinate to the caller's different process space. If you want to initialize the public variables to achieve multi-process sharing is not feasible, but also pay attention to the conflicts caused by public variables.
The second is the initialization of the DLL in the Begin ... end section of the library unit. If you want to have the corresponding code at the end of the DLL, you can take advantage of a EXITPROC process variable that is automatically created by the DLL, which is a pointer to the exit process. Create a process of your own and assign the address of the process to Exitproc. Because Exitproc is present when the DLL was created, this step should be done in the Begin ... end section. Create a temporary pointer variable to hold the original Exitproc value, and assign the Exitproc value back to your own exit. This is done in order to perform its own exit operation, can complete the default DLL exit operation (as in the overloaded Destory method, the meaning of inherated is the same, completed its own destory, but also the default parent class Destory to complete).
Examples are as follows:
library MyDLL;
Var
Oldexitproc: pointer; / / a public variable. Save the original exitproc pointer for
procedure MyExitProc;
Begin
//Corresponding initialization end code
Exitproc: = oldexitproc; / / remember to assign exitproc back
End;
Begin
//Initialization code
OldExitProc := ExitProc;
ExitProc := @MyExitProc;
End.
The third method is similar to Exitproc, where a pointer variable dllproc is predefined in the system unit (this method requires a reference to the Windows unit). When using Dllproc, you must first write a program with the following prototype:
And at the begin of the library. End, the execution address of this Dllhandler program is assigned to Dllproc, which can be processed according to the value of the parameter reason respectively. Examples are as follows:
library MyDLL;
procedure MyDLLHandler( dwReason : DWORD );
Begin
case dwReason of
DLL_Process_Attach :
; / / when the process enters
DLL_Process_Detach :
; / / when the process exits
DLL_Thread_Attach :
; / / when the thread enters
DLL_Thread_Detach :
; / / when the thread exits
End;
End;
Begin
//Initialization code
DLLProc := @MyDLLHandler;
MyDLLHandle( DLL_Process_Attach );
End.
Visible, Dllproc is more powerful and flexible than exitproc when dealing with multiple processes. static (implicit) Call DLL
DLL is already there, so let's look at how to invoke and debug it. Normal DLLs do not need to be registered, but are included in the Windows search path to be found. The search paths are in the following order: current directory; path path; windows directory; Widows system directory (systems, System32).
Declarative methods for introducing DLL routines
The function/procedure is predefined before code that requires the use of external routines (DLL functions/procedures). This is declared as it is defined in the DLL, and only needs to be declared. In addition, external suffix is introduced, which corresponds to export derivation. There are also three ways to determine the routines (in the case of function declarations), based on the three index syntax of exports:
Function name (parameter table): return value; external ' dll filename ';
Function name (parameter table): return value; external ' DLL filename ' index number;
Function name (parameter table): return value; external ' dll filename ' name new name;
If you do not determine the routine name, you can introduce it in an indexed manner. If a conflict occurs by the introduction of the original name, it can be introduced with "new names".
DLL functions are used in the same way as normal functions after declaration. Static invocation is simple, but calls into the DLL as an alternate procedure when the caller is started. If this DLL file does not exist, it will prompt for errors at startup and terminate the program immediately, regardless of whether the definition is used.
The Quick View DLL routine definition can be used with the tool Tdump.exe included with Borland (in the Bin directory of Delphi or BCB), as shown in the following example:
Tdump C:/windows/system/user32.dll > User32.txt
Then open the User32.txt file and find the exports from USER32.dll line, the part below is the DLL routines defined, such as:
VA Ord. Hint Name
-------- ---- ---- ----
00001371 1 0000 ActivateKeyboardLayout
00005C20 2 0001 AdjustWindowRect
0000161B 3 0002 AdjustWindowRectEx
The Name column is the example of the routine, and Ord is the routine index number. Note that the tool is not available for the parameter table of the routine. If the parameter is wrong, calling the DLL routine causes a stack error that causes the calling program to crash.
Calling code
Create a common project, place a Tshelltreeview control (Samples page) on the main form, and then place a button that adds the following code:
function DeleteDir( DirName : Pchar ) : boolean; stdcall;
external ‘FileOperate.dll‘;
procedure TForm1.Button1Click( Sender : TObject );
Begin
if DirectoryExists( ShellTreeView.Path ) then
If application. MessageBox (PChar ('ok to delete directory '+ QuotedStr (shelltreeview. Path)
+ '? ‘ ), ‘Information‘, MB_YESNO ) = IDYes then
if DeleteDir( Pchar( ShellTreeView.Path ) ) then
Showmessage ('deletion succeeded ');
End;
This example invokes the DLL that was created earlier.
Note that the stdcall suffix is included in the declaration to ensure that parameter values such as Pchar are passed correctly in the routines that call the Delphi-developed DLL. We are interested to experiment, do not join stdcall or safecall suffix to execute the above code, will not guarantee the success of passing string parameters to the DLL function.
Debugging methods
Select Parameters in the Run project of the Delphi main menu to open the Run Parameters dialog box.
A host program is populated in host application (the program calls the DLL that will be debugged), and you can enter parameters in parameters. Save the content, and then you can set breakpoints, track/step execution in the DLL project.
Run the DLL project, and then run the host program. Executes the operation that invokes the DLL and then tracks the code into the DLL, followed by the same debug operation as the normal program.
Because of an operating system or other software impact, there may be cases where the above steps are still not able to track/break DLL code properly.
At this point you can try the menu project | The Linker page of the Options dialog box selects the Include TD32 Debug info and include remote debug symbols two options in the EXE and DLL options.
If still can not interrupt that had to create a reference to execute the code unit of the application, write code call routine debugging completed before compiling the DLL (in fact, the method is sometimes very convenient, but sometimes very troublesome).
Introducing Files
When a DLL is complex, you can create a single ingest unit for its declaration, which makes the DLL easier to maintain and view. The format of the introduction unit is as follows:
unit MyDllImport; { Import unit for MyDll.dll }
interface
procedure MyDllProc;
implementation
procedure MyDllProc; external ‘MyDll‘ index 1;
end.
When you want to use the routines in Mydll later, simply add Mydllimport to the uses clause in the program module. In fact, this is just a handy technique to develop, and you can see similar practices when you open a unit that introduces Windows APIs such as Windows.
Dynamic (Explicit) Call DLL
As mentioned in the preceding static call to the DLL, the DLL is called when the caller is started. So this can only serve as a common DLL and reduce the size of the running file, and DLL loading error will immediately cause the entire boot process to terminate, even if the DLL in the run only a trivial role.
By using a dynamic call DLL, the DLL is only loaded with memory when calling an external routine (the DLL is automatically purged from memory when the reference count is 0), thus saving memory space. It is also possible to determine whether the load is correct to avoid a crash of the calling program and to lose the routine functionality.
While dynamic invocation has these advantages, for frequently used routines, there is additional performance loss due to DLL call-in and release, so such routines are suitable for static ingestion.
invocation Example
DLL dynamic invocation is the principle of declaring a function/procedure type first and creating a pointer variable. To ensure that the pointer is consistent with the external routine pointer to make sure that the assignment is correct, the declaration of the function/procedure must be compatible with the original declaration of the external routine (compatible meaning 1, the parameter name can be different; 2, the parameter/return value type remains at least mutually assignable, such as the original type is declared as Word, The new declaration can be an integer, and if the passed argument is always within the scope of word, there will be no error.
Next, the specified library file is introduced through the Windows API function LoadLibrary, and the LoadLibrary parameter is the DLL file name, returning a thandle. If the step succeeds, the entry address of the routine is obtained through another API function GetProcAddress, the parameters are LoadLibrary pointers and routine names, and finally the entry pointers of the routines are returned. Assign the pointer to our pre-defined function/procedure pointer, and you can then use the function/procedure. Remember to use the API function FreeLibrary to reduce the number of DLL references in the end, so that the memory can be purged after the DLL is used. The Delphi declarations for these three API functions are as follows:
Change the code for the previous static call DLL routine to a dynamic call, as follows:
Type
TDllProc = function( PathName : Pchar ) : boolean; stdcall;
Var
LibHandle : THandle;
DelPath : TDllProc;
Begin
LibHandle := LoadLibrary( Pchar( ‘FileOperate.dll‘ ) );
if LibHandle >= 32 then
Begin
Try
DelPath := GetProcAddress( LibHandle, Pchar( ‘DeleteDir‘ ) );
if DirectoryExists( ShellTreeView.Path ) then
if Application.MessageBox
(PChar ('are you sure to delete directory '+ QuotedStr (shelltreeview. Path) +'? ),
‘Information‘, MB_YESNO ) = IDYes then
if DelPath( Pchar( ShellTreeView.Path ) ) then
Showmessage ('deletion succeeded ');
Finally
FreeLibrary( LibHandle );
End;
End;
End;
Delphi Development DLL FAQ
String parameters
As mentioned earlier, in order to ensure the correctness of DLL parameter/return value delivery, especially for host programs developed for other languages such as C + +, use pointers or basic types as much as possible, since other languages may be different from Delphi's variable storage allocation methods. C + + character characters is the basic type, string is the character of the linear chain list. Therefore, it is best to cast the string to Pchar.
If both the DLL and the host program are developed with Delphi and use a string (as well as a dynamic array, whose data structure is similar) as the parameter/return value of the exported routine, add Sharemem as the first reference unit of the uses statement for the project file. SHAREMEM is the interface unit of the Borland shared Memory manager Borlndmm.dll. The publication of a DLL referencing the cell needs to include Borlndmm.dll, otherwise the use of string is avoided.
Creating and displaying forms in a DLL
All forms-based Delphi applications automatically include a global object application, which is familiar to everyone. It is worth noting that the DLL created by Delphi also has a separate application. So if a form created in a DLL is to be a modal form of an application, the application must be replaced with an application, otherwise the result is unpredictable (after the form is created, actions such as minimizing it will not be subordinate to any main form). In the DLL, avoid using showmessage and use the MessageBox.
Creating a modal form in a DLL is simpler, passing the Application.handle property as a parameter to the DLL routine, assigning the handle to the DLL's Application.handle, and then creating the form with application.
Modeless forms are more complex, and there must be a corresponding release window method in addition to creating a display window. You need to be very careful with modeless forms, and the calls to create and release routines need to be controlled in the calling program. There are two layers of meaning: one to prevent multiple creation of the same instance of the form; second, creating a modeless form by the application must be guaranteed to be released by the application, otherwise the call to release routine will fail if another code in the DLL is released in advance.
The following is the code for the DLL form:
The unit uSampleForm;
interface
USES
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls StdCtrls;
The type
TSampleForm = class(TForm)
The Panel: TPanel;
The end;
Procedure CreateAndShowModalForm(AppHandle: THandle; Caption: PChar);
Export; Stdcall;
Function CreateAndShowForm(AppHandle: THandle) : LongInt; Export; Stdcall;
Procedure CloseShowForm(AFormRef: LongInt); Export; Stdcall;
implementation
{$R *. DFM}
// mode form
Procedure CreateAndShowModalForm(AppHandle: THandle; Caption: PChar);
var
Form: TSampleForm;
STR: string;
The begin
Application. Handle: = AppHandle;
Form := tsampleform.create (Application);
The try
STR: = Caption;
Form. Caption: = STR;
Form. ShowModal;
The finally
Form. Free;
The end;
The end;
// non-modal form
Function CreateAndShowForm(AppHandle: THandle) : LongInt;
var
Form: TSampleForm;
The begin
Application. Handle: = AppHandle;
Form := tsampleform.create (Application);
Result := LongInt(Form);
Form. The Show;
The end;
Procedure CloseShowForm(AFormRef: LongInt);
The begin
If AFormRef > 0 then
TSampleForm (AFormRef). The Release;
The end;
The end.
The derivation declaration of the DLL Engineering unit:
exports
CloseShowForm,
CreateAndShowForm,
CreateAndShowModalForm;
Application Invocation Declaration:
procedure CreateAndShowModalForm(Handle : THandle;Caption : PChar);stdcall;external ‘FileOperate.dll‘;
function CreateAndShowForm(AppHandle : THandle):LongInt;stdcall;external ‘FileOperate.dll‘;
procedure CloseShowForm(AFormRef : LongInt);stdcall;external ‘FileOperate.dll‘;
In addition to the normal form, how to create Tmdichildform in the DLL?
This is similar to creating a normal form, but this time you need to pass the application.mainform of the calling program as a parameter:
function ShowForm( mainForm : TForm ) : integer;
Stdcall
Var
Form1 : TForm1;
ptr : PLongInt;
Begin
PTR: = @ (application. MainForm); / / first save the MainForm handle of the DLL without releasing it, just replace it
PTR ^: = Longint (MainForm); / / replace the DLL's MainForm with the caller's MainForm
Form1: = TForm1. Create (MainForm); / / create with parameters
End;
The reason for a temporary pointer in the code is that the Application.mainform is a read-only property. The Formstyle of an MDI form is not set to Fmmdichild.
Initializing COM libraries
If a COM component such as tadoconnection is used in a DLL, or an ActiveX control is called, the error "tag without reference storage" is prompted, because COM is not initialized. DLL does not call Coinitilizeex, initializing the COM library is considered the responsibility of the application, which is the implementation strategy of the Borland.
What you need to do is 1. Refer to the ActiveX unit to ensure that the Coinitilizeex function is correctly called
2. Add initialization and exit codes at the unit level:
initialization
Coinitialize(nil);
finalization
CoUninitialize;
end.
3. At the end, remember to close the connection and data set, otherwise you will also report an address error.
To elicit an object from a DLL
From the example of a DLL form, you can see that the handle is passed as a parameter to an instance where dll,dll can point to the handle. Similarly, the basic idea of drawing an object from a DLL is to return the pointer to the object in the DLL through the function, assign the pointer to the variable of the host program, and make the variable point to the address of an object in memory. The operation of the variable is the operation of the object in the DLL.
This article is no longer detailed in the code, only a few rules to note:
An application can only access virtual methods in an object, so the object method to be referenced must be declared as a virtual method;
Both the DLL and the application require the same object and method definitions, and the method definition order must be consistent;
The object in the DLL cannot be inherited;
Object instances can only be created in DLLs.
The purpose of declaring a virtual method is not to overload, but to add the method to the virtual method table. The method of the object is different from the normal routine, so that the application gets a pointer to the method.
DLL, after all, is the product of the era of structured programming, based on function-level code sharing, the realization of the object has been inadequate. Now, the new way to provide powerful support for objects, such as DLL functionality, has been widely used, such as interfaces (com/dcom/com+). The in-Process service-side program is a DLL file from the outside, but it does not elicit an application through an external routine, but instead publishes a series of interfaces to support it by registering. It differs from the use of DLLs in two major differences: the need to register to invoke the service by creating an interface object. It can be seen that although the DLL through some techniques can also draw objects, but the use of inconvenience, and often the object is forced into a process of the way, in this case it is best to consider the new implementation method.
Note: The code in this article was debugged in Delphi6, 7.
Attached: This article refers to the "DELPHI5 Developer Guide" and other books and materials. Delphi Write DLL experience, Thanksgiving predecessors summary (outside a article)
1. Each function body (including exports and non-exports functions) is appended with ' stdcall; ' to write a generic DLL
2. The exports function must be appended with ' export; ' (Put in ' stdcall; ') Front
3. String types are available for non-exports functions, and parameter passing is recommended using string types
4. For the exports function, use the Pchar type for parameter passing.
5. If exports calls other functions, it is recommended to use a variable transition in the EXPORTS function body, and then call other functions, and say: Try not to call other functions as arguments to the exports.
6. Exports function If there is a callback parameter: if the non-address type (such as Integer,boolean and other basic types) use the var prefix, if the address type do not use the Var prefix (such as Pchar or array, etc.). For parameters that do not use the var prefix, use the memory copy class function, such as Strpcopy,copymemory,move. Cause: DLLs and main applications do not share a good chunk of memory, so a memory copy is required to properly return (copy) the contents of the DLL to the main application. Therefore, the address of the callback to identify class parameters, before calling the DLL must be memory allocation, such as in Delphi: AllocMem (N integer), PB: Space (Nlong). Note that when the DLL function declaration is called at the DLL, if the Delphi parameter declaration is in the same DLL as the parameter declaration (the callback address type parameter does not need to add Var), if the PB callback parameter must be prefixed with ref.
7. The parameters of the non-exports function must follow the rules: The callback parameter plus the prefix var, you can completely treat the non-exports function and write the function in the Delphi application
8. If there is an array parameter in a non-exports function, whether or not it is a callback, add the Var prefix, which is the address call
9. Boolean in DLL note the difference between bool and Boolean, which may cause different results in the caller's environment
10. Avoid using Delphi-specific data types or classes in DLL functions, such as tstringlist, etc.
11. Reduce the size of the DLL by reducing references to unnecessary cells in the use list
12. DLL debugging: You can debug using ShowMessage (use dialogs), or you can configure the host program in [Run]->[parameters] to step through the execution of the DLL
13. Note that all memory requested in the DLL must be disposed correctly, or the DLL may have an address reference error after being called n Times
14. When calling the DLL:
1) Operating environment: can be placed directly in the application of the same directory, can also be placed under a folder, if placed in a folder
You must set this folder path to an environment variable that you can set in your application or set in the DLL:
var
PathBuf : array [ 0 .. 2048 ] of Char;
Pathstr : string;
begin
FillChar( PathBuf, 2048, ‘ ‘ );
windows.GetEnvironmentVariable( ‘PATH‘, PathBuf, 2048 );
Pathstr := string( PathBuf );
Pathstr := Trim( Pathstr );
if Pos( lowerCase( AppPath + ‘tuxedo/dll‘ ), lowerCase( Pathstr ) ) <= 0 then
begin
Pathstr := Pathstr + ‘;‘ + AppPath + ‘tuxedo/dll‘;
SetEnvironmentVariable( ‘PATH‘, PAnsiChar( Pathstr ) );
end;
end;
2) Development environment: If Delphi is no different from the operating environment, it is to compile and build the application directly and run the application;
If PB, must be the path of the DLL relative to the PB development tool application to set, such as put to Pb9.0.exe in the same directory, of course you can
Set [Hkey_local_machine/software/microsoft/windows/currentversion/app paths/] below for your open
Set the path of the DLL under the application name directory of the Hair tool (semicolon-separated to add both, do not overwrite the original path)
Get the path to the DLL in the DLL:
var
Buffer:array [0..255] of char;
tmpstr:String;
begin
GetModuleFileName(HInstance, Buffer, SizeOf(Buffer));
tmpstr:=ExtractFilePath(Buffer);
//...
end;
Tip information Try not to showmessage in the DLL, preferably as an information parameter back, the host program again based on the results of information prompts, so also can not reference dialogs unit
In-depth DLL programming under Delphi