用 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

Delphi中编写无输出函数名的DLL文件(有点意思)(400多篇博客)的更多相关文章

  1. Javascript Jquery 中的数组定义与操作_子木玲_新浪博客

    body{ font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI& ...

  2. C++中实现对map按照value值进行排序 - 菜鸟变身记 - 51CTO技术博客

    C++中实现对map按照value值进行排序 - 菜鸟变身记 - 51CTO技术博客 C++中实现对map按照value值进行排序 2012-03-15 15:32:36 标签:map 职场 休闲 排 ...

  3. 撰写一篇博客要求讲述四则运算2的设计思想,源程序代码、运行结果截图、编程总结分析,并按照PSP0级的要求记录开发过程中的时间记录日志。

    一.撰写一篇博客要求讲述四则运算2的设计思想,源程序代码.运行结果截图.编程总结分析,并按照PSP0级的要求记录开发过程中的时间记录日志. 1.设计思想: ①创建test.jsp建立第一个前端界面,提 ...

  4. 修复在“Android 在ScrollView中嵌入ViewPage后ViewPage不能很好的工作的问题解决”这篇博客中MyScrollView出现滑动一会就不会上下滑动的问题

    在“Android 在ScrollView中嵌入ViewPage后ViewPage不能很好的工作的问题解决”,这篇博客中的大部分问题已经解决了. 唯一遗憾的是,ViewPage随人能够工作了,但是My ...

  5. 鸿蒙内核源码分析(编译脚本篇) | 如何防编译环境中的牛皮癣 | 百篇博客分析OpenHarmony源码 | v58.01

    百篇博客系列篇.本篇为: v58.xx 鸿蒙内核源码分析(环境脚本篇) | 编译鸿蒙原来如此简单 | 51.c.h.o 本篇用两个脚本完成鸿蒙(L1)的编译环境安装/源码下载/编译过程,让编译,调试鸿 ...

  6. 在Delphi中编写res文件

    delphiimagedosinterfaceborland脚本先用记事本编写一个rc的文件. 如内容为: _Comms RCData Comms.jpg Comms.jpg为图片名称, 然后在这个r ...

  7. Golang调用windows下的dll动态库中的函数 Golang 编译成 DLL 文件

    Golang调用windows下的dll动态库中的函数 package main import ( "fmt" "syscall" "time&quo ...

  8. .net 中使用配置文件需注意引用dll文件

    需要用到sqlhelper和配置文件时发现加了using System.Configuration;还是不能用ConfigurationManager. 查了几遍msdn未果,直接百度才发现还需要引用 ...

  9. Delphi中拖动无边框窗口的5种方法

    1.MouseMove事件中加入: // ReleaseCapture;// Perform(WM_SYSCOMMAND, $F017 , 0); 2.MouseDown事件中加入: // POSTM ...

随机推荐

  1. GridView点击空白地方事件扩展

    我们通常在ListView或者GridView响应点击Item事件,但很多时候我们同样也 希望监听到点击空白区域的事件来做更多的处理.本文以GridView为例给出一个实现 的方法,扩展GridVie ...

  2. Debian安装Nexus

    前置条件 安装jdk (如果使用 nexus-2.6 以上版本需要jdk7) 1 apt-get install openjdk-6-jre / apt-get install openjdk-6-j ...

  3. Java读写Word文件常用技术

      Java操作操作Word文件,最近花了几天时间解决使用Word模板导出数据的问题,收集到一些资料分享下. 常见的技术如下: 1.POI(兼容doc.docx文件) 官方网站:http://poi. ...

  4. 参考storm中的RotatingMap实现key超时处理

    storm0.8.1以后的RotatingMap完全可以独立于storm用来实现hashmap的key超时删除,并调用回调函数 RotatingMap.java: import java.util.H ...

  5. linux 下启动jar小程序

    下面是我的三个可运行jar程序 1.启动 采集话单文件应用程序 nohup java -jar gather.jar > logs/gather/console.out & 2.启动   ...

  6. Python 中的类的相关操作

    构造函数 构造函数是任何类都有的特殊方法.当要创建一个类时,就要调用构造函数.他的名字是__init__.init的前后分别是两个下划线.时间类Time的构造函数如下: >>> cl ...

  7. sql: DUAL

    FROM <<Oracle.Database.11g.SQL>> dual is a table that contains a single row. The followi ...

  8. 14.10.5 Reclaiming Disk Space with TRUNCATE TABLE 回收空间使用TRUNCATE TABLE

    14.10.5 Reclaiming Disk Space with TRUNCATE TABLE 回收空间使用TRUNCATE TABLE 回收操作系统磁盘空间当truncate 一个InnoDB ...

  9. hdu4726贪心

    Kia's Calculation Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  10. DButils工具类能够用来获取数据库连接向数据库插入更新删除对象2

    package com.ctl.util; import java.awt.Color; import java.awt.Font; import java.awt.Insets; import ja ...