2010年09月 存档

VBS实现“多线程”

2010年09月30日,星期四

今天有人发邮件问我一个问题:

想请教一下VBS中INPUTBOX函数能否超时关闭?
如果可以的话,应该如何超时关闭输入框? 万分感谢

乍一看这是不可能实现的,因为InputBox函数本身没有超时关闭的参数,而且程序会一直等待InputBox返回才继续运行,后面的语句不可能在InputBox返回之前执行。

如果VBS能实现高级语言的多线程的话……只可惜VBS不可能实现多线程,但是可以用setTimeout方法模拟“多线程”。

Dim IE
Set IE = CreateObject("InternetExplorer.Application")
IE.Navigate "about:blank"
Set window = IE.Document.parentWindow
id = window.setTimeout(GetRef("on_timeout"),3000,"VBScript")
name = InputBox("Please enter your name","InputBox Timeout")
window.clearTimeout id
If name <> "" Then MsgBox "Hello," & name
IE.Quit

'By Demon
'https://demon.tw

Sub on_timeout()
    Dim WshShell
    set WshShell = CreateObject("wscript.Shell")
    WshShell.SendKeys "{ESC}"
End Sub

用setTimeout方法设定3秒超时,3秒后用SendKeys方法发送ESC键结束InputBox。当然,用SendKeys是很不靠谱的,我一般很少用SendKeys方法,因为它做了太多的假设,万一InputBox不是激活窗口呢?这里只是为了程序简单而用了SendKeys,可以换成结束脚本本身。

同理,想在VBS中实现VB中的Timer事件的话可以用setInterval方法,我就不写例子了,自己看文档。

参考链接:setTimeout Method (window, Window Constructor)

 

AscW函数返回负数的问题

2010年09月29日,星期三

其实这个问题在以前写《VBS实现PHP的urlencode函数》的时候就碰到了,但是当时没有记下来,造成写前面一篇文章《VBS实现Unicode转UTF-8》的时候重蹈覆辙。还是记录下来吧,免得以后又忘记。

MSDN文档对AscW的说明是:AscW是为使用Unicode字符的32位平台提供的。它返回Unicode(宽型)字符代码,因此可以避免从ANSI到Unicode的代码转换。

按照参考手册的定义,AscW函数应该返回一个字符的Unicode字符编码,但是直接拿返回的结果来用的话会有潜在的BUG,正如我碰到的。

“魔”字的Unicode编码是39764,测试如下代码

c = AscW("")
If c > 127 Then
	WScript.Echo "Not ASCII"
Else
	WScript.Echo "ASCII"
End If

你认为返回的结果是什么?"Not ASCII"?错!返回的结果是"ASCII"。

这就是潜在的BUG,对某些中文(当然还有其他字符)AscW函数返回的值是负数!如果你的代码拿这个值与一个正数比较大小,逻辑值将是False!

为什么呢?因为AscW的返回值的子类型是Integer,而VBS中Integer的取值范围是从-32768到32767。39764 > 32767,造成了溢出,所以返回负数。

怎样才能得到正确的结果呢?答案把子类型是转化成Long,Long的取值范围是-2,147,483,648到2,147,483,647,不会造成溢出。

WScript.Echo CLng("&H" & Hex(AscW("")))

先用Hex函数把AscW的返回值转化成十六进制的字符串,加上VBS中十六进制前缀&H,最后用CLng函数把子类型转化成Long。这样就能得到39764这个正确的Unicode编码值了。

VBS实现Unicode(UTF-16)转UTF-8

2010年09月28日,星期二

有UTF-8转Unicode当然就有Unicode转UTF-8。

'Author: Demon
'Website: https://demon.tw
'Date: 2010/9/28
Function UnicodeToUtf8(str)
    Dim i, c, length
    out = ""
    length = Len(str)
    For i = 1 To length
        c = CLng("&H" & Hex(AscW(Mid(str,i,1))))
        If (c >= &H0001) And (c <= &H007F) Then
            out = out & ChrB(c)
        ElseIf c > &H07FF Then
            out = out & ChrB(&HE0 Or (c\(2^12) And &H0F))
            out = out & ChrB(&H80 Or (c\(2^ 6) And &H3F))
            out = out & ChrB(&H80 Or (c\(2^ 0) And &H3F))
        Else
            out = out & ChrB(&HC0 Or (c\(2^ 6) And &H1F))
            out = out & ChrB(&H80 Or (c\(2^ 0) And &H3F))
        End If
    Next
    UnicodeToUtf8 = out
End Function

参考链接:UTF-8 – 维基百科,自由的百科全书

VBS实现UTF-8转Unicode(UTF-16)

2010年09月27日,星期一

本文源于一个VBS群里的一个看起来很牛逼的人给别人的一个UTF-8转Unicode的函数Utf8ToUnicode。代码有60多行,放在了文章后面,以免喧宾夺主~

代码太长了,不知道是他自己写的还是复制粘贴的。我没有仔细看,但是简单测试了一下,貌似是正确的。

当时回了一句“Utf8ToUnicode函数哪需要这么复杂”,谁知他来了句“如果用api的话,当然一个了。”

算了,看在他的代码功能是正确的份上,我就不多说什么了。下面给出我写的自以为比他的简单的Utf8ToUnicode函数。 (更多…)

VBS中的GUI界面(EditPlus注册机)

2010年09月26日,星期日

其实用VBS也可以写出很漂亮的用户界面,大体上有两种方法,一种是HTA,一种是InternetExplorer.Application。这两种方法都是基于html的,也就是说,网页可以做得多漂亮,我们的界面就可以做得多漂亮。

虽然用HTA可以超越浏览器对脚本的禁锢,但是我不喜欢,还是喜欢纯VBS。所以只简单的说一下用InternetExplorer.Application创建GUI。

首先我们要创建一个InternetExplorer.Application对象

Set IE = CreateObject("InternetExplorer.Application")

然后打开一个空白页面about:blank,并把ToolBar设为False(不显示工具栏),StatusBar设为False(不显示状态栏),Visible设为True。

IE.Navigate "about:blank"
IE.ToolBar = False
IE.StatusBar = False
IE.Visible = True

剩下的就是网页设计的事情了,用Document的write方法写入html代码。

IE.Document.write "<input type='text' />"
IE.Document.write "<input type='button' value='OK' />"

就像设计网页一样设计我们的界面就行了,下面给出一个示例。用VBS写的带GUI界面的EditPlus注册机。

参考链接:

  1. 如何使用 InputBox 来屏蔽密码?
  2. InternetExplorer Object