博文

句柄与ID的区别〔转〕(2007-06-19 22:49:00)

摘要:  在Windows程序设计中,句柄是无法精确定义的术语。随便找一个高手,让他给你讲讲句柄是什么,恐怕他都很难给你一个具体的定义来。

在Windows程序设计中,句柄无所不在,窗口有窗口的句柄HWND,线程和进程也有句柄HANDLE,甚至有人把套接字也称为句柄(我就是这样的)。

句柄在英文中是handle,作为动词讲是处理的意思。简而言之,句柄是处理对象的一个接口,对于程序中所涉及的对象,你可以通过句柄去操作他。你不应该试图去回答句柄是什么,而应该从务虚的角度去理解他,知道他干什么即可。

有人说,因为handle的定义是void *,因此他是一个指针。有些熟悉内核的人说这是一个索引。这些说法都是不准确的。需要注意的是,微软并没有精确定义句柄的含义,也许在某个特殊的操作系统中,他使用了一种内部含义,但是在其他版本中,就不保证这样了。任何对句柄的内在假设都可能导致灾难性的后果。

API是接口,句柄是接口,两者有什么区别?API是一个通用的函数族,他处理所有的对象,而句柄是和某个具体对象相关联的数据结构。只有借助句柄,API才知道处理哪个对象。

有些对象有ID。句柄表示特殊的对象,ID也表示某个对象,为什么要两个东西来表示?

首先,句柄不能唯一表示对象。一个对象可以有多个句柄。例如:假设我们用CreateProcess创建一个进程,该进程的第一个线程的句柄会返回给调用CreateProcess的进程。同时,在新创建的进程中,该线程也会有一个句柄。这样,这个线程就有两个句柄。我们也可以用DuplicateHandle复制一个句柄,这个句柄和原来句柄是不一样的,但是他们都表示同一个对象。而每个有ID的对象,在系统范围内,ID肯定是唯一的。

其次,句柄所能实现的功能ID不能实现。毕竟ID只是一个数字,他不能记录很多信息。而句柄可能在其内部结构中记录了很多信息(如权限、有无信号等)。

总之,如果试图解释他到底是什么,学习句柄就会误入歧途。从虚的角度去理解,对于新手是难一点,但是这也许是唯一正确的办法。   引用地址:http://blog.vckbase.com/arong/archive/2005/03/19/3732.aspx......

阅读全文(2133) | 评论:1

怎样知道一个DSN是系统DSN还是用户DSN(2007-03-08 11:27:00)

摘要:我从INI文件中读到一个DSN,怎样判断这个DSN是一个系统DSN还是一个用户DSN?

我知道的一个方法:
查注册表,
如在
[HKEY_LOCAL_MACHINE\Software\ODBC\ODBC.INI\ODBC Data Sources]中
找到键名为你的DSN,键值非空(字符型)
则你的DSN为系统DSN
如在
[HKEY_LOCAL_USER\Software\ODBC\ODBC.INI\ODBC Data Sources]中
找到键名为你的DSN,键值非空(字符型)
则你的DSN为用户DSN
如两者都找到(在系统DSN、是用户DSN同名情况下就会出现这样情况),我不能确定ODBC系统会使用 系统DSN 还是 用户DSN。。。

^-^,来晚了。不过还是说说吧: 在注册表里它们的位置不同。 系统的在 HKEY_LOCAL_MACHINE\Software\ODBC\ODBC.INI\ 用户的在 HKEY_CURRENT_USER\Software\ODBC\ODBC.INI\ ......

阅读全文(2341) | 评论:0

ODBC中的用户DSN,文件DSN,系统DSN有什么不一样(2007-03-08 11:19:00)

摘要:用户DSN:该数据源只能对建立数据源的用户可见.ODBC用户数据源存贮了如何与指定数据库提供者连接的信息.只对当前用户可见,而且只能用于当前机器上.这里的当前机器是只这个配置只对当前的机器有效,而不是说只能配置本机上的数据库.它可以配置局域网中另一台机器上的数据库的.             系统DSN:该数据源对当前机器上所有的用户可见.ODBC系统数据源存贮了如何指定数据库提供者连接的信息系统数据对当前机器上的所有用户都是可见的,包括NT服务.也就是说在这里配置的数据源,只要是这台机器的用户都可以访问 .文件DSN:该数据源对安装了相同驱动的用户可见 用户DSN只被用户直接使用,它只能用于当前机器中,ASP不能使用它.系统DSN允许所有的用户登陆到特定服务器上去访问数据库,任何具有权限有用户都可以访问系统DSN.在WEB应用程序中访问数据库时,通常都是建立系统DSN. 文件DSN将信息存储在后缀为.dsn的文本文件中,优点古玩便于移动. 用户DSN只是针对当前用户或者特定用户;系统DSN是底层的,针对全部用户。
一般没有特殊情况时,建议使用使用系统DSN,通用性好  ......

阅读全文(3032) | 评论:0

如何利用FindWindow()函数查找程序(2007-03-03 11:03:00)

摘要:假设我想运行的外部程序是ABC.EXE,在VB中应如何利用FindWindow()函数查找该程序是否仍在运行? 要使用API,评选建立一个.BAS模块,然后从winapi32.txtk 中Copy如下的FIndWindow()函数的声明: Declare Function FindWindow Lib "user32" Alias "FindWindowA"(ByVal LpClassName as String,Byval lpWindowName as Stirng ) as Long 这个函数有两个基本点参数,第一个是要找的窗口的类,第二个是要找的窗口的标题.在搜索的时候一定两者都知道,但至少要知道其中的一个.有的窗口的标题的比较容易得到的,如"计算器":,所以搜索时就使用标题进行搜索.但有的软件的标题不是固定的,如"记事本",如果打开的文件不同,窗口标题也不同,这时使用窗口类搜索就比较方便.如果找到了满足条件的窗口,这个函数返回该窗口的句柄,否则返回0. 前面提到的VB的FindWindow()函数的声明将两个基本点参数都定义为String类型,而在实际使用过程中,如果我们忽略某个参数就将该参数的定义又As StriNG书库As Any.这里的As Any 相当于C语言中的强制类型转换.例如,如果我们忽略窗口的类,就将定义修改如下: Declare Function FIndWindow lib "user32" alias "findwoindowA"(ByVal lpClassName as Any,ByVal lpWIndowName as String) as Long 然后,在调用使用如下语句: :hwndCalc=FindWIndow(0&,"计算器") 这里的0&就表示忽略类名.需要注意的是FindWindow(0&,"计算器"),和FindWindow("","计算器")在两种完全不同的含义前者表示忽略窗口的类,后者表示窗口的类是个空串.类似的,我们也可以忽略标题而搜索指定的类. 从上面的讨论中可以看出,如果说要搜索的外部程序的窗口标题比较容易的话,怎么问题是比较简单的.可如果窗口的标题不固定的或者根本就没有标题,怎么得到窗口的类吧?如果你安装了Visual C++,你可以攻玉使用其中之一的Spy++......

阅读全文(3696) | 评论:1

关于VB类的开发(2007-01-20 11:50:00)

摘要:对程序员和编程爱好者来说,VB中类的技术是学习中的一个难点,在大型软件的开发过程中,模块(Moudle)、控件(Active ocx)、链接库(Active dll)和类(Class moudle)构成了系统化、高效化的软件工程,而类的技术是控件和链接库技术的基础,因此掌握类的理论和编程方法是非常有意义的。   (一)类的基本定义和应用概述;  
   类是包含了方法、属性、数据成员的高级代码模块,它既在模块的范畴之内,又是一个没有图形界面的Active ocx,程序员可以象使用控件一样使用它,但却不能看到它,值得注意的是,类是不能继承的。 类能够使我们高效的完成对某一个或者某几个特定的对象的复杂操作,对象的动作就是类的方法,对象的属性就是类的属性过程。相对而言,如果编程的对象是一组事物,那么,我们采用标准模块的方式是非常合适的,在下列两种情况下,应该使用类进行代码处理:     (1)创建大量性质相近的对象;   (2)提高代码的封装性。    类的创建非常简单,在进行代码编写的时候,在“工程”菜单中选择“添加类模块”项目,就可以添加一个空白的类。    类文件一般以.cls作为扩展名保存。
  (二)类的方法的实现;    类的方法类似于动态链接库的接口函数,它能够接受其他窗体代码的指定类型参数,并且传递到类中。一般来说类的方法是能够指定是否有返回值的。它在类中通常是一个public过程。请看下面的代码示例,它使一个密码框拒绝非字母的输入:   (1)类cls的代码;    Option Explicit'变量检查     Private WithEvents mytxt As TextBox     '本类中的方法接受和控制一个text密码框     Dim isNUM As Boolean     '类的模块级变量     Public Sub Attach(itTEXT As TextBox)     '接受外部变量到mytxt中     Set mytxt = itTEXT    End Sub    Private Sub mytxt_KeyUp(KeyCode As Integer, Shift As Integer)     isNUM = (KeyCode >= 65) And (Ke......

阅读全文(2103) | 评论:0

VB程序中处理随机事件(2007-01-20 11:07:00)

摘要:在程序设计过程中,如何轻松地处理众多的随机事件,往往是制作大型系统首先要考虑的问题之一。用C语言开发Windows程序时,可以方便地使用消息机制(Message),但是,设计VB程序时,就没有这样的方便条件了。例如,多个窗口同时打开同一个表(Table),当在一个窗口中对数据进行了修改,而其他的窗口也能够随之进行数据更新,这时就需要有一条说明数据改变了的消息在所有的窗口间进行广播。如果使用的语言是C,只需要定义一条用户消息(UserMessage),就可以实现这一点。可是如果是用VB编程,做起来就不是那么简单了,最初我是试着这样实现的: 自定义了一个消息结构(VbMsg),并在程序的主窗体内,建立一个消息广播引擎,主要由一个消息队列和一个定时消息广播器所组成。消息广播器固定隔一定时间检查一次消息队列,如果有消息存在,就将其发送给所有的打开的窗口,并将该消息从队列中删除。如此再定义一个全局的消息发送过程(SendMsg),将要发送的消息(VbMsg)送入消息队列。这样当需要广播消息时,只需填充好消息结构,调用SendMsg过程即可。这里较为复杂的是消息广播器如何将消息发送到各窗口:这需要作个硬性规定,就是每一个窗体都必须定义一个形式完全相同的消息接收函数(RecMsg),在这个函数中对接收到的消息进行处理,当然也可以什么都不做。有了这样的规定之后,消息广播器在进行广播时,就可以是利用VB系统定义的全局变量Forms,遍历所有的窗体,并调用一遍每个窗体的消息接收函数,其样子大致如下: Public Sub SendMsgToForms(msg as VbMsg) Dim frm as Form For Each frm In Forms frm.RecMsg msg Next frm End Sub 通过上面的这些过程,就可以实现在独立的程序中,对随机事件进行异步处理。这一方法我曾经在早期开发的几个系统中使用,效果基本还是令人满意的。但是它有几个较大的局限性,当开发更大一些的系统时,就显得不能够满足需要。主要有以下几点: 1.定时检查消息队列,需要利用Timer控件进行触发。这在程序运行时,就必然要牺牲一部分效率; 2.消息广播的范围限定在一个程序模块内,如果整个系统分成多个大的模块,那么存在于动态连接模块(.DLL)中的窗体,将不能直接接收到广播......

阅读全文(1459) | 评论:0

Rundll32.exe和Rundll.exe的区别 (2007-01-19 12:16:00)

摘要:动态链接库函数启动器——Rundll32

经常听到有些朋友说:呀!系统的注册表启动项目有rundll32.exe,系统进程也有rundll32.exe,是不是病毒呀?其实,这是对rundll32.exe接口不了解,它的原理非常简单,了解并掌握其原理对于我们平时的应用非常有用,如果能理解了原理,我们就能活学活用,自己挖掘DLL参数应用技巧。

Rundll32.exe和Rundll.exe的区别

所谓Rundll.exe,可以把它分成两部分,Run(运行)和DLL(动态数据库),所以,此程序的功能是运行那些不能作为程序单独运行的DLL文件。而Rundll32.exe则用来运行32位DLL文件。Windows 2000/XP都是NT内核系统,其代码都是纯32位的,所以在这两个系统中,就没有rundll.exe这个程序。

相反,Windows 98代码夹杂着16位和32位,所以同时具有Rundll32.exe和Rundll.exe两个程序。这就是为什么Windows 98的System文件夹为主系统文件夹,而到了Windows 2000/XP时就变成System32为主系统文件夹(这时的System文件夹是为兼容16位代码设立的)。

Rundll.exe是病毒?

无论是Rundll32.exe或Rundll.exe,独立运行都是毫无作用的,要在程序后面指定加载DLL文件。在Windows的任务管理器中,我们只能看到rundll32.exe进程,而其实质是调用的DLL。我们可以利用进程管理器等软件(本刊2004年21期有介绍)来查看它具体运行了哪些DLL文件。

有些木马是利用Rundll32.exe加载DLL形式运行的,但大多数情况下Rundll32.exe都是加载系统的DLL文件,不用太担心。另外要提起的是,有些病毒木马利用名字与系统常见进程相似或相同特点,瞒骗用户。所以,要确定所运行的Rundll32.exe是在%systemroot%system32目录下的,注意文件名称也没有变化。

相信大家在论坛上很常看见那些高手给出的一些参数来简化操作,如rundll32.exe shell32.dll,Control_RunDLL,取代了冗长的“开始→设......

阅读全文(1544) | 评论:0

Rundll32.exe浅谈(2007-01-19 12:12:00)

摘要:Rundll32.exe浅谈

Rundll32.exe是什么?顾名思意,“执行32位的DLL文件”。它的作用是执行DLL文件中的内部
函数,这样在进程当中,只会有Rundll32.exe,而不会有DLL后门的进程,这样,就实现了进程上的隐藏。
如果看到系统中有多个Rundll32.exe,不必惊慌,这证明用Rundll32.exe启动了多少个的DLL文件。当然,
这些Rundll32.exe执行的DLL文件是什么,我们都可以从系统自动加载的地方找到。

    现在,我来介绍一下Rundll32.exe这个文件,意思上边已经说过,功能就是以命令行的方式调用动
态链接程序库。系统中还有一个Rundll.exe文件,他的意思是“执行16位的DLL文件”,这里要注意
一下。在来看看Rundll32.exe使用的函数原型:
    Void CALLBACK FunctionName (
    HWND hwnd,
    HINSTANCE hinst,
    LPTSTR lpCmdLine,
    Int nCmdShow
    );

    其命令行下的使用方法为:Rundll32.exe DLLname,Functionname [Arguments]
    DLLname为需要执行的DLL文件名;Functionname为前边需要执行的DLL文件的具体引出函数;
[Arguments]为引出函数的具体参数。

略谈Rundll32.exe的作用  (我是菜鸟)    

   

    常用Windows9x的朋友一定对Rundll32.exe和Rundll.exe这两个档案不会陌生吧,不过,由於这两个程式
......

阅读全文(2451) | 评论:0

VB编程之提升篇(2007-01-18 23:17:00)

摘要:   ● 判断空字符串    判断空字符串的常用方法是使用下面的语句:If my_string = "" Then... ,但是请采用另外一种方法,就是判断字符串的长度是否为0,这要比前者运行快,代码是: If Len(my_string) = 0 Then ... 。    ● 使用With命令引用多次使用的对象    这要比在每条语句中都完整地引用对象名称执行速度快许多!    ● 少有字符串操作函数    尽可能少地使用字符串操作函数,它们运行很慢。    ● 定制Select Case语句    Select Case是处理多重条件判断的语句,请将经常要用到的选择排列在前面的选项,以增加该选项提前被选择命中的机会。    ● 尽可能的使用by ref参数调用函数和子程序    ● 将从不需要的表单设置为nothing    如果有许多要标明的表单,采用这个策略,将节省内存并减少运行时间。如果只有少数几个表单,请将它们全部装载进内存并隐藏之,这样将在随后的使用中速度更快。    ● 预想一下程序的速度    对程序的运行速度进行想象是非常重要的,设想一下点击按钮后,等待10秒钟。这将是一个非常长的时间!请添加一个进程条显示程序的进展情况,用户就不会感到等待。    ● 使用mid$函数而不是mid    如果需要执行许多字符串/文件操作,请使用mid$(以及trim$等等)函数而不是mid。因为后者将数据类型看作是variant 而不是 string,速度将慢3倍。    ● 尽快显示启动表单    尽快地显示启动表单可以使程序看起来很快。在表单的Load事件中使用Show命令,从而在执行长时间的启动计算工作前就能显示出程序界面。    ● 尽可能地在Form_Load事件中放置少量的代码    ● 使用splash技术过渡中间操作    如果初始化的表单要运行很长时间,请先立即显示一个splash画面,然后在初始表单完全装载后,再去除它。关于如果创建不同种类splash画面的资料,请查阅Advanced Visual Basic Techniques。    ● 在模块中将子程序分组    当一个程序调用另外一个程序时,另外的程序所在的模块将被装载。如果一个程序需要调用多个不同模块中的程序,那么所有的这些模块都要被装......

阅读全文(1558) | 评论:0

VB编程优良习惯(补充版)(2007-01-18 23:08:00)

摘要:用程序频繁使用许多菜单控件,对于这些控件具备一组唯一的命名约定很实用。除了最前面 "mnu" 标记以外,菜单控件的前缀应该被扩展:对每一级嵌套增加一个附加前缀,将最终的菜单的标题放在名称字符串的最后。下表列出了一些例子。 推荐使用的菜单前缀
菜单标题序列 菜单处理器名称
File Open mnuFileOpen
File Send Email mnuFileSendEmail
File Send Fax mnuFileSendFax
Format Character mnuFormatCharacter
Help Contents mnuHelpContents 当使用这种命名约定时,一个特定的菜单组的所有成员一个接一个地列在 Visual Basic 的“属性”窗口中。而且,菜单控件的名字清楚地表示出它们所属的菜单项。 为其它控件选择前缀 对于上面没有列出的控件,应该用唯一的由两个或三个字符组成的前缀使它们标准化,以保持一致性。只有当需要澄清时,才使用多于三个字符的前缀。 常量和变量命名约定
除了对象之外,常量和变量也需要良好格式的命名约定。本节列出了 Visual Basic 支持的常量和变量的推荐约定。并且讨论标识数据类型和范围的问题。 变量应该总是被定义在尽可能小的范围内。全局 (Public) 变量可以导致极其复杂的状态机构,并且使一个应用程序的逻辑非常难于理解。全局变量也使代码的重用和维护更加困难。 Visual Basic 中的变量可以有下列范围

范围 声明位置 可见位置
过程级 过程,子过程或函数过程中的 ‘Private’ 在声明它的过程中
模块级 窗体或代码模块(.frm、.bas )的声明部分中的 ‘Private’ 窗体或代码模块中的每一个过程
全局 代码模块(.bas)的声明部分中的 ‘Public’ 应用程序中的每一处 在 Visual Basic 的应用程序中,只有当没有其它方便途径在窗体之间共享数据时才使用全局变量。当必须使用全局变量时,在一个单一模块中声明它们,并按功能分组。给这个模块取一个有意义的名称,以指明它的作用,如 Public.bas。 较好的编码习惯是尽可能写模块化的代码。例如,如果应用程序显示一个对话框,......

阅读全文(1614) | 评论:0