Re:谁知道禁用USB端口的函数啊!?! 是不是要自己写方法哦!
http://www.codeproject.com/system/EnumDevices.asp
http://www.codeproject.com/system/change_drive_sn.asp
http://www.codeproject.com/system/installed_programs.asp
http://www.codeproject.com/system/enum_display_modes.asp
http://www.codeproject.com/system/serial_portsenum_fifo.asp
1Minimize any window to system tray using Windows Hook
http://www.codeproject.com/system/DevicePropertySheet.asp
http://www.codeproject.com/system/chaiyasit_t.asp
http://www.codeproject.com/system/DevMgr.asp     001
http://www.codeproject.com/system/eject_cdrom.asp
http://www.codeproject.com/system/serviceskeleton.asp    002
http://www.codeproject.com/useritems/HwDetect.asp    003








Re:谁知道禁用USB端口的函数啊!?! 是不是要自己写方法哦!
我做了个MP3的量产软件,当对MP3的文件download完成后会将MP3安全移除。
问题是:我用GUID{0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED}会将USB键盘和USB鼠标全都枚举出来,这样我就无法区分谁是MP3,谁是USB键盘和鼠标了。虽然枚举时我可以得到PID和VID,但是我们的PID和VID可能会被代理商更改,所以也就不能通过PID和VID来区分了,不知PC上的安全删除U盘是怎样做到的,PC应该可以将盘符和对应的设备对应起来,且能用唯一的标识来区分每台设备,情况紧急,求求各位高手拉我一把吧,非常感谢!

我的代码如下:
void CLogicDriveList::RemoveDevice(size_t index)
{
char szDevDesc[256] = {0};
HDEVINFO hDevInfo;
string Prod;
string Rev;

//遍历所有的设备
hDevInfo = SetupDiGetClassDevs((LPGUID)&GUID_CLASS_USB_DEVICE, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE) if ( INVALID_HANDLE_VALUE == hDevInfo)return;

SP_DEVINFO_DATA devInfoData;
devInfoData.cbSize = sizeof(devInfoData);

int Index = 0;
while(SetupDiEnumDeviceInfo(hDevInfo, Index++, &devInfoData))
{
//获取设备ID
std::string devId;
memset(szDevDesc, 0, sizeof(szDevDesc));
devInfoData.cbSize = sizeof(devInfoData);

CM_Get_Device_ID(devInfoData.DevInst, szDevDesc, sizeof(szDevDesc),0);
devId = szDevDesc;
cout<<devId<<endl;
//比较设备ID
if(这里该怎样填呢?)
{
if(EjectDevice(devInfoData))
{
cout<<"Remove device "<<m_LogicDrives [index].Symbol<<": ok"<<endl;
break;
}
else
cout<<"Remove device "<<m_LogicDrives[index].Symbol<<": fail"<<endl;
}
}
}

bool CLogicDriveList::EjectDevice(const SP_DEVINFO_DATA &devInfoData)
{
PNP_VETO_TYPE   pnpvietotype;  
char vetoname[MAX_PATH] = {0};  
CONFIGRET cr = CM_Request_Device_Eject(devInfoData.DevInst,  
                        &pnpvietotype,
vetoname,
MAX_PATH,
0);  
return CR_SUCCESS==cr;
}
posted @ 2011-01-26 10:44 wrh 阅读(944) | 评论 (0)编辑 收藏
void   CRegExplorerView::EnumerateValues(HKEY   hKey,   LPCTSTR   cstrKey) 
{ 
 static   HKEY   hLastKey   =   hKey; 
 LONG   lResult; 
 DWORD   dwIndex   =   0; 
 HKEY   hCurKey   =   hKey; 
 DWORD   dwKeyType;   
 DWORD   dwKeyDataLength,   dwKeyNameLen; 
 LPBYTE   pbbinKeyData   =   NULL;   
 TCHAR   *tcKeyName   =   NULL; 
 TCHAR   tcDataType[1024]   =   _T( " "); 
 lResult   =   RegOpenKeyEx(hCurKey,   cstrKey,   0,   KEY_QUERY_VALUE   ,   &hKey); 
 if(lResult   !=   ERROR_SUCCESS) 
  return; 
 DWORD   lNoOfValues   =   0; 
 DWORD   lLongestKeyNameLen   =   1; 
 DWORD   lLongestDataLen   =   1; 

 lResult   =   RegQueryInfoKey(hKey,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   &lNoOfValues,   &lLongestKeyNameLen,   &lLongestDataLen,NULL,   NULL); 

 if(lResult   !=   ERROR_SUCCESS) 
  return; 
 hLastKey   =   hKey; 
 lLongestKeyNameLen++; 
 lLongestDataLen++; 
 tcKeyName   =   new   TCHAR[lLongestKeyNameLen]; 
 pbbinKeyData   =   new   BYTE[lLongestDataLen]; 
 CString   cstrFinalData,   cstrTemp; 
 while(TRUE) 
 { 
  memset(pbbinKeyData,   0,   lLongestDataLen); 
  memset(tcKeyName,   0,   lLongestKeyNameLen); 
  dwKeyType   =   dwKeyDataLength   =   dwKeyNameLen   =   0; 
  dwKeyNameLen   =   lLongestKeyNameLen; 
  dwKeyDataLength   =   lLongestDataLen; 
  lResult   =   RegEnumValue(hKey,   dwIndex,   tcKeyName,   &dwKeyNameLen,   NULL,   &dwKeyType,   pbbinKeyData,   &dwKeyDataLength); 
  if(lResult   ==   ERROR_NO_MORE_ITEMS) 
   break; 
  AddRegistryItem(tcKeyName,   dwKeyType,   pbbinKeyData,   dwKeyDataLength,   dwIndex);//显示数据于ListView 
  dwIndex++; 
 } 
 RegCloseKey(hKey); 
 delete   tcKeyName; 
 delete   pbbinKeyData; 
}
posted @ 2011-01-05 13:27 wrh 阅读(302) | 评论 (0)编辑 收藏
请教各位: 
  用RegEnumKeyEx枚举一个键下的所有子键,例如HKEY_LOCAL_MACHINE\Software\ListItem下有6个子键,分别是111,432fdksaf,fd3425,fd5432,89342,tewjfds,用RegEnumKeyEx可以枚举出后3个子键(我是从后向前进行的),但是只能得到后3个的全名,前3个就只能得到前2个或3个字母(例如:432fdksaf就只能得到432),不知道为什么,如果是从前向后进行就只能得到前3个的全名,后3个就只能前2个或3个字母了。
这是一个简单的例子。 
查看 "//注意这两行 "的注释处。:) 

void   CRegistryView::OnButton3()   
{ 
//   TODO:   Add   your   control   notification   handler   code   here 
HKEY   hkey; 
LPCSTR   data_Get= "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run "; 
long   ret0=::RegOpenKeyEx(HKEY_LOCAL_MACHINE,data_Get,0,KEY_ALL_ACCESS,&hkey); 
if   (ret0!=ERROR_SUCCESS) 
{ 
MessageBox( "Error! "); 
return; 
} 
TCHAR   szBuffer[256]; 
DWORD   dwSize=256; 
ZeroMemory(szBuffer,256); 
DWORD   dIndex; 
dIndex=0L; 
while(RegEnumValue(hkey,dIndex,szBuffer,&dwSize,NULL,NULL,NULL,NULL)==ERROR_SUCCESS) 
{ 
MessageBox(szBuffer, " "); 
dIndex++; 
ZeroMemory(szBuffer,256);   //注意这两行 
dwSize=256;                               // 
} 
return; 
}

问题解决了,不过我发现ZeroMemory(szBuffer,256);   这行可以不要要,只用重新设置dwSize的值就行了,因为RegEnumKeyEx是用&dwSize来调用的,完成后dwSize的值就会改变了,只要重新设置一下就行了,至于上面那行,应该是为防止缓冲区中的值出错而设置的。
posted @ 2011-01-05 13:24 wrh 阅读(1893) | 评论 (0)编辑 收藏

#include "Wininet.h"
#pragma comment(lib,"Wininet.lib")

DWORD   flags;//上网方式  
BOOL   m_bOnline;//是否在线  
   
m_bOnline=InternetGetConnectedState(&flags,0);  

 if(m_bOnline)//在线  
{  
          int b;
          if ( flags& INTERNET_CONNECTION_MODEM )
          {
                 b = flags& INTERNET_CONNECTION_MODEM;
          } 
          else if ( flags&INTERNET_CONNECTION_LAN )
          {
                 b = flags&INTERNET_CONNECTION_LAN;
          }
          else if ( flags& INTERNET_CONNECTION_PROXY )
          {
                 b = flags& INTERNET_CONNECTION_PROXY;
          }
          switch(b)  
          {  
          case   INTERNET_CONNECTION_MODEM   :  
                  AfxMessageBox("在线:拨号上网");  
                  break;  
          case   INTERNET_CONNECTION_LAN   :  
                  AfxMessageBox("在线:通过局域网");  
                  break;  
          case   INTERNET_CONNECTION_PROXY   :  
                  AfxMessageBox("在线:代理");  
                  break;  
          }  
          if(flags&INTERNET_CONNECTION_MODEM_BUSY==INTERNET_CONNECTION_MODEM_BUSY)  
                  AfxMessageBox("MODEM被其他非INTERNET连接占用");  
}  
else  
              AfxMessageBox("不在线");

或者
#include "Wininet.h"
#pragma comment(lib,"Wininet.lib")

DWORD   flags;//上网方式  
BOOL   m_bOnline;//是否在线  
   
m_bOnline=InternetGetConnectedState(&flags,0);  

 if(m_bOnline)//在线  
{  
          if ( flags& INTERNET_CONNECTION_MODEM )
              AfxMessageBox("在线:拨号上网");  

         else if ( flags&INTERNET_CONNECTION_LAN  )
              AfxMessageBox("在线:通过局域网");

         else if ( flags& INTERNET_CONNECTION_PROXY)
              AfxMessageBox("在线:代理");
        
         else if ( flags&INTERNET_CONNECTION_MODEM_BUSY )
               AfxMessageBox("MODEM被其他非INTERNET连接占用");   
}  
else  
              AfxMessageBox("不在线");


详细说明:
虽然MSDN中定义了7种参数类型,但实际中wininet.h头文件中只对四种类型的值进行了定义
7种类型:
INTERNET_CONNECTION_LAN          局域网
INTERNET_CONNECTION_MODEM        拨号上网
INTERNET_CONNECTION_PROXY       代理
INTERNET_CONNECTION_MODEM_BUSY  代理被占用

INTERNET_CONNECTION_CONFIGURED    虽然可以联网,但当前不可用
INTERNET_CONNECTION_OFFLINE     离线
INTERNET_RAS_INSTALLED       RAS安装

 Wininet.h头文件中值定义:
// Flags for InternetGetConnectedState
#define INTERNET_CONNECTION_MODEM             1
#define INTERNET_CONNECTION_LAN                2
#define INTERNET_CONNECTION_PROXY             4
#define INTERNET_CONNECTION_MODEM_BUSY      8

然而实际的返回值却并不是这四种值,本人现在是windows xp操作系统,vc++ 6.0,局域网上网,结果返回值是18,也就是10010,所以比INTERNET_CONNECTION_LAN的值2多了一位,也就是00010,返回值最高位1是多出来的,


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/sichuanpb/archive/2010/09/21/5898449.aspx

posted @ 2011-01-02 18:04 wrh 阅读(725) | 评论 (0)编辑 收藏
Visual C++ 确定要使用的导出方法 (转自MSDN)

若要确定用于导出函数的方法(.def 文件或 __declspec(dllexport) 关键字),请回答下列问题:

  • 是否要一直添加附加的导出函数?

  • 谁要使用 DLL?例如,是由许多无法重新生成的可执行文件使用的第三方 DLL 还是仅由可以轻松重新生成的应用程序使用的 DLL?

使用 .DEF 文件的优缺点

在 .def 文件中导出函数使您得以控制导出序号。当将附加的导出函数添加到 DLL 时,可以给它们分配更高的序号值(高于任何其他导出函数)。当您进行此操作时,使用隐式链接的应用程序不必与包含新函数的新导入库重新链接。这非常重要,例如,在设计将由许多应用程序使用的第三方 DLL 时。可以通过添加附加功能不断地增强 DLL,同时确保现有应用程序继续正常使用新的 DLL。MFC DLL 是使用 .def 文件生成的。

使用 .def 文件的另一个优点是:可以使用 NONAME 属性导出函数,该属性仅将序号放到 DLL 的导出表中。对具有大量导出函数的 DLL,使用 NONAME 属性可以减小 DLL 文件的大小。有关编写模块定义语句的信息,请参见模块定义语句的规则。有关序号导出的更多信息,请参见按序号而不是按名称从 DLL 导出函数

使用 .def 文件的主要缺点是:在 C++ 文件中导出函数时,必须将修饰名放到 .def 文件中,或者通过使用外部“C”用标准 C 链接定义导出函数,以避免编译器进行名称修饰。

如果需要将修饰名放到 .def 文件中,则可以通过使用 DUMPBIN 工具或 /MAP 链接器选项来获取修饰名。请注意,编译器产生的修饰名是编译器特定的。如果将 Visual C++ 编译器产生的修饰名放到 .def 文件中,则链接到 DLL 的应用程序必须也是用相同版本的 Visual C++ 生成的,这样调用应用程序中的修饰名才能与 DLL 的 .def 文件中的导出名相匹配。

使用 __declspec(dllexport) 的优缺点

使用 __declspec(dllexport) 非常方便,因为不必考虑维护 .def 文件和获取导出函数的修饰名。例如,如果您设计的 DLL 供自己控制的应用程序使用,则此方法很适用。如果通过新的导出函数重新生成 DLL,还必须重新生成应用程序,因为如果使用不同版本的编译器进行重新编译,则导出的 C++ 函数的修饰名可能会发生变化。

posted @ 2010-12-28 13:48 wrh 阅读(558) | 评论 (0)编辑 收藏
转载自 yibansha0
最终编辑 yibansha0

调用DLL有两种方法:静态调用和动态调用.
(一).静态调用其步骤如下:
1.把你的youApp.DLL拷到你目标工程(需调用youApp.DLL的工程)的Debug目录下;
2.把你的youApp.lib拷到你目标工程(需调用youApp.DLL的工程)目录下;
3.把你的youApp.h(包含输出函数的定义)拷到你目标工程(需调用youApp.DLL的工程)目
录下;
4.打开你的目标工程选中工程,选择Visual C++的Project主菜单的Settings菜单;
5.执行第4步后,VC将会弹出一个对话框,在对话框的多页显示控件中选择Link页。然
后在Object/library modules输入框中输入:youApp.lib
6.选择你的目标工程Head Files加入:youApp.h文件;
7.最后在你目标工程(*.cpp,需要调用DLL中的函数)中包含你的:#include "youApp.h "
注:youApp是你DLL的工程名。
2.动态调用其程序如下:
动态调用时只需做静态调用步骤1.
{
HINSTANCE hDllInst = LoadLibrary( "youApp.DLL ");
if(hDllInst)
{
typedef DWORD (WINAPI *MYFUNC)(DWORD,DWORD);
MYFUNC youFuntionNameAlias = NULL; // youFuntionNameAlias 函数别名
youFuntionNameAlias = (MYFUNC)GetProcAddress
(hDllInst, "youFuntionName ");
// youFuntionName 在DLL中声明的函数名
if(youFuntionNameAlias)
{
youFuntionNameAlias(param1,param2);
}
FreeLibrary(hDllInst);
}
}

 

 

 

 

原文出处: codeguru

我正在学习DLLs,谈不上对其有什么高屋建瓴的见解;本文只是(通过)编码让你看到并想知道代码是如何运行的。在本文中,我假定你知道如何使用你的编译器特性,比如设置目录路径等等。

 

为了建立项目,请选择Win32 控制台项目(Win32 Console Application),并且在应用程序设置标签(the advanced tab)上,选择DLL和空项目选项。DLLs可能并不如你想像的那样难。首先写你的头文件(header file);称为DLLTutorial.h。这个文件与其它头文件一样,其中只是一些函数的原型。

#ifndef _DLL_TUTORIAL_H_
#define _DLL_TUTORIAL_H_
#include <iostream> #if defined DLL_EXPORT
#define DECLDIR __declspec(dllexport)
#else
#define DECLDIR __declspec(dllimport)
#endif

extern "C"
{
DECLDIR int Add( int a, int b );
DECLDIR void Function( void );
}
#endif

前面两行指示编译器只包含这个文件一次。extern "C"告诉编译器该部分可以在C/C++中使用。

在VC++中这里有两个方法来导出函数:

     1、使用__declspec,一个Microsoft定义的关键字。

     2、创建一个模块定义文件(Module-Definition File即.DEF)。第一种方法稍稍比第二种方法简单些,但两种都工作得很好。

__declspec(dllexport)导出函数符号到在你的DLL中的一个存储类。当下面一行被定义时我定义DECLDIR来运行这个函数,

#define DLL_EXPORT

同时也导入函数如果下面一行

#define DLL_EXPORT

没有在源文件中出现。在此情况下,你将导出函数Add(int a, int b)和Function()。

现在,你需要写一个将要称为DLLTutorial.cpp的源文件。

#include <iostream>
#include "DLL_Tutorial.h"

#define DLL_EXPORT extern "C"
{
DECLDIR int Add( int a, int b )
{
return( a + b );
} DECLDIR void Function( void )
{
std::cout << "DLL Called!" << std::endl;
} }

这里你定义了(DLL中的)所有函数。Int Add(int a, int b)只简单地将两个数相加而void Function(void)只是在你的DLL被调用时(将信息)通知你。在我像你展示如何使用DLL前,我想告诉你一些关于模块定义文件(.def)的内容。

模块定义文件(.def)

模块定义文件是一个有着.def文件扩展名的文本文件。它被用于导出一个DLL的函数,和__declspec(dllexport)很相似,但是.def文件并不是Microsoft定义的。一个.def文件中只有两个必需的部分:LIBRARY 和 EXPORTS。让我们先看一个基本的.def文件稍后我将解析之。

LIBRARY dll_tutorial
DESCRIPTION "our simple DLL"
EXPORTS
Add @1
Function @2

第一行,''LIBRARY''是一个必需的部分。它告诉链接器(linker)如何命名你的DLL。下面被标识为''DESCRIPTION''的部分并不是必需的,但是我喜欢把它放进去。该语句将字符串写入 .rdata 节[据 MSDN],它告诉人们谁可能使用这个DLL,这个DLL做什么或它为了什么(存在)。再下面的部分标识为''EXPORTS''是另一个必需的部分;这个部分使得该函数可以被其它应用程序访问到并且它创建一个导入库。当你生成这个项目时,不仅是一个.dll文件被创建,而且一个文件扩展名为.lib的导出库也被创建了。除了前面的部分以外,这里还有其它四个部分标识为:NAME, STACKSIZE, SECTIONS, 和 VERSION。我将不再在本文中涉及这些内容,但是如果你在Internet上搜索,我想你将找到一些东西(译注: MSDN2003上对模板定义文件各部分内容有详尽解释,请参阅)。另外,一个分号(;)开始一个注解,如同''//''在C++中一样。

现在你已经创建了你的DLL,你需要学习如何在一个应用程序中使用它了。当这个DLL被生成后,它创建了一个.dll文件和一个.lib文件;这两个都是你需要的。

隐式链接

这里有两个方法来载入一个DLL;一个方法是捷径另一个则相比要复杂些。捷径是只链接到你.lib 文件并将.dll文件置入你的新项目的路径中去。因此,创建一个新的空的Win32控制台项目并添加一个源文件。将你做的DLL放入你的新项目相同的目录下。

 

#include <iostream>
#include <DLLTutorial.h>

int main()
{
Function();
std::cout << Add(32, 58) << "\n";
return(1);
}

你必需要链接到DLLTutorial.lib文件。我在项目属性中设置了,但是你可能会用下面的语句代替:

#pragma comment(lib, "DLLTutorial.lib")


请注意我让编译器来查看我的DLL文件夹已获得.lib文件同时让它顺便看下该目录中的DLL头文件。如果你不想这么做,你可以总是把他们放入你的新项目的目录中并使用""(引号)而不是<>。这就是载入一个DLL的简单方法。

显示链接

难点的加载DLL的方法是有稍微有点复杂的。你将需要函数指针和一些Windows函数。但是,通过这种载入DLLs的方法,你不需要DLL的.lib或头文件,而只需要DLL。下面列出一些代码,我稍后将解析之。

#include <iostream>
#include <windows.h>

typedef int (*AddFunc)(int,int);
typedef void (*FunctionFunc)();

int main()
{
AddFunc _AddFunc;
FunctionFunc _FunctionFunc;
HINSTANCE hInstLibrary = LoadLibrary("DLL_Tutorial.dll"); if (hInstLibrary == NULL)
{
FreeLibrary(hInstLibrary);
}

_AddFunc = (AddFunc)GetProcAddress(hInstLibrary, "Add");
_FunctionFunc = (FunctionFunc)GetProcAddress(hInstLibrary, "Function"); if ((_AddFunc == NULL) || (_FunctionFunc == NULL))
{
FreeLibrary(hInstLibrary);
} std::cout << _AddFunc(23, 43) << std::endl;
_FunctionFunc(); std::cin.get(); FreeLibrary(hInstLibrary); return(1);
}

首先你会注意到:这里包括进了文件“windows.h”同时移走了“DLL_Tutorial.h”。原因很简单:因为windows.h包含了一些Windows函数,当然你现在将只需要其中几个而已。它也包含了一些将会用到的Windows特定变量。你可以去掉DLL的头文件(DLL_Tutorial.h)因为-如我前面所说-当你使用这个方法载入DLL时你并不需要它。

下面你会看到:以下面形式的一小块古灵精怪的代码:

typedef int (*AddFunc)(int,int);
typedef void (*FunctionFunc)();

这是函数指针。因为这是一个关于DLL的自学指南,深入探究函数指针超出了本指南的范围;因此,现在我们只把它们当作DLL包含的函数的别名。我喜欢在尾部用“Func”命名之。(int,int)部分是这个函数的参数部分,比如,Add函数要获得两个整数;因此,你需要它们(译注:指(int,int)部分)作为函数指针的参数。Function函数没有参数,因此你让它为空。main()部分中的前面两行是声明函数指针以使得你可以认为它们等同于DLL内部的函数。我只是喜欢预先定义它们。

一个HINSTANCE是一个Windows数据类型:是一个实例的句柄;在此情况下,这个实例将是这个DLL。你可以通过使用函数LoadLibrary()获得DLL的实例,它获得一个名称作为参数。在调用LoadLibrary函数后,你必需查看一下函数返回是否成功。你可以通过检查HINSTANCE是否等于NULL(在Windows.h中定义为0或Windows.h包含的一个头文件)来查看其是否成功。如果其等于NULL,该句柄将是无效的,并且你必需释放这个库。换句话说,你必需释放DLL获得的内存。如果函数返回成功,你的HINSTANCE就包含了指向DLL的句柄。

一旦你获得了指向DLL的句柄,你现在可以从DLL中重新获得函数。为了这样作,你必须使用函数GetProcAddress(),它将DLL的句柄(你可以使用HINSTANCE)和函数的名称作为参数。你可以让函数指针获得由GetProcAddress()返回的值,同时你必需将GetProcAddress()转换为那个函数定义的函数指针。举个例子,对于Add()函数,你必需将GetProcAddress()转换为AddFunc;这就是它知道参数及返回值的原因。现在,最好先确定函数指针是否等于NULL以及它们拥有DLL的函数。这只是一个简单的if语句;如果其中一个等于NULL,你必需如前所述释放库。

一旦函数指针拥有DLL的函数,你现在就可以使用它们了,但是这里有一个需要注意的地方:你不能使用函数的实际名称;你必需使用函数指针来调用它们。在那以后,所有你需要做的是释放库如此而已。

现在你知道了DLL的一些基本知识。你知道如何创建它们,你也知道如何用两种不同的方法链接它们。这里仍然有更多的东西需要我们学习,但我把它们留给你们自己探索了和更棒的作者来写了。

posted @ 2010-12-28 13:47 wrh 阅读(402) | 评论 (0)编辑 收藏
显式(静态)调用:
LIB   +   DLL   +   .H,注意.H中dllexport改为dllimport

隐式(动态)调用:
DLL   +   函数原型声明,先LoadLibrary,再GetProcAddress(即找到DLL中函数的地址),不用后FreeLibrary
显式(静态)调用:
LIB   +   DLL   +   .H,注意.H中dllexport改为dllimport

隐式(动态)调用:
DLL   +   函数原型声明,先LoadLibrary,再GetProcAddress(即找到DLL中函数的地址),不用后FreeLibrary
显式(静态)调用:
LIB   +   DLL   +   .H,注意.H中dllexport改为dllimport

隐式(动态)调用:
DLL   +   函数原型声明,先LoadLibrary,再GetProcAddress(即找到DLL中函数的地址),不用后FreeLibrary
显式(静态)调用:
LIB   +   DLL   +   .H,注意.H中dllexport改为dllimport

隐式(动态)调用:
DLL   +   函数原型声明,先LoadLibrary,再GetProcAddress(即找到DLL中函数的地址),不用后FreeLibrary

调用DLL有两种方法:静态调用和动态调用.
(一).静态调用其步骤如下:
1.把你的youApp.DLL拷到你目标工程(需调用youApp.DLL的工程)的Debug目录下;
2.把你的youApp.lib拷到你目标工程(需调用youApp.DLL的工程)目录下;
3.把你的youApp.h(包含输出函数的定义)拷到你目标工程(需调用youApp.DLL的工程)目
录下;
4.打开你的目标工程选中工程,选择Visual   C++的Project主菜单的Settings菜单;
5.执行第4步后,VC将会弹出一个对话框,在对话框的多页显示控件中选择Link页。然
后在Object/library   modules输入框中输入:youApp.lib
6.选择你的目标工程Head   Files加入:youApp.h文件;
7.最后在你目标工程(*.cpp,需要调用DLL中的函数)中包含你的:#include   "youApp.h "
注:youApp是你DLL的工程名。
2.动态调用其程序如下:
动态调用时只需做静态调用步骤1.
{
HINSTANCE   hDllInst   =   LoadLibrary( "youApp.DLL ");
if(hDllInst)
{
typedef   DWORD   (WINAPI   *MYFUNC)(DWORD,DWORD);
MYFUNC   youFuntionNameAlias   =   NULL;   //   youFuntionNameAlias   函数别名
youFuntionNameAlias   =   (MYFUNC)GetProcAddress
(hDllInst, "youFuntionName ");
//   youFuntionName   在DLL中声明的函数名
if(youFuntionNameAlias)
{
youFuntionNameAlias(param1,param2);
}
FreeLibrary(hDllInst);
}
}






显式(静态)调用:
LIB   +   DLL   +   .H,注意.H中dllexport改为dllimport

隐式(动态)调用:
DLL   +   函数原型声明,先LoadLibrary,再GetProcAddress(即找到DLL中函数的地址),不用后FreeLibrary



调用DLL,首先需要将DLL文件映像到用户进程的地址空间中,然后才能进行函数调用,这个函数和进程内部一般函数的调用方法相同。Windows提供了两种将DLL映像到进程地址空间的方法:

1. 隐式的加载时链接
这种方法需要DLL工程经编译产生的LIB文件,此文件中包含了DLL允许应用程序调用的所有函数的列表,当链接器发现应用程序调用了LIB文件列出的某个函数,就会在应用程序的可执行文件的文件映像中加入一些信息,这些信息指出了包含这个函数的DLL文件的名字。当这个应用程序运行时,也就是它的可执行文件被操作系统产生映像文件时,系统会查看这个映像文件中关于DLL的信息,然后将这个DLL文件映像到进程的地址空间。
系统通过DLL文件的名称,试图加载这个文件到进程地址空间时,它寻找DLL 文件的路径按照先后顺序如下:
·程序运行时的目录,即可执行文件所在的目录;
·当前程序工作目录
·系统目录:对于Windows95/98来说,可以调用GetSystemDirectory函数来得到,对于WindowsNT/2000来说,指的是32位Windows的系统目录,也可以调用GetSystemDirectory函数来得到,得到的值为SYSTEM32。
·Windows目录
·列在PATH环境变量中的所有目录
VC中加载DLL的LIB文件的方法有以下三种:
①LIB文件直接加入到工程文件列表中
在VC中打开File View一页,选中工程名,单击鼠标右键,然后选中“Add Files to Project”菜单,在弹出的文件对话框中选中要加入DLL的LIB文件即可。
②设置工程的 Project Settings来加载DLL的LIB文件
打开工程的 Project Settings菜单,选中Link,然后在Object/library modules下的文本框中输入DLL的LIB文件。
③通过程序代码的方式
加入预编译指令#pragma comment (lib,”*.lib”),这种方法优点是可以利用条件预编译指令链接不同版本的LIB文件。因为,在Debug方式下,产生的LIB文件是Debug版本,如Regd.lib;在Release方式下,产生的LIB文件是Release版本,如Regr.lib。
当应用程序对DLL的LIB文件加载后,还需要把DLL对应的头文件(*.h)包含到其中,在这个头文件中给出了DLL中定义的函数原型,然后声明。
2 显式的运行时链接  ,(我用的是此方法)
隐式链接虽然实现较简单,但除了必须的*.dll文件外还需要DLL的*.h文件和*.lib文件,在那些只提供*.dll文件的场合就无法使用,而只能采用显式链接的方式。这种方式通过调用API函数来完成对DLL的加载与卸载,其能更加有效地使用内存,在编写大型应用程序时往往采用此方式。这种方法编程具体实现步骤如下:
①使用Windows API函数Load Library或者MFC提供的AfxLoadLibrary将DLL模块映像到进程的内存空间,对DLL模块进行动态加载。
②使用GetProcAddress函数得到要调用DLL中的函数的指针。
③不用DLL时,用Free Library函数或者AfxFreeLibrary函数从进程的地址空间显式卸载DLL。
例:在应用程序中调用dll文件

——在应用程序中要首先装入dll后才能调用导出表中的函数,例如用mfc

创建基于对话框的工程test,并在对话框上放置"load"按钮,先添加装载代码。
1.首先在testdlg.cpp的首部添加变量设置代码:

//设置全局变量glibsample用于存储dll句柄

HINSTANCE  glibsample=null;   //如果定义成HANDLE类型,则出错

//第二个变量showme是指向dll
库中showme()函数的指针

typedef int(* Showme)(void);

Showme showme;

2.利用classwizard为"load"按钮添加装载dll的代码

void ctestdlg::onloadbutton()

{

//要添加的代码如下

if(glibsample!=NULL)

{

AfxMessageBox("the sample.dll has already been load.");

return;

}

//装载sample.dll,未加路径,将在三个默认路径中寻找 (1)windows的系统目录:\windows\system;

//(2)dos中path所指出的任何目录;

//(3)程序所在的目录;


glibsample=Loadlibrary("sample.dll");

//返回dll中showme()函数的地址

showme=(Showme)GetProcAddress(glibsample,"showme");

posted @ 2010-12-27 13:15 wrh 阅读(3553) | 评论 (0)编辑 收藏
可利用SDK   API:GetAdaptersInfo以及GetIfEntry实现。  
        GetAdaptersInfo返回系统中的所有网卡信息。  
        GetIfEntry则返回制定网口的速率、状态等信息。  
        如果觉得将相关数据结构改造到VB下很痛苦的话,可编写一个短小的DLL完成网口检测工作,并仅返回检测结果即可。  
        VC代码:  
        DWORD   dwOutBufLen=0;  
         
          PIP_ADAPTER_INFO   pAdapterInfo=NULL,pAdapter=NULL;  
         
          MIB_IFROW   zSNMP;  
         
          char   sTemp[20];  
         
          int   iReturn;          
         
          iReturn=GetAdaptersInfo(pAdapterInfo,&dwOutBufLen);  
         
          if(iReturn!=ERROR_BUFFER_OVERFLOW)  
         
          {  
         
          return   0;  
         
          }  
                   
          pAdapterInfo   =(PIP_ADAPTER_INFO)   HeapAlloc(GetProcessHeap(),   0,   dwOutBufLen);  
         
          iReturn=GetAdaptersInfo(pAdapterInfo,&dwOutBufLen);  
         
          if(iReturn!=ERROR_SUCCESS)  
         
          {  
         
          HeapFree(GetProcessHeap(),   0,   pAdapterInfo);  
         
          return   0;  
         
          }  
         
          pAdapter=pAdapterInfo;  
         
         
         
          //find   if   there   is   ppp   adapter  
         
          while(pAdapter!=NULL   )  
         
          {  
         
          zSNMP.dwIndex   =   pAdapter-> Index;  
         
          iReturn=GetIfEntry(&zSNMP);  
         
          if(iReturn!=NO_ERROR)  
         
          return   0;  
         
         
         
          m_iIfSpeed=zSNMP.dwSpeed/(1000*1000);  
         
          m_iIfAdminStatus=zSNMP.dwAdminStatus;  
         
          m_iIfOperStatus=zSNMP.dwOperStatus;  
         
          …  
         
          pAdapter=pAdapter-> Next;  
         
          }
posted @ 2010-12-17 11:26 wrh 阅读(942) | 评论 (0)编辑 收藏
#include <windows.h>
#include <stdio.h>
#include <iostream.h>
#include "vfw.h"
#pragma comment( lib, "vfw32.lib" )

void main()
{
  
    char strDeviceVersion[80];    //设备版本信息
    char strDeviceAndVersion[160];  //设备名和版本信息
    int nIndex;
    int nDriverCount = 0;                //支持的设备驱动程序个数
  
  
    for(nIndex=0; nIndex <9; nIndex++)
    {
        if(capGetDriverDescription(nIndex,(LPSTR)strDeviceAndVersion,sizeof(strDeviceAndVersion),(LPSTR)strDeviceVersion,sizeof(strDeviceVersion)))
        {
            strcat(strDeviceAndVersion,",");
            strcat(strDeviceAndVersion,strDeviceVersion);
            nDriverCount++;                  //得到vfw设备信息及连的设备数量
        }
        else
            break;
    }
    if (nDriverCount==0)
        cout <<"没有摄像头"<<endl;
    else
        cout <<"有摄像头"<<endl;
}
posted @ 2010-12-17 11:20 wrh 阅读(1056) | 评论 (0)编辑 收藏

经常看见网上有人问如何得到网线连上与拔出的状态,在这里介绍几种方法,也许对大家会有所帮助

第一种是通过OID进行查询的方法

 DWORD dwObj, dwStatus, dwBytesRet;
 dwOIDCode = OID_GEN_MEDIA_CONNECT_STATUS;
 DeviceIoControl(hAdapter, IOCTL_NDIS_QUERY_GLOBAL_STATS, &dwOIDCode, sizeof(dwOIDCode), &dwStatus,sizeof(dwStatus), &dwBytesRet, NULL); 
 printf("state is:%d\n",dwStatus);

dwStatus=0表示连上了,1代表未连上

但是经过我的测试,好像这里的状态并不是代表网线的,而是代表网络可用与不可用,网线插上,网络正在连接,这种状态下的网络是不可用的

第二种是通过WMI进行查询,WMI的功能很强大的

 while (pEnumerator)
 {
  HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, 
   &pclsObj, &uReturn);

  if(0 == uReturn)
  {
   break;
  }
  VARIANT vtProp;
  hr = pclsObj->Get(L"NdisMediaConnectStatus", 0, &vtProp, 0, 0);
  if (vtProp.bstrVal)
  {
   NdisMediaConnectStatus++;
  }
  VariantClear(&vtProp);
 }

经过测试,这种方法可以得到网线的状态,如果要实时得到网线的连接状态的话,可以开线程,当然资源充足的话也可以1秒查询一次,但是这种方法在有多个网线的时候是不行的

posted @ 2010-12-16 09:42 wrh 阅读(2091) | 评论 (0)编辑 收藏
仅列出标题
共25页: 1 2 3 4 5 6 7 8 9 Last 

导航

<2024年4月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

统计

常用链接

留言簿(19)

随笔档案

文章档案

收藏夹

搜索

最新评论

阅读排行榜

评论排行榜