﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-一江春水向东流-文章分类-win32</title><link>http://www.blogjava.net/huyi2006/category/27011.html</link><description>                            做一个有思想的人</description><language>zh-cn</language><lastBuildDate>Sun, 11 May 2008 23:30:22 GMT</lastBuildDate><pubDate>Sun, 11 May 2008 23:30:22 GMT</pubDate><ttl>60</ttl><item><title>在VC6.0中使用sqlite数据库</title><link>http://www.blogjava.net/huyi2006/articles/199720.html</link><dc:creator>胡意</dc:creator><author>胡意</author><pubDate>Sat, 10 May 2008 08:21:00 GMT</pubDate><guid>http://www.blogjava.net/huyi2006/articles/199720.html</guid><wfw:comment>http://www.blogjava.net/huyi2006/comments/199720.html</wfw:comment><comments>http://www.blogjava.net/huyi2006/articles/199720.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/huyi2006/comments/commentRss/199720.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/huyi2006/services/trackbacks/199720.html</trackback:ping><description><![CDATA[
		<p>在sqlite.org 上下载得到Windows版本的sqlite,它是以sqlitedll.zip文件提供的,其中有sqlite3.def和 sqlite3.dll文件,当然可以直接通过LoadLibrary等WIN32API来操作dll,查找其中包含的函数,并使用这些函数,但是一般都 不这么做,原因很简单:这样太麻烦,所以一般先使用LIB命令生成用于链接的lib,然后把sqlite头文件sqlite3.h包含进程序中,<br />这样直接调用 sqlite的API就方便多了.当然sqlite3.h文件得从sqlite源代码（以sqlite-source-3_3_4.zip文件提供）中搞到,在源码中sqlite3.h这个头文件是sqlite3.h.in存在的，解压出来改成sqlite.h就可以了. <br />使用VC++的LIB命令有以下步骤： <br />（1）设置VC98中LIB.exe所在的路径： <br />D:\MyDoc\db\capi&gt;set path=%path%;"D:\Program Files\Microsoft Visual Studio\VC98\Bin" <br />(2)生成SQLite的lib文件： <br />D:\MyDoc\db\capi&gt;LIB /DEF:SQLITE3.DEF /MACHINE:IX86 </p>
		<p>Microsoft (R) Library Manager Version 6.00.8168 Copyright (C) Microsoft Corp 1992-1998. All rights reserved. Creating library SQLITE.lib and object SQLITE.exp <br />  这样就成功地创建了在WIN32程序中访问sqlite所需要的库,可以用于链接WIN32程序. <br />    到此所有使用sqlite的准备工作已告罄.现在在MSVC6中新建一个Win32 Console Application工程,把sqlite.dll,sqlite.h和sqlite.lib文件复制到工程文件夹中,把sqlite.h文件加入到项 目中,然后在Project Setting的Link中的对象库模块中增加sqlite.lib文件. 或者project-&gt;add to project-&gt;files，选择这个lib文件<br />然后修改加入如下代码即可: </p>
		<p>#include &lt;IOSTREAM&gt;<br />#include &lt;STRING&gt;<br />#include &lt;SSTREAM&gt;<br />#include &lt;stdio.h&gt;<br />#include "sqlite3.h"</p>
		<p>using namespace std;</p>
		<p>sqlite3* pDB;</p>
		<p>int createTable()<br />{<br />  char* errMsg;<br />  std::string dropTab="drop table test_tab;";<br />  string strSQL= "create table test_tab (f1 int, f2 long, f3 varchar(20));";<br />  int res = sqlite3_exec(pDB,dropTab.c_str(),0,0, &amp;errMsg);<br />  if (res != SQLITE_OK)<br />  {<br />   std::cout &lt;&lt; "执行SQL 出错." &lt;&lt; errMsg &lt;&lt; std::endl;<br />   //return -1;<br />  } </p>
		<p>  res = sqlite3_exec(pDB,strSQL.c_str(),0,0, &amp;errMsg);</p>
		<p>  if (res != SQLITE_OK)<br />  {<br />    std::cout &lt;&lt; "执行创建table的SQL 出错." &lt;&lt; errMsg &lt;&lt; std::endl;<br />    return -1;<br />  }<br />  else<br />  {<br />      std::cout &lt;&lt; "创建table的SQL成功执行."&lt;&lt; std::endl;<br />  }</p>
		<p>  return 0;<br />}</p>
		<p>int insert1()<br />{<br />  char* errMsg;</p>
		<p>  int res = sqlite3_exec(pDB,"begin transaction;",0,0, &amp;errMsg);</p>
		<p>  for (int i= 1; i &lt; 100; ++i)<br />  {<br />    std::stringstream strsql;<br />    strsql &lt;&lt; "insert into test_tab  values(";<br />    strsql  &lt;&lt; i &lt;&lt; ","&lt;&lt; (i+10) &lt;&lt;",'huyi'"&lt;&lt; ");";<br />    std::string str = strsql.str();<br />    cout &lt;&lt; str &lt;&lt;endl;<br />    res = sqlite3_exec(pDB,str.c_str(),0,0, &amp;errMsg);<br />    if (res != SQLITE_OK)<br />    {<br />      std::cout &lt;&lt; "执行SQL 出错." &lt;&lt; errMsg &lt;&lt; std::endl;<br />      return -1;<br />    }<br />  }<br />  res = sqlite3_exec(pDB,"commit transaction;",0,0, &amp;errMsg);<br />  std::cout &lt;&lt; "SQL成功执行."&lt;&lt; std::endl;<br />  return 0; <br />}</p>
		<p>
				<br />int select1()<br />{<br />  char* errMsg;<br /> int nrow = 0, ncolumn = 0;<br /> char **azResult; //二维数组存放结果<br />  string strSQL= "select * from test_tab;";<br />     /*<br />  int res = sqlite3_exec(pDB,strSQL.c_str(),0,0, &amp;errMsg);</p>
		<p>  if (res != SQLITE_OK)<br />  {<br />    std::cout &lt;&lt; "执行SQL 出错." &lt;&lt; errMsg &lt;&lt; std::endl;<br />    return -1;<br />  }<br />  else<br />  {<br />       std::cout &lt;&lt; "SQL成功执行."&lt;&lt; std::endl;<br />  }<br />  */<br />  sqlite3_get_table(pDB, strSQL.c_str(), &amp;azResult, &amp;nrow, &amp;ncolumn, &amp;errMsg);<br />     int i = 0;<br />  for( i=0 ; i&lt;( nrow + 1 ) * ncolumn ; i++ )<br />  {<br />   if (i&gt;0 &amp;&amp; i%ncolumn==0)<br />    printf("\n");<br />      printf( "%s ",azResult[i]);<br />  }<br />         printf("\n");<br />  //释放掉 azResult 的内存空间<br />  sqlite3_free_table( azResult );<br />  sqlite3_close(pDB); //关闭数据库<br />  return 0;<br />}</p>
		<p>int main(int argc, char* argv[])<br />{<br />  if (argc &lt; 2)<br />  {<br />    std::cout &lt;&lt; "请输入命令行参数：sqlite数据库名." &lt;&lt; std::endl;<br />    return 0;<br />  }</p>
		<p>  int res = sqlite3_open(argv[1], &amp;pDB);</p>
		<p>  if( res ){<br />    std::cout &lt;&lt; "Can't open database: "&lt;&lt; sqlite3_errmsg(pDB);<br />    sqlite3_close(pDB);<br />    return -1;<br />  }<br />  res = createTable();<br />  if (res != 0)<br />  {<br />      return 0;<br />  }<br />  res = insert1();<br />  if (res != 0)<br />  {<br />      return 0;<br />  }<br />  select1();<br />   return 0;<br />}<br /></p>
<img src ="http://www.blogjava.net/huyi2006/aggbug/199720.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/huyi2006/" target="_blank">胡意</a> 2008-05-10 16:21 <a href="http://www.blogjava.net/huyi2006/articles/199720.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>dll基础</title><link>http://www.blogjava.net/huyi2006/articles/180170.html</link><dc:creator>胡意</dc:creator><author>胡意</author><pubDate>Sat, 16 Feb 2008 04:06:00 GMT</pubDate><guid>http://www.blogjava.net/huyi2006/articles/180170.html</guid><wfw:comment>http://www.blogjava.net/huyi2006/comments/180170.html</wfw:comment><comments>http://www.blogjava.net/huyi2006/articles/180170.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/huyi2006/comments/commentRss/180170.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/huyi2006/services/trackbacks/180170.html</trackback:ping><description><![CDATA[
		<div class="post_content">自从微软推出第一个版本的Windows操作系统以来，动态链接库（DLL）一直是Wind <br />ows操作系统的基础。 <br />动态链接库通常都不能直接运行，也不能接收消息。它们是一些独立的文件，其中 <br />包含能被可执行程序或其它DLL调用来完成某项工作的函数。只有在其它模块调用动 <br />态链接库中的函数时，它才发挥作用。 <br />Windows API中的所有函数都包含在DLL中。其中有3个最重要的DLL，Kernel32.dll <br />，它包含用于管理内存、进程和线程的各个函数；User32.dll，它包含用于执行用 <br />户界面任务（如窗口的创建和消息的传送）的各个函数；GDI32.dll，它包含用于画 <br />图和显示文本的各个函数。 <br />           静态库和动态库 <br />静态库：函数和数据被编译进一个二进制文件(通常扩展名为.LIB)。在使用静态库 <br />的情况下，在编译链接可执行文件时，链接器从库中复制这些函数和数据并把它们 <br />和应用程序的其它模块组合起来创建最终的可执行文件(.EXE文件)。 <br />在使用动态库的时候，往往提供两个文件：一个引入库和一个DLL。引入库包含被D <br />LL导出的函数和变量的符号名，DLL包含实际的函数和数据。在编译链接可执行文件 <br />时，只需要链接引入库，DLL中的函数代码和数据并不复制到可执行文件中，在运行 <br />的时候，再去加载DLL，访问DLL中导出的函数。 <br />使用动态链接库的好处 <br />可以采用多种编程语言来编写。 <br />增强产品的功能。 <br />提供二次开发的平台。 <br />简化项目管理。 <br />可以节省磁盘空间和内存。 <br />有助于资源的共享。 <br />有助于实现应用程序的本地化。 <br />动态链接库被多个进程访问 <br />动态链接库加载的两种方式 <br />预备知识 <br />：：：：：：：：：：：：：：：：：：：：：：：：：：：：：：：：：：：： <br />：：：：：：：：：：：：：：：：：：：：：：：：：：：：：：：：：：：： <br />：：：： <br />进程的虚拟地址空间： <br /> 在32为系统中，系统为没个进程分配2^32的地址空间 <br />具体可参看《windows核心编程》 <br />预处理命令： <br />没有什么可以说的了 <br />看看代码就明白了！！ <br />环境变量：（环境变量的概念我就不介绍了，具体的可以参看windows 核心编程， <br />上面有很详细的说明）把DLL放到当前任意的环境变量中就可以加载 <br />定义函数指针 <br />格式：typedef  int (*proc)(int a,int b); <br />注意：proc是一个函数指针类型而不是一个变量 <br />然后我们可以用这个指针类型去定义变量 <br />Proc myproc;这里的myproc就是一个指针变量 <br />要是实在无聊 内心空虚 没事可做的话 可以去这个网站看看函数的指针http://uf <br />o.tyedu.com/study/programmer/language_C/200412/1472.html   <br />函数的调用约定（可以不必了解，但是理解后可以让你理解DLL的调用更为深刻） <br />函数的调用约定：函数调用约定是函数调用者和被调用的函数体之间关于参数传递 <br />、返回值传递、堆栈清除、寄存器使用的一种约定; <br />   它是需要二进制级别兼容的强约定,函数调用者和函数体如果使用不同的调用约 <br />定,将可能造成程序执行错误,必须把它看作是函数声明的一部分; <br />常见的函数调用约定： <br />VC6中的函数调用约定： <br />       调用约定        堆栈清除    参数传递 <br />       __cdecl         调用者      从右到左,通过堆栈传递 <br />       __stdcall       函数体      从右到左,通过堆栈传递 <br />       __fastcall      函数体      从右到左,优先使用寄存器(ECX,EDX),然后 <br />使用堆栈 <br />       thiscall        函数体      this指针默认通过ECX传递,其它参数从右 <br />到左入栈 <br />__cdecl是C\C++的默认调用约定; VC的调用约定中并没有thiscall这个关键字,它是 <br />类成员函数默认调用约定; <br />C\C++中的main(或wmain)函数的调用约定必须是__cdecl,不允许更改; <br />默认调用约定一般能够通过编译器设置进行更改,如果你的代码依赖于调用约定,请 <br />明确指出需要使用的调用约定; <br />常见的函数调用约定中,只有cdecl约定需要调用者来清除堆栈; <br />C\C++中的函数支持参数数目不定的参数列表,比如printf函数;由于函数体不知道调 <br />用者在堆栈中压入了多少参数, <br />所以函数体不能方便的知道应该怎样清除堆栈,那么最好的办法就是把清除堆栈的责 <br />任交给调用者; <br />这应该就是cdecl调用约定存在的原因吧; <br />VB一般使用的是stdcall调用约定;(ps：有更强的保证吗) <br />Windows的API中,一般使用的是stdcall约定;(ps: 有更强的保证吗) <br />建议在不同语言间的调用中(如DLL)最好采用stdcall调用约定,因为它在语言间兼容 <br />性支持最好; <br />三:函数返回值传递方式 <br />  其实，返回值的传递从处理上也可以想象为函数调用的一个out形参数； 函数返 <br />回值传递方式也是函数调用约定的一部分； <br />  有返回值的函数返回时：一般int、指针等32bit数据值(包括32bit结构)通过ea <br />x传递，(bool,char通过al传递，short通过 ax传递),特别的__int64等64bit结构( <br />struct) 通过edx,eax两个寄存器来传递(同理：32bit整形在16bit环境中通过dx,a <br />x传递); 其他大小的结构(struct)返回时把其地址通过eax返回；(所以返回值类型 <br />不是1,2,4,8byte时，效率可能比较差) <br />  参数和返回值传递中，引用方式的类型可以看作与传递指针方式相同； <br />  float\double(包括Delphi中的extended)都是通过浮点寄存器st(0)返回； <br /><br />具体的分析参看：http://blog.csdn.net/avalonbbs/archive/2004/12/25/229300 <br />.aspx <br />：：：：：：：：：：：：：：：：：：：：：：：：：：：：：：：：：：：： <br />：：：：：：：：：：：：：：：：：：：：：：：：：：：：：：：：：：：： <br />：：：：：：： <br /><br /><br /><br /><br />隐式链接 <br />本文现在对隐式链接不作具体的说明，只是做一个大概的介绍（下次再做具体的说 <br />明）.当进程运行的时候，所有的相关的DLL都被加载到内存，然后映射到进程的地 <br />址空间，当一个进程要调用很多个DLL的时候，这种方法就显得特别浪费内存，所以 <br />在加载很多个DLL的时候，最好用显示加载的方式 <br />在调用DLL里面的函数时候 <br />要用extern 声明是外部变量 <br />比如 extern int add(int num1,int num2); <br />但是还应该注意的就是：在编译DLL时，要把编译的LIB文件放到执行文件的目录下 <br />，并且在编译执行文件的时候要连接LIB文件。 <br />在写DLL的时候要导出的函数也就是在能被外部程序调用的函数前面加上 <br />一般大型项目在开发DLL中，要进行预定义声明的 <br /><br />＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝ <br />＝＝ <br />在定义DLL的时候要定义导出函数就要在该函数前面加__declspec(DLLexport)时， <br />C++编译器为了支持函数的重载会进行函数名字改编，当可执行模块执行该函数时由 <br />于找不到该函数的名字，于是调用就会出现错误！当使用extern “C”时就可以告 <br />诉编译器不必修改函数名和变量名。这样就可以用C++或C编译器程序调用该函数。 <br /><br />以上操作只有在VC++创建的的可执行模块来调用该DLL，如果使用其他的编译器的模 <br />块来调用该DLL，就需要执行一些额外的操作。 <br />C编译在进行编译的时候也会进行名字的改编，当函数使用_stdcall(WINAPI)调用 <br />规则时，MS编译器就会改编函数的名称。 <br />比如：__declspec(DLLexport)  LONG __stdcall  Proc(int a ,int b); <br />编译器会改编为__Proc@8 <br />因此 当非C++或非C编译器调用该DLL中的函数Proc时，就会出现找不到函数的情况 <br />。 <br />这样我们就可以定义DEF文件来解决，并且在DEF文件加上下面的EXPORTS： <br />EXPORTS <br />       Proc <br />Def模块执行原理：当连接程序分析这个DEF文件时，它发现Proc和__Proc@8都被输 <br />出，由于这两个函数是相互匹配的，因此连接程序使用Proc来输出该函数，根本不 <br />使用__Proc@8来输出函数名 <br />＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝ <br />＝＝＝ <br /><br />                 <br /><br /><br /><br /><br />下面是def的具体使用方法 <br /><br />------------------------------------------------------------------------ <br />----------------------------------------------模块定义文件(.DEF)是一个或 <br />多个用于描述DLL属性的模块语句组成的文本文件，每个DEF文件至少必须包含以下 <br />模块定义语句： <br />* 第一个语句必须是LIBRARY语句，指出DLL的名字； <br />* EXPORTS语句列出被导出函数的名字；将要输出的函数修饰名罗列在EXPORTS之下 <br />，这 <br />个名字必须与定义函数的名字完全一致，如此就得到一个没有任何修饰的函数名了 <br />。 <br />* 可以使用DESCRIPTION语句描述DLL的用途(此句可选)； <br />* ";"对一行进行注释(可选)。 <br />------------------------------------------------------------------------ <br />---------------------------------------------- <br /><br /><br />//////////////////////////////////////////////////////////////////////// <br />//////////////////////////////////////////////////////////////////////// <br />dlltest.h <br />#ifdef DLL1_API <br />#else <br />#define DLL1_API extern "C" _declspec(dllimport) <br />#endif <br /><br />DLL1_API int _stdcall add(int a,int b); <br />DLL1_API int _stdcall subtract(int a,int b); <br />//////////////////////////////////////////////////////////////////////// <br />////////////////////////////////////////////////////////////////////// <br /><br /><br />\\\\\\\\\\\\\\\\\\ <br />\\\\\\\\\\\\\\\\\\// <br />dlltest.cpp <br />#define DLL1_API extern "C" _declspec(dllexport) <br />#include "Dll1.h" <br />#include &lt;stdio.h&gt; <br />int _stdcall add(int a,int b) <br />{ <br />    return a+b; <br />} <br /><br />int _stdcall subtract(int a,int b) <br />{ <br />    return a-b; <br />} <br />\\\\\\\\\\\\\\\\\\ <br />\\\\\\\\\\\\\\\\\\ <br /><br />//////////////////////////////////////////////////////////////////////// <br />//////////////////////////////////////////////////////////////////// <br />// def文件 <br />LIBRARY dlltest <br />EXPORTS <br />add <br />subtract <br />//////////////////////////////////////////////////////////////////////// <br />//////////////////////////////////////////////////////////////////// <br /><br />有了上面的那些文件之后就可以在如何地方调用这些函数了 <br /><br />void CDllTestDlg::OnBtnSubtract() <br />{ <br />    // TODO: Add your control notification handler code here <br />    CString str; <br />    str.Format("5-3=%d",subtract(5,3)); <br />    MessageBox(str); <br />} <br /><br />void CDllTestDlg::OnBtnOutput() <br />{ <br />    // TODO: Add your control notification handler code here <br />    Point pt; <br />    pt.output(5,3); <br />}下面具体介绍显示加载 <br />显示加载 <br />VC++编译器在编译DLL的时候函数会发生名字改编；主要在非C++环境中就不能识别 <br />该函数了，所以这里应该定义模块文件类型DEF，主要就方便了非C++程序可以调用 <br />该DLL里面的函数 <br />再使用显示加载前必须要注意的是名字的改编问题，因为再动态加载中名字改编后 <br />在加载就得不原来的函数名字了，这样加载就会失败。但是可以用另外一种方法加 <br />载：MSDN上对GetProAddress中的第二个参数是这样说明的Pointer to a null-ter <br />minated string that specifies the function or variable name, or the func <br />tion's ordinal value.也就是说可以使用函数的序号来调用该函数，具体使用方法 <br />是ProcAdd = (MYPROC) GetProcAddress(hinstLib, MakeIntResource(i)); (i代表 <br />函数在DLL中的序号，可以用DUMPBIN工具查看)，但是一般的都不用这种转换序号的 <br />方式来取得函数的地址，因为这样非常的不直观！下面就用模块定义文件（DEF）来 <br />避免DLL中函数的名字的改编问题 <br /><br /><br /><br /><br /><br />显示加载DLL <br />//MSDN上的对DLL进程显示加载的DEMO <br />Using Run-Time Dynamic Linking <br />You can use the same DLL in both load-time and run-time dynamic linking. <br />The following example uses the LoadLibrary function to get a handle to <br />the Myputs DLL (see Creating a Simple Dynamic-Link Library). If LoadLibr <br />ary succeeds, the program uses the returned handle in the GetProcAddress <br />function to get the address of the DLL's myPuts function. After calling <br />the DLL function, the program calls the FreeLibrary function to unload <br />the DLL. <br />Because the program uses run-time dynamic linking, it is not necessary t <br />o link the module with an import library for the DLL. <br />This example illustrates an important difference between run-time and lo <br />ad-time dynamic linking. If the DLL is not available, the application us <br />ing load-time dynamic linking must simply terminate. The run-time dynami <br />c linking example, however, can respond to the error. <br />// A simple program that uses LoadLibrary and <br />// GetProcAddress to access myPuts from Myputs.dll. <br /><br />#include &lt;stdio.h&gt; <br />#include &lt;windows.h&gt; <br />typedef int (*MYPROC)(LPTSTR); <br />VOID main(VOID) <br />{ <br />   HINSTANCE hinstLib; <br />   MYPROC ProcAdd; <br />   BOOL fFreeResult, fRunTimeLinkSuccess = FALSE; <br /> // Get a handle to the DLL module. <br />hinstLib = LoadLibrary(TEXT("DllTest")); <br />// If the handle is valid, try to get the function address. <br />if (hinstLib != NULL) <br />   { <br />       ProcAdd = (MYPROC) GetProcAddress(hinstLib, TEXT("Proc")); <br />// If the function address is valid, call the function. <br /> if (NULL != ProcAdd) <br />       { <br />           fRunTimeLinkSuccess = TRUE; <br />           (ProcAdd) (TEXT("Message via DLL function\n")); <br />       } <br /> // Free the DLL module. <br />fFreeResult = FreeLibrary(hinstLib); <br />   } <br /> // If unable to call the DLL function, use an alternative. <br />if (! fRunTimeLinkSuccess) <br />      printf("Message via alternative method\n"); <br />} <br /><br />对以上的几个函数作一些必要的说明： <br />LoadLibrary：加载指定的DLL，加载方式是先在当前目录中查找，如果找不到再再 <br />环境变量目录下查找； <br />还是看MSDN上的说明 <br />The LoadLibrary function maps the specified executable module into the a <br />ddress space of the calling process. <br />HMODULE LoadLibrary( <br /> LPCTSTR lpFileName <br />); <br />Parameters <br />lpFileName <br />[in] Pointer to a null-terminated string that names the executable modul <br />e (either a .dll or .exe file). The name specified is the file name of t <br />he module and is not related to the name stored in the library module it <br />self, as specified by the LIBRARY keyword in the module-definition (.def <br />) file. <br /><br />GetProcAddress：是取得已知的DLL中的函数，返回指定函数的地址 <br />MSDN上的说明 <br />This function returns the address of the specified exported DLL function <br />. <br />FARPROC GetProcAddress( <br /> HMODULE hModule, <br /> LPCWSTR lpProcName <br />); <br />Parameters <br />hModule <br />[in] Handle to the DLL module that contains the function. <br />The LoadLibrary or GetModuleHandle function returns this handle. <br />lpProcName <br />[out] Pointer to a null-terminated string containing the function name, <br />or specifies the function's ordinal value. <br />If this parameter is an ordinal value, it must be in the low-order word; <br />the high-order word must be zero. <br />The lpProcName parameter must be in Unicode. <br />Remark: <br />The GetProcAddress function is used to retrieve addresses of exported fu <br />nctions in DLLs. <br />The spelling and case of the function name pointed to by lpProcName must <br />be identical to that in the EXPORTS statement of the source DLL's modul <br />e-definition (.def) file. <br />The exported names of Win32 APIs might differ from the names you use whe <br />n calling these functions in your code. This difference is hidden by mac <br />ros used in the SDK header files.</div>
<img src ="http://www.blogjava.net/huyi2006/aggbug/180170.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/huyi2006/" target="_blank">胡意</a> 2008-02-16 12:06 <a href="http://www.blogjava.net/huyi2006/articles/180170.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>删除windows服务</title><link>http://www.blogjava.net/huyi2006/articles/168603.html</link><dc:creator>胡意</dc:creator><author>胡意</author><pubDate>Tue, 18 Dec 2007 14:45:00 GMT</pubDate><guid>http://www.blogjava.net/huyi2006/articles/168603.html</guid><wfw:comment>http://www.blogjava.net/huyi2006/comments/168603.html</wfw:comment><comments>http://www.blogjava.net/huyi2006/articles/168603.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/huyi2006/comments/commentRss/168603.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/huyi2006/services/trackbacks/168603.html</trackback:ping><description><![CDATA[
		<table style="TABLE-LAYOUT: fixed">
				<tbody>
						<tr>
								<td>
										<div class="cnt">
												<div class="tit">
												</div>
												<table style="TABLE-LAYOUT: fixed">
														<tbody>
																<tr>
																		<td>
																				<div class="cnt">
																						<p>删除的办法有两个：</p>
																						<p>
																								<strong>
																										<font color="#000080">办法一： 用sc.exe这个Windows命令<br /></font>
																								</strong>         开始——运行——cmd.exe，然后输入sc就可以看到了。使用办法很简单：<br />         sc delete "服务名"   (如果 衩 屑溆锌崭瘢 托枰 昂蠹右 牛?br /&gt;          如针对上面的： sc delete KSD2Service </p>
																						<p>
																								<strong>
																										<font color="#000080">方法二：直接进行注册表编辑（不推荐）<br /></font>
																								</strong>       打开注册表编辑器，找到下面的键值：<br />       HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services   一般服务会以相同的名字在这里显示一个主健，直接删除相关的键值便可。</p>
																						<p>
																								<strong>特殊情况</strong>
																						</p>
																						<p>      1、如果服务显示的是rundll32.exe，并且这个文件是位于system32目录下，那么就不能删除这个rundll32.exe文件，它是Windows系统的文件。这时只要清除相关的服务就可以了</p>
																						<p>       2、如果一个服务删除了马上又自动建立了，说明后台有进程在监视、保护。需要先在进程管理器中杀掉相应的进程，或者启动后按F8，到安全模式下删除</p>
																				</div>
																		</td>
																</tr>
														</tbody>
												</table>
										</div>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/huyi2006/aggbug/168603.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/huyi2006/" target="_blank">胡意</a> 2007-12-18 22:45 <a href="http://www.blogjava.net/huyi2006/articles/168603.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>