为MSSQL添加扩展存储过程--地宝原创,转贴请注明出自微软BI开拓者www.windbi.com MSSQL
中的sysprocesses
中的hostname
可以获取连接客户端的机器名,net_address
可以获取连接的客户端的网卡(或者ARP
代理)Mac
地址,虽说可以通过Pinghostname
的方法来获取IP
地址,也可以通过建立好的局域网Mac
地址表来反查到IP
地址,但我们是否能够通过任意一个局域网IP
地址来查询到hostname
与mac
地址呢?MSSQL
看来很难做到这一点。是否能通过曲线救国的方式来实现呢?这是能够做到的,那就是使用vc
中的Extended Stored Proc Wizard
来创建一个扩展存储过程(好像回到了过去,用vb
调用vc
的dll ^_^
)。具体创建方法如下:打开vc
选择File->New
,在对话框中选择Projects
,在项目列表中选择Extended Stored Proc Wizard
,输入Project Name
后,点击finish
,VC
++就会自动的为你创建出一个模版。仔细看看模版是不是很简单呀!实际上写 Extended Proc
很简单,主要就是就是这么几个函数:1)srv_sendmsg
用来显示sql
执行后的消息2)srv_describe
用来设置描述行3)srv_setcoldata srv_setcollen
用来显示数据行4)srv_sendrow
将生产的数据行发送出去5)srv_senddone
显示执行sql
后所返回的数据行数在若扩展存储涉及参数输入问题,则需注意这么几个函数1)srv_rpcparams
返回输入参数中的个数2)srv_paraminfo
获取输入参数的类型,如参数的长度,参数的数据类型等3)srv_paramdata
获取输入参数的数值介绍完这些,我们就开始完成这个扩展存储过程了。以下是详细代码:/*
根据指定的IP
地址返回网卡的Mac
地址*/
#include <stdafx.h>
#include "stdio.h"
#include "stdlib.h"
#include "Winsock2.h"
#include "iphlpapi.h"
#pragma comment ( lib, "ws2_32.lib" )
#pragma comment ( lib, "Iphlpapi.lib" )
#define XP_NOERROR 0
#define XP_ERROR 1
#define MAXCOLNAME25
#define MAXNAME255
#define MAXTEXT255
#ifdef __cplusplus
extern "C" {
#endif
RETCODE __declspec(dllexport) xp_proc5(SRV_PROC *srvproc);
#ifdef __cplusplus
}
#endif
RETCODE __declspec(dllexport) xp_proc5(SRV_PROC *srvproc)
{
DBSMALLINT i = 0;
DBCHAR colname[MAXCOLNAME];
DBCHAR spText[MAXTEXT];
DBCHAR spIP[MAXTEXT];
DBCHAR spHostName[MAXTEXT];
DBCHAR spMac[18];
DBCHAR szFileName[MAX_PATH+1];
struct hostent *remoteHostent;
int numberOfHost = 1;
int nArgs = srv_rpcparams(srvproc);//
检测参数个数if (nArgs=1)
{
//
初始化SOCKET
WSADATA wsaData;
int iRet =WSAStartup(MAKEWORD(2,1), &wsaData);
if ( iRet != 0 )
exit( 0 );
}
BYTE bType;
unsigned long cbMaxLen;
unsigned long cbActualLen;
BOOL fNull;
intret=srv_paraminfo(srvproc,1,&bType,&cbMaxLen,&cbActualLen,NULL,&fNull);
if (cbActualLen){
ZeroMemory(szFileName, MAX_PATH+1);
memcpy(szFileName, srv_paramdata(srvproc,1), cbActualLen);
}
else{
return XP_ERROR;
}
int nRemoteAddr=inet_addr((constchar*)szFileName);
_snprintf(spText, MAXTEXT, "%s
示例扩展存储过程", szFileName);
srv_sendmsg(
srvproc,
SRV_MSG_INFO,
0,
(DBTINYINT)0,
(DBTINYINT)0,
NULL,
0,
0,
spText,
SRV_NULLTERM);
remoteHostent= (structhostent*)malloc( sizeof(struct hostent ));
struct in_addr sa;
for ( int i = 0; i < numberOfHost;i ++ )
{
//
获取远程机器名sa.s_addr = nRemoteAddr;
_snprintf(spIP,MAXTEXT,"%s\0",inet_ntoa( sa ) );//
输出IP
地址remoteHostent = gethostbyaddr((char*)&nRemoteAddr,4, AF_INET );
if ( remoteHostent )
_snprintf(spHostName,MAXTEXT,"%s\0",remoteHostent->h_name);
else
_snprintf(spHostName,5,"null");
//
发送ARP
查询包获得远程MAC
地址unsigned char macAddress[6];
ULONG macAddLen = 6;
iRet=SendARP(nRemoteAddr,(unsigned long)NULL,(PULONG)&macAddress, &macAddLen);
if ( iRet == NO_ERROR )
{
sprintf(spMac,"%02X-%02X-%02X-%02X-%02X-%02X",
macAddress[0],macAddress[1],macAddress[2],macAddress[3],macAddress[4],macAddress[5]);
}
else
sprintf(spMac,"null");
nRemoteAddr = htonl( ntohl(nRemoteAddr ) + 1 );
}
}
//
设置列名称 _snprintf(colname, MAXCOLNAME, "IP");
srv_describe(srvproc, 1, colname, SRV_NULLTERM, SRVCHAR, MAXTEXT,SRVCHAR, 0, NULL);
_snprintf(colname, MAXCOLNAME, "HOSTNAME");
srv_describe(srvproc, 2, colname, SRV_NULLTERM, SRVCHAR, MAXNAME,SRVCHAR, 0, NULL);
_snprintf(colname, MAXTEXT, "MAC");
srv_describe(srvproc, 3, colname, SRV_NULLTERM, SRVCHAR, MAXTEXT,SRVCHAR, 0, NULL);
//
读进数据srv_setcoldata(srvproc, 1, spIP);
srv_setcollen(srvproc, 1, static_cast<int>(strlen(spIP)));
srv_setcoldata(srvproc, 2,spHostName);
srv_setcollen(srvproc, 2,static_cast<int>(strlen(spHostName)));
srv_setcoldata(srvproc, 3, spMac);
srv_setcollen(srvproc, 3, static_cast<int>(strlen(spMac)));
//
发送整行 srv_sendrow(srvproc);
//
现在返回已处理的行数srv_senddone(srvproc,SRV_DONE_MORE | SRV_DONE_COUNT, (DBUSMALLINT)0, (DBINT)i);
return XP_NOERROR ;
}
=============================当我们编译完后,怎样添加到mssql
中呢?使用sp_addextendedproc
sp_addextendedproc 'xp_proc5','dllpath'
调用方法:xp_proc5 '10.50.80.22' --10.50.80.22
为输入参数返回效果:IP HOSTNAME MAC
--------------------------------------------------------
10.50.80.22 sunshine 00-80-C8-EE-11-03
卸载的方法:sp_dropextendedproc 'xp_proc5'
当扩展存储在SQLServer
中执行时,它要装入内存,会一直驻留在内存中,直到SQL Server
关闭,或者你用DBCC xp_proc5(Free)
来释放。==============================最后,想获取更多的有关编写扩展存储的信息,你可以到msdn
中查询 “extendedstored procedures”
。