铁匠

做人要低调
随笔 - 125, 评论 - 250 , 引用 - 184

导航

公告

文章分类

存档

随笔分类

相册

BLOG

网站

论坛

2008年9月16日

IE8和Google Chrome的对比

上上周装了Google Chrome后,很快就删了,头脑一发热就又去把IE7给升级成IE8了。看了一下IE8好像除了界面的颜色更柔合了一点,没有啥大的变化。但是经过几个小时的试用后,我发现IE8很好很强大,偶还常向同事推荐它。

现在说说偶觉IE8的亮点吧:

1.有强大的开发者工具,第一次看到开发者工具是在FF上面看到的,不过这些工具和IE8带的比起来,简直就像是小孩的玩具了。

里面有颜色拾取器和标尺,想想以前作网页的时候,要抄别人的页面经常得抓下图来,在PS里面取颜色和取尺寸,现在这些内置工具解决了这个问题。

开发者工具里面还带了JS的调试器,而且启用简单,容易使用,而且功能强大,无论是单独的JS文件也好,还是内嵌在网页里的JS块也好,一切都可以调试。

DOM查看器也是我所希望的那样子,虽然FF里面也有DOM查看器,不过它的显示模式让人感觉使用不方便,特别是DOM很深的时候,FF里面简直就没有办法用了。它的CSS栏里面,可以轻松地看到哪些CSS 是有效的,哪些是无效的。

2.已经开始面向W3C的标准了。这个偶也说不上它是一个进步还是一个倒退。不过作为易用性来说,IE8作的还是很不错的,因为它提供了兼容模式,一步操作就可以实现IE7和IE8模式的切换。这个我相信会让用户很方便的。对于用户来说,网页的标准是次要的,最重要的是他手上的浏览器能无误地打开他所需要的网站,并进行他所需要的操作。

差点跑题了:)

现在比比这两个浏览器了:

1.易用性:我觉得IE8要得高分,因为它能很好地兼容不同的网站,而Chrome却只能无误地打开有限的网站,而且错了也不报,让用户无所适从。

2.性能:不用怀疑,IE8确实要吃更多的内存,速度上来说,我并没有觉得太大的差别。

3.稳定性:我觉得IE8要更胜一筹,用了一两个星期了,以前打开一些老容易把浏览器卡死的网站,现在不会出现这种性况了。

再说说Chrome所说的一些新特性,其实在IE8里面早就是这样去实现的了:比如说每个TAB页单独的进程,隐私模式等等。基本上Chrome所说的亮点,在IE8里面早就存在了。

posted @ 21:49 | Feedback (0)

2008年9月3日

Google Chrome(谷歌浏览器)试用感受

打开下载链接,发现只有四百多K ,心中在想是不是又一个基于IE内核的浏览器,不过,很快推翻了我的想法,因为旁边有一个完整版的下载,那个400K只是一个浏览器的下载器,最讨厌这种发布方式,让人白开心了一把,如果上网不方便的,下载回去装,结果发现还得接着下,那叫一个郁闷。

安装过程太傻瓜了,一点选择权都没有,不是很爽,偶的C盘没有空间了,这样装,只好玩完以后就删了。

用的时候,发现速度还可以,不过有时候CPU的使用还是比IE高,多TAB页关掉的时候,没有释放内存,这个和IE是一样的。发现里面有一个任务管理器,可以看到每个页面占用的CPU,内存等。

继续用下去,发现问题来了,兼容性是一个大问题,IE和FF都能正常跑的页面,它跑不下去了,而且没有错误控制台,也不知道是哪个JS 出的错,再试一下百度的地图,结果发现用不了。再用google的地图发现可以用,难道被屏蔽了?

最终的结论是:我一会儿就会把它删掉,再没有更好的更新前,我不会使用它。

posted @ 10:22 | Feedback (2)

2008年8月30日

编程实现SqlServer扩展存储过程并实现Image类型参数的输入和结果的返回

SQLServer有一项即将要过时的功能,那就是扩展存储过程(在MSDN上查询该方面的资料的时候,上面都有一个提示说是这个功能将会在以后的SQL版本中删除,建议使用CLR集成)。虽然要过时了,但是看着现在有不少的DB还在用SQL2000说明这个功能至少还有几年有效期。对了,忘了说了扩展存储过程是干啥用的,懒得查最官方的说法了,用我的语言来说,那就是使用自己的开发语言,来实现一些数据库没有实现的功能,比如说我想在数据库里面直接作MD5的加密和解密,这个功能SQL Server本来不具有的,但是可以自己写一个扩展存储过程来实现。

开发扩展存储过程的开发语言还是有些要求的,就是要能实现导出函数的,如C(VC,BCB,其它的C),Delphi等,C#由于无法实现导出函数,所以就不能开发了,不过他可以开发CLR集成。由于我只会Delphi,所以我就用它来作例子。

扩展存储过程的hellowolrd(铁匠出品)

如果仅仅写一个hello wolrd,Delphi是不需要任何东西就可以实现,那就是:新建一个DLL的工程,在里面写个如下函数:

function xp_helloWorld: Boolean; stdcall;
begin
//在这里面可以写一个文件好看到效果,具体的代码我就不写了
end;

然后把它放在导出函数里面:

exports
xp_helloWorld;

再在SQLSERVER里去注册,注意注册扩展存储过程只能在Master库里实现,还要求操作者有一定的权限,SQL如下:

if exists
     (select * from master.dbo.sysobjects where id = object_id('xp_helloWorld'))
     execute sp_dropextendedproc 'xp_helloWorld'
go
--我编写的dll在'D:\PersonWork\SQLExtProcedure\目录下面,修改成你的编写的目录
execute sp_addextendedproc 'xp_helloWorld', 'D:\PersonWork\SQLExtProcedure\sqlExtProcedure.dll'
go

然后在写SQL exec Master.dbo.xp_helloWorld就能看到效果了。

实用的扩展存储过程(铁匠出品)

但是我们开发东西不是一个helloworld就能够用的,所以我们就得引入新的东西:MsOdsApi,这个是一个我们的代码去调用sql现有功能的入口,因为Sqlserver的SDK并没有给Delphi作个版本,所以我们只好自己辛苦一下来转换他们的头文件,不过还好网上的很多前辈们已经帮我们完成了这个工作,在本文的结束时会附上该文件。我觉得会最常用的几个函数如下(具体的参数可以看定义,上面应该写得比较清楚了):

srv_rpcparams:获取参数的个数

srv_paraminfo:获取指定参数的信息,数据的长度,类型,数据等

srv_paramdata:获取image一类的值的指针

srv_describe:创造返回值的描述

srv_setcoldata:给返回的字段赋值

srv_sendrow:返回一行数据

srv_senddone:表示返回已经完成了。

于是我们开始构建新的扩展存储过程:

function xp_Test(pSrvProc: SRV_PROC): Boolean; stdcall;//这个传时来的参数pSrvProc就是相当于是和sqlserver交互的上下文的指针了
var
  PType : Byte;
  cbMaxLen , ParaLen : DWORD;
  IsNULL : BOOL;

  fs: TFileStream;
  p: Pointer;
  n: integer;
begin
  n := srv_rpcparams(pSrvProc);//先取一下有几个参数
  srv_paraminfo(pSrvProc, 1, @PType, @cbMaxLen, @ParaLen,  nil, @IsNULL);//取第一个参数的定义,注意参数的下标是从1开始的,而不是习惯上的0
  p := srv_paramdata(pSrvProc, 1);//由于我们要取image类型的,所以得用这个取数据的指针,否则就用下面这个,注意在这之前,p要先开好内存
  //srv_paraminfo(pSrvProc, 1, @PType, @cbMaxLen, @ParaLen,  @p, @IsNULL);
  fs := TFileStream.Create('d:\test.jpg', fmCreate);//由于无法debug只好能过文件把一些中间变量写到文件里,再用winhex来看了
  try
    fs.Write(n, SizeOf(Integer));
    fs.Write(cbMaxLen, SizeOf(DWORD));
    fs.Write(ParaLen, SizeOf(DWORD));
    fs.Write(p^, ParaLen)
  finally
    FreeAndNil(fs);
  end;

//下面开始返回一行数据
  n := ParaLen;
  srv_describe(pSrvProc, 1 ,  'Data', SRV_NULLTERM,  SRV_TDS_IMAGE,
                n, SRVBIGVARCHAR, n,  NIL);
    srv_setcoldata(pSrvProc, 1 , p);
    srv_sendrow(pSrvProc);
    srv_senddone(pSrvProc, (SRV_DONE_COUNT or SRV_DONE_MORE), 0, 1);
end;

还是按hellowolrd的方法把它注册到SQLServer里面去。不过由于Image类型的字段不能在存储过程里设置临时变量,所以我们还有再麻烦一下:

Create PROCEDURE [dbo].[UXP_Test]
@in1 Image
AS
BEGIN
Insert into Test1(Data)
    exec Master.dbo.xp_Test @in1
END
GO

这样来把我们处理过后的Image类型的字段插入到DB里面去。

最后来看看那个Test.jpg的内容:

image

Offset      0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F

00000000   01 00 00 00 10 00 00 00  72 03 00 00 47 49 46 38   ........r...GIF8
00000010   39 61 A0 00 58 00 A2 00  00 63 9C 9C FF 63 00 00   9a?X.?.c湝c..
00000020   9C 00 00 63 FF CE 31 31  FE 01 02 00 00 00 00 00   ?.c?1?......
00000030   00 21 FF 0B 4E 45 54 53  43 41 50 45 32 2E 30 03   .!.NETSCAPE2.0.

点它一下看大图,就可以看到前四位是1,也就是传入了1个参数,接下来4位值是16(从这里也可以看出来那些image类型 的定义果真是16位这么长),再接下来4位这才是数据的真正长度,我是插入了一个GIF动画,所以它的长度和文件的长度是一样的:882,再后面就是文件的开始了GIF89a一个标准的GIF文件头

看看这些数据插入到DB里是不是正确的呢?来看下图:

image 

0x开头,说明它是以16进制数显示的,看开头的几位:474946383961和上面的16进制数对比一下可以看到,这里面的数据是正确的,也就是说我们的Image传入处理后,再返回来这一切都是成功的。

最后贴一下:MsOdsApi.pas(从下一行开始复制)

unit MsOdsApi;

//------------------------------------------------------------
// Open Data Services header file: srv.h
// Copyright (c) 1989, 1990, 1991, 1997 by Microsoft Corp.
//

// Avoid double inclusion
//#ifndef _ODS_SRV_H_
//  _ODS_SRV_H_

//#include "windows.h"

// ODS uses pack(4) on all CPU types
//#pragma pack(4)

//#ifdef __cplusplus
//extern "C" {
//#endif

// define model
//#if !defined( FAR )
//  FAR far
//#endif

//------------------------------------------------------------
// Formats of data types
//#if !defined(DBTYPEDEFS) // Do not conflict with DBLIB definitions
//#if !defined(MAXNUMERICLEN) // Do not conflict with ODBC definitions

//  DBTYPEDEFS

interface

uses
  Windows;

type
  DBBOOL      = Byte;
  DBBYTE      = Byte;
  DBTINYINT   = Byte;
  DBSMALLINT  = Smallint;
  DBUSMALLINT = Word;
  DBINT       = Longint;
  DBCHAR      = Char;
  PDBCHAR     = ^DBCHAR;
  DBBINARY    = Byte;
  DBBIT       = Byte;
  DBFLT8      = Double;

  srv_datetime = record
    // Format for SRVDATETIME
    dtdays: Longint;  // number of days since 1/1/1900
    dttime: Longword; // number 300th second since mid
  end;
  DBDATETIME = srv_datetime;

  srv_dbdatetime4 = record
    // Format for SRVDATETIM4
    numdays: Word; // number of days since 1/1/1900
    nummins: Word; // number of minutes sicne midnight
  end;
  DBDATETIM4 = srv_dbdatetime4;

  srv_money = record
    // Format for SRVMONEY
    mnyhigh: Longint;
    mnylow : Longword;
  end;
  DBMONEY = srv_money;

  DBFLT4   = Double;
  DBMONEY4 = Longint;

const
  MAXNUMERICDIG     = 38;
  DEFAULTPRECISION  = 19; // 18
  DEFAULTSCALE      = 0;
  MAXNUMERICLEN       = 16;

type
  srv_dbnumeric = packed record
    // Format for SRVNUMERIC,SRVNUMERICN,SRVDECIMAL,SRVDECIMALN
    precision: Byte;
    scale    : Byte;
    sign     : Byte;                               // 1 = Positive, 0 = Negative
    val      : array [0..MAXNUMERICLEN-1] of Byte; // Padded little-endian value
  end;
  DBNUMERIC = srv_dbnumeric;
  DBDECIMAL = DBNUMERIC;

//#endif  // #if !defined(MAXNUMERICLEN)
//#endif  // #if !defined( DBTYPEDEFS )

//------------------------------------------------------------
// Constants used by APIs

// Type Tokens
const
  SRV_TDS_NULL           = $1f;
  SRV_TDS_TEXT           = $23;
  SRV_TDS_GUID           = $24;
  SRV_TDS_VARBINARY      = $25;
  SRV_TDS_INTN           = $26;
  SRV_TDS_VARCHAR        = $27;
  SRV_TDS_BINARY         = $2d;
  SRV_TDS_IMAGE          = $22;
  SRV_TDS_CHAR           = $2f;
  SRV_TDS_INT1           = $30;
  SRV_TDS_BIT            = $32;
  SRV_TDS_INT2           = $34;
  SRV_TDS_DECIMAL        = $37;
  SRV_TDS_INT4           = $38;
  SRV_TDS_DATETIM4       = $3a;
  SRV_TDS_FLT4           = $3b;
  SRV_TDS_MONEY          = $3c;
  SRV_TDS_DATETIME       = $3d;
  SRV_TDS_FLT8           = $3e;
  SRV_TDS_NUMERIC        = $3f;
  SRV_TDS_NTEXT            = $63;
  SRV_TDS_BITN            = $68;
  SRV_TDS_DECIMALN       = $6a;
  SRV_TDS_NUMERICN       = $6c;
  SRV_TDS_FLTN           = $6d;
  SRV_TDS_MONEYN         = $6e;
  SRV_TDS_DATETIMN       = $6f;
  SRV_TDS_MONEY4         = $7a;
  SRV_TDS_INT8           = $7f;  // SQL 2000 and later
  SRV_TDS_BIGVARBINARY   = $A5;
  SRV_TDS_BIGVARCHAR     = $A7;
  SRV_TDS_BIGBINARY      = $AD;
  SRV_TDS_BIGCHAR        = $AF;
  SRV_TDS_NVARCHAR       = $e7;
  SRV_TDS_NCHAR            = $ef;

// Datatypes
// Also: values of symbol parameter to srv_symbol when type = SRV_DATATYPE
  SRVNULL        = SRV_TDS_NULL;
  SRVTEXT        = SRV_TDS_TEXT;
  SRVGUID        = SRV_TDS_GUID;
  SRVVARBINARY   = SRV_TDS_VARBINARY;
  SRVINTN        = SRV_TDS_INTN;
  SRVVARCHAR     = SRV_TDS_VARCHAR;
  SRVBINARY      = SRV_TDS_BINARY;
  SRVIMAGE       = SRV_TDS_IMAGE;
  SRVCHAR        = SRV_TDS_CHAR;
  SRVINT1        = SRV_TDS_INT1;
  SRVBIT         = SRV_TDS_BIT;
  SRVINT2        = SRV_TDS_INT2;
  SRVDECIMAL     = SRV_TDS_DECIMAL;
  SRVINT4        = SRV_TDS_INT4;
  SRVDATETIM4    = SRV_TDS_DATETIM4;
  SRVFLT4        = SRV_TDS_FLT4;
  SRVMONEY       = SRV_TDS_MONEY;
  SRVDATETIME    = SRV_TDS_DATETIME;
  SRVFLT8        = SRV_TDS_FLT8;
  SRVNUMERIC    = SRV_TDS_NUMERIC;
  SRVNTEXT    = SRV_TDS_NTEXT;
  SRVBITN    = SRV_TDS_BITN;
  SRVDECIMALN    = SRV_TDS_DECIMALN;
  SRVNUMERICN    = SRV_TDS_NUMERICN;
  SRVFLTN        = SRV_TDS_FLTN;
  SRVMONEYN      = SRV_TDS_MONEYN;
  SRVDATETIMN    = SRV_TDS_DATETIMN;
  SRVMONEY4      = SRV_TDS_MONEY4;
  SRVINT8        = SRV_TDS_INT8;        // SQL 2000 and later
  SRVBIGVARBINARY = SRV_TDS_BIGVARBINARY;
  SRVBIGVARCHAR  = SRV_TDS_BIGVARCHAR;
  SRVBIGBINARY   = SRV_TDS_BIGBINARY;
  SRVBIGCHAR     = SRV_TDS_BIGCHAR;
  SRVNVARCHAR    = SRV_TDS_NVARCHAR;
  SRVNCHAR    = SRV_TDS_NCHAR;

// values for srv_symbol type parameter
SRV_ERROR     = 0;
SRV_DONE      = 1;
SRV_DATATYPE  = 2;
SRV_EVENT     = 4;

// values for srv_symbol symbol parameter, when type = SRV_ERROR
  SRV_ENO_OS_ERR    = 0;
  SRV_INFO          = 1;
  SRV_FATAL_PROCESS = 10;
  SRV_FATAL_SERVER  = 19;

// Types of server events
// Also: values for srv_symbol symbol parameter, when type = SRV_EVENT
  SRV_CONTINUE      = 0;
  SRV_LANGUAGE      = 1;
  SRV_CONNECT       = 2;
  SRV_RPC           = 3;
  SRV_RESTART       = 4;
  SRV_DISCONNECT    = 5;
  SRV_ATTENTION     = 6;
  SRV_SLEEP         = 7;
  SRV_START         = 8;
  SRV_STOP          = 9;
  SRV_EXIT          = 10;
  SRV_CANCEL        = 11;
  SRV_SETUP         = 12;
  SRV_CLOSE         = 13;
  SRV_PRACK         = 14;
  SRV_PRERROR       = 15;
  SRV_ATTENTION_ACK = 16;
  SRV_CONNECT_V7    = 16; // TDS type for TDS 7 clients.  Overloaded with SRV_ATTENTION_ACK
  SRV_SKIP       = 17;
  SRV_TRANSMGR       = 18;
  SRV_OLEDB       = 20;
  SRV_INTERNAL_HANDLER    = 99;
  SRV_PROGRAMMER_DEFINED  = 100;

// values for srv_config option parameter
  SRV_CONNECTIONS        = 1;
  SRV_LOGFILE            = 2;
  SRV_STACKSIZE          = 3;
  SRV_REMOTE_ACCESS      = 7;
  SRV_REMOTE_CONNECTIONS = 9;
  SRV_MAX_PACKETS        = 10;
  SRV_MAXWORKINGTHREADS  = 11;
  SRV_MINWORKINGTHREADS  = 12;
  SRV_THREADTIMEOUT    = 13;
  SRV_MAX_PACKETSIZE    = 17;
  SRV_THREADPRIORITY    = 18;
  SRV_ANSI_CODEPAGE    = 19;
  SRV_DEFAULT_PACKETSIZE = 26;
  SRV_PASSTHROUGH    = 27;

// vlaues for srv_config value parameter when option = SRV_THREADPRIORITY
  SRV_PRIORITY_LOW      = THREAD_PRIORITY_LOWEST;
  SRV_PRIORITY_NORMAL   = THREAD_PRIORITY_NORMAL;
  SRV_PRIORITY_HIGH     = THREAD_PRIORITY_HIGHEST;
  SRV_PRIORITY_CRITICAL = THREAD_PRIORITY_TIME_CRITICAL;

// values for srv_sfield field parameter
  SRV_SERVERNAME = 0;
  SRV_VERSION    = 6;

// Length to indicate string is null terminated
  SRV_NULLTERM   = -1;

// values of msgtype parameter to srv_sendmsg
  SRV_MSG_INFO   = 1;
  SRV_MSG_ERROR  = 2;

// values of status parameter to srv_senddone
// Also: values for symbol parameters to srv_symbol when type = SRV_DONE
  SRV_DONE_FINAL     = $0000;
  SRV_DONE_MORE        = $0001;
  SRV_DONE_ERROR     = $0002;
  SRV_DONE_COUNT     = $0010;
  SRV_DONE_RPC_IN_BATCH   = $0080;

// return values of srv_paramstatus
  SRV_PARAMRETURN     = $0001;
  SRV_PARAMDEFAULT        = $0002;

// return values of srv_rpcoptions
  SRV_RECOMPILE           = $0001;
  SRV_NOMETADATA          = $0002;

// values of field parameter to srv_pfield
//  SRV_LANGUAGE 1   already defined above
//  SRV_EVENT    4   already defined above
  SRV_SPID                = 10;
  SRV_NETSPID             = 11;
  SRV_TYPE             = 12;
  SRV_STATUS             = 13;
  SRV_RMTSERVER             = 14;
  SRV_HOST             = 15;
  SRV_USER             = 16;
  SRV_PWD             = 17;
  SRV_CPID             = 18;
  SRV_APPLNAME             = 19;
  SRV_TDS             = 20;
  SRV_CLIB             = 21;
  SRV_LIBVERS             = 22;
  SRV_ROWSENT             = 23;
  SRV_BCPFLAG             = 24;
  SRV_NATLANG             = 25;
  SRV_PIPEHANDLE          = 26;
  SRV_NETWORK_MODULE          = 27;
  SRV_NETWORK_VERSION          = 28;
  SRV_NETWORK_CONNECTION       = 29;
  SRV_LSECURE             = 30;
  SRV_SAXP             = 31;
  SRV_UNICODE_USER          = 33;
  SRV_UNICODE_PWD          = 35;
  SRV_SPROC_CODEPAGE           = 36;

// return value of SRV_TDSVERSION macro
  SRV_TDS_NONE  = 0;
  SRV_TDS_2_0   = 1;
  SRV_TDS_3_4   = 2;
  SRV_TDS_4_2   = 3;
  SRV_TDS_6_0   = 4;
  SRV_TDS_7_0   = 5;

// Return values from APIs
type
SRVRETCODE = Integer;        // SUCCEED or FAIL
RETCODE    = Integer;

const
  SUCCEED = 1;   // Successful return value
  FAIL    = 0;   // Unsuccessful return value

  SRV_DUPLICATE_HANDLER   = 2;   // additional return value for srv_pre/post_handle

//------------------------------------------------
//PreDeclare structures
//
{struct srv_server;
typedef struct srv_server SRV_SERVER;

struct srv_config;
typedef struct srv_config SRV_CONFIG;

struct srv_proc;
typedef struct srv_proc SRV_PROC;}
type
  SRV_SERVER = Pointer;
  SRV_CONFIG = Pointer;
  SRV_PROC   = Pointer;

//------------------------------------------------
//------------------------------------------------
// ODS MACROs & APIs

// Describing and sending a result set
function srv_describe(srvproc: SRV_PROC;
  colnumber: Integer; column_name: PCHAR; namelen: Integer;
  desttype, destlen, srctype, srclen: Integer; srcData: Pointer
): Integer; cdecl;

function srv_setutype(srvproc: SRV_PROC; column: Integer; usertype: Longint): Integer; cdecl;
function srv_setcoldata(srvproc: SRV_PROC; column: Integer; data: Pointer): Integer; cdecl;
function srv_setcollen(srvproc: SRV_PROC; column, len: Integer): Integer; cdecl;
function srv_sendrow(srvproc: SRV_PROC): Integer; cdecl;
function srv_senddone(srvproc: SRV_PROC; status, curcmd: Word; count: Longint): Integer; cdecl;

// Dealing with Extended Procedure parameters
function srv_rpcparams(srvproc: SRV_PROC): Integer; cdecl;
function srv_paraminfo(srvproc: SRV_PROC; n: Integer; pbType: PByte;
  pcbMaxLen, pcbActualLen: PULONG; pbData: PByte; pfNull: PBOOL): Integer; cdecl;
function srv_paramsetoutput(srvproc: SRV_PROC;
  n: Integer; pbData: PByte; cbLen: ULONG; fNull: BOOL): Integer; cdecl;

function srv_paramdata(srvproc: SRV_PROC; n: Integer): Pointer; cdecl;
function srv_paramlen(srvproc: SRV_PROC; n: Integer): Integer; cdecl;
function srv_parammaxlen(srvproc: SRV_PROC; n: Integer): Integer; cdecl;
function srv_paramtype(srvproc: SRV_PROC; n: Integer): Integer; cdecl;
function srv_paramset(srvproc: SRV_PROC; n: Integer; data: Pointer; int: Integer): Integer; cdecl;

function srv_paramname(srvproc: SRV_PROC; n: Integer; var len: Integer): PChar; cdecl;
function srv_paramnumber(srvproc: SRV_PROC; name: PChar; namelen: Integer): Integer; cdecl;

//--------------------------------------------------------------
//--------------------------------------------------------------
// The rest of these APIs are still supported, in SQL Server 7.0,
// but may not be supported after SQL Server 7.0

// MACROs
{  SRV_GETCONFIG(a)      srv_getconfig     ( a )
  SRV_GETSERVER(a)      srv_getserver     ( a )
  SRV_GOT_ATTENTION(a)   srv_got_attention ( a )
SRV_EVENTDATA(a)      srv_eventdata     ( a )
SRV_IODEAD(a)         srv_iodead        ( a )
SRV_TDSVERSION(a)      srv_tdsversion     ( a )}

function srv_getconfig(server: SRV_SERVER): SRV_CONFIG; cdecl;
function srv_getserver(srvproc: SRV_PROC): SRV_SERVER; cdecl;
function srv_got_attention(srvproc: SRV_PROC): Bool; cdecl;
function srv_eventdata(srvproc: SRV_PROC): Pointer; cdecl;

// Memory
function srv_alloc(ulSize: Longint): Pointer; cdecl;
function srv_bmove(from: Pointer; pto: Pointer; count: Longint): Integer; cdecl;
function srv_bzero(location: Pointer; count: Longint): Integer; cdecl;
function srv_free(ptr: Pointer): Integer; cdecl;

function srv_config_fn(config: SRV_CONFIG; option: Longint; value: PChar; valuelen: Integer): Integer; cdecl;
function srv_config_alloc: SRV_CONFIG; cdecl;
function srv_convert(srvproc: SRV_PROC; srctype: Integer; src: Pointer; srclen: DBINT;
  desttype: Integer; dest: Pointer; destlen: DBINT): Integer; cdecl;
{
int (*  srv_errhandle(int (* handler)(SRV_SERVER * server,
     SRV_PROC   * srvproc,
     int         srverror,
     BYTE           severity,
     BYTE           state,
     int         oserrnum,
     char     * errtext,
     int         errtextlen,
     char     * oserrtext,
     int         oserrtextlen)))
   ( SRV_SERVER * server,
    SRV_PROC   * srvproc,
    int        srverror,
    BYTE          severity,
    BYTE          state,
    int        oserrnum,
    char     * errtext,
    int        errtextlen,
    char     * oserrtext,
    int        oserrtextlen );
}
function srv_event_fn(srvproc: SRV_PROC; event: Integer; data: PByte): Integer; cdecl;
function srv_getuserdata(srvproc: SRV_PROC): Pointer; cdecl;
function srv_getbindtoken(srvproc: SRV_PROC; token_buf: PChar): Integer; cdecl;
function srv_getdtcxact(srvproc: SRV_PROC; ppv: Pointer): Integer; cdecl;

//typedef int (* EventHandler)(void*);
type
  EventHandler = Pointer;
function srv_handle(server: SRV_SERVER; int: Longint; handler: EventHandler): EventHandler; cdecl;

function srv_impersonate_client(srvproc: SRV_PROC): Integer; cdecl;
function srv_init(config: SRV_CONFIG; connectname: PChar; namelen: Integer): SRV_SERVER; cdecl;
function srv_iodead(srvproc: SRV_PROC): Bool; cdecl;

function srv_langcpy(srvproc: SRV_PROC; start, nbytes: Longint; buffer: PChar): Longint; cdecl;
function srv_langlen(srvproc: SRV_PROC): Longint; cdecl;
function srv_langptr(srvproc: SRV_PROC): Pointer; cdecl;

function srv_log(server: SRV_SERVER; datestamp: Bool; msg: PChar; msglen: Integer): Integer; cdecl;
function srv_paramstatus(srvproc: SRV_PROC; n: Integer): Integer; cdecl;
function srv_pfield(srvproc: SRV_PROC; field: Integer; len: PInteger): PChar; cdecl;

function srv_returnval(srvproc: SRV_PROC; value_name: PDBCHAR; len: Integer; status: Byte;
  iType, maxlen, datalen: DBINT; value: PByte): Integer; cdecl;

function srv_revert_to_self(srvproc: SRV_PROC): Integer; cdecl;

function srv_rpcdb(srvproc: SRV_PROC; len: PInteger): PChar; cdecl;
function srv_rpcname(srvproc: SRV_PROC; len: PInteger): PChar; cdecl;
function srv_rpcnumber(srvproc: SRV_PROC): Integer; cdecl;
function srv_rpcoptions(srvproc: SRV_PROC): Word; cdecl;
function srv_rpcowner(srvproc: SRV_PROC; len: PInteger): PChar; cdecl;

function srv_run(server: SRV_SERVER): Integer; cdecl;

function srv_sendmsg(srvproc: SRV_PROC;
  msgtype: Integer; msgnum: DBINT; msgClass, state: DBTINYINT;
  rpcname: PChar; rpcnamelen: Integer;
  linenum: Word; msg: PChar; msglen: Integer): Integer; cdecl;

function srv_ansi_sendmsg(srvproc: SRV_PROC;
  msgtype: Integer; msgnum: DBINT; msgClass, state: DBTINYINT;
  rpcname: PChar; rpcnamelen: Integer;
  linenum: Word; msg: PChar; msglen: Integer): Integer; cdecl;

function srv_sendstatus(srvproc: SRV_PROC; status: Longint): Integer; cdecl;
function srv_setuserdata(srvproc: SRV_PROC; ptr: Pointer): Integer; cdecl;
function srv_sfield(server: SRV_SERVER; field: Integer; len: PInteger): PChar; cdecl;
function srv_symbol(iType, symbol: Integer; len: PInteger): PChar; cdecl;
function srv_tdsversion(srvproc: SRV_PROC): Integer; cdecl;
function srv_writebuf(srvproc: SRV_PROC; ptr: Pointer; count: Word): Integer; cdecl;
function srv_willconvert(srctype, desttype: Integer): Bool; cdecl;
procedure srv_ackattention(srvproc: SRV_PROC); cdecl;
function srv_terminatethread(srvproc: SRV_PROC): Integer; cdecl;
function srv_sendstatistics(srvproc: SRV_PROC): Integer; cdecl;
function srv_clearstatistics(srvproc: SRV_PROC): Integer; cdecl;
function srv_setevent(server: SRV_SERVER; event: Integer): Integer; cdecl;
function srv_message_handler(srvproc: SRV_PROC;
  errornum: Integer; severity, state: Byte; oserrnum: Integer; errtext: PChar;
  errtextlen: Integer; oserrtext: PChar; oserrtextlen: Integer): Integer; cdecl;

function srv_pre_handle(server: SRV_SERVER; srvproc: SRV_PROC;
                   event: Longint; handler: EventHandler;  remove: Bool): Integer; cdecl;
function srv_post_handle(server: SRV_SERVER; srvproc: SRV_PROC;
                   event: Longint; handler: EventHandler;  remove: Bool): Integer; cdecl;

function srv_post_completion_queue(srvproc: SRV_PROC; inbuf: PChar; inbuflen: PChar): Integer; cdecl;
function srv_IgnoreAnsiToOem(srvproc: SRV_PROC; bTF: BOOL): Integer; cdecl;

//#ifdef __cplusplus
//}
//#endif

//#pragma pack()

const
  SS_MAJOR_VERSION   = 7;
  SS_MINOR_VERSION   = 00;
  SS_LEVEL_VERSION   = 0000;
  SS_MINIMUM_VERSION = '7.00.00.0000';
  ODS_VERSION        = ((SS_MAJOR_VERSION shl 24) or (SS_MINOR_VERSION shl 16));

//#endif //_ODS_SRV_H_

//////////////////////////////////////////////////////////////////
// Suggested implementation of __GetXpVersion
//
//__declspec(dllexport) ULONG __GetXpVersion()
//   {
//   return ODS_VERSION;
//   }
//////////////////////////////////////////////////////////////////

implementation

const
  sLibName = 'Opends60.DLL';

function srv_describe;                  external sLibName name 'srv_describe';
function srv_setutype;                  external sLibName name 'srv_setutype';
function srv_setcoldata;                external sLibName name 'srv_setcoldata';
function srv_setcollen;                 external sLibName name 'srv_setcollen';
function srv_sendrow;                   external sLibName name 'srv_sendrow';
function srv_senddone;                  external sLibName name 'srv_senddone';

// Dealing with Extended Procedure parameters
function srv_rpcparams;                 external sLibName name 'srv_rpcparams';
function srv_paraminfo;                 external sLibName name 'srv_paraminfo';
function srv_paramsetoutput;            external sLibName name 'srv_paramsetoutput';

function srv_paramdata;                 external sLibName name 'srv_paramdata';
function srv_paramlen;                  external sLibName name 'srv_paramlen';
function srv_parammaxlen;               external sLibName name 'srv_parammaxlen';
function srv_paramtype;                 external sLibName name 'srv_paramtype';
function srv_paramset;                  external sLibName name 'srv_paramset';

function srv_paramname;                 external sLibName name 'srv_paramname';
function srv_paramnumber;               external sLibName name 'srv_paramnumber';

//--------------------------------------------------------------
// The rest of these APIs are still supported, in SQL Server 7.0,
// but may not be supported after SQL Server 7.0

function srv_getconfig;                 external sLibName name 'srv_getconfig';
function srv_getserver;                 external sLibName name 'srv_getserver';
function srv_got_attention;             external sLibName name 'srv_got_attention';
function srv_eventdata;                 external sLibName name 'srv_eventdata';

// Memory
function srv_alloc;                     external sLibName name 'srv_alloc';
function srv_bmove;                     external sLibName name 'srv_bmove';
function srv_bzero;                     external sLibName name 'srv_bzero';
function srv_free;                      external sLibName name 'srv_free';

function srv_config_fn;                 external sLibName name 'srv_config';
function srv_config_alloc;              external sLibName name 'srv_config_alloc';
function srv_convert;                   external sLibName name 'srv_convert';
function srv_event_fn;                  external sLibName name 'srv_event';
function srv_getuserdata;               external sLibName name 'srv_getuserdata';
function srv_getbindtoken;              external sLibName name 'srv_getbindtoken';
function srv_getdtcxact;                external sLibName name 'srv_getdtcxact';
function srv_handle;                    external sLibName name 'srv_handle';
function srv_impersonate_client;        external sLibName name 'srv_impersonate_client';
function srv_init;                      external sLibName name 'srv_init';
function srv_iodead;                    external sLibName name 'srv_iodead';
function srv_langcpy;                   external sLibName name 'srv_langcpy';
function srv_langlen;                   external sLibName name 'srv_langlen';
function srv_langptr;                   external sLibName name 'srv_langptr';
function srv_log;                       external sLibName name 'srv_log';
function srv_paramstatus;               external sLibName name 'srv_paramstatus';
function srv_pfield;                    external sLibName name 'srv_pfield';
function srv_returnval;                 external sLibName name 'srv_returnval';
function srv_revert_to_self;            external sLibName name 'srv_revert_to_self';

function srv_rpcdb;                     external sLibName name 'srv_rpcdb';
function srv_rpcname;                   external sLibName name 'srv_rpcname';
function srv_rpcnumber;                 external sLibName name 'srv_rpcnumber';
function srv_rpcoptions;                external sLibName name 'srv_rpcoptions';
function srv_rpcowner;                  external sLibName name 'srv_rpcowner';

function srv_run;                       external sLibName name 'srv_run';

function srv_sendmsg;                   external sLibName name 'srv_sendmsg';
function srv_ansi_sendmsg;              external sLibName name 'srv_ansi_sendmsg';

function srv_sendstatus;                external sLibName name 'srv_sendstatus';
function srv_setuserdata;               external sLibName name 'srv_setuserdata';
function srv_sfield;                    external sLibName name 'srv_sfield';
function srv_symbol;                    external sLibName name 'srv_symbol';
function srv_tdsversion;                external sLibName name 'srv_tdsversion';
function srv_writebuf;                  external sLibName name 'srv_writebuf';
function srv_willconvert;               external sLibName name 'srv_willconvert';
procedure srv_ackattention;             external sLibName name 'srv_ackattention';
function srv_terminatethread;           external sLibName name 'srv_terminatethread';
function srv_sendstatistics;            external sLibName name 'srv_sendstatistics';
function srv_clearstatistics;           external sLibName name 'srv_clearstatistics';
function srv_setevent;                  external sLibName name 'srv_setevent';
function srv_message_handler;           external sLibName name 'srv_message_handler';

function srv_pre_handle;                external sLibName name 'srv_pre_handle';
function srv_post_handle;               external sLibName name 'srv_post_handle';
function srv_post_completion_queue;     external sLibName name 'srv_post_completion_queue';
function srv_IgnoreAnsiToOem;           external sLibName name 'srv_IgnoreAnsiToOem';

end.

posted @ 10:08 | Feedback (0)

2008年8月25日

AVI文件格式研究中碰到的一些问题的解决办法

最近在研究AVI文件格式的生成问题,碰到以下的问题,找到解决办法,共享如下:

1.生成的文件格式的校验问题:

因为是根据AVI RIFF File Refence这个文档来生成的,所以对错不知道。因此需要一个校验工具。偶觉得有两个工具不错:

a. Gsport这个是暴风影音一类的工具会带的工具。如果格式有错误,它会提示出来。

image

b.VirtualDub 在这里面点工具菜单里面有十六进制编辑器,按Ctrl+R可以显示出RIFF的树,这样比较容易找出问题来。

image

2.一切都是按文档的说明来生成的,用播放器来播放是正常的,但是用如上的校验工具来看,里面有错位。在trunck列表里面,发现只有第一个是识别出来,后面的跳了一位无法识别。

经研究发现是存在着奇偶对齐的问题,如果内容是奇数位,那么得在后面补上一位来对齐,但是这一位不能记在这个trunck的长度里面,否则解码器多读了一位可能会引起解码错误。

计划把音频加入,以及功能完善化后,发布DLL供人调用。

posted @ 14:54 | Feedback (0)

2008年8月8日

在sql server里面插入,修改,删除数据时,同步把变动的数据取出来

别的不多说,直接上SQL:

修改时:

update [res].[dbo].[IP] set

    ip1 = ID+1

output INSERTED.ID,

       INSERTED.ip1

where Country = 'IANA'

 

插入时:

insert into [res].[dbo].[IP](ID, startip, endip)

output INSERTED.ID,INSERTED.startip,INSERTED.endip

values(234666,'12334', '34445')

 

删除时:

delete from [res].[dbo].[IP]

output deleted.ID, deleted.startip, deleted.endip

where ID = 234666

posted @ 4:37 | Feedback (2)

2008年7月22日

进程外插件的实现

插件机制附处可见,甚至连很多WEB程序也会有。比如说DZ的论坛,动网的论坛等。在应用程序里面,跑插件的时候,最大的问题有两个:

1.插件的crash引起整个应用程序的crash

2.插件有问题时,修改后,需要停下整个程序,来更换插件。

在这时候,进程外插件的好处就显而易见:因为插件加载在进程外,所以插件crash了,不会影响主进程。同时可以自由地卸载插件。

在.net里面,实现进程外的插件的原理是:让插件跑在和主进程不同的AppDomain里面。

但是跨AppDomain来加载程序集确会有权限的问题,所以不能再像以前加载一个DLL后,去遍历每个类,来看有没有合适的插件在里面。它只能根据已知的类名来加载程序集。所以我先设计一个接口:

public interface IPlugInSum
{
    string[] GetPlugIns();
}

在这个接口里面实现对每个插件的描述:

public class PlugInSum :MarshalByRefObject, IPlugInSum
{
    public string[] GetPlugIns()
    {
        return new string[] { "DemoPlugIn.DemoPlugIn", "DemoPlugIn.DemoPlugIn2" };
    }
}

在这里面我实现了两个插件。同时强制要求这个描述对象的typename为:DemoPlugIn.PlugInSum。这样主进程里面获取了所有的类名后,就可以一个一个地去把插件加载起来了。

posted @ 10:36 | Feedback (0)

2008年7月3日

TFS下的一个问题解决(转)

最近碰到了一个机子上的项目死活不能和TFS绑定,困扰很久,终于找到解决方案,原因很简单,成因也很简单,但是就是没有看到。

废话少说看原文:原文地址:http://teamfoundation.blogspot.com/2007/12/offline-and-back-again-in-vs2008.html

One of the most painful issues in VS2005 was its quirky offline support.

One of the first features I have checked in Visual Studio 2008 was working offline. And what can I say - it (mostly) rocks!

Let's do it step-by-step.


  • You open the solution under source control and there is no connection to the server. What you get is the dialog, indicating offline condition

    In Output window pane appears the log message, indicating detailed reason for the offline

    Important note: Once the solution is opened offline, next time you open it in Visual Studio the dialog won't appear (but the output pane will show same message every time)


  • If you choose to change files in your solution/project when is offline, you will have a message that file is read-only once you save the changes. There is no indication of "under source control" status for offline projects or solutions

    Important note: When working offline, you may edit or delete existing files or add new ones, and these types of changes will be supported when going "online" with TFS server. However, file renames are not supported

  • Now let's go online. You open solution in VS and you have connection - but tranistion to online will not happen automatically. To sync solution/project back online you should use "Go Online" menu, that available on right-click in Solution Explorer or in "File"->"Source Control" menu.

    Once you hit "Go Online" requested, the dialog with changes "Go Online" dialog will appear detailing the changes performed while online. The dialog shows files and
    changes (add/edit/delete) performed while offline. You may choose not to pend the changes for specific files (then the file will remain writable, but will not have pending changes).

    Important note: If you did not perform any changes while offline, the appropriate message will appear
    Once online, the pending changes indications will appear in Solution Explorer.

  • If you want to unbind your solution/project from source control, all you need to do is to go to "Source Control"->"Change Source Control" menu. The message will appear asking you whether you want to go online or permanently unbind your solution.



But of course, there were several "Things I did not like":

  1. No cancel on Offline dialog - either go offline or ...?
  2. No indication for source controlled files in Solution Explorer in offline mode (similar to that of VSS) - only read-only flag on file serves as an indication
  3. "Change Source Control" dialog does not allow one to "Disconnect", you can only "Unbind; so going offline happens only when server is not available


Overall, I should say I liked VS2008 experience very much (especially as compared with previous version). I can feel that feedback on TFS2005 offline experience was not wasted!

posted @ 13:36 | Feedback (2)

2008年6月14日

在Windows NT Services中使用ADOConnection

在开发windows服务的时候,想要连接数据库,可是发现在创建的时候就出错了,看看VCL里面的ADO创建的代码,发现是基于COM的调用的:

FConnectionObject := CreateADOObject(CLASS_Connection) as _Connection;
OleCheck(ConnectionPoint.Advise(Self as IUnknown, FConnEventsID));

所以得在服务启动的时候,初始化一下COM:

CoInitialize(nil);

对应的,在服务停止的时候,需要:

CoUninitialize;

posted @ 12:08 | Feedback (0)

DELPHI调试WINDOWS服务的一点心得

Delphi可以很轻松地开发windows服务,可是调试的时候,确有问题。服务能跑起来,可以把把调试器附加到服务的进程上。如果服务起不来呢?该如何调试呢?

如果直接按F9,则服务只是被创建,还没有起动,就会自已退出去了。

我想到的办法就是让服务以普通程序的方式来运行。

为了使用同一份代码,所以我彩用条件编译的方式来实现,在工程的DPR文件里面加上条件:

DELPHI的VCL可以说是一个很精妙的设计。对于一个普通程序来说,它初始化出来的Application是TApplication,而服务的Application是TServiceApplication,所以在想让服务以应用程序的方式来运行的话,一定得处理单元头:

uses
  {$IFDEF RUNASAPP}
  Forms,
  {$ELSE}
  SvcMgr,
  {$ENDIF}

在这里,我的条件是RUNASAPP,在调试的时候,我就加上这个条件来编译,在正常发布的时候就把这个条件去掉。

由于要调用服务的ServiceStart方法,所以得定义一个变量:

{$IFDEF RUNASAPP}
var
  b: Boolean;
{$ENDIF} 

同时,原来的应用程序代码也要改成:

Application.Initialize;
Application.CreateForm(TMyservice, MyService);
{$IFDEF RUNASAPP}
MyService.ServiceStart(nil, b);
{$ENDIF}
Application.Run;
{$IFDEF RUNASAPP}
Readln;
{$ENDIF}

加Readln的目标是不让ServiceStart完成后,就退出程序。

这下,服务也可以和应用程序一样的,按F9后开始调试。

posted @ 4:30 | Feedback (1)

2008年5月4日

在服务里面弹出一个窗口到用户的桌面上

曾几何时,服务里面弹出一个窗口到桌面上不再是那么地容易了:以前只要把服务设置为允许和桌面交互就可以直接在服务启动的时候,把一个窗口弹给用户。但是现在在vista(其它的OS 下没有测试,未知)下要弹出这样的窗体,首先会弹出一个提示框提示是否接否一个服务弹出来的消息,点接受后,才会在一个全灰的桌面里面弹出这个窗口。不用想,这样的用户体验,肯定是会被直接PASS。原因很简单,因为不同的用户间的桌面是不一样的,服务用的是System的权限,在vista里面是Session0,而用户的帐户不是这个(肯定大于0)。

看来,想弹出一个窗体,需要另一个程序来作辅助了。解决方案有两种:

  1. 开发一个程序A在启动的时候,随系统启动,并监控指定文件M,服务S有消息的时候,放在文件M里,A 感受了文件变化了,就去读这个文件里的内容,根据规则来作对应的动作。坏处很明显,当用户为了让系统跑得快的时候,这种自启动文件很容易被砍掉,导致了有些功能莫名奇妙地不可用。
  2. 同样地,也是开发一个程序A,用CreateProcessAsUser这个API来创建这个A ,并且发送到用户的桌面上去。好处是可以把这个A和服务S 放在同一个程序文件里面,根据不同的参数来启动不同的功能。这样用户除非是删除整个服务,否则不会有部分功能能用,又有部分功能不能用的问题。

现在来看看第二种方案,要想用CreateProcessAsUser这个API ,有这样几个步骤:

1.取得用户的令牌(Token)

2.指定好虚拟桌面

3.调用API创建这个用户进程。

在取得用户令牌的时候,又有几个方法:

1.从用户的进程上去剥

2.先用WTSGetActiveConsoleSessionId得到用户会话ID,再用WTSQueryUserToken这个API去取。

不过在vista下面,服务里面的WTSGetActiveConsoleSessionId这个API得到的总是0,也就是Session0,用这个创建出来的进程,还是属于一个服务进程。(而且这个API是XP以及以后的系统才会提供的,在早点的系统上就会调用失败)所以我们只好从用户的进程上去找,用户登录的时候,一定会有的进程就是:explorer.exe,这样可以遍历所有的进程去找到这个(如果是多人同时登录这个系统里,我也不知道该怎么办了,不知道有没有高人指点一下)。

这样创建出来的用户进程,在进程列表里面可以看到是活动用户的。但是如果在这里面使用一下文件选择框,或是去取一些系统目录,比如说用户的桌面,用户的收藏夹等,都会得到空。这时候因为没有指定用户环境造成的。使用CreateEnvironmentBlock这个API就可以搞定了。

posted @ 7:17 | Feedback (0)

京ICP备 05050892号