用 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. cocos2d-x游戏开发系列教程-中国象棋01-工程文件概述

    上一篇博文我们看到了象棋的效果图,这一张我们来看象棋代码的整体概述 让我们先对整个代码框架有个了解. 主目录: 主目录包含内容如上图: classes目录:业务代码 proj.win32:包括main ...

  2. windows安装Apache,注册服务出现“(OS 5)拒绝访问。 : AH00369: Failed to open the WinNT service manager..."错误

    原文:http://blog.csdn.net/jaray/article/details/9950211 在安装Apache的时候,我下载的是zip格式,不是msi安装版,需要自己注册服务,才能在桌 ...

  3. [poj 1265]Area[Pick定理][三角剖分]

    题意: 给出机器人移动的向量, 计算包围区域的内部整点, 边上整点, 面积. 思路: 面积是用三角剖分, 边上整点与GCD有关, 内部整点套用Pick定理. S = I + E / 2 - 1 I 为 ...

  4. SAP 标准单价、移动单价在 AP 中的影响--(详细)

    今天我将向大家介绍下SAP中两种单价模式在系统中所产生的影响,先主要讲讲在AP中影响,它主要有两个方面产生影响(物料收货migo,发票校验miro). 演示背景(假设以下都为本位币交易): 库存(单价 ...

  5. Vistual Studio 2012更换皮肤

    早就装上VS2012了,可是除了在家里练习玩玩的时候使用外,在公司都还在用2010,也没好好研究过2012.这两天把公司的电脑换了系统,也就把vs换成了2012.可是看着不是白白的皮肤就是深色的皮肤, ...

  6. response.sendRedirect("")和request.getRequestDispatcher("").forward(req,resp);

    1:request.getRequestDispatcher("转发路径").forward(req,resp)该语句是实现请求转发的,当请求进入到该servlet中执行到该语句时 ...

  7. <转载>div+css布局教程之div+css常见布局结构定义

    在使用div+css布局时,首先应该根据网页内容进行结构设计,仔细分析和规划你的页面结构,你可能得到类似这样的几块: 页面层容器.页面头部.标志和站点名称.站点导航(主菜单).主页面内容.子菜单.搜索 ...

  8. Eclipse用法和技巧七:自动生成get和set方法2

    上一篇文章中我们介绍了自动批量生成get和set函数的方法.这个方法一般在声明完类的数据域之后使用,比较方便快捷.这里再补充几个自动生成get和set函数的方法. 步骤一:在声明的数据域中按Ctrl+ ...

  9. Eclipse用法和技巧六:自动生成get和set方法1

    java的类中,除了常量声明为静态且公有的,一般的对象数据作用域,都是声明为私有的.这样做能保护对象的属性不会被随意改变,调试的时候也会方便很多:在类的公有方法中大一个调用栈就能看到哪里改了属性值.声 ...

  10. Java Thread 那些事

    这篇文章被压在草稿箱许久,最近公司内部的技术社区有同学贴出了几篇分享 Java线程的文章,发觉有很多概念没有讲清楚,所以花点时间继续撰写,便有了这篇博文. 本文只聚焦 JVM 层面的线程模型,不考虑和 ...