WizKnowledge插件范例:自动下载博客插件
WizKnowledge自带了一个自动下载博客的插件,利用这个插件,您可以在指定的时间,自动下载一个博客里面新发布的文章。下面是这个插件的原理介绍。
该插件在WizKnowledge安装目录下面的plugins\{6957D596-7CD9-4ddf-A129-7BD093BC5320}文件夹中。
该文件夹一共有三个文件:

首先看Plugin.ini文件,这个是插件描述文件
在Common部分,描述了插件的名称,GUID,类型(目前仅支持Normal),版本以及插件功能的数量(1)。
[Common]
AppName=Blog Downloader…
AppName_2052=博客下载器…
AppName_1028=博客下载器…
AppGUID={6957D596-7CD9-4ddf-A129-7BD093BC5320}
AppType=Normal
AppVersion=1.0
PluginCount=1
在Plugin_0部分,描述了具体的插件功能:
[Plugin_0]
Caption=Blog Downloader…
Caption_2052=博客下载器…
Caption_1028=博客下载器…
GUID={8324D9C5-46B2-4f2e-8D26-12B5B610AFF1}
HtmlDialogFileName=BlogDownloader.htm
HtmlDialogTitle=Blog Downloader
HtmlDialogTitle_2052=博客下载器
HtmlDialogTitle_1028=博客下载器
HtmlDialogWidth=500
HtmlDialogHeight=630
Type=HtmlDialog
BeginGroup=0
这部分描述了插件的功能,是一个Html对话框类型的插件。同时制定了Html文件名:BlogDownloader.htm。
Strings部分,是插件的字符串资源,主要是为了支持多语言。
然后是BlogDownloader.htm文件。这个就是插件功能的界面部分,用户点击“博客下载器”这个菜单后,WizKnowledge会显示一个Html对话框。Html对话框里面的内容,就是这个Html文件。
这个Html界面如下:

其中都是一些标准的html表单控件,例如编辑框,复选框,下拉框。比较特殊的一个就是WizKnowledge目录树。这个目录树,是一个ActiveX控件,可以显示WizKnowledge数据库里面的目录。
Html代码如下:
<object id=”folder” classid=”clsid:26C7C9DF-8814-4FB5-925A-C720E75C924A” width=”300″ height=”250″>
</object>
其中26C7C9DF-8814-4FB5-925A-C720E75C924A就是WizKnowledge目录树的ActiveX控件的class id。
用户的操作,以及插件的功能实现,都在通过html里面的脚本实现的
//
function formatInt(val) //格式化整数,主要是用来生成日期类型的目录
{
if (val < 10)
return “0″ + val;
else
return “” + val;
}
//
function OnFolderSelChanged() { //当用户更改了选中的文件夹(目录树ActiveX控件),在html里面,动态显示用户选择的目录。
var selectedFolder = folder.SelectedFolder; //选中的文件夹
if (selectedFolder != null
&& textBlogName.value != null
&& textBlogName.value != “”) { //如果不为空
labelSaveToResult.innerHTML = “<strong>” + selectedFolder.Location + textBlogName.value + “/</strong>”; //显示用户的选择的目录
}
}
//
var objApp = new ActiveXObject(“WizExplorer.WizExplorerApp”); //获得当前正在运行WizExplorer实例
var objCommon = new ActiveXObject(“WizKMControls.WizCommonUI”); //一个通用的函数库
var database = objApp.Database; //获得WizExplorer正在打开的数据库
//
var appGUID = objApp.GetPluginAppGUID(document); //获得当前插件的App GUID,也可以直接通过Plugin.ini获得。
//
for (var i = 0; i < 24; i++) { //添加24小时定时下载下拉框
var optionTime1 = document.createElement(“OPTION”);
optionTime1.value = formatInt(i) + “:00″;
optionTime1.text = optionTime1.value;
selectTime.add(optionTime1);
//
var optionTime2 = document.createElement(“OPTION”);
optionTime2.value = formatInt(i) + “:00″;
optionTime2.text = optionTime2.value;
selectTime.add(optionTime2);
}
//
var settings_meta = “Plugin_BlogDownloader”; //用户录入的信息保存在数据库中,以便下次直接显示用户上次输入的信息。这个变量设置了保存信息的位置,类似于ini文件的section。
//
textBlogName.value = database.Meta(settings_meta, “BlogName”) ; //从已经保存的记录中初始化博客名称
textRssFeedURL.value = database.Meta(settings_meta, “RssFeedURL”); //博客URL
checkAddToTaskScheduler.checked = database.Meta(settings_meta, “AddToTaskScheduler”); //是否添加到计划任务
var downloadTime = database.Meta(settings_meta, “AutoDownloadTime”); //自动下载的时间
if (downloadTime == null || downloadTime == “”)
downloadTime = “12:00″;
selectTime.value = downloadTime;
if (selectTime.selectedIndex == -1)
selectTime = 24;
//
var saveContentOnly = database.Meta(settings_meta, “SaveContentOnly”); //是否只保存正文
if (saveContentOnly == null || saveContentOnly == “” || saveContentOnly == “1″)
checkSaveContentOnly.checked = true;
//
if (textBlogName.value == null || textBlogName.value == “”) {
textBlogName.value = objApp.LoadPluginString(appGUID, “WizBrotherBlogName”);
}
if (textRssFeedURL.value == null || textRssFeedURL.value == “”) {
textRssFeedURL.value = objApp.LoadPluginString(appGUID, “WizBrotherBlogFeedURL”);
}
//
folder.Database = database; //初始化目录树
folder.StateSection = “Folder_Plugin_BlogDownloader”; //设置目录树的记录状态
folder.Border = true; //设置显示边框
folder.OnSelChanged = OnFolderSelChanged; //响应用户选择目录事件
//
objApp.PluginLocalizeHtmlDialog(document); //本地化html对话框
//
function CloseDialog(ret) { //当用户点击确定或者取消按钮的时候,关闭对话框
if (ret == 1) { //如果用户点击了确定按钮,检查用户录入的信息
if (textBlogName.value == null || textBlogName.value == “”) {
alert(objApp.LoadPluginString(appGUID, “EnterBlogName”));
textBlogName.focus();
return;
}
if (textRssFeedURL.value == null || textRssFeedURL.value == “”) {
alert(objApp.LoadPluginString(appGUID, “EnterRssFeedURL”));
textRssFeedURL.focus();
return;
}
//
var selectedFolder = folder.SelectedFolder;
if (selectedFolder == null){
alert(objApp.LoadPluginString(appGUID, “SelectFolder”));
return;
}
//
var pluginPath = objApp.AppPath + “plugins\\” + appGUID + “\\”; //获得插件的路径
var scriptTemplateFileName = pluginPath + “BlogDownloader.js”; //BlogDownloader.js是一个下载Blog的脚本模板
//
var scriptText = objCommon.LoadTextFromFile(scriptTemplateFileName); //加载脚本模板
//
scriptText = scriptText.replace(“%blog_name%”, textBlogName.value); //替换模板里面的博客名称
scriptText = scriptText.replace(“%rss_feed_url%”, textRssFeedURL.value.replace(/\\/g, “\\\\”)); //替换模板里面的rss种子
scriptText = scriptText.replace(“%save_to%”, selectedFolder.Location); //替换博客中的选中的文件夹location
scriptText = scriptText.replace(“%database_path%”, database.DatabasePath.replace(/\\/g, “\\\\”)); //替换模板中的数据库路径
scriptText = scriptText.replace(“%save_content_only%”, checkSaveContentOnly.checked ? “1″ : “0″); //替换模板中的是否保存正文的参数
//
var scriptFileName = objApp.DataStore + “BlogDownloaderScripts\\Download “ + textBlogName.value + “.js”; //设置利用模板生成的新的脚本文件的文件名
//
objCommon.SaveTextToFile(scriptFileName, scriptText, “”); //保存成脚本文件
//
var exeFileName = objCommon.GetSpecialFolder(“SystemFolder”) + “wscript.exe”; //获得wscript文件名
//
objCommon.RunExe(exeFileName, “\”" + scriptFileName + “\”", false); //执行脚本
//
database.Meta(settings_meta, “BlogName”) = textBlogName.value; //保存用户录入的信息
database.Meta(settings_meta, “RssFeedURL”) = textRssFeedURL.value;
database.Meta(settings_meta, “AddToTaskScheduler”) = checkAddToTaskScheduler.checked ? “1″ : “0″;
database.Meta(settings_meta, “AutoDownloadTime”) = selectTime.value;
database.Meta(settings_meta, “SaveContentOnly”) = checkSaveContentOnly.checked ? “1″ : “0″;
//
if (checkAddToTaskScheduler.checked) { //如果用户选择了添加到计划任务,则将加入js计划任务中。
var schtasksFileName = objCommon.GetSpecialFolder(“SystemFolder”) + “schtasks.exe”;
var schtasksParams = “/Create /TN \”WizBrother\\BlogDownloader\\Download “ + textBlogName.value + “\” /SC DAILY /ST “ + selectTime.value + “:00 /TR \”‘” + scriptFileName + “‘\”";
objCommon.RunExe(schtasksFileName, schtasksParams, false);
}
}
//
objApp.Window.CloseHtmlDialog(document, ret); //关闭对话框
}
</script>
BlogDownloader.js文件
这是一个下载博客的模板文件,在BlogDownloader.Htm里面,使用用户录入的信息替换模板中的变量,然后生成一个真正的js文件。
var RSS_URL = “%rss_feed_url%”; //rss种子URL
var SAVE_TO = “%save_to%”; //保存文件夹
var DATABASE_PATH = “%database_path%”; //数据库文件夹
var SAVE_CONTENT_ONLY = “%save_content_only%”; //是否只保存正文
//
var objDatabase = new ActiveXObject(“WizKMCore.WizDatabase”); //创建数据库对象
objDatabase.Open(DATABASE_PATH); //打开数据库
//
function jsAlert(msg) {
var objShell = new ActiveXObject(“WScript.Shell”);
return objShell.Popup(msg, 10000, “WizKnowledge”, 0);
}
function formatInt(val) {
if (val < 10)
return “0″ + val;
else
return “” + val;
}
//利用MSXml获得RSS节点
function getRssItemNodes() {
var objXml = new ActiveXObject(“MSXML.DOMDocument”);
objXml.async = false;
if (!objXml.load(RSS_URL)) {
jsAlert(“Can not download: “ + RSS_URL)
return null;
}
//
var channelNode = objXml.selectSingleNode(“/rss/channel”);
if (channelNode == null) {
jsAlert(“\”" + RSS_URL + “\” is not a valid rss feed”);
return null;
}
//
return channelNode.childNodes;
}
//获得保存网页的flag
function getUpdateDocumentFlags() {
var wizUpdateDocumentSaveSel = 0×0001;
var wizUpdateDocumentIncludeScript = 0×0002;
var wizUpdateDocumentShowProgress = 0×0004;
var wizUpdateDocumentSaveContentOnly = 0×0008;
var wizUpdateDocumentSaveTextOnly = 0×0010;
var wizUpdateDocumentDonotDownloadFile = 0×0020;
var wizUpdateDocumentAllowAutoGetContent = 0×0040;
//是否只保存正文
var flag = 0;
if (SAVE_CONTENT_ONLY == “1″)
flag |= wizUpdateDocumentSaveContentOnly;
return flag;
}
//获得当前日期
var myDate = new Date();
var year = myDate.getFullYear();
var month = myDate.getMonth() + 1;
var day = myDate.getDate();
//保存的博客所在的文件夹
var document_location = SAVE_TO + BLOG_NAME + “/” + year + formatInt(month) + “/”;
//获得RSS里面链接
var arrayLinks = new Array();
//
var nodes = getRssItemNodes();
if (nodes != null) {
for (var i = nodes.length - 1; i >= 0; i–) {
var node = nodes[i];
//
if (node.nodeType != 1)
continue;
//
if (node.nodeName != “item”)
continue;
//
var linkNode = node.selectSingleNode(“link”);
if (null == linkNode)
continue;
//
//
var link = linkNode.text;
if (link == null || link.length == 0)
continue;
//
try {
//从数据库中通过URL查询,如果已经保存过,就不再重新保存
var documents = objDatabase.DocumentsFromURL(link);
if (documents != null && documents.Count > 0)
continue;
}
catch (e) {
}
//
var titleNode = node.selectSingleNode(“title”);
var title = null;
if (titleNode != null)
title = titleNode.text;
if (title == null)
title = “”;
//
arrayLinks.push(link);
arrayLinks.push(title);
}
}
//
//下载任务
if (arrayLinks.length > 0) {
var objDownloader = new ActiveXObject(“WizKMControls.WizBatchDownloader”); //创建批量下载网页的对象
//
var flags = getUpdateDocumentFlags();
//
for (var i = 0; i < arrayLinks.length; i += 2) {
var link = arrayLinks[i];
var title = arrayLinks[i + 1];
//添加任务
if (title.length == 0) {
objDownloader.AddJob(DATABASE_PATH, document_location, link, “”, flags, true, true);
}
else {
objDownloader.AddJob(DATABASE_PATH, document_location, link, title, flags, true, true);
}
}
//显示下载窗口,并且自动开始下载。
objDownloader.ShowWindow(true);
}
通过上面的描述,我们可以看到WizKnowledge的二次开发能力是非常的强大。
强大无比,希望WizK越来越强大
很好很强大,个人认为Wiz唯有2点美中不足
一就是就是视图了,虽然界面很漂亮,但是仅大纲视图(分类列和搜索列)占用太大空间,导致正文显示的面板太小,而对于频繁切换页面的人来说,全屏太不方便,所以建议作者改进一下视图,最好能切换成树状管理发刚模式
还有一个是编辑窗口和显示窗口独立,能嵌入到显示窗口就好了