Delphi中编写无输出函数名的DLL文件

简介: 用 Delphi 用长了,总是发现,有些和 MS 不同的地方。例如,MS 的公开库中,常常隐藏了许多重要函数,这些函数在系统中常常有起着非常巨大的作用。


用 Delphi 用长了,总是发现,有些和 MS 不同的地方。例如,MS 的公开库中,常常隐藏了许多重要函数,这些函数在系统中常常有起着非常巨大的作用。一旦知道如何调用,可以给自己的应用程序提供很强的功能和很大的灵活性。但,这些函数通常又没有函数名(即使用 ExeScope 查看 DLL 文件的导出表也看不出函数意义),仅仅只有一个序号来表示。有时候我又自己想,为什么我在写程序的时候不能学学 MS 隐藏一些自己不希望公开的函数呢?
 
其实用 Delphi 写 DLL 的时候,使用简单的技巧就可以实现隐藏函数名的效果。让我们来看看下面这个 DLL 源码:
 
library   proDll;
 
uses
   Windows;
 
{$R *.res}
 
procedure   ShowMessageA(hWnd: HWND);  stdcall ;
begin
   MessageBox(hWnd, '您调用的是 ShowMessageA 函数', 'DLL 函数信息',
     MB_ICONINFORMATION);
end ;
 
procedure   ShowMessageB(hWnd: HWND);  stdcall ;
begin
   MessageBox(hWnd, '您调用的是 ShowMessageB 函数', 'DLL 函数信息',
     MB_ICONINFORMATION);
end ;
 
exports
   ShowMessageA  index   1  name   '',
   ShowMessageB  index   2  name   '';
 
begin
end .
 
注意看 exports 部分,用 index 关键字指定输出函数的序号,后面紧跟一个 name 关键字指明输出函数名称。关键就在这里,name 后面是一个空字符串,这样就给函数生成了一个空字符串名。实际效果既是隐藏了输出函数的名称。是不是很容易呢?
 
那么我们怎样调用这样的输出函数呢?由于没有了函数名,我们调用起来会显得和以前不一样。其实也不用担心,调用同样非常简单。我下面就静态调用和动态调用制作了两个工程,源码如下:
 
静态调用例子:
 
unit   Unit1;
 
interface
 
uses
   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Dialogs, StdCtrls;
 
type
   TForm1 =  class (TForm)
     Button1: TButton;
     Button2: TButton;
     procedure Button1Click(Sender: TObject);
     procedure Button2Click(Sender: TObject);
   private
     { Private declarations }
   public
     { Public declarations }
   end ;
 
var
   Form1: TForm1;
 
implementation
 
{$R *.dfm}
 
procedure   ShowMessageA(hWnd: HWND);  stdcall ;  external   'proDll.dll' index 1;
procedure   ShowMessageB(hWnd: HWND);  stdcall ;  external   'proDll.dll' index 2;
 
procedure   TForm1.Button1Click(Sender: TObject);
begin
   ShowMessageA(Handle);
end ;
 
procedure   TForm1.Button2Click(Sender: TObject);
begin
   ShowMessageB(Handle);
end ;
 
end .
 
动态调用的例子:
 
unit   Unit2;
 
interface
 
uses
   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Dialogs, StdCtrls;
 
type
   TForm2 =  class (TForm)
     Button1: TButton;
     Button2: TButton;
     procedure Button1Click(Sender: TObject);
     procedure Button2Click(Sender: TObject);
   private
     { Private declarations }
   public
     { Public declarations }
   end ;
 
var
   Form2: TForm2;
 
implementation
 
{$R *.dfm}
 
type
   TDllShowMessageFunc =  procedure   (hWnd: HWND);  stdcall ;
 
var
   hDllHandle: THandle;
   ShowMessageA, ShowMessageB: TDllShowMessageFunc;
 
procedure   LoadFuncDll;
begin
   if   hDllHandle = 0  then
   begin
     hDllHandle := LoadLibrary('proDll.dll');
     if   hDllHandle = 0  then
       raise   Exception.Create('proDll.dll 加载失败');
     try
       {
       lpProcName: the second argument of function GetProcAddress
         Points to a null-terminated string containing the function name,
         or specifies the function's ordinal value. If this parameter is
         an ordinal value, it must be in the low-order word; the high-order
         word must be zero.
       }
       @ShowMessageA := GetProcAddress(hDllHandle, Pointer(HiWord(0)  or   LoWord(1)));
       if   @ShowMessageA =  nil then
         raise   Exception.Create('proDll.dll 中没有输出 ShowMessageA 函数');
       @ShowMessageB := GetProcAddress(hDllHandle, Pointer(HiWord(0)  or   LoWord(2)));
       if   @ShowMessageB =  nil then
         raise   Exception.Create('proDll.dll 中没有输出 ShowMessageB 函数');
     except
       FreeLibrary(hDllHandle);
       hDllHandle := 0;
       raise ;
     end ;
   end ;
end ;
 
procedure   FreeFuncDll;
begin
   if   hDllHandle <> 0  then
   begin
     FreeLibrary(hDllHandle);
     hDllHandle := 0;
     @ShowMessageA :=  nil ;
     @ShowMessageB :=  nil ;
   end ;
end ;
 
procedure   TForm2.Button1Click(Sender: TObject);
begin
   if   @ShowMessageA =  nil then   LoadFuncDll;
   ShowMessageA(Handle);
end ;
 
procedure   TForm2.Button2Click(Sender: TObject);
begin
   if   @ShowMessageB =  nil then   LoadFuncDll;
   ShowMessageB(Handle);
end ;
 
initialization
   // do nothing
finalization
   FreeFuncDll;
end .

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/aroc_lo/archive/2010/07/27/5769801.aspx

相关文章
|
编译器 API C++
python 外部传参程序编写并打包exe及其调用方式
每种编程语言相互联系又相互独立,为此使用某种编程语言编写的程序都能够独立封装和生成自己的运行程序exe或者其他的API接口。而对于这样的运行程序目的往往不是用于双击使其运行的,而是通过外部传入的参数运行其中的内核函数达到某种目的的。所以在此研究python如何编写外部传参的程序,并将其封装未exe便于外部使用。
825 0
python 外部传参程序编写并打包exe及其调用方式
|
Windows
找不到mfc110.dll,无法执行代码
找不到mfc110.dll,无法执行代码
203 0
找不到mfc110.dll,无法执行代码
VC通过函数名调用DLL的标准范例
VC通过函数名调用DLL的标准范例
69 0
|
C++ 索引
VC通过函数索引调用DLL范例
VC通过函数索引调用DLL范例
62 0
|
C#
C#调用dll代码范例
C#调用dll代码范例
119 0
C++ 编写DLL文件给易语言调用
  摸索了两天了,终于解决了所有问题,在此跟大家分享。   需要三个文件,dll_demo.h、dll_demo.cpp、dll_dome.def   直接上代码:   头文件如下: 1 #ifndef _DLL_DEMO_H_ 2 #define _DLL_DEMO_H_ 3 #ifdef DL...
2174 0
|
开发工具
Excel 宏编程-使用excel宏编写第一个Hello World程序实例演示!
Excel 宏编程-使用excel宏编写第一个Hello World程序实例演示!
484 0
Excel 宏编程-使用excel宏编写第一个Hello World程序实例演示!
|
XML 数据格式
【Tip】如何让引用的dll随附的xml注释文档、pdb调试库等文件不出现在项目输出目录中
原文:【Tip】如何让引用的dll随附的xml注释文档、pdb调试库等文件不出现在项目输出目录中 项目输出目录(bin/debug|release)中经常是这个样子: main.exemain.pdb a.dll a.xml b.dll b.pdb b.xml ... 其中xml是同名dll的注释文档,pdb是调试库。
951 0
|
XML 数据格式 移动开发
转载 VC轻松解析XML文件 - CMarkup类的使用方法
VC轻松解析XML文件 - CMarkup类的使用方法http://www.cctry.com/thread-3866-1-1.html VC解析XML文件的工具有很多,CMarkup, tinyXML,还有IBM的,MS的等等。
840 0