返回列表 发帖
◎VBS脚本编程简明教程之十六(响应事件)
        什么是事件?在我看来,事件就象我们手机上的闹钟,闹钟一响,我们就要去做某些特定的事情。或者这样说,事件就像警钟,当程序运行时,有特殊的事情发生,就会激发事件,事件本身就是一条消息,如果你编写的脚本要对事件进行处理,就需要一个特殊的过程或者函数来接受和处理事件。那么这个特殊的过程或者函数在程序运行时,就不断的监听,看系统是否传来了相应的事件,一旦接受到事件,脚本对此作出反应。
        那么事件是从那里来的呢?是否需要我们在脚本中对事件进行编写呢?一般情况下,事件是某个程序在运行中的特殊状态发出的,我们不需要对事件进行编写,只需要编写处理事件的函数。比如说我们用VBS建立了ie的一个实例,那么当ie的窗口被关闭的时候,就会激发出一个叫做OnQuit的事件。
是不是脚本自然而然就能接受事件并进行处理呢?我们说不是的,在创建对象的时候,我们将使用WSH的CreateObject命令,例如:
Set objie=WScript.CreateObject("internetexplorer.application","event_")
注意到了吗?多了一个参数,这个参数的作用是什么呢?它叫做事件接收端,当脚本连接的对象包含事件时,如果对象调用的事件是OnBegin,那么WSH将会在脚本中调用一个event_OnBegin的事件处理程序。当然事件接受端并不是固定的,如果对象将其定义为MyObj_的话,那么事件处理程序将是:MyObj_OnBegin。
是否很熟悉?在打造个性化QQ一讲中,曾经出现过Window_OnSize(cx,cy)函数,它其实就是一个事件处理程序。
让我们来举个实际的例子完整的看看事件的处理过程:
Set objie=WScript.CreateObject("InternetExplorer.Application","event_")
objie.Visible=True
MsgBox "请关闭浏览器窗口看看效果!",VBSystemModal
WScript.sleep 6000
MsgBox "现在已经正常关闭了"
Sub event_onquit()
MsgBox "您确定要关闭浏览器吗?",VBSystemModal
End Sub
这段脚本打开了一个IE窗口,然后要求你关闭IE窗口,当你关闭窗口的时候,自动调用事件响应程序。COPY

TOP

◎VBS脚本编程简明教程之十七——访问ADO数据库之一
ADO是Microsoft提供和建议使用的新型数据访问接口,它是建立OLEDB之上的一个抽象层。微软公司在操作系统中默认提供了 Access 的 ODBC 驱动程序以及 JET 引擎,
一、对ADO对象的主要操作,一般包括6个方面:
1.连接到数据源。通常使用ADO的Connection对象。一般使用相应的属性打开到数据源的连接,设置游标的位置,设置默认的当前数据库,设置将使用的OLEDBProvider,直接提交SQL脚本等。
2.向数据源提交命令。通常涉及ADO的Command对象。可查询数据库并返回结果在Recordset对象中。
3.执行SELECT查询命令。在提交SQL脚本的任务时,不用创建一个Command对象,就可完成查询。
4.可以通过ADO的Recordset对象对结果进行操作。
5.更新数据到物理存储。
6.提供错误检测。通常涉及ADO的Error对象。
二、ADO中主要对象的功能
Recordset对象,用来封装查询的结果。
Field对象,用来表达一行结果中各子段的类型和值。
Error对象,用来检测和判断在数据库操作中出现的错误,比如连接失败。 在ADO中,许多对象名后多了一个"s",比如Error->Errors,Field->Fields等等。添加"s"意味着是相应对象的Collection(集合)对象,比如Errors是Error对象的Collection对象。Collection有点像数组(Array),但不同的是,Collection可以以不同类型的数据或对象作为自己的元素,而数组中的各元素通常都是相同类型的。所以,在看到一个对象名最后是"s",通常表明这是一个Collection对象,比如Errors中的各元素是由Error对象的实例组成的。
三、具体应用
1、创建mdb数据库
ADOX 是ADO 对象的扩展库。它可用于创建、修改和删除模式对象,如数据库和表格等。
其常用的对象有:Catalog—>创建数据库。Column—>表示表、索引或关键字的列。
Key—>表示数据库表中的关键字。
常用的方法有: Append 将对象添加到 其集合。Delete 删除集合中的对象。
set cat= createobject("ADOX.Catalog")
cat.Create "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=d:\shujuku.mdb"
Set  tbl=createobject("ADOX.Table")
tbl.Name ="MyTable"
tbl.Columns.Append  "姓名",  202  'adInteger
tbl.Columns.Append  "性别",  3  'adInteger
tbl.Columns.Append  "工作单位",  202  ,50  'adVarWChar
cat.Tables.Append  tbl
不过你要操纵数据库就连一个数据库也不建,未免懒惰了点,用代码虽然可以完成,但是我觉得对数据约束完成的比较困难,本代码也就是示范个例子,并不推荐使用此类方法。
2、打开数据库
Provider=″Provider=Microsoft.Jet.OLEDB.4.0 ; Data Source="
Set Objconn = createobject("ADODB.Connection")
Objconn.Open Provider & "数据库名称"
3、创建记录集
Set Objrs = CreateObject("ADODB.Recordset")
4、执行SQL查询语句
Sql="SQL查询语句"  '例如:Select count(*) from table1
Set objrs = objconn.execute(sql)
一般情况下,我们将绝大多数的操作转化为SQL语句完成。COPY

TOP

◎VBS脚本编程简明教程之十七——访问ADO数据库之二
在学习SQL语句之前,让我们先来对数据库做一个基本的了解。一个数据库中可能包含了很多个基本单位叫做表。表格被分为“行”和“列”。每一行代表表的一个单独组成部分,每一列代表相同性质的一组数据。举例来说,如果我们有一个记载顾客资料的表格,行包括姓、名、地址、城市、国家、生日等。而一列则代表了所有的地址或者国家等。
一、建立数据表,我们前边说过利用ADOX.Catalog建立数据库和数据表的方法,但是用的似乎不是很多,一般情况下,如果我们需要在数据库中动态建立一个表,我们将工作交给SQL语句来做,其基本语法是:
CREATE TABLE [表格名]([列名1] 数据类型 , [列名2]  数据类型,... )
例如我们要建立一个基本顾客表:
Create table [顾客表]([姓名] text(8), [性别] text(2),[住址] text(30))
二、插入数据项
insert into [数据表名称] (数据项1,数据项2,...) values (值1,值2,...)
insert into语句用来添加新的数据到数据库中的指定表。通过(数据项1,数据项2,...) values (值1,值2,...)来为新添加的数据赋初值。
三、删除数据项
delete from [数据表名称] where [数据项1] like [值1] and/or [数据项2] like [值2] ...作者:临汾市外事旅游局薛靖澜,转载请注明出处]
四、更新数据项
update [数据表名称] set 数据项1=值1,数据项2=值2,... where [数据项1] like [值1] and/or [数据项2] like [值2] ...
该语句可以修改数据库中指定数据表内的指定数据,如果不是用where限定条件就表示修改该表内所有的数据条目。
五、查询数据项
select [数据内容] from [数据表名称] where [数据项1] like [值1] and/or [数据项2] like [值2] ... order by [数据项] asc/desc
[数据内容]部分表示所要选取的表格中的数据项,使用*表示选取全部。[数据表名称]表示要从哪一个表格中选取,如果你没有接触过数据库可能很难了解什么是数据表格,没关系,我将在后面用到它的时候再说明。where表示选取的条件,使用like表示相等,也支持>=这样的判断符号,同时使用多个条件进行选取时中间要使用and进行连接。order by决定数据的排列顺序,asc表示按照[数据项]中的数据顺序排列,desc表示倒序,默认情况为顺序。select语句中除select和from之外其它均为可选项,如果都不填写表示选取该数据表中的全部数据。例如:下面的语句查询某数据库中表名称为:testtable中姓名为“张三”的nickname字段和email字段。
SELECT nickname,email FROM testtable WHERE name='张三'
(一) 选择列表
选择列表(select_list)指出所查询列,它可以是一组列名列表、星号、表达式、变量(包括局部变量和全局变量)等构成。
1、选择所有列
例如,下面语句显示testtable表中所有列的数据:
SELECT * FROM testtable
2、选择部分列并指定它们的显示次序查询结果集合中数据的排列顺序与选择列表中所指定的列名排列顺序相同。
例如:SELECT nickname,email FROM testtable
3、更改列标题
在选择列表中,可重新指定列标题。定义格式为:列标题=列名
列名 列标题如果指定的列标题不是标准的标识符格式时,应使用引号定界符,例如,下列语句使用汉字显示列标题:
SELECT 昵称=nickname,电子邮件=email FROM testtable
(二) FROM子句指定SELECT语句查询的表。
最多可指定256个表,它们之间用逗号分隔。如果选择列表中存在同名列,这时应使用对象名限定这些列所属的表或视图。例如在usertable和citytable表中同时存在cityid列,在查询两个表中的cityid时应加以限定。
◎VBS脚本编程简明教程之十七——访问ADO数据库之三
(三) WHERE子句设置查询条件
WHERE子句设置查询条件,过滤掉不需要的数据行。例如下面语句查询年龄大于20的数据:
SELECT * FROM usertable WHERE age>20
WHERE子句可包括各种条件运算符:
比较运算符(大小比较):>、>=、=、<、<=、<>、!>、!<
范围运算符(表达式值是否在指定的范围):BETWEEN…AND
NOT BETWEEN…AND
列表运算符(判断表达式是否为列表中的指定项):IN (项1,项2……)
NOT IN (项1,项2……)
模式匹配符(判断值是否与指定的字符通配格式相符):LIKE、NOT LIKE
空值判断符(判断表达式是否为空):IS NULLNOT IS NULL
逻辑运算符(用于多条件的逻辑连接):NOTANDOR
1、范围运算符例:age BETWEEN 10 AND 30相当于age>=10 AND age<=30
2、列表运算符例:country IN ('Germany','China')
3、模式匹配符例:常用于模糊查找,它判断列值是否与指定的字符串格式相匹配。可用于char、 varchar、text、ntext、datetime和smalldatetime等类型查询。
可使用以下通配字符:
百分号%:可匹配任意类型和长度的字符,如果是中文,请使用两个百分号即%%。
下划线_:匹配单个任意字符,它常用来限制表达式的字符长度。
方括号[]:指定一个字符、字符串或范围,要求所匹配对象为它们中的任一个。
[^]:其取值也[] 相同,但它要求所匹配对象为指定字符以外的任一个字符。
例如:作者:临汾市外事旅游局薛靖澜,转载请注明出处]
限制以Publishing结尾,使用LIKE '%Publishing'
限制以A开头:LIKE '[A]%'
限制以A开头外:LIKE '[^A]%'
4、空值判断符例WHERE age IS NULL
5、逻辑运算符:优先级为NOTANDOR
最后,让我们用一个简单的例子结束这篇教程:
Objku = InputBox("请输入单位数据库的路径","默认位置","d:\jbqk.mdb")
Set Objconn = createobject("adodb.connection")
Objconn.open ="provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Objku
作者:临汾市外事旅游局薛靖澜,转载请注明出处]
sql = "CREATE TABLE [单位资料](ID Autoincrement PRIMARY KEY,[姓名] text(8),[性别] text(2),[科室] text(6),[住址] text(30))"
Objconn.execute(sql)
sql = "INSERT INTO [单位资料]([姓名],[性别],[科室],[住址]) VALUES('张三','男','行管科','解放路12号')"
Objconn.execute(sql)
sql = "INSERT INTO [单位资料]([姓名],[性别],[科室],[住址]) VALUES('李斯','女','市场科','五一路12号')"
Objconn.execute(sql)
sql = "DELETE FROM [单位资料] WHERE [姓名] = '张三' "
Objconn.execute(sql)
sql = "UPDATE [单位资料]"
sql = "SELECT COUNT(ID) FROM [单位资料]"COPY

TOP

◎WMI轻松入门之一——基本概念
其实我给文章起这样的名字,绝对没有轻视WMI的意思,事实上就连微软也有“WMI非常难于学习而且更难于使用”的说法,在近日的学习过程中更感觉到了WMI检索功能的强大,之所以起个“轻松入门”的名字,我只是有感于外国人写教程在思路上和国人不太一致,西方式的幽默看起来困难无比,再加上一上手就在类的基本结构上展开讨论,吓跑了无数Vbs的爱好者,想从国人常见的角度出发来说说怎么学习WMI而已。百度空间的长度限制太讨厌了,一次发不完,只好分割成三部分,题目只能大致起了,见谅。
一、什么是WMI?微软有很多说法,大家可以到脚本中心查阅,我这样理解,WMI是一个用于管理Windows系统资源的对象,其内部应是一个树状的数据库,数据库中包含了很多个分支,每个分支被称作命名空间,每个命名空间包含了很多个对托管资源的抽象定义,这种定义叫做类。在很多计算机教材中喜欢把类比作建筑蓝图,依据蓝图建造的楼宇叫做类的实例,我更喜欢将类和其实例的关系比作表格,类就是表格的字段定义,而表中的数据就是一个个的类的实例,也许我这样说会让很多朋友更加糊涂,但是依此类推,WMI中最终存在的是各种软硬件资源的抽象定义,我们利用WMI,就是要按图索骥,通过类定义,获得类实例,检索出符合要求的属性,调用其内置的方法,实现我们的目标。相信很多朋友已经发现,我将WMI等同于CIM库了,我清楚他们不是一回事,但我相信这样更容易理解。如图:
二、WMI的基本结构
严格说来,WMI由四部分组成:
1、         公共信息模型对象管理器——CIMOM
2、         公共信息模型——CIM
3、         WMI提供程序
4、         WMI脚本对象库
其中其第123三个部分,在使用中很少加以区别,我们一般统称为CIM库。
所以我们可以认为WMI实际是由两部分组成:CIM库和WMI脚本对象库。在具体使用过程中,我们是通过WMI脚本对象库去访问CIM库,管理托管的资源。也就是说,在我们编写脚本的过程大致可以分为这么几步:
1、         创建WMI对象脚本库的指针实例;
2、         调用其实例的方法,连接到CIM库,并指明需要访问的资源的逻辑位置;
3、         获得托管资源也就是类的实例的集合;
4、         枚举实例,完成工作。
这几个步骤在我们将来编写的代码中可以明确的反映出来。
三、常用的命名空间
命名空间是个很复杂的概念,相信在微软的网站上一定有很多的篇幅介绍这个概念,据我个人理解,命名空间是对类所处逻辑位置的一个约定。打个比方说:张家也有个孩子叫小强,李家也有个孩子小强。大家站在一起,你大声叫"小强",你说这到底是叫哪一个小强呢?张家,李家都是一个姓,一个人的姓实际上就是现实中的一种名字空间。好了,现在你大声叫“张小强”,我们就明确的知道你到底是叫哪一个小强了。这就好比在变量名前加上名字空间前缀。所以可以通俗的说,名字空间就是一个变量的姓氏。问题是这样我们还会碰到一个问题,世界上有很多姓张的,也有可能有很多的张小强,这怎么办呢?这时候我们可以这样说"张老三家的小强",张是一个名字空间,张老三又是张下面的二级名字空间.
张.老三的家.小强 = 110
张.三丰的家.小强= 119
也许说的更糊涂,但大致就这样吧,我本来也就不是说明这个的。
据微软称,WMI的命名空间共有16个,不过不用担心,我们常用的只有两个:
1、         root\cimv2  在这个命名空间里包括了绝大多数与计算机、操作系统相关联的类。
2、         root\default  管理注册表的类
在使用中,我们用一个字符串表示命名空间,就像文件路径一样。COPY

TOP

◎WMI轻松入门之二——连接到指定的CIM命名空间
四、常用的脚本对象库
WMI脚本对象库由24个对象组成,在脚本中心有一副脚本库对象模型的图,有兴趣的朋友可以参考一下,作为入门,我们一般只用到其中的四个对象,其继承和层级关系如下:
SwbemLocator教本库对象→SwbemServicesWMI服务对象→SwbemObjectSet类实例集合对象→SwbemObject类的实例
好了,现在让我们来举个例子,详细说明一下这四个对象在脚本中的应用方法:
例一:用来检索计算机上安装的光驱:
strComputer = "."
Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator")
Set objSWbemServices = objSWbemLocator.ConnectServer
Set colItems = objSWbemServices.ExecQuery("Select * from Win32_CDROMDrive")
For Each objItem in colItems
   WScript.Echo "光盘驱动器的类型: " & objItem.Caption
   WScript.Echo "盘符是: " & objItem.Id
Next
例二:用来检索CPU型号
strComputer = "."
Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator")
Set objSWbemServices = objSWbemLocator.ConnectServer
Set objSWbemObjectSet = objSWbemServices.InstancesOf("Win32_Processor")
For Each objSWbemObject In objSWbemObjectSet
   Wscript.echo  "CPU的型号为:" & objSWbemObject.name
Next
请注意,这两个脚本虽然简单,却代表了WMI脚本设计中最普遍的东西,可以说是很典型的脚本。让我们来仔细观察一下这两个脚本,讨论讨论一下脚本访问WMI的基本方法:我们可以看到整个脚本的执行过程基本相同:
①定义了SwbemLocator的实例;SwbemServices、SwbemObjectSet、SwbemObject对象;创建了SwbemLocator的实例;②通过SwbemLocator的ConnectServer方法连接到WMI,获得SwbemServices的实例集合;③枚举集合中的每个实例;④显示各实例的一些属性。
让我们来详细说明一下各行代码的详细含义,并请仔细回想我们第二部分WMI基本结构中谈到的编写WMI脚本的基本步骤:(注意:考虑到脚本的简易,我们编写的脚本一般只在本地计算机进行检索,我们只介绍涉及本地的这一部分,涉及到访问远程计算机的部分我们就省略了,其实随着计算机安全技术的发展,仅凭WMI访问远程计算机的可行性是越来越小了)
1、连接到指定的CIM命名空间
要用WMI对象编程,必须首先创建WMI对象脚本库的实例,连接到目标计算机的CIM命名空间。
方法一:
步骤一、建立SwbemLocator对象的实例。代码为:
Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator")
然后用SwbemLocator对象的ConnectServer方法(SwbemLocator对象只有1个只读属性Security_和1个方法ConnectServer)建立WMI服务的连接,返回一个命名空间的连接(SwbemServices对象),代码为:
Set objSWbemServices = objSWbemLocator.ConnectServer()
ConnectServer方法共有8个参数,所有参数都是可选的,其参数格式如下:
ConnectServer([strComputName],[strNamespace],[strUser],[strPassword],[strLocale],[strAuthority],[iSecurityFlags],[objwbemNamedValueSet])
考虑到WMI的复杂性,在使用中我们如果只是在本地计算机上进行检索和查询,那么我们只需要设置第12个参数,其它参数都可以省略;如果想连接到远程计算机,一般需要对前4个参数进行设置,我们也只对此做个简单的介绍。
strServer——计算机名,缺省为本机,本机也可以用”.”
strNamespace——需要登录的CIM命名空间,例如:"root\CIMV2",缺省为"root\CIMV2"
方法二:用moniker名字法建立WMI服务的连接,这也是微软推荐的连接方法
moniker名字法是利用GetObject函数直接建立WMI服务的连接,它的要点就是通过编写一个moniker字符串作为GetObject函数的参数,然后返回一个SwbemServices对象。
关于moniker字符串的完整格式如下:
"winmgmts:[{SecuritySettings}!][\\ComputerName][\Namespace][:ClassName][.KeyProperty='Value']"
"winmgmts:"是前缀, 表示为WMI服务,必须使用;第二部分用来验证权限和假冒级别的,省略。第三部分为计算机名字:"\\.\"是计算机名字,默认可省略,其余同上;第四部分CIM命名空间:缺省的命名空间为"root\CIMV2",默认可省略。
第五部分为类名。第六部分为属性值。注意:当该moniker字符串不包括最后2项时(即为:"winmgmts:[\\ComputerName][\Namespace]"),则GetObject(moniker字符串)返回的是一个命名空间的已验证的连接(SwbemServices对象);当不包括最后1项时,返回的是一个CIM类(SWbemObject对象);当包括最后2项时,返回的是一个类的单独实例(SWbemObject对象)。COPY

TOP

◎WMI轻松入门之三——获得类的实例
2.获得类的实例
我们有4种方法获得类的实例,其中方法1和方法2是通过SwbemServices对象的InstancesOf方法和ExecQuery方法来获得某个类的多个实例组成的集合对象。方法3和方法4则是返回单独的类的实例,即返回的是一个SWbemObject对象。
1)InstancesOf方法获得类的实例集合
InstancesOf方法的语法参数格式如下:
SwbemServices.InstancesOf(strClass)
strClass为类名,例如"Win32_Service"
回顾例二,就是用语句:Set objSWbemObjectSet = objSWbemServices.InstancesOf("Win32_Processor ") 来获得"Win32 Processor "类的所有实例集合,然后我们可以用
For Each objSWbemObject In objSWbemObjectSet
……
Next
语句获得每一个类的实例SWbemObject对象,然后就可以根据我们的需要,进行相应的操作。
2)ExecQuery方法获得类的实例集合
与InstancesOf方法不一样的是,ExecQuery方法可以通过查询语句,只返回匹配部分实例和属性。ExecQuery方法的语法参数格式如下:
SwbemServices.ExecQuery(strQuery)
strQuery为WMI查询语言(WQL)构造的一个查询语句字符串。
例如:
Set objSWbemObjectSet = objSWbemServices.ExecQuery("select ProcessorId from Win32_Processor where DeviceID='cpu0'")
3)Get方法获得一个类的实例(SWbemObject对象)
此方法也就不必再用 For Each objSWbemObject In objSWbemObjectSet :……:Next 语句从SWbemObjectSet对象中获得每一个类的实例SWbemObject对象,Get方法的语法参数格式如下:
SwbemServices.Get([strObjectPath][.KeyProperty='Value'])
strObjectPath是类的名字
KeyProperty是主键属性名
Value是指定的主键属性值
这里要注意的是如果要获得一个类的实例,则strObjectPath.KeyProperty='Value'中的任何一项都不能省略,例如:
Set objSWbemServices = GetObject("winmgmts:")
Set objSWbemObject = objSWbemServices.Get("Win32_Processor.DeviceID='cpu0'")
Wscript.echo “CPU的型号为”:" & objSWbemObject.ProcessorId
看,结果一样,脚本却简化了不少。
4)直接用moniker名字法获得一个类的实例
在说明Moniker名字法的时候我们说过,当包括最后2项时,返回的是一个类的单独实例,如:
Set objSWbemObject = GetObject("winmgmts:Win32_Processor.DeviceID='cpu0'")
Wscript.echo "首枚CPU序列号:" & objSWbemObject.ProcessorId
是不是更加简单?仅仅2条语句就获得了CPU的序列号。
3.读取类的实例属性,调用类的方法
实在是太多了,你可以参照C:/WINDOWS/system32/wbem/cimwin32.mfl文件中,对所有类的属性和方法的描述。也可以用下列代码查询,虽然看起来有点困难,不过看的多了也就明白了。
strClass=inputbox("请输入你要查询的类")
strComputer = "."
strNameSpace = "root\cimv2"
Const wbemFlagUseAmendedQualifiers = &h20000
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\" & strNameSpace)
Set objClass = objWMIService.Get(strClass, wbemFlagUseAmendedQualifiers)
strMOF = objClass.GetObjectText_
WScript.Echo strMOFCOPY

TOP

◎WMI轻松入门之四——解析类定义
  在上一篇文章中我们说过,WMI中用类对托管资源进行抽象定义和和管理,那么,什么是类?
  类的定义相信在很多面向对象的计算机教材中都能找到,我的理解是:类,是包含了一组独立功能的模块,这个模块由数据和功能组成,其中数据叫做类的属性,完成功能的部分叫做类的方法。我认为类的优点是:类完全可以由张三进行设计,李四可以拿来直接使用,在使用的时候,李四不需要知道类是如何设计、如何实现的,只要知道:这个类可以实现什么样的功能,这个类包含有什么样的方法和属性就可以了。更加重要的是,类还可以进行继承,就像父亲亡故,儿子继承了父亲所有的财产一样,如果我们发现某个类A已经完成了我们需要的大部分功能,我们再去重新设计一个新类来完成我们所有的功能,未免费时费力,根据类可以继承的特性,我们只要声明一个类继承了类A,然后按照需要添加需要的新的数据元素、扩展现有的功能模块,相信工作会简单很多。我看到很多书里都在说代码重用,我不是程序员,不知道所谓的代码重用具体是如何实现的,但是相信类应该在其中起了很重要的作用。
  在微软的教程中,对类从功能和继承关系上进行了详细的说明,我不再赘述,仅仅做一个摘要:
  任何资源如果要求WMI进行托管,至少需要两个文件:提供程序和托管对象格式 (MOF) 文件。提供程序是一个中间件,通过调用托管资源的本地 API 来响应 WMI 请求。
  每一个WMI托管的硬件和软件资源均有一个类来定义,反过来说,一个CIM类就是一个WMI托管资源的模板,而且资源的所有实例都使用这个模板。这些模板是由属性、方法和限定符组成的。这些属性、方法和限定符都定义在MOF文件中。方法和属性是我们经常遇到的,那么什么是限定符呢?限定符是关于类、属性或方法类型的附加修饰符,类是静态的、抽象的、还是关联的,属性是只读的还是可写的,方法的返回参数等,都定义在其中,那么我们如何知道某个类有那些限定符呢?如下代码可以帮助我们方便的获得类的属性、方法和限定符的信息。
Code:
strComputer = "."
strNameSpace = "root\cimv2"
strClass=inputbox("请输入你要查询的类")
Set objClass = GetObject("winmgmts:\\" & strComputer & _
                           "\" & strNameSpace & ":" & strClass)
WScript.Echo strClass & " 的类限定信息如下:"
WScript.Echo "------------------------------"
i = 1
For Each objClassQualifier In objClass.Qualifiers_
      If VarType(objClassQualifier.Value) = (vbVariant + vbArray) Then    '常数 VBVariant 只与 VBArray 一起返回,以表明 VarType 函数的参数是一个 Variant 类型的数组。
          strQualifier = i & ". " & objClassQualifier.Name & " = " & _
                                    Join(objClassQualifier.Value, ",")
      Else
          strQualifier = i & ". " & objClassQualifier.Name & " = " & _
                                    objClassQualifier.Value
      End If
      WScript.Echo strQualifier
      strQualifier = ""
      i = i + 1
Next
WScript.Echo
WScript.Echo strClass & " 类的属性和属性限定信息"
WScript.Echo "-------------------------------------------------"
i = 1 : j = 1
For Each objClassProperty In objClass.Properties_
      WScript.Echo i & ". " & objClassProperty.Name
      For Each objPropertyQualifier In objClassProperty.Qualifiers_
          If VarType(objPropertyQualifier.Value) = (vbVariant + vbArray) Then
              strQualifier = i & "." & j & ". " & _
                             objPropertyQualifier.Name & " = " & _
                             Join(objPropertyQualifier.Value, ",")
          Else
              strQualifier = i & "." & j & ". " & _
                             objPropertyQualifier.Name & " = " & _
                             objPropertyQualifier.Value
          End If
          WScript.Echo strQualifier
          strQualifier = ""
          j = j + 1
      Next
      WScript.Echo
      i = i + 1 : j = 1
Next
WScript.Echo
WScript.Echo strClass & " 类的方法和方法限定信息"
WScript.Echo "-------------------------------------------------"
i = 1 : j = 1
For Each objClassMethod In objClass.Methods_
      WScript.Echo i & ". " & objClassMethod.Name
      For Each objMethodQualifier In objClassMethod.Qualifiers_
          If VarType(objMethodQualifier.Value) = (vbVariant + vbArray) Then
              strQualifier = i & "." & j & ". " & _
                             objMethodQualifier.Name & " = " & _
                             Join(objMethodQualifier.Value, ",")
          Else
              strQualifier = i & "." & j & ". " & _
                             objMethodQualifier.Name & " = " & _
                             objMethodQualifier.Value
          End If
          WScript.Echo strQualifier
          strQualifier = ""
          j = j + 1
      Next
      WScript.Echo
      i = i + 1 : j = 1
Next
如果我们执行上述代码来查找win32_service类的限定符,一般情况下可以得到如下信息:
win32_service 的类限定信息如下:
------------------------------
1. dynamic = True
2. Locale = 1033
3. provider = CIMWin32
4. SupportsUpdate = True
5. UUID = {8502C4D9-5FBB-11D2-AAC1-006008C78BC7}
win32_service 类的属性和属性限定信息
------------------------------------------------------
1. AcceptPause
1.1. CIMTYPE = boolean
1.3. read = True
……
win32_service 类的方法和方法限定信息
-------------------------------------------------
1. StartService
1.1. MappingStrings = Win32API|Service Functions|StartService
1.2. Override = StartService
1.3. ValueMap = 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,..
……
  返回的信息很多,我省略了其中的绝大部分,只保留了一部分典型的来说明我们应该如何读懂类的限定信息。
  返回信息的第一部分表明了对于此类的限定信息:
  1. dynamic = True    Abstract——抽象类,Dynamic——动态类,Association——关联类,表明win32_service类是动态类。
  2. Locale = 1033      代表着区域设置或者叫本地化编码,是一组与用户的语言、国家/地区以及文化传统有关的用户首选信息,确定诸如:键盘布局、字母的排序顺序,以及日期、时间、数字、货币等的格式,一般不用管它。
  3. provider = CIMWin32    Provider代表的是类的提供程序,说明win32_service类是由CimWin32.dll提供的。
  4. SupportsUpdate = True    指出类是否支持实例的修改。
  5. UUID = {8502C4D9-5FBB-11D2-AAC1-006008C78BC7}    代表本地计算机上的全球通用唯一的标识符,我不知道有什么用处。
  
  返回信息的第二部分代表了类的属性限定符
  1. AcceptPause
  这第一行表明检索到的类的属性名是:AcceptPause
  1.1. CIMTYPE = boolean    CIMType代表属性的数据类型,说明这个属性是布尔型。
  1.3. read = True     read代表属性可读,而Write则代表属性的值是否可以修改,如果属性没有定义Write限定符,代表什么意思呢?它代表从该类获得的实例的那个属性是不可以改写的,也就是说不能给这个属性赋值。这其实解决了一个困惑我很久的一个问题,为什么我在对很多类的属性进行了赋值后,用Put_方法对修改进行了提交,可是事实上却什么也没有改变。此外还有Key限定符指出该属性是类的键,用于识别在相同资源集合中的托管资源的唯一实例。
  
  返回信息的第三部分代表了类的方法及方法的限定符。现在我们能用到的还不多,就不介绍了,有兴趣的朋友可以参照:http://msdn2.microsoft.com/en-us/library/aa393650.aspx
  需要说明的是,不是在每一个类定义或者属性、方法定义中,这所有的限定符都要出现的,可能只出现了其中的一部分。
  当然,我们也可以从system32\wbem\cimwin32.mof以及system32/wbem/cimwin32.mfl两个文件中读取整个托管资源的类定义和类描述,以及对每个类的属性、方法和限定符的描述,其中包含的信息很多,也包含了更多的类限定符,阅读起来有一定的难度。将上面的例子的代码和vbsedit中包含的Object Browser联合起来,可以得到我们需要的绝大部分的信息。COPY

TOP

◎简单WSC组件的基本结构
WSC是微软公司提供的使用脚本语言来创建 COM 部件的便利途径,它可以应用于支持 COM 部件的应用程序。WSC采用XML语言编写。一个标准的WSC组件本身涉及到XML标记相当复杂,但幸好它的结构非常规范,了解结构,填入代码,一个WSC脚本部件就可以工作了。
就我个人而言,把WSC部件分成三个部分:注册部分,定义属性、方法、事件部分和实现部分。
1、注册部分:
主要包含了向注册表注册部件时需要填写的信息。一般包含了部件描述、版本信息、progid、clsid等四个内容。基本格式如下:
<registration
description="部件描述的信息"
version="部件的版本号"
progid="XXXX.XXX"        /程序ID
clsid="xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx"/>
需要说明的是:
①registration是XML标记。
②progid是VBS通过CreateObject函数通过绑定组件创建实例时的标志,一个组件如果没有ProgId,几乎是无法使用的。例如:
Set obj=CreateObject("scripting.filesystemobject")
代码中的scripting.filesystemobjec就是ProgId。
③Clsid是部件在注册表项中的唯一标志,系统注册时把有关部件的信息放在注册表中,应用时通过读取注册信息,应用程序可以找到并载入该部件。可以使用Uuidgen.exe 的程序随机生成。当然如果你不指定Clsid,系统注册时regsvr32会为它自动创建一个,但正常情况下应该指定一个。由于我的计算机上没有安装VC,所以Uuidgen.exe和GUIDGen.exe文件,Clsid从一直是我极为头疼的问题,幸好UMU给出了一个脚本产生,现把代码抄录如下:
Dim objSLTL
Set objSLTL = CreateObject( "Scriptlet.TypeLib" )
Wscript.echo objSLTL.GUID
Set objSLTL = Nothing
2、定义属性、方法、事件部分
在这个部分定义了用户在脚本中可以使用的属性、方法、事件,其基本结构如下:
<Public>
<property name="属性一" >
<get/>
       <Put/>
</property>
<method name="方法一">
       <parameter name="参数一"/>
</method>
<event name="事件一">
       <parameter name="参数一"/>
</event>
</Public>
其中Public是XML的标记,property、method、event标记分别定义了部件属性、方法、事件。Name标记定义了其名称,Parameter标记定义了其参数。作为property标记来说,本身带有两个子标记,它们分别是<get/><put/>,它们两个分别定义了读写属性的方式。当需要读写属性的时候,就会自动执行它们中的一个。在实现部分中,它们会以Put_属性名 或者 Get_属性名的形式出现。如果忽略了<get/>标记,则此属性是只可写的,忽略了<Put/>标记,说明此属性是只读的。作为vbs脚本,在脚本中响应事件的机会是比较少的,对此也就不再详细的说明。
3、实现部分
在上一部分定义的所有的属性、方法、事件的实现函数都必须包含在<Script>标记中。结构如下:
<script language="VBScript">
<![CDATA[
定义公用变量
进行初始化
Function 函数名称()
函数实现
End funciton
]]>
</script>
抛开XML的标记不管,我们只需要有关的部分进行修改就可以了。在Public部分定义的属性和方法,在本部分必须定义相应的变量和函数。
当然,WSC作为一个XML格式的文件,一些基本的标记还是需要知道的,下面有关标记说明摘自微软。
<component><package>元素:<component> 元素包含的是一个完整的脚本部件定义。在同一个 .wsc 文件中可以出现多个 <component> 元素,但这些元素应包含在一个 <package> 元素内。
<registration>元素:包括用来将脚本部件注册为 COM 部件的信息。
<public>元素:包含脚本部件所说明的属性、方法和事件的定义。这些定义指向定义在独立的 <script> 块中的变量或函数。
<implements>元素:给脚本部件指定COM接口处理程序,这将确定该脚本部件属于哪种COM部件类型。例如,通过指定 <implements type=ASP>,就可以实现 ASP 接口处理程序,并因此在脚本部件中可以访问ASP对象模型。
<public>元素:指定了脚本部件将实现 COM Automation 接口处理程序。因此,对 Automation 处理程序无需创建<implements>元素。
<script>元素:包含用来实现脚本部件逻辑的脚本,这取决于所创建的COM部件类型。例如,如果要创建的是 COM Automation 部件,则可以在
<public> 元素中声明属性、方法和事件,然后用一个或多个 <script> 元素编写脚本来定义这些内容。
<object>元素:包含脚本中所使用的某个对象的信息,如另一个 COM 部件的信息。
<resource>元素:包含不应被硬编码到脚本部件代码中的值。资源元素可能包括在各个版本间可能更改的信息,可能需要翻译的字符串以及其他值。
<reference>元素:引用在脚本中需要使用的类型库。
<comment>元素:包含在分析和执行该脚本部件时将被忽略的文字,说明或者注释。
了解了这些知识,让我们来看一个最最简单的例子:
<?XML version="1.0"?>
       <package>
         <component id="test">
           <registration
             progid="ID"
             description="description"
             version="1"
             clsid="{A66E243C-CF13-42AC-BE67-558F2FA82B39}"/>
           <public>
             <property name="du"/>
               <get/>
             <method name="xie"/>
           </public>
           <script language="VBScript">
             <![CDATA[
               dim du
               function get_du()
          du=get_du
               End function
               Function xie()
                 msgbox du
               End Function
             ]]>
           </script>
         </component>
       </package>
用代码调用
Set test=CreateObject("ID")
test.du=5
test.xie
显示正常COPY

TOP

◎使用脚本部件向导简化WSC设计
尽管XML语言被设计成为一种相对精简的标记语言,符合XML格式的WSC部件也设计的极为规范,但就我而言,在具体的设计过程中,出错最多的仍然在XML的各种标记上,幸好,微软推出了专门生成WSC部件代码的工具Windows Script Component Wizard,这个工具可以迅速的为我们搭建好WSC部件的框架,极大的方便了我们对WSC部件的编写,此向导除了在微软的网站上下载外,在我的网盘上也有一份拷贝。
它的使用方法也极为简单,就连诸如我之流E文程度极差者也能使用。
如上例,生成如下代码:
<?xml version="1.0"?>
<component>
<?component error="true" debug="false"?>
<registration
       description="测试用的WSC部件"
       progid="test.WSC"
       version="1.00"
       classid="{155642f0-fbad-4f98-90cb-b38b7a3cf428}"
>
</registration>
<public>
       <property name="start">
              <get/>
       </property>
       <property name="end">
              <get/>
              <put/>
       </property>
       <method name="print">
              <PARAMETER name="para1"/>
              <PARAMETER name="para2"/>
       </method>
       <method name="list">
              <PARAMETER name="para3"/>
       </method>
</public>
<implements type="Behavior" id="Behavior"/>
<script language="VBScript">
<![CDATA[
dim start
dim end
function get_start()
       get_start = start
end function
function get_end()
       get_end = end
end function
function put_end(newValue)
       end = newValue
end function
function print(para1,para2)
       print = "Temporary Value"
end function
function list(para3)
       list = "Temporary Value"
end function
]]>
</script>
</component>
呵呵,该有的东西全有了,属性对应的变量也定以来,我们只要对其中实现部分稍加修改就可以注册应用了,需要注意的是,如果在WSC编码设计中出现汉字,则必须在第一行添加encoding="gb2312"标记,既第一行为:
<?xml version="1.0" encoding="gb2312" ?>
才能正常通过注册。COPY

TOP

◎Adodb.Stream 的使用说明(转发)
  ADODB.Stream组件是很重要的组件,以前一直找不全,先转过来有时间好好看看。
  1、注册ADODB.Stream组件
  regsvr32 "C:\Program Files\Common Files\System\ado\msado15.dll"
  
  2、使用说明
  组件:"Adodb.Stream"
  有下列方法:
  Cancel 方法
  使用方法如下
  Object.Cancel
  说明:取消执行挂起的异步 Execute 或 Open 方法的调用。
  Close 方法
  使用方法如下
  Object.Close
  :关闭对像
  CopyTo 方法
  使用方法如下
  Object.CopyTo(destStream,[CharNumber])
  说明:将对像的数据复制,destStream指向要复制的对像,CharNumber为可选参数,指要复制的字节数,不选为全部复制。
  Flush 方法
  使用方法如下
  Object.Flush
  说明:
  LoadFromFile 方法
  使用方法如下
  Object.LoadFromFile(FileName)
  说明:将FileName指定的文件装入对像中,参数FileName为指定的用户名。
  Open 方法
  使用方法如下
  Object.Open(Source,[Mode],[Options],[UserName],[Password])
  说明:打开对像,
  参数说明:Sourece 对像源,可不指定
  Mode 指定打开模式,可不指定,可选参数如下:
  adModeRead =1
  adModeReadWrite =3
  adModeRecursive =4194304
  adModeShareDenyNone =16
  adModeShareDenyRead =4
  adModeShareDenyWrite =8
  adModeShareExclusive =12
  adModeUnknown =0
  adModeWrite =2
  Options 指定打开的选项,可不指定,可选参数如下:
  adOpenStreamAsync =1
  adOpenStreamFromRecord =4
  adOpenStreamUnspecified=-1
  UserName 指定用户名,可不指定。
  Password 指定用户名的密码
  Read 方法
  使用方法如下:
  Object.Read(Numbytes)
  说明:读取指定长度的二进制内容。
  参数说明:Numbytes指定的要读取的找度,不指定则读取全部。
  ReadText 方法
  使用方法如下:
  Object.ReadText(NumChars)
  说明:读取指定长度的文本
  参数说明:NumChars指定的要读取的找度,不指定则读取全部。
  SaveToFile 方法
  使用方法如下:
  Object.SaveToFile(FileName,[Options])
  说明:将对像的内容写到FileName指定的文件中
  参数说明:FileName指定的文件
  Options 存取的选项,可不指定,可选参数如下:
  adSaveCreateNotExist =1
  adSaveCreateOverWrite =2
  SetEOS 方法
  使用方法如下:
  Object.setEOS()
  说明:
  SkipLine 方法
  使用方法如下:
  Object.SkipLine()
  说明:
  Write 方法
  使用方法如下:
  Object.Write(Buffer)
  说明:将指定的数据装入对像中。
  参数说明:Buffer 为指定的要写入的内容。
  WriteText 方法
  使用方法如下:
  Object.Write(Data,[Options])
  说明:将指定的文本数据装入对像中。
  参数说明:Data 为指定的要写入的内容。
  Options 写入的选项,可不指定,可选参数如下:
  adWriteChar =0
  adWriteLine =1
  有下列属性:
  Charset
  EOS 返回对像内数据是否为空。
  LineSeparator 指定换行格式,可选参数有
  adCR =13
  adCRLF =-1
  adLF =10
  Mode 指定或返加模式。
  Position 指定或返加对像内数据的当前指针。
  Size 返回对像内数据的大小。
  State 返加对像状态是否打开。
  Type 指定或返回的数据类型,可选参数为:
  adTypeBinary =1
  adTypeText =2
  用了6行代码实现了无组件上传:
  strFileName = Request.QueryString("file1")
  Set objStream = Server.CreateObject("ADODB.Stream")
  objStream.Type = 1 ' adTypeBinary
  objStream.Open
  objStream.LoadFromFile strFileName
  objStream.SaveToFile Server."123_onweb.gif",2
  使用方法:
  把上面的代码写成upload.asp
  在浏览器里面输入:
  http://XXX/upload.asp?file1=c:\上传文件\123.gif
  XXX为你的主机地址
  执行完后你会看到你的目录下面多了一个123_onweb.gif
  他就是你要文件拉!!!!
  根据原理我们可以扩展以下代码:
  upload.asp文件
  <%
  Function GetFileName(ByVal strFile)
  If strFile <> "" Then
  GetFileName = mid(strFile,InStrRev(strFile, "\")+1)
  Else
  GetFileName = ""
  End If
  End function
  strFileName = Request.Form("file1")
  Set objStream = Server.CreateObject("ADODB.Stream")
  objStream.Type = 1 ' adTypeBinary
  objStream.Open
  objStream.LoadFromFile strFileName
  objStream.SaveToFile Server.MapPath(GetFileName(strFileName)),2
  objStream.Close
  %>
  upload.htm文件
  <form name="FORM" action="upload.asp" method="post">
  <input type="submit" name="submit" value="OK">
  <input type="file" name="file1" style="width:400" value="">
  </form>
  读文件不想用FSO,有的空间不支持。
  有一个LoadFromFile的方法。可以读取文件。
  下面是我的代码。
  function readfile(URL,chartype)
  set srmObj = server.CreateObject("adodb.stream")
  srmObj.type=1
  srmObj.mode=3
  srmObj.open
  srmObj.Position=0
  srmObj.LoadFromFile URL
  srmObj.Position = 0
  srmObj.type=2
  srmObj.charset=chartype
  readfile=srmObj.readtext()
  end function
  两个参数。URL是文件的路径,好像只能绝对路径。chartype是文件以什么编码存放的。
  返回一个字符串,存放文件的内容。
  这个函数只能读文本文件。读二进制文件也差不多。要用的人可以自己改
  < = src="/article/js/c9.js"> 基于adodb.stream的文件操作类
  <%
  ’*************************************************************
  ’转发时请保留此声明信息,这段声明不并会影响你的速度!
  ’*************************************************************
  ’*************************************************************
  ’@author: 面条
  ’@realname: 徐仁禄
  ’@email: xurenlu@sohu.com
  ’@QQ: 55547082
  ’@Homepage: http://www.ksdn.net
  ’@版权申明:
  ’ 非盈利性质团体或者个人可以免费使用.
  ’*************************************************************
  ’*************************************************************
  ’ 类名称: files
  ’ 类功能: 实现文件读写功能,利用adodb.stream实现,在不支持fso的主机上也可以读写文件.
  ’*************************************************************
  class files
  private adSaveCreateOverWrite ’创建文件的时候可以覆盖已经存在的文件.
  private adSaveCreateNotExist ’保存文件的时候如果文件不存在,可以创建文件.
  ’*************************************************************
  ’ 事件名称: Class_Initialize()
  ’ 事件发生条件: 类创建时候产生该事件
  ’ 事件内容: 给私有变量赋值
  ’ 事件传入参数: 无
  ’*************************************************************
  sub Class_Initialize()
  adSaveCreateOverWrite =2
  adSaveCreateNotExist = 1
  end sub
  ’*************************************************************
  ’ 函数名称: function readfile(filepath)
  ’ 函数内容: 读出文件
  ’ 传入参数: filepath:要读的文件的绝对路径
  ’ 返回参数: 要读的文件的内容.
  ’*************************************************************
  function readfile(filepath)
  on error resume next
  dim stm2
  set stm2 =server.createobject("ADODB.Stream")
  stm2.Charset = "gb2312"
  stm2.Open
  stm2.LoadFromFile filepath
  readfile = stm2.ReadText
  end function
  ’*************************************************************
  ’ 函数名称: function writefile(filepath,str)
  ’ 函数内容: 写入文件
  ’ 传入参数: filepath:要读的文件的绝对路径
  ’ str: 要写入的内容
  ’ 返回参数: 无返回
  ’*************************************************************
  function writefile(filepath,str)
  on error resume next
  Set stm = server.createobject("ADODB.Stream")
  stm.Charset = "gb2312"
  stm.Open
  stm.WriteText str
  stm.SaveToFile filepath, adSaveCreateOverWrite
  end function
  ’*************************************************************
  ’ 函数名称: function copy(filepath_s,filepath_d)
  ’ 函数内容: 读出文件
  ’ 传入参数: filepath_d:目的文件的绝对路径
  ’ filepath_s:源文件路径
  ’*************************************************************
  function copy(filepath_s,filepath_d)
  on error resume next
  dim stm2
  set stm2 =server.createobject("ADODB.Stream")
  stm2.Charset = "gb2312"
  stm2.Open
  stm2.LoadFromFile filepath_s
  stm2.SaveToFile filepath_d, adSaveCreateOverWrite
  end function
  end class
  利用Adodb.Stream直接下载文件
  在浏览器的地址栏里直接输入一个doc或xls或jpg的文件的url路径,那么该文件会直接显示在浏览器里。而在很多时候我们希望能直接弹出下载提示框让用户下载,我们该怎么办呢?这里有两种方法:
  1、设置你的服务器的iis,给doc等后缀名做映射
  2、在向客户端发送时设置其contenttype
  下面详细说明方法2
  程序代码:
  _code style="DISPLAY: none" name="html_code"><%
  Response.Buffer = true
  Response.Clear
  dim url
  Dim fso,fl,flsize
  dim Dname
  Dim objStream,ContentType,flName,isre,url1
  '*********************************************调用时传入的下载文件名
  Dname=trim(request("n"))
  '******************************************************************
  If Dname<>"" Then
  '******************************下载文件存放的服务端目录
  url=server.MapPath("/")&"\"&Dname
  '***************************************************
  End If
  Set fso=Server.CreateObject("Scripting.FileSystemObject")
  Set fl=fso.getfile(url)
  flsize=fl.size
  flName=fl.name
  Set fl=Nothing
  Set fso=Nothing
  %>
  <%
  Set objStream = Server.CreateObject("ADODB.Stream")
  objStream.Open
  objStream.Type = 1
  objStream.LoadFromFile url
  Select Case lcase(Right(flName, 4))
  Case ".asf"
  ContentType = "video/x-ms-asf"
  Case ".avi"
  ContentType = "video/avi"
  Case ".doc"
  ContentType = "application/msword"
  Case ".zip"
  ContentType = "application/zip"
  Case ".xls"
  ContentType = "application/vnd.ms-excel"
  Case ".gif"
  ContentType = "image/gif"
  Case ".jpg", "jpeg"
  ContentType = "image/jpeg"
  Case ".wav"
  ContentType = "audio/wav"
  Case ".mp3"
  ContentType = "audio/mpeg3"
  Case ".mpg", "mpeg"
  ContentType = "video/mpeg"
  Case ".rtf"
  ContentType = "application/rtf"
  Case ".htm", "html"
  ContentType = "text/html"
  Case ".txt"
  ContentType = "text/plain"
  Case Else
  ContentType = "application/octet-stream"
  End Select
  Response.AddHeader "Content-Disposition", "attachment; filename=" & flName
  Response.AddHeader "Content-Length", flsize
  Response.Charset = "UTF-8"
  Response.ContentType = ContentType
  Response.BinaryWrite objStream.Read
  Response.Flush
  response.Clear()
  objStream.Close
  Set objStream = Nothing
  %>
  _lightcode style="BORDER-RIGHT: #999999 1px dotted; PADDING-RIGHT: 5px; BORDER-TOP: #999999
  1px dotted; PADDING-LEFT: 5px; FONT-SIZE: 11px; PADDING-BOTTOM: 5px; BORDER-LEFT: #999999
  1px dotted; PADDING-TOP: 5px; BORDER-BOTTOM: #999999 1px dotted; FONT-FAMILY: sans-serif;
  HEIGHT: 40px; BACKGROUND-COLOR: #f9f9f9" name="html_lightcode"><%
  Response.Buffer = true
  Response.Clear
  dim url
  Dim fso,fl,flsize
  dim Dname
  Dim objStream,ContentType,flName,isre,url1
  '*********************************************调用时传入的下载文件名
  Dname=trim(request("n"))
  '******************************************************************
  If Dname<>"" Then
  '******************************下载文件存放的服务端目录
  url=server.MapPath("/")&"\"&Dname
  '***************************************************
  End If
  Set fso=Server.CreateObject("Scripting.FileSystemObject")
  Set fl=fso.getfile(url)
  flsize=fl.size
  flName=fl.name
  Set fl=Nothing
  Set fso=Nothing
  %>
  <%
  Set objStream = Server.CreateObject("ADODB.Stream")
  objStream.Open
  objStream.Type = 1
  objStream.LoadFromFile url
  Select Case lcase(Right(flName, 4))
  Case ".asf"
  ContentType = "video/x-ms-asf"
  Case ".avi"
  ContentType = "video/avi"
  Case ".doc"
  ContentType = "application/msword"
  Case ".zip"
  ContentType = "application/zip"
  Case ".xls"
  ContentType = "application/vnd.ms-excel"
  Case ".gif"
  ContentType = "image/gif"
  Case ".jpg", "jpeg"
  ContentType = "image/jpeg"
  Case ".wav"
  ContentType = "audio/wav"
  Case ".mp3"
  ContentType = "audio/mpeg3"
  Case ".mpg", "mpeg"
  ContentType = "video/mpeg"
  Case ".rtf"
  ContentType = "application/rtf"
  Case ".htm", "html"
  ContentType = "text/html"
  Case ".txt"
  ContentType = "text/plain"
  Case Else
  ContentType = "application/octet-stream"
  End Select
  Response.AddHeader "Content-Disposition", "attachment; filename=" & flName
  Response.AddHeader "Content-Length", flsize
  Response.Charset = "UTF-8"
  Response.ContentType = ContentType
  Response.BinaryWrite objStream.Read
  Response.Flush
  response.Clear()
  objStream.Close
  Set objStream = Nothing
  %>COPY

TOP

◎VBS脚本编程简明教程(补充读物-初窥WMI)
    今天,我沼泽将给大家介绍个朋友,它就是Microsoft Windows Management Instrumentation (WMI)。中文名字叫Windows管理规范。从Windows 2000开始,WMI(Windows 管理规范)就内置于操作系统中,并且成为了Windows系统管理的重要组成部分。所以大家很容易就能见到它的,因为我们至少也应该是个Windows 2000的使用者了。下面我将详细介绍它的每个细节,让你从不认识它到喜欢上它。
WMI能做什么?
WMI不仅可以获取想要的计算机数据,而且还可以用于远程控制。远程控制计算机可是大家都喜欢的东西。很多远程监视控制类软件通常的做法是:在远程计算机上运行服务端后台程序,在本地计算机上运行一个客户端控制程序,通过这二个程序的勾结来实现对计算机的远程控制。这种作法的缺点是十分明显的,当服务端程序关了,这种远程监控就无法实现了,因为没有内线了。而WMI实现的远程监视和控制完全不需要另外装什么服务端的东西,系统默认就将WMI服务给开了。具体说来,WMI的本领如下:
1.获取本地和远程计算机的硬件软件信息。
2.监视本地和远程计算机的软件和服务等运行状况。
3.控制本地和远程计算机的软件和服务运行。
4.高级应用。
如何访问WMI?
当我们知道WMI的某些本领后,我们已经很想知道如何认识他并利用他了。利用WMI有许多途径,简单说来有三种了:
1.通过微软给我们提供的各种工具来实现普通查询和操作。主要包括命令提示符下面的WMIC,还有就是微软给我们提供的WMI TOOL,大家可以到微软的网站上免费下载,当然我也可以给大家免费提供。
2.通过自己编写脚本来实现更灵活操作。要想真正灵活实用,对WSH脚本的熟悉是必须的,当然如果你不熟悉也没有关系,稍后我会给大家详细解释的。
3. 通过编写我们自己的程序来访问并操作它。什么语言都行。如果用.NET类程序要简单些了,如果用VC等要复杂些了,起码我是这么认为的。
4.还有个访问它的方法,就是到它的一个巢穴。在C:\WINDOWS\system32\wbem目录中的东西都和它有密切联系,有日志和各种工具,在里面你可以找到很多答案的。不过这些东西一般都不适合我们新手玩了,感觉有点吓人。
我们今天的任务?
今天我们的任务有五个:
任务一:利用WMIC列出远程计算机上的所有进程。
任务二:利用WMIC关闭本地进程。
任务三:通过WMIC把远程主机的进程信息保存在一个网页中
任务四:利用脚本实时监视对方进程
任务五:利用脚本给对方开放共享
查看和监视进程,还要把进程给杀掉,最后还要给对方开个共享,我们这位朋友快把坏事做尽了。明白了我们的任务,我们就可以上路了。这次我们将主要借助WMIC和脚本来实现我们的任务,所以我们将主要分为两大部分来讲解。在五个任务的实战中我们将更加深入地理解它,没有基础没有关系,我将尽力去解释所有的所谓的基础,让大家能很轻松地和这位朋友交流。
第一部分:利用WMIC来认识WMI
WMIC是Windows Management Instrumentation Commandline的简称,WMIC扩展WMI,提供了从命令行接口和批命令脚本执行系统管理的支持。为WMI名称空间提供了一个强大的、友好的命令行接口。有了WMIC,WMI就显的平易近人了。
执行"WMIC"命令将启动WMIC命令行环境。第一次执行WMIC命令时,Windows首先要安装WMIC,然后显示出WMIC的命令行提示符。在WMIC命令行提示符上,命令将以交互的方式执行。如果你不知道该如何和它交互,请敲个"/?",细细看完全部的说明,你就知道了。WMIC也可以按照非交互的模式运行。如果要执行某个单步的任务,或者运行批命令中的一系列WMIC命令,非交互模式就很有用。要使用非交互模式,只要在同一个命令行上启动WMIC并输入要执行的命令就可以了。
1.任务一:利用WMIC列出远程计算机上的所有进程
这是一个实现起来很简单的任务,和你用一个DOS命令一样简单,因为我们要循序渐进嘛,所以安排了这么一个热身任务。在命令提示符下敲入下面的命令,我们将看到。
WMIC /node:192.168.1.2 /user:net process
解说:
1)上面命令中的NODE和USER是全局开关。如果你不愿意另外输一次密码,你也可以用PASSWORD开关,后面写上密码就可以了(WMIC /node:192.168.1.2 /user:net /password:password process)。千万要注意,这里的用户名和密码都必须是管理员级别的,其它的无效。WMIC提供了大量的全局开关、别名、动词、命令和丰富的命令行帮助增强用户接口。全局开关是用来配置整个WMIC会话的选项。
2Process是个别名,执行了一个Win32_process类的WQL查询,至于说是WMI的类是什么东西,感兴趣的就自己找资料多多了解,如果你很懒的话,就等我有时间给你开课讲解。别名是用户和WMI名称空间一个简化语法的中间层。当你指定一个别名时,动词(Verb)表示要执行的动作。
3)如果你愿意,你可以在该后面加上个动词等,比如 LIST FULL等(如:WMIC /node:192.168.1.2 /user:net /password:password process),这样你就看得更清楚了。
小提示:安装了WMIC的机器可以连接到任何一台安装了WMI的机器,被连接的机器不需要安装WMIC。
2.任务二:利用WMIC关闭本地进程
执行下面的命令将关闭正在运行的QQ。我比较胆小,所以不敢关别人的QQ,只能拿我的QQ试验了,如果你的智商还够用的话,胆子比较大的话,你很快就会去关别人的了。
WMIC
process where name="qq.exe" call terminate
解说:
1)这次我们是用交互式的方法来执行任务,具体界面我就不多说了,图上画的比我说的好多了。
2)Call也是个动词,这个动词可是厉害了,控制类的没有不用它的,它就是可以调用各种类的各种方法的大将。这里我们调用了terminate方法。从字面上你就可以看出是恶狠狠的。
3)Where能够让你查询和筛选。在超级多的实例中找到你想要的。实例就是指每个类的具体实现了。前面的例子中看到的各个进程都分别算是WIN32_PROCESS中的一个实例。
3.任务三:通过WMIC把远程主机的进程信息保存在一个网页中
这个任务和任务一中的大致相同,是任务一的加强。在任务一中信息以文本的形式显示出来了。其实除了文本形式的输出之外,WMIC还能够以其他形式返回命令执行结果,例如XML、HTML或者CSV(逗号分隔的文本文件),如图3所示。我们可以敲入下面的命令:
wmic /output:C:\1.html /node:192.168.1.2 /user:net process list full /format:hform.xsl
输入密码 :******
解释:
1)全局开关OUTPUT指明将这些信息保存在什么地方。
2)全局开关FORMAT指明了用什么样的格式,至于说有那些格式可以用,你可以参看C:\WINDOWS\system32\wbem目录中的*.xsl文件,你甚至不用管它们从哪里来的,用就是了。挨着看看,一定可以找到你喜欢的。
第二部分:利用脚本来认识WMI
命令提示符的工具确实好用,但是却显示不出我们是高手,高手都是能利用程序来实现目的的。下面我们就开始用脚本来实现我们的任务,功能将更加强大,操作将更加灵活。
无论脚本还是真正意义上的程序,要检索 WMI 托管资源信息进而查询并利用WMI,都需要遵循以下三个步骤的。
1.连接到 WMI 服务。建立一个到目标计算机上的 Windows 管理服务的连接。
2.检索 WMI 托管资源的实例。主要取决于要执行的任务。
3.显示WMI 某实例属性和调用其方法。
1.任务四:利用脚本实时监视对方进程
在任务一和任务三中我们都是在查看对方的进程,出来的结果对我们意义不是很大,在这个任务中我们要从现在开始每当他开一个任务我们就察觉到,并把它记录下来。我们要在他开进程的那一秒开始报告并记录,我们要清楚他所开的程序所在的位置,我们要比他更清楚地知道这些信息。
现在我们就按照前面提到的三个步骤来实现任务。
首先,我们连接到对方的WMI。在这里我们首先调用 VBScript 的中的CreateObject()来得到一个对象,然后利用这个特殊的对象的方法来连接到远程的计算机上。这个特殊的对象就是wbemscripting.swbemlocator。
set olct=CreateObject("wbemscripting.swbemlocator")
set wbemServices=olct.connectserver(strComputer,"root\cimv2",strUser,strPwd)
注意其中的strComputer就是你所要连接的计算机的名称或者IP地址,strUser,strPwd当然就是用户名和密码了,我们说过这个用户必须是具有管理员权限的才可以。root\cimv2是WMI的命名空间,关于WMI的命名空间,大家可以到"计算机管理\WMI控件"中看到,这里面的学问就大了,得慢慢琢磨,为了我们的任务快速实现,我就不多解释了。用这种方法连接到WMI,返回一个对SWbemServices对象的引用,一旦有一个对 SWbemServices对象的引用。我们就可以进行第二个步骤了。
在第二个步骤中,我们将得到WMI 托管资源的实例,我们利用WbemServices中的一个方法ExecNotificationQuery可以查询我们所要的类,进而可以得到该类中实例。
Set colMonitoredProcesses = wbemServices. _
ExecNotificationQuery("select * from __instancecreationevent " _
& " within 1 where TargetInstance isa 'Win32_Process'")
注意这里有个类似于SQL语言的查询语言,这里叫做WQL语言,懂SQL的一看就明白了,不懂的就在网上找找它的资料,满天都是。得到的colMonitoredProcesses是所查询的类的实例的集合。有了这些我们的第三个步骤就可以开始了。
在第三个步骤中,我们将显示出得到的实例中的属性。刚才我们得到的是实例的集合,在这里我们通过colMonitoredProcesses.NextEvent来获取每一个具体的实例,得到每一个具体的实例后,我们就可以显示出他们的属性,也就是我们想看的东西了。这里我们显示了CommandLine的属性值。
到现在你是否有些迷惑了,因为你还不知道到底WMI里面有那些类,具体类又有哪些属性,呵呵,没有关系的,用一些工具可以很轻松的得到这些信息。比如系统自带的wbemtest,在运行中敲入这个程序名,你就可以看到这些了,它也遵循连接、查询、枚举这三个步骤。自己慢慢玩吧,很快你就会发现WMI太大了,单是命名空间就有10多个,然后单是我们常用的空间root\CIMV2里面就有近1000个类,每个类里面又有好多的属性,有些类还有好多方法。哈哈,头晕了吧?没关系,其实你只需要知道其中的一些就好了。
看到这些估计你的头已经很大了,但是恭喜你,我们的这个任务已经完成了,是的,就是这么简单,下面我将完整代码奉献出来。
Set colArgs = WScript.Arguments
If WScript.arguments.count < 3 then
WScript.Echo "USAGE:" & vbCrLf & " Monitor Computer User Password files"
WScript.quit
End If
strComputer = WScript.arguments(0)
strUser = WScript.arguments(1)
strPwd = WScript.arguments(2)
strFile = WScript.arguments(3)
set olct=CreateObject("wbemscripting.swbemlocator")
set wbemServices=olct.connectserver(strComputer,"root\cimv2",strUser,strPwd)
Set colMonitoredProcesses = wbemServices. _
ExecNotificationQuery("select * from __instancecreationevent " _
& " within 1 where TargetInstance isa 'Win32_Process'")
i = 0
Do While i = 0
Set objLatestProcess = colMonitoredProcesses.NextEvent
WScript.Echo now & " " & objLatestProcess.TargetInstance.CommandLine
Set objFS = CreateObject("Scripting.FileSystemObject")
Set objNewFile = objFS.OpenTextFile(strFile,8,true)
objNewFile.WriteLine Now() & " " & objLatestProcess.TargetInstance.CommandLine
objNewFile.Close
Loop
到这个程序的核心了吧?相信你已经懂了其中的很多,剩余的部分代码我稍后解释。我们先来感性认识一下,先看它该怎么用吧!把上面的代码拷贝到记事本中,然后保存为monitor.vbs的文件,然后在命令提示符下输入:
CSCRIPT monitor.vbs
回车,你就会看到帮助,下面举例说明这个脚本的具体用法:
CSCRIPT monitor.vbs 192.168.1.2 user password C:\1.txt
在命令提示符下敲入上面的命令就OK了,每当对方开一个程序的时候,你就可以看到时间,程序路径和程序名。如果你没有时间去看这些信息,你还可以等有时间的时候到C:\1.txt看到这些信息。
小知识:
每次使用脚本,都必须敲入CSCRIPT和脚本的后缀名,很麻烦。这是因为系统默认的执行引擎是WScript,可以将它改成CSCRIPT。另外一个让人不爽的是脚本执行后总要显示微软的说明,好像脚本不是我们写的一样。不过你可以通过在命令提示符下敲入下面的命令来解决这个问题:
cscript //nologo //h:cscript //s
这样你以后再运行这些脚本的时候就不用在敲入CSCRIPT了,也不用在写入.vbs的后缀名了,就上面的例子来说,你可以这样用:
monitor 192.168.1.2 user password C:\1.txt
解释:
1)前面的那几行,大概就是为了显示帮助和处理我们在后面输入的参数。应用到了WScript.Arguments这个对象,利用它我们可以来获取并处理脚本的参数。
2)那个死循环是为了让我们一直监视他(她),每当他开一个程序,我们就得到一个新的实例,我们就可以知道他更多的信息,哈哈,够狠吧。这样你也就知道了,当我们这个脚本运行后,只有通过我们人为中止才能中断监视,人为中止的方法大家可以用CTRL+C来完成,也可以用各种野蛮的方法来中止。
3)在代码中出现的另外一个核心对象就是FileSystemObject,应该是大家的老朋友了吧,我这里就不再做解释了,我们在这里应用它主要是为了将结果同时保存到一个文件中,我们利用它来创建或打开一个文件,将信息追加进去。
4)至于那个NOW,虽然体积很小,但是却正是它给我们提供了时间这个重要的信息。
5)如果你想要监视的是自己的计算机而不是远程的计算机(据我所知,这个应用还是很广的)。那么请将计算机名的参数写为一个小点,用户名和密码留为空。如下所示:
monitor . "" "" C:\1.txt
2.任务五:利用脚本给对方开放共享
有了任务四的基础,这次我们就先看代码吧:
Set colArgs = WScript.Arguments
If WScript.arguments.count < 5 then
WScript.Echo "USAGE:" & vbCrLf & " Rshare Computer User Password SharePath ShareName"
WScript.quit
End If
strComputer = WScript.arguments(0)
strUser = WScript.arguments(1)
strPwd = WScript.arguments(2)
strPath = WScript.arguments(3)
strShareName = WScript.arguments(4)
intMaximumAllowed = 1
strDescription = "Temporary share"
Const SHARED_FOLDER = 0
set olct=CreateObject("wbemscripting.swbemlocator")
set wbemServices=olct.connectserver(strComputer,"root\cimv2",strUser,strPwd)
Set objSWbemObject = wbemServices.Get("Win32_Share")
intReturnValue = objSWbemObject.Create(strPath, _
strShareName, _
SHARED_FOLDER, _
intMaximumAllowed, _
strDescription)
if(intReturnValue = 0) Then
WScript.Echo "The share have been created successfully"
End If
解说:
1)我们可以看出来前面的那几行是为显示帮助和处理输入参数而存在的。
2)紧接着设置了几个变量,为以后做参数用的。这里我们可以先不理会它。
3)连接到主机的WMI,然后就是查询。前面已经说的很详细了。
4)这次得到实例集后,我们用了它的一个方法,也就是这个方法让共享成为了可能,联系到第二部分的内容,我们不难知道第一个参数表示要共享的路径和文件名,第二个参数表示共享名,第三个参数为0就可以了,第四个参数是指可以连接的人数,第五个参数是共享描述了,而我们只关心前面的两个参数。如果手头有MSDN那就好办了,到MSDN中可以查到该方法的更详细的内容。
5)这次我们根据第四步的返回值来得到共享是否成功,并给出提示。不同的返回值代表不同的意义。这个信息在MSDN中可以很清楚地查到。比如0代表成功返回,2代表拒绝访问,9代表用户名错误,25代表主机名没有找到等等。
6)这次我们要注意的是,用这个脚本来实现远程文件共享,要求远程存在这个文件,否则无法共享。当然你也可以利用教本创建自己的文件夹,很容易的,自己创建吧。
7)如上脚本创建后的共享是完全共享。就是可以删除修改文件的。
8)用法举例:share netp net swswsw C:\dodo marsh
好了,到现在为止,大家应该对这位朋友有些了解了,我的介绍任务也就告一段落了,如果大家想进一步认识它,那就主要靠大家的主动性了。这次我们主要通过WMIC和脚本来认识它,下次我将带领大家通过真正的程序代码来认识它,让它也有个象Windows一样漂亮的脸蛋。今天我所提到的估计只能算是WMI的万分之一,都算不上是冰山一角。剩余的要靠自己来发挥了。如果你肯利用你的所学,那么奇迹就会产生COPY

TOP

◎VBS脚本应用(打造个性化QQ)
       昨天,要找一个以前写的VBS脚本,可是当时写的就随便,名起的也糊涂,就搜索了一下,咦!~~QQ下怎么还有VBScript.dll和VBScript.vbs这么两个文件来着???我实在太奇怪了。复制出来,打开看看。当然是先看脚本啦!
我晕倒,居然是真正的VBS脚本文件,哦,几个函数似乎在脚本里没有定义,不过很正常,现在好多软件都是这么干的。挨个往下看,Window_OnSize(cx,cy)大概是拉伸面板时调用的吧,Window.LockPaint() 锁定绘图,当然了还有onClick、onMouseMove、onMouseLeave等等都是响应事件的函数,Window.ExeCommand 1,2这是干什么的,网上搜搜,Window.ExeCommand n,m是QQ内部的一些命令,n、m值如下的时候代表不同的操作:1,1 皮肤管理器;1,2 最小化;1,3 close;4,1 ChatRoom;4,2 发送手机短信;4,3 search;4,4 腾讯浏览器;4,5 Game;4,6 信息管理器;4,7 color;4,8 个人帐户;4,9 面板选择;4,10 Mail相关;50,1 显示信息;60,2 个人设置;7,1 Mail;15,1 host
呵呵,太好了,让我修改它一下看看,有响应没有。得了,捡不如撞,就在Window_OnSize(cx,cy)函数的响应后添加一个MsgBox "你确定要改变吗?"退出qq,再次进入,拖动边框,呵呵,出来了。好了,再加一句:CreateObject("WScript.shell").run "notepad.exe",呵呵,退出qq,再次进入,拖动边框,咦?!没有反应?百度一下,哦,QQ自带的VBScript.dll文件不支持外部调用,要外部调用,必须用破解的VBScript.dll文件覆盖原来的?太麻烦了,要不用系统自带的覆盖行不行?试验一下,呵呵,可以!赶紧试试其他的按钮啊,功能啊什么的有没有变化?似乎没有,那!?QQ自己带的这个VBScript.dll到底干了些什么工作?还是有什么我没有发现?!不管它,我们接着来,比如说,我的QQ上的那个收发邮件的那个按钮我从来也不用,放着也是闲着,要不……,把它换成我常用的记事本程序,可以方便我在聊天的时候粘贴从网上复制下的好文章,ok,让我搜索一下mail,找到Sub MailButton_onClick()函数,在函数代码Window.ExeCommand 7,1前加一个小小的 ‘ ,然后加入一行代码:
CreateObject("WScript.shell").run "notepad.exe",退出,重新进入,单击"收发邮件"按钮,呵呵记事本打开了。可是上面怎么老是显示收发邮件啊,怎么能改一下呢?百度一下,ok,图表啊、说明啊,都在Config.xml文件中放着,坏了,xml我不是很熟悉,不过没关系,只要我认识汉字就可以了,还是拿记事本打开看看,单击搜索,填入收发邮件,找到,修改为"记事本",保存,退出QQ,再次进入,呵呵,鼠标移到那个图标上,显示"记事本",完成。呵呵,如果愿意甚至可以把常用的软件的快捷方式都放在QQ皮肤上,把QQ打造成一个完全个性的软件,彻底改变QQ的用处。COPY

TOP

这个没必要转了,以前在管理群里讨论过,都放在这里:
批处理之家VBS系列教程——第一节 工具与资料
http://www.bathome.net/thread-2382-1-1.html
命令行参考:hh.exe ntcmds.chm::/ntcmds.htm
求助者请拿出诚心,别人才愿意奉献热心!
把查看手册形成条件反射!

TOP

自己保存的文件自己找不到的人我见的多了去了。

这句话太好了...说的不就是我嘛...

TOP

写的比较口语化啊 通俗易懂 不像官方教程那么难以理解

TOP

返回列表