利用网页快讯让读者快速获取更新信息

大家可能已经注意到侧边栏的Last Update栏目会在IE8或者IE9浏览器访问下会有个绿色的框框,类似于下面这种:

文档内发现

其实这个就是微软在IE8及后续浏览器上应用的一个新功能,叫“网页快讯”,当然这样鼠标移上去出现的绿框框叫做文档内发现。通过文档内发现我们可以指示读者如何正确获取快讯内容。

网页快讯

网页快讯有什么用呢

通过网页快讯,访问者可以在不打开你的网站的前提下通过收藏栏已订阅的网页快讯获取你网站的更新内容,这样岂不是很便捷。

如何使用

其实应用网页快讯的文档内发现非常容易,你只需要简单的修改相关的标签属性就可以了。

网页快讯标识属性为hslice,另外还要添加上id属性(id属性必不可少)。比如像下面这样:

<div class="hslice" id="score">
</div>

这样div包含的内容将加上绿框框被剪辑出来。当然有人肯定要问如果我有另外一个已定义样式的class怎么办,其实你可以通过空格分隔各个class属性,就像下面这样。

<div class="hslice mydefined" id="score">
</div>

如何更改网页快讯的名称

添加网页快讯

其实我们可以分别用entry-title和entry-content的class属性来分别标识我们的名称和内容。当然包含这些属性的标签必须是包含hslice的子标签。

<div class="hslice" id="score">
   <h2 class="entry-title">My Title</h2>
   <p class="entry-content">My Content</p>
</div>

当然如果你需要应用其他名称并且这些名称不想给浏览用户看到时,这里有个小技巧,可以给标签加上display:none属性。比如:

<div class="hslice" id="score">
   <div class="entry-title" style="display:none">
       Full Description
   </div>
   <h2>My Simple Title</h2>
   <p class="entry-content">My Content</p>
</div>

好了就介绍这么多,如果你对这个感兴趣的话不妨看下微软的官方文档 《使用网页快讯订阅内容》

Posted in:
  • 前端开发与用户体验
  • Web开发及相关
Tagged
  • 网页快讯

Webkit内核浏览器下搜索框大小及文字下沉问题

感谢 Prouz 的提出这个问题
问题如下图所示(Safari或者Chrome等基于Webkit核心的浏览器):

搜索框错位

由于很少使用基于Webkit内核的浏览器,比如Safari和Chrome什么的,以至于自己一直没有很好的重视这个问题,今天 Prouz 提出了这个问题,于是我便开始研究,但是随着研究的深入,发现问题也越来越多。

首先是在Webkit内核浏览器下搜索框特有的样式,通过Google的开发人员工具结合网上搜索发现这么一个Webkit的私有属性-webkit-appearance,关于这个的介绍可以看 CSS Webkit Appearance 这篇文章,其定义了input在Webkit浏览器下的各种表现,尤其在苹果的Safari浏览器下,比如搜索框是这个样子的:

Safari搜索框

这样就导致我们原先定义的样式全部失效,当然我们可以将input的type="search"改成type="text"来解决这个问题,当然这是一种偷懒的做法,也不符合HTML5的定义,当然对于HTML5定义的表单可以参考 A Form of Madness 这篇文章,这篇文章作者告诉我们可以通过定义-webkit-appearance:textfield来解决这个问题,不过也有网友建议使用-webkit-appearance:none。

input[type="search"] {
    -webkit-appearance: textfield;
}

问题是解决了,但是发觉在Webkit核心下搜索框高度无法和其他内核浏览器一样,这是个很奇怪的问题,同样的也导致了搜索文字的下沉,也就是 Prouz 所反映的情况,通过调用Chrome开发人员工具,找到问题所在。

.search {
    height:20px !important;
    height:21px;
}

一个为了兼容IE6的写法,开始以为是!important导致的,但是后来发现如果height有覆盖属性搜索框就一定会有个怪异的高度。

后来通过搜索得到CSS Tricks的 WebKit HTML5 Search Inputs ,但是感觉其只是描述了问题所在,没有给出个较好的解决方案,当然也没有用到属性覆盖,试了下这篇文章下面网友评论的方法,就是禁用Webkit搜索表现特性:

input[type="search"]::-webkit-search-decoration,
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-results-button,
input[type="search"]::-webkit-search-results-decoration {
    display: none;
}

但是问题依旧,这个问题只能先放这儿,改天详细研究,目前给搜索框留了个高度,去掉!important覆盖,然后改小了padding值,于是搜索框稍稍正常些,但是细心的网友会发现其实还是有几像素的区别,但是至少不会在Chrome和Safari下产生怪异的高度了。

Posted in:
  • 前端开发与用户体验
  • Web开发及相关
Tagged
  • 浏览器兼容
  • webkit

使用pngout和RIOT压缩优化你的图片

很多朋友在完成一份网页作品时往往欣喜不已,尤其是在本地浏览时的那份UI的完美呈现,但是在实际部署时往往发觉网页的浏览会很慢,尤其是在小水管网速的情况下,使用 PageSpeed 查看发现原来是图片拖累了加载速度,当然 PageSpeed 也很厚道的提供了份压缩好的图片给我们,我们可以直接用 PageSpeed 压缩的图片,在网页前端完成后我们往往会忽略很多后续工作,压缩优化图片就是其中一项重要的工作。

下面我向大家介绍下压缩图片的小工具,具体的效果由个人把握,当然减少体积的前提是损失质量,具体还要看大家权衡。

PNGOUT
一个非常好用的小工具,我们可以访问 Ken Silverman的主页 以获取其最新版本,下载好PNGOUT.EXE然后将其放至指定目录,当然这是控制台程序,也就是说我们必须在命令提示符的状态下才能使用。简单的命令如下:

pngout 输入文件 输出文件

比如 pngout logo.gif logo_out.png ,那么logo_out.png就是我们压缩好的,输入文件支持png、gif、bmp、jpg、tga、pcx等格式,输出文件貌似只支持压缩成png。当然还有很多指示压缩级别的开关选项,具体可以查看作者给我们提供的 在线手册

RIOT
如果说大家对PNGOUT控制台命令行过敏的话不妨试试这个,我们可以访问其 官方主页 获得最新版本,不过貌似其官方网站上始终下载不了,我后来在国外某知名下载站点弄到后放在 这里 提供给不能下载的童鞋们,RIOT给我们提供了一个易用的GUI,当然更重要的是其可以压缩输出jpg、gif、png等3种格式,基本囊括了网页上使用的图片,如果大家对刚才介绍的PNGOUT恋恋不舍的话,我们的RIOT可以将PNGOUT作为插件进行调用,这样我们可以借用RIOT的壳然后用PNGOUT的内核进行PNG图片的压缩,怎么样够强大的吧,当然你需要把刚才下载的PNGOUT.EXE放在RIOT安装目录的plugins文件夹下,然后启动RIOT并切换到PNG选项卡,然后如下图设置:

RIOT使用PNGOut

具体怎么使用我相信很简单,那些洋文应该难不倒大家,不过要提醒的是在没有熟练使用前记得备份你的源文件哦。

2011年5月11日更新

最近经常在公共电脑上写文章,图片本地压缩比较麻烦,不过我找到一个在线压缩的,还是比较方便的,网址: http://www.punypng.com/

Posted in:
  • 软件推荐及相关资讯
Tagged
  • 网站优化
  • 图片与图像
  • 图像压缩

使用YUI Compressor优化你的网页

YUI Compressor是做什么的

这个小工具主要是用来压缩CSS和JavaScript文件的,当然你觉得可以混淆这些文件里的代码也是可以的,不过我们使用它还是看中其压缩优化的功能。

为什么要优化

因为这样可以减少网页传输中不必要的字节数,节省带宽,加快页面访问速度,具体优化守则可以参考 雅虎网页优化14条准则

使用YUI Compressor的好处

方便快捷,压缩后的代码文件体积小,有效率高,当然市面上不乏有很多压缩工具,但是很多工具尤其在处理压缩一些大型脚本后往往导致脚本出错失效,这点我对YUI Compressor很放心,毕竟有雅虎这个大公司的技术支持,至少我用到现在没有压坏一个脚本。

如何获取YUI Compressor

下载地址
http://yuilibrary.com/downloads/#yuicompressor

项目主页
http://developer.yahoo.com/yui/compressor/

但是有些朋友下载下来可能会有些小小的失望,为什么呢?因为这个工具是用Java编写的,也就是说我在使这个工具生效前还 必须安装 Java的运行环境,当然已经安装了的话,我们就可以接着开始了,关于Java运行环境JRE的下载见 这里

如何使用

将下载到的YUI Compressor包中的yuicompressor-2.4.2.jar拷贝到指定的目录下。然后通过下面的命令行进行相关操作。

压缩优化JavaScript
java -jar yuicompressor-2.4.2.jar --type js --charset utf-8 -v orginal.js > packed.js

压缩优化CSS
java -jar yuicompressor-2.4.2.jar --type css --charset utf-8 -v orginal.css > packed.css

可见--type指定了压缩文件的类型,--charset指定了压缩文件的编码,紧接着-v开关后面是要压缩的源文件orginal,>后是压缩好的文件packed。

对于CSS的压缩,我发现了一点奇怪的现象,比如形如 body {color:#000;background:#fff} 会变成 body {color:#000;background:#fff ; },最后花括号前面的分号是可以省略的,我一直也是省略的写法,不晓得为什么压缩后又添加上去了。

Posted in:
  • 前端开发与用户体验
  • 软件推荐及相关资讯
  • Web开发及相关
Tagged
  • 网站优化
  • yui

使用srvany.exe将任何程序作为Windows服务运行

srvany.exe是什么?

srvany.exe是Microsoft Windows Resource Kits工具集的一个实用的小工具,用于将任何EXE程序作为Windows服务运行。也就是说srvany只是其注册程序的服务外壳,这个特性对于我们来说非常实用,我们可以通过它让我们的程序以SYSTEM账户启动,或者实现随机器启动而自启动,也可以隐藏不必要的窗口,比如说控制台窗口等等。

如何获取?

你可以通过 下载并安装Microsoft Windows Resource Kits 获得或者可以通过我分享的 下载地址1(国内线路) 下载地址2(国外线路) 得到。

如何使用?

当你获取到srvany后并决定将某程序作为服务启动后,请先将srvany安装为系统服务,具体的安装方法有很多,比如说可以通过Microsoft Windows Resource Kits中另外一个实用的小工具instsrv.exe进行安装( 下载地址 ),将srvany.exe和instsrv.exe拷贝到C:\Windows\System32\后,我们可以通过下面的命令行进行srvany.exe的服务安装:

instsrv ServiceName C:\Windows\System32\srvany.exe

ServiceName 即你自己定义的服务名称,可以是要作为系统服务启动的应用程序的名称。

安装完毕后,我们需要对srvany.exe进行配置,以便于能够加载我们指定的程序,配置的方法是,开始 - 运行 - regedit,打开注册表,定位到下面的路径。

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ ServiceName

同样的 ServiceName 是你刚才安装服务时自定义的服务名称。

如果该服务名下没有Parameters项目,则对服务名称项目右击新建项,名称为Parameters,然后定位到Parameters项,新建以下几个字符串值。

名称 Application 值为你要作为服务运行的程序地址。
名称 AppDirectory 值为你要作为服务运行的程序所在文件夹路径。
名称 AppParameters 值为你要作为服务运行的程序启动所需要的参数。

比如这里是个配置实例,我们这里配置的服务名称是NGINX,其余是nginx的安装配置情况。

srvany配置

当然还有一个比较简单的做法,那就是将下面的文本保存为*.reg文件,然后双击导入注册表。

Windows Registry Editor Version 5.00 

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\服务名称\Parameters] 
"Application"="值为你要作为服务运行的程序地址"
"AppDirectory"="值为你要作为服务运行的程序所在文件夹路径"
"AppParameters"="值为你要作为服务运行的程序启动所需要的参数"

2011年7月14日更新

找到微软的官方文章 《如何创建用户定义的服务》 ,大家可以看一看。

2012年2月27日更新

今天有朋友问到将某窗体程序通过srvany作为服务运行的时候,桌面右下角图标和窗体无法显示,这个就涉及到服务的运行方式了,一般服务程序是不包含窗体的,所以系统默认可能会抑制这些服务程序产生的窗体,如果你的服务程序比较特殊,确实需要出现窗体,可以参考下面的办法:

控制面板 - 管理工具 - 服务(或者 开始 - 运行 - services.msc 确认)打开服务管理器,选择你刚刚安装并需要展示窗体的服务,然后右击选择属性,切换到 “登录” 选项卡,勾选上 “允许服务与桌面交互” 然后按确定保存,重启你的服务,看看窗体是否出现了:

允许服务与桌面交互

2012年7月3日更新

为了大家利用srvany.exe创建自定义服务的方便我特别写了个名叫SrvanyUI的服务创建管理的小工具,大家可以移步这篇文章 《SrvanyUI服务管理工具发布》 来获得详细信息,这里放个截图:

SrvanyUI服务管理工具

2012年7月5日更新

找到微软的一篇文章可以参考 《故障排除使用 Cmd.exe 的 SrvAny》

2012年7月23日更新

近期有朋友咨询为什么勾选上 “允许服务与桌面交互”,窗体程序依旧不能显示,其实这个办法只适用于Windows XP或者Windows 2003系列的操作系统,对于以上版本的Windows Vista、Windows 2008、Windows 7以及Windows 2008 R2,微软做了改变,使用了Session 0会话隔离策略,所以再使用这个办法强制服务窗体显示就会出现提示框,只有手动允许后才会出现界面,并且桌面风格也将被更改:

交互式服务检测提示 [caption id="attachment_656" align="aligncenter" width="441"] 交互式服务检测 此计算机上运行的程序正在尝试显示一条消息,程序可能需要您的信息或权限来完成任务。[/caption]
交互式服务检测 此计算机上运行的程序正在尝试显示一条消息 程序可能需要您的信息或权限来完成任务。

关于Vista及高版本Windows交互出现提示框是由Interactive Services Detection服务控制的。禁用此服务将不会出现上述提示框,当然窗体也就不会显示了。

更详细的信息可以参考MSDN的 《Interactive Services》 文章。

特别注意下面这段:

Important Services cannot directly interact with a user as of Windows Vista. Therefore, the techniques mentioned in the section titled Using an Interactive Service should not be used in new code.

如果要在新的Vista及以上操作系统上显示窗体,我们应当使用新的技术,比如使用WTSSendMessage在用户会话显示对话框,或者将服务程序与窗体分离开来再使用进程通信(推荐)。

关于编程的方法可以参考这篇文章 《解决vista和win7在windows服务中交互桌面权限问题:穿透Session 0 隔离》

抱歉的是目前的办法仅限于编程方面的,其他有效的办法我暂时还没有找到。

部分参考文档:

2012年2月27日更新

对于带参数的命令行方式直接利用srvany.exe创建自定义服务请参考文章 《WScript/VBScript命令行参数使用srvany.exe创建自定义服务》

END

Posted in:
  • 软件推荐及相关资讯
Tagged
  • 系统工具
  • Windows服务

配置Windows+Nginx+MySQL+PHP备忘

Nginx实际主要还是部署运行于Linux之下的,本文仅介绍在Windows下的开发环境部署,适用于开发人员。

1.准备安装包

除了Windows系统外,我们还需额外下载Nginx、MySQL和PHP的程序包,相关资源地址列表如下:

Nginx
http://nginx.org/en/download.html

MySQL
http://www.mysql.com/downloads/

PHP
http://windows.php.net/download/

2.安装部署

我们这里主要选择磁盘D,作为目的磁盘。第一步将Nginx解压至D:\Nginx路径下;第二步双击安装MySQL,选择开发模式安装;第三步将PHP解压至D:\PHP。

3.更新配置

配置PHP,进入PHP的安装目录D:\PHP,找到php.ini,如果没有的话请把php.ini-recommended改为php.ini,然后修改下面几项:

error_reporting = E_ALL
display_errors = On
extension_dir = "D:\PHP\ext"
; CGI 设置
cgi.force_redirect = 1
cgi.fix_pathinfo = 1
cgi.rfc2616_headers = 1

如果需要加载扩展,请去掉相应的扩展extension前面的分号。
比如我们需要加载PDO MySQL扩展,只需要将相应的设置更改如下:

extension = php_pdo.dll
extension = php_pdo_mysql.dll

配置PHP的FastCGI
打开命令提示符,切换至PHP的安装目录下,然后运行下面的命令:

D:/PHP/php-cgi.exe -b 127.0.0.1:9000 -c D:/PHP/php.ini

需要注意的是9000为相应的端口号,请确保不被占用,或者选用其他端口号。

我们可以通过将上面的命令建立批处理或者使用srvany.exe方便我们加载php-cgi.exe, 关于srvany的使用方法可以参考这篇文章

这些都完成后我们可以启动php-cgi.exe,稍后完成下面的步骤。

配置Nginx
打开Nginx的配置文件D:\Nginx\conf\nginx.conf,部分修改如下:

location / {
    root   D:/wwwroot;
    index  index.php index.html index.htm;
}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
location ~ \.php$ {
#   root           html;
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  D:/wwwroot$fastcgi_script_name;
    include        fastcgi_params;
}

D盘下的wwwroot作为我们存放php测试脚本的地方,注意这里路径建议使用'/'分隔,否则最好采用转义模式,比如“D:\\wwwroot”。配置完成后可以 采用srvany.exe将Nginx作为后台服务运行
然后建立index.php文件,内容如下:

<?php phpinfo();?>

放入D:\wwwroot,然后打开浏览器输入http://localhost/index.php,就可以看到效果了。

有时可能需要更改默认的80端口,你只需要打开Nginx的配置文件D:\Nginx\conf\nginx.conf,将其中的listen 80;改成你所需要的端口号就可以了。

Posted in:
  • 计算机应用及维护
  • Windows系统
Tagged
  • php配置
  • nginx
  • mysql

解决Windows下IIS配置PHP页出错空白的问题

最近在捣鼓PHP,在Windows下以FastCGI方式安装开发环境还是很顺利的,但是在调试时发现,PHP的错误始终显示不出来,整个页面是一片空白,上网查询了相关资料后,得知必须打开PHP.ini这个配置文件。找到display_errors和error_reporting,将原来的值改成display_errors= On 和error_reporting= E_ALL ,改写完毕后重新启动IIS,继续运行出错的PHP页,还是一片空白,弄了半天才知道是什么原因,打开任务管理器,显示所有进程,选中所有php-cgi.exe进程,并结束,然后重启IIS,这下访问原先的错误就显示出来了,当然你也可以选择最简单的办法就是重启你的计算机。

当然在网上还找到这样的代码级解决方案,不用修改配置文件,图方便的朋友不妨试试看。

<?php error_reporting(E_ALL); ini_set('display_errors','On');?>
Posted in:
  • 网络编程与数据库
  • Web开发及相关
Tagged
  • iis
  • php配置

VPN同时连接并使用内网和外网资源的办法

公司内部网络通过VPN连接,同时客户端还想使用外网资源,但实际发现连接内网后,外网将无法正常访问,这是因为VPN的服务器端接管了你的默认网关,等于说默认的流量全部走VPN服务器了,这个给内网和外网的使用带来了不便,更重要的是加重了服务器的负担,如何才能在连接上VPN内网后同时能使用内网和外网资源呢?其实很简单,对VPN拨号项目右击属性,切换到网络选项卡,然后选中 Internet 协议 (TCP/IP) ,单击属性,在 Internet 协议 (TCP/IP) 属性对话框中,单击高级,取消“在远程网络上使用默认网关”这个勾,全部确认保存即可。

VPN同时使用内网和外网资源.png

Posted in:
  • 计算机应用及维护
  • Windows系统
Tagged
  • vpn

L2TP预共享密钥解决内网VPN连接问题

原文发表于2008年9月30日

阅读时请注意,本文讨论的是一种客户端到服务器端的网络技术,主要应用于企业内部网络,并不提供私服、外挂、代理VPN的相关信息。

大概是一个月前的事情了,主要是一个VPN解决方案,服务器配置是Windows 2003 + ISA 2006,单网卡连接路由上网,设置好路由并通过ISA的配置顺利启用了PPTP的VPN,通过客户端ADSL拨号,成功连接,本来以为事情这样就结束了,事实上问题还没有解决。在另外一个客户端中启用连接,停留在验证用户名和密码阶段,然后就发生错误,详细如下。

错误 721 : 远程计算机没反应。

我发现两个客户端就是网络环境不同,这个客户端位于一个局域网中。有问题百度一下,有个解决方案就是修改注册表的,本来以为可以轻松解决这个问题的,但我又想错了,我开始怀疑是这个客户端所在局域网搞的鬼。实际上通过服务器的防火墙监视发现,服务器已经启用了该PPTP连接,但事实上有个数据包不能正常抵达客户端,所以造成这个错误。进一步上网查询,得知这个数据包很有可能是GRE协议,这个协议由于客户端局域网的限制未能正常抵达,所以造成这个错误。本来以为这是个个别现象,回到学校,使用校园网,于是我又尝试连接VPN,一样的错误!回家后使用ADSL上网,连接该VPN,一切正常。断开后启用虚拟机,打开一个虚拟的Windows XP系统,建立VPN连接,拨号,同样的错误!于是我想貌似通常的局域网内部机器都不能正常拨号,若要想正常拨号就必须要去修改局域网配置!但一般修改自己局域网配置是可以的但是修改别人的局域网配置就难了。这个问题困扰了我很多天。

我在PPTP连接上越陷越深,偶然的一次看到某论坛上一位朋友遇到和我一样的问题,据他说使用L2TP可以实现内网访问VPN,我似乎看到了救命稻草,于是我便开始配置ISA的L2TP访问,但有个问题是L2TP必须使用IPSec然后就是什么证书的,比较麻烦,幸好捷径还是有的,IPSec可以预共享密钥。

服务器端设置

服务器端IP地址分配

分配静态地址,DHCP配置有点麻烦。

服务器端身份验证

设置验证方式,注意这里务必勾选“未加密密码(PAP)(U)”和“允许L2TP连接自定义IPSec策略(L)”并且设置好预共享密钥。

服务器端启用VPN访问

启用客户端访问。

服务器端协议

启用PPTP和L2TP/IPSec,当然你不需要PPTP可以先关闭它。

客户端和服务器端设置

设置完毕后,启用连接,无法连接。由于本地计算机没有证书等一般安全措施,所以在使用VPN L2TP方式进行连接时必然会遇到类似于“vpn 错误789: L2TP 连接尝试失败,因为安全层在初始化与远程计算机的协商时遇到一个处理错误”这样的错误,即使设置了IPSec预共享密钥也无济于事,这种情况经常出现在一些中小企业在不能使用PPTP方式而必须采用L2TP方式访问企业资源的情景下,原来服务器和客户端都要求使用证书这种加密模式,怎样才能让它们认可预共享密钥连接呢?其实微软已经给我们方法了,修改注册表。

微软文章: http://support.microsoft.com/kb/310109/zh-cn

其实你可以使用下面命令很简单的完成操作

reg add "HKLM\SYSTEM\CurrentControlSet\Services\RasMan\Parameters" /v ProhibitIPSec /t REG_DWORD /d 1

客户端取消证书加密

完成操作后请重启服务器和客户端。

重启完毕下面 只要修改客户端 就足够了。

客户端设置

修改先前的VPN连接。

客户端拨号连接

打开连接对话框,点击属性。

客户端选择VPN类型

切换到“网络”选项卡,并选择VPN类型。

客户端安全设置

切换到“安全”选项卡,单击“IPSec设置(P)…”

客户端设置IPSec

输入刚才设定的密钥,确认。

确认所有对话框,这时输入VPN用户名和密码,登录,成功!问题解决!

希望我的这篇文章对您有所帮助。欢迎交流,请在评论中留下您宝贵的意见。

注意: 貌似由于服务器端验证方式的设置原因,这里预共享密钥IPSec可以不用设置,原文不当,给大家带来不便还望见谅。

Posted in:
  • 计算机应用及维护
  • Windows系统
Tagged
  • vpn

利用Scripting.FileSystemObject组件来枚举文件

基本的算法思想就是首先获得文件夹下的文件集合,然后枚举文件,然后再获得文件夹下子文件夹的集合,然后递归枚举,实际操作时为了更好的模块化,使用了回调函数,如果找到文件就自动交给指定函数处理,我们约定函数的格式如下:

FUNCTION(FileSystemObject, FileObject, Parameter) RETURN AS BOOL

首先第一个参数是FileSystemObject,就是将创建好的Scripting.FileSystemObject对象传入函数让我们加以利用。
其次第二个参数是FileObject,也就是枚举出的单独文件对象,我们可以通过这个对象获得文件一系列的属性和方法。
最后一个参数是Parameter,是在调用枚举时传入的参数,没有特殊需要可以忽略。
返回值,如果返回TRUE则中止枚举,否则将继续枚举直到枚举结束。

VBScript实现如下。

Class FileOperation

    Private AxFile   
    Private Sub Class_Initialize()
        Set AxFile = WSH.CreateObject("Scripting.FileSystemObject")
    End Sub
    
    Private Sub Class_Terminate()
        Set AxFile = Nothing
    End Sub
    
    Private Function GetSubFolders(strFolder)
        If AxFile.FolderExists(strFolder) Then
            Dim oFolders
            Set oFolders = AxFile.GetFolder(strFolder)
            Set GetSubFolders = oFolders.SubFolders
            Set oFolders = Nothing
        Else
            Set GetSubFolders = Nothing
        End If
    End Function

    Private Function GetSubFiles(strFolder)
        If AxFile.FolderExists(strFolder) Then
            Dim oFolders
            Set oFolders = AxFile.GetFolder(strFolder)
            Set GetSubFiles = oFolders.Files
            Set oFolders = Nothing
        Else
            Set GetSubFiles = Null
        End If
    End Function

    Public Function EnumFiles(strFolder, fCallBackName, Param)
        EnumFiles = True
        If Not AxFile.FolderExists(strFolder) Then
            EnumFiles = False
            Exit Function
        End If
        
        Dim fCallBack
        Dim SubFiles, SubFile, SubFolders, SubFolder
        
        Set fCallBack = GetRef(fCallBackName)
        
        Set SubFiles = GetSubFiles(strFolder)
        For Each SubFile In SubFiles
            If fCallBack(AxFile, SubFile, Param) Then Exit For
        Next
        Set SubFiles = Nothing
        
        Set SubFolders = GetSubFolders(strFolder)
        For Each SubFolder In SubFolders
            Call EnumFiles(AxFile.GetAbsolutePathName(SubFolder), _
                                  fCallBackName, Param)
        Next
        Set SubFolders = Nothing
        
        Set fCallBack = Nothing
    End Function
    
End Class

貌似VBScript没有函数指针的概念,在查阅了脚本手册后找到GetRef函数,用以根据字符串格式的函数名获取函数的引用,虽然看上去比较别扭,但是还是可以实现函数指针这个功能的。

JavaScript/JScript实现如下。

function FileOperation() {
    this.self = WSH.CreateObject("Scripting.FileSystemObject");

    this.getSubFolders = function(fdr) {
        if (!this.self.FolderExists(fdr))
            return null;
        return (this.self.GetFolder(fdr).SubFolders);
    }

    this.getSubFiles = function(fdr) {
        if (!this.self.FolderExists(fdr))
            return null;
        return (this.self.GetFolder(fdr).Files);
    }

    this.enumFiles = function(fdr, callback, param) {
        if (!this.self.FolderExists(fdr))
            return false;
        var SubFiles = new Enumerator(this.getSubFiles(fdr));
        for (; !SubFiles.atEnd(); SubFiles.moveNext())
        {
            if (callback(this.self, SubFiles.item(), param))
                return true;
        }
        var SubFolders = new Enumerator(this.getSubFolders(fdr));
        for (; !SubFolders.atEnd(); SubFolders.moveNext()) {
            this.enumFiles(
            this.self.GetAbsolutePathName(SubFolders.item()),
            callback, param);
        }
        return true;
    }
}

JavaScript/JScript的将函数名作为变量传入很方便的实现了函数指针的功能,在这点上JavaScript/JScript的灵活性还是略胜一筹的,不过其foreach功能就没有VBScript那么好用了。

2012年3月21日更新

对VBScript类做了修改,增加了文件夹枚举搜索,增加递归开关,并且为了保证调用灵活,修改了回调原型函数。

' Author : wangye
' http://wangye.org
Class FileOperation
 
    Private AxFile   
    Private Sub Class_Initialize()
        Set AxFile = WSH.CreateObject("Scripting.FileSystemObject")
    End Sub
 
    Private Sub Class_Terminate()
        Set AxFile = Nothing
    End Sub
 
    Private Function GetSubFolders(strFolder)
        If AxFile.FolderExists(strFolder) Then
            Dim oFolders
            Set oFolders = AxFile.GetFolder(strFolder)
            Set GetSubFolders = oFolders.SubFolders
            Set oFolders = Nothing
        Else
            Set GetSubFolders = Nothing
        End If
    End Function
 
    Private Function GetSubFiles(strFolder)
        If AxFile.FolderExists(strFolder) Then
            Dim oFolders
            Set oFolders = AxFile.GetFolder(strFolder)
            Set GetSubFiles = oFolders.Files
            Set oFolders = Nothing
        Else
            Set GetSubFiles = Null
        End If
    End Function
    
    ' EnumFiles 枚举指定文件夹文件
    '
    ' 回调函数原型为 CallBack(self, fso, file, param)
    '     self  Class FileOperation实例化对象
    '     fso   Scripting.FileSystemObject对象
    '     file  枚举到的文件对象
    '     param 传递给回调函数的参数(如果需要)
    '
    ' strFolder     要枚举的文件所在的文件夹
    ' fCallBackName 列出的每个文件所调用的回调函数名称
    ' Recursion     是否递归搜索
    ' Param         传递给回调函数的参数(如果需要)
    Public Function EnumFiles(strFolder, fCallBackName, Recursion, Param)
        EnumFiles = True
        If Not AxFile.FolderExists(strFolder) Then
            EnumFiles = False
            Exit Function
        End If
 
        Dim fCallBack
        Dim SubFiles, SubFile, SubFolders, SubFolder
 
        Set fCallBack = GetRef(fCallBackName)
        
        If TypeName(strFolder) = "Folder" Then
            Set SubFiles = strFolder.Files
        Else
            Set SubFiles = GetSubFiles(strFolder)
        End If
        For Each SubFile In SubFiles
            If fCallBack(Me, AxFile, SubFile, Param) Then Exit For
        Next
        Set SubFiles = Nothing
 
        If Recursion Then
        Set SubFolders = GetSubFolders(strFolder)
            For Each SubFolder In SubFolders
                Call EnumFiles(AxFile.GetAbsolutePathName(SubFolder), _
                          fCallBackName, Recursion, Param)
            Next
            Set SubFolders = Nothing
        End If
        
        Set fCallBack = Nothing
    End Function
 
    ' EnumFolders 枚举指定文件夹
    '
    ' 回调函数原型为 CallBack(self, fso, folder, param)
    '     self  Class FileOperation实例化对象
    '     fso   Scripting.FileSystemObject对象
    '     folder  枚举到的文件夹对象
    '     param 传递给回调函数的参数(如果需要)
    '
    ' strFolder     要枚举的文件夹所在的文件夹
    ' fCallBackName 列出的每个文件夹所调用的回调函数名称
    ' Recursion     是否递归搜索
    ' Param         传递给回调函数的参数(如果需要)
    Public Function EnumFolders(strFolder, fCallBackName, Recursion, Param)
        EnumFolders = True
        If Not AxFile.FolderExists(strFolder) Then
            EnumFolders = False
            Exit Function
        End If
        
        Dim fCallBack
        Dim SubFolders, SubFolder, ChildFolders, ChildFolder
 
        Set fCallBack = GetRef(fCallBackName)
        Set SubFolders = GetSubFolders(strFolder)
        For Each SubFolder In SubFolders
            If fCallBack(Me, AxFile, SubFolder, Param) Then Exit For
            If Recursion Then
                Set ChildFolders = SubFolder.SubFolders
                For Each ChildFolder In ChildFolders
                    If fCallBack(Me, AxFile, ChildFolder, Param) Then Exit For
                    Call EnumFolders(AxFile.GetAbsolutePathName(ChildFolder), _
                              fCallBackName, Recursion, Param)
                Next
                Set ChildFolders = Nothing
            End If
        Next
        Set SubFolders = Nothing
        Set fCallBack = Nothing
    End Function
End Class

' Example:
' Function ParseFiles(self, fso, file, param)
'     WSH.Echo file.Name & " at " & fso.GetAbsolutePathName(file)
' End Function
' Dim fp
' Set fp = New FileOperation
'     fp.EnumFiles "C:\", "ParseFiles", True, Null
' Set fp = Nothing
Posted in:
  • VBScript/JavaScript/Python
  • 系统应用程序开发
Tagged
  • wscript

© Wang Ye / 王 晔. All rights reserved.