Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1658676
  • 博文数量: 230
  • 博客积分: 10045
  • 博客等级: 上将
  • 技术积分: 3357
  • 用 户 组: 普通用户
  • 注册时间: 2006-12-30 20:40
文章分类

全部博文(230)

文章存档

2011年(7)

2010年(35)

2009年(62)

2008年(126)

我的朋友

分类:

2010-07-10 22:50:29

Build Simple Asynchronous Pluggable Protocols for Windows

You're not limited to the familiar asynchronous pluggable protocols (APPs) such as ftp://, and javascript:// that are built into Windows; you can implement your own protocols, add them to Windows' recognized protocol list, and then use them from any application—and you can implement your protocol in any language. This article uses the Rebol scripting language to create a protocol that works similarly to the javascript:// protocol, compiling and evaluating arbitrary Rebol statements and displaying the results.
very protocol—whether familiar (such as http, mailto, ftp, and about) or less familiar (such as JavaScript, VBScript, Outlook, NNTP, news, snews, and so forth)—is implemented on Windows machines as an asynchronous pluggable protocol (APP). These protocols can plug directly into Windows' existing protocol framework. The only common protocol not implemented as an APP (at least on my computer) is SMTP. You can call any of these protocols from any interface in Windows that allows protocol interaction, regardless of whether the interface is programmatic or graphical.

To prove it, go to the Run command on your Start button and write the following:


javascript: alert("hello world");

This should initiate whichever application is associated with the JavaScript protocol on your system, probably Internet Explorer, and execute the script. This is the same principle involved in . A bookmarklet "a tiny program (a JavaScript application) contained in a bookmark (the URL is a "javascript:" URL) which can be saved and used the same way you use normal bookmarks."

You can use the JavaScript protocol from other browsers such as Mozilla, as Mozilla does not start up Internet Explorer when someone writes the code above in its address bar. Mozilla will pass any APP that it does not handle natively to the proper system handler. As I showed above, you can even use the JavaScript protocol from the Run box under your Start menu.

What You Need
Windows 98 or later with IE 4 or later, Wscript, , and a text editor.

MSDN provides some about APPs, but be wary of what you read: You may come away with a misconception about what is required to achieve the most basic implementation of an APP under Windows. For example, implies that to write an APP one needs to implement certain interfaces, but APPs are actually very flexible. The basic implementation of an APP under Windows requires only that you make the proper entries in the registry for your protocol and that the handler for your protocol is a valid Windows .exe file. You can see an example at . The "note" protocol defined in that example opens Notepad, similar to the way the view-source:// protocol can be used to open the .htm source of an HTML file in Notepad. For example, try putting this in your browser: view-source:http://www.devx.com.

I doubt that Notepad implements or any related interfaces, as to do so it should be a COM implementation and found at the following registry address HKEY_CLASSES_ROOT\PROTOCOLS. Without these related interfaces, in the end all that happens is the protocol address is passed as a string via the command line to your application for analysis.

The W3C provides of addressing schemes, which you can use to search your system to see if these addressing schemes are implemented as APPs. Those that do more than just call over the command line should be found at the HKEY_CLASSES_ROOT\PROTOCOLS\Handler registry key.

There are many tools that allow you to dynamically load files via the command line, and pass on command lines to files. One example is script interpreters such as Wscript.exe. Here is the sample registry file, which shows how to set a simple WScript as the handler for a protocol called ws-proto.


Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\ws-proto]
@="\"URL: ws-proto Protocol\""
"URL Protocol"=""

[HKEY_CLASSES_ROOT\ws-proto\shell]

[HKEY_CLASSES_ROOT\ws-proto\shell\open]

[HKEY_CLASSES_ROOT\ws-proto\shell\open\command]
@="wscript.exe c:\\wsproto.js %1"

Here is the protocol that handles the WScript. (Both the registry file and the protocol handler are available in the code download for this article—see left column).


WScript.Echo(WScript.Arguments(0));


: Howdy. As you can see the first command line argument passed on to our Wscript is everything you wrote in your address bar.
To test this handler you can either make a new text file called settings.reg, copy the registry settings there, and then click to add the settings to the registry or use the settings.reg file in the code download. You should save the protocol handler code in c:\ in a file called wsproto.js. Once you've done this you can interact with the protocol in the same way you would with any other protocol. As an example, open your preferred browser and write the following: ws-proto://howdy. The result are shown in .




A JavaScript Alternative: Rebol
Most protocol implementations are done with a particular goal in mind, however there are certain protocols, such as the JavaScript protocol, that are designed to extend the functionality of the system as a whole, and the browser in particular.

It is this latter type that I will build in this article, using the JavaScript protocol as a model. The JavaScript protocol allows you to transmit JavaScript code that will then be evaluated within the browser. This means that the objects available to the protocol are the objects exposed by the browser. In our earlier example, the alert() functioned because alert() is supported in the browser environment.


: Security Check. Rebol's default security asks you before it opens a port to our protocol interpreting script.
I'm willing to bet there are a lot of folks out there, like me, who like scripting languages but abhor JavaScript. Using the same technique of dynamically loading a script in an .exe, as shown in the ws-proto example, it should be possible to make a protocol handler that accepts script in your favorite scripting language and evaluates it. This opens up the possibility of bookmarklets written in languages such as Python and Perl, as well as the usual VBScript and JavaScript. In the next part of the article I will make a protocol handler that accepts script in my favorite scripting language, .

Why Rebol? Because Rebol is particularly good at handling protocols. By implementing a dynamic evaluating protocol in Rebol, I can very easily add functionality to interact with ftp, smtp, http, etc. (These protocols are easily accessible from Rebol using Rebol's one-liner scripts, e.g. one line of code to read a URL and write the output to a local file.) Rebol can interact with any protocol that can be called via bookmarklet-type behavior, from a link on a web page, from writing in the address bar, from shortcuts, or from most any programming language/environment in the Windows system.


: Rebol View. The large text area contains the URL body you passed by clicking on the link.
You can download a free, noncommercial version of Rebol from . It includes a Rebol dialect (sort of a DSL) for graphical interfaces, which I will use to implement a small form in my script. This form will help me decide, by showing the code passed to it, whether to evaluate the code, append it to a local file containing the script fragments I receive, or to edit it and then evaluate it.

It's time to implement the Rebol script. There are links at various points to the , which provides definitions of built-in Rebol functions to help you along. In the code download for this article there is a registry file called rebsettings.reg, which sets the reb protocol to be evaluated using a script called reb.r. Reb.r is the protocol handler that the registry files point at (see ). Install Rebol in the default installation folder c:\rebol\view. Be advised that the Rebol installation program asks you for information such as your email address, email server etc., which it needs to send and receive mail and for the examples to work.

Once Rebol is installed, you should merge the accompanying .reg file and also install the files in the downloadable sample code (see link in left column) to the c:\rebol\view directory. When you've done that, open the example.html file in your default browser. shows the contents of the example.html file.

This file has three simple JavaScript functions called callreb(),browseloc(), and insertPrompt().

  • Callreb() takes a string parameter, which should be a reb:// link, and then uses the browser's location.href method to navigate to the reb:// link.
  • When executed in a link, browseloc() will tell Rebol to browse the page on which the link was executed.
  • The insertPrompt() function accepts three arguments and builds a string containing the reb:// protocol. The middle argument is the result of a JavaScript prompt that gets a user-entered value and places it in the middle of the reb:// protocol.

The first link in the HTML page is:



read a local file and write result to new local file

Everything past the reb:// is legal Rebol code. And it does exactly what the link text tells you: It reads a local file, contained in the code download called oldfile.txt and writes a local file called newfile.txt. (Note that the parameters are intentionally opposite their function—this is because of the evaluation order of Rebol syntax). The % before the file names tells Rebol that these are in fact files. When you click on the link you should see something similar to :

The popup is generated by Rebol's built-in security (more information on controlling Rebol security settings). When you click Yes, reb.r loads (see ).

Pressing Do causes the Rebol interpreter to evaluate the text contained in the '; tpl += '

'; tpl += '
'; tpl += '
'; tpl += ''; tpl += '
'; tpl += '
'; tpl += '
'; $('.z_move_comment').html(''); $(this).parents('.Blog_right1_8').find('.z_move_comment').html(tpl).show(); }); //引用的评论提交 $('#quota_sbumit').live('click' , function(){ if(isOnLine == '' ) { //showErrorMsg('登录之后才能进行此操作' , '消息提示'); showErrorMsg('操作失败,您需要先登录!', '消息提示', 'http://account.chinaunix.net/login'); return false; } var bid = $(this).attr('bid'); var tid = $(this).attr('tid');//被引用人的id var qid = $(this).attr('cid');//引用的id var url = $(this).attr('url'); var text = $('#rmsg').val(); var tname = $(this).attr('tname'); if(text == '' || text=='文明上网,理性发言...') { showErrorMsg('评论内容不能为空!' , '消息提示'); return false; } else { if(mb_strlen(text) > 1000){ showErrorMsg('评论内容不能超过500个汉字' , '消息提示'); return false; } } $.ajax({ type: "post", url: url , data: {'bid': bid , 'to' : tid , 'qid' : qid , 'text': text , 'tname' : tname }, dataType: 'json', success: function(data){ if(data.code == 1){ var tpl = '
'; tpl+= ''; tpl+= '
'; tpl+= '

' + data.info.username + '' + data.info.dateline + '

'; tpl+= '

' + data.info.quota.username + ':'+ data.info.quota.content + '

'; tpl+= '

' + data.info.content + '

回复 |  删除 |  举报
'; tpl+= ''; tpl+= '
'; $('#replyList .Blog_right1_8:first').before(tpl); $('.z_move_comment').html('').hide(); } else if(data.code == -1){ //showErrorMsg(data.info , '消息提示'); showErrorMsg('操作失败,您需要先登录!', '消息提示', 'http://account.chinaunix.net/login'); } }, error: function(){//请求出错处理 } }); }); //底部发表评论 $('#submitmsg').click(function(){ if(allowComment == 1) { showErrorMsg('该博文不允许评论' , '消息提示'); return false; } var bid = $(this).attr('bid'); var toid = $(this).attr('toid'); var text = $('#reply').val(); var url = $(this).attr('url'); if(text == '' || text=='文明上网,理性发言...') { showErrorMsg('评论内容不能为空!' , '消息提示'); return false; } else { if(mb_strlen(text) > 1000){ showErrorMsg('评论内容不能超过500个汉字' , '消息提示'); return false; } } $.ajax({ type: "post", url: url , data: {'bid': bid , 'to' : toid ,'text': text}, dataType: 'json', success: function(data){ if(data.code == 1) { var tpl = '
'; tpl += ''; tpl += '
'; tpl += '

' + data.info.username + '' + data.info.dateline + '

'; tpl += '

' + data.info.content + '

'; tpl += '
回复 |  删除 |  举报
'; tpl += ''; tpl += '
'; $('.Blog_tit3:first').after(tpl); $('#reply').val('文明上网,理性发言...'); } else if(data.code == -1) { showErrorMsg(data.info , '消息提示'); } }, error: function(){//请求出错处理 } }); }); //底部评论重置 $('#reset_comment').click(function(){ $('#reply').val('文明上网,理性发言...'); }); //取消回复 $('#qx_comment').live('click' , function(){ $('.z_move_comment').html('').hide(); }); $('#rmsg, #reply').live({ focus:function(){ if($(this).val() == '文明上网,理性发言...'){ $(this).val(''); } }, blur:function(){ if($(this).val() == ''){ $(this).val('文明上网,理性发言...'); } } }); //删除留言确认 $('.comment_del_mark').live('click' , function(){ var url = $(this).attr('url'); asyncbox.confirm('删除留言','确认', function(action){ if(action == 'ok') { location.href = url; } }); }); //删除时间确认 $('.del_article_id').click(function(){ var delurl = $(this).attr('delurl'); asyncbox.confirm('删除文章','确认', function(action){ if(action == 'ok') { location.href = delurl; } }); }); /* //字数限制 $('#rmsg, #reply').live('keyup', function(){ var id = $(this).attr('id'); var left = Util.calWbText($(this).val(), 500); var eid = '#errmsg'; if(id == 'reply') eid = '#rerrmsg'; if (left >= 0) $(eid).html('您还可以输入' + left + '字'); else $(eid).html('您已超出' + Math.abs(left) + ''); }); */ //加载表情 $('#face').qqFace({id : 'facebox1', assign : 'reply', path : '/image/qqface/'}); $('#mface').qqFace({id : 'facebox', assign : 'rmsg', path:'/image/qqface/'}); /* $('#class_one_id').change(function(){ alert(123213); var id = parseInt($(this).val() , 10); if(id == 0) return false; $('.hidden_son_class span').each(function( index , dom ){ if( dom.attr('cid') == id ) { } }); }); */ //转载文章 var turn_url = "/blog/viewClassPart.html"; $('#repost_bar').click(function(){ if(isOnLine == '' ) { //showErrorMsg('登录之后才能进行此操作' , '消息提示'); showErrorMsg('操作失败,您需要先登录!', '消息提示', 'http://account.chinaunix.net/login'); return false; } var id = $(this).attr('bid'); asyncbox.open({ id : 'turn_class_thickbox', url : turn_url, title : '转载文章', width : 330, height : 131, scroll : 'no', data : { 'id' : id }, callback : function(action){ if(action == 'close'){ $.cover(false); } } }); }); /* //转发文章 $('#repost_bar').live('click' , function(){ if(isOnLine == '' ) { //showErrorMsg('登录之后才能进行此操作' , '消息提示'); showErrorMsg('操作失败,您需要先登录!', '消息提示', 'http://account.chinaunix.net/login'); return false; } var bid = $(this).attr('bid'); var url = $(this).attr('url'); asyncbox.confirm('转载文章','确认', function(action){ if(action == 'ok'){ $.ajax({ type:"POST", url:url, data: { 'bid' : bid }, dataType: 'json', success:function(msg){ if(msg.error == 0){ showSucceedMsg('转发成功!', '消息提示'); }else if(msg.error == 1){ //location.href = '/index.php?r=site/login'; showErrorMsg('操作失败,您需要先登录!', '消息提示', 'http://account.chinaunix.net/login'); }else{ showErrorMsg(msg.error_content, '消息提示'); } } }); } }); }); */ });