VBScript实现浏览文件对话框

Posted 平静的寄居者

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VBScript实现浏览文件对话框相关的知识,希望对你有一定的参考价值。

闲着没事,折腾VBScript。VBScript最大的优点大概是三条,一是Windows内建,不需要安装其他软件,二是双击即可执行,无须编译,三是可以利用hta,比较容易做界面(至少比python强)。缺点除了出错处理比较烂之外,主要是比较老旧,微软没有兴趣维护,有的功能在新版Windows里已经失效了。

想用vbscript实现一个浏览文件对话框的功能,这个在.net winform里有现成的组件OpenFileDialog,但是在VBScript里实现却比较麻烦。先是找到一个BrowseForFolder,最初找到的写法是:

Set WshShell=CreateObject("Wscript.Shell")

WshShell.BrowseForFolder(0, "Please select the folder.", &H4000, "")

调试后发现,首先Wscript.Shell应该改为Shell.Application,其次,虽然可以打开显示文件列表的对话框,但是一旦选中文件后就会提示Unspecified error,查了资料,说Win 7 以后就不能用了(严格地说,如果文件的后缀名是pdf, zip, html,这个方法是可以的。另外,如果把&H4000改成0,光是用来选择文件夹,倒还是能用)。

又查到两种方法,分别是用UserAccounts.CommonDialog和mscomdlg.CommonDialog,结果都不行,貌似win 7以后也不能用了。

最后查到一种方法:

    Dim wso: Set wso = CreateObject("Wscript.Shell")
    Dim hta: hta = """about:<input type=file id=file>"                          & vbcrlf _
                 & "<script>resizeTo(0,0);"                                     & vbCrLf _
                 & "   file.click();"                                           & VbCrLf _
                 & "   fso = new ActiveXObject(\'Scripting.FileSystemObject\');"  & vbCrLf _
                 & "   fso.GetStandardStream(1).WriteLine(file.value);"         & vbCrLf _
                 & "   close();"                                                & VbCrLf _
                 & "</script>"""

    Dim strFileName : strFileName = wso.Exec("mshta.exe " & hta).StdOut.ReadLine

调试后报错,说string未结尾。调试了一会,发现是/s和两个单引号在作怪。分别用Chr(47)代替斜杠和用Chr(39)代替单引号,终于正常了。这个方法确实很巧妙,但这个例子也充分说明了VBScript的缺陷。

如何使用VBScript中的常用“另存为”对话框?

我想让我的VBScript显示Windows另存为对话框,但我找不到如何做到这一点。

使用此代码:

Dim sfd
Set sfd = CreateObject("UserAccounts.CommonDialog")
sfd.ShowOpen

我可以得到一个Open对话框,但是这个对象没有ShowSave方法(因为在Visual Basic非脚本中似乎有类似的对象)。

我搜索了StackOverflow并搜索了“[vbscript] save dialog”(以及“Windows Script Host”),但我只找到了关于从网页访问常用对话框的线程和BrowseForFolder对话框的解决方案,并没有真正关于调用Save对话框的内容。

实际上,我可以使用“打开”对话框来实现我的目的,因为我只需要一个文件名...但是由于我想将某些东西保存到选定的路径,对话框的标题栏中的“另存为”会更合适。

答案

我可以明确地说,没有解决方案在Windows以外的Windows版本下显示VBScript的“另存为”对话框,而不依赖于您必须安装和注册的某些外部依赖项。除了这对于脚本的简单拖放部署造成的明显干扰外,它还会带来一系列与安全性和权限相关的其他问题,特别是在客户端的计算机上绕过UAC进行安装并注册一个依赖DLL。

到目前为止,已经提出的解决方案依赖于刚刚恰好包含在Windows XP中的DLL文件,从Windows XP的用户帐户控制面板调用“另存为”对话框,和/或仅为其安装一个软件。在卸载之后留下MSComDlg DLL,然后您可以使用VBScript。这些解决方案都没有真正满足上述要求,并且所提供的答案都没有考虑到他们提出的解决方案可能出现的安全障碍,正如我在上面提到的那样。

而且因为你不能直接从VBScript直接调用Windows API(它只是方便地包含这样的另存为对话框)(不仅因为它会带来安全风险,而且还因为VBScript的松散[缺乏] ?]打字),几乎让任何想要在寒冷中做到这一点的人。同样,无法进行API调用也排除了使用任何黑客攻击,如调用SetWindowText来更改Open对话框的标题,如问题所示。

我意识到这不是每个人都想要的答案。它甚至不是我想要的答案。但唉,这是正确的答案。

话虽如此,这里有几个可能的解决方法:

  1. 如果您倾向于接受已经建议的任何答案,那么您已经决定将DLL文件的外部依赖性引入到VBScript部署中。一旦你实现了这一飞跃,为什么还要“借用”或以其他方式劫持DLL?只做一次自己。使用Visual Basic 6将Windows API提供的本机常用对话框函数包装到ActiveX DLL中是很简单的,然后可以通过VBScript调用它。风险很小,因为几乎任何现代版本的Windows都可以安装Visual Basic运行时,并且因为你可能已经知道VBScript,所以在VB 6中敲出一些代码应该不是一件非常困难的事情。您可以包含所需的任何自定义功能,最重要的是,您将完全控制。你不必担心其他应用程序的卸载程序删除脚本所需的DLL,你不必为安装和卸载一些随机的,已弃用的应用程序而烦恼,而且你不必只是指责和希望。我们知道,作为程序员,这绝不是一个好的选择。 是的,我建议实际包装Windows API公开的常用对话框函数,而不是依赖Visual Basic提供的常用对话框OCX(comdlg32.ocx)。它在Windows 7中存在一些问题,并且它不会为您提供Windows现在提供的华丽的新对话框。一篇优秀的文章解释了您需要了解的有关Open和Save Common Dialog API以及如何在VB 6中使用它们的所有信息,这些文章是available here on VBnet。当然,如果你真的想全力以赴,那么你可以用常见的对话框做很多有趣的事情,所有这些都记录在案(包括代码!)here on VB Accelerator
  2. 但是现在我已经让你们都相信在VB 6中编写了一个ActiveX DLL,它包含了在你的VBScript中使用的常用对话框功能,我不得不问一个问题:为什么要停在那里?一旦你在VB 6中编写了一些代码,为什么不将所有代码都移到VB 6中呢?当然,这是一种“死”的语言,但它并不像VBScript非常活跃。正如我之前提到的,语法差异几乎为零,VBScript开发人员的学习曲线与人们预期的一样浅。此外,您可以获得完整IDE,静态类型,(稍微)更好的错误处理的所有好处,等等等等。哦是的,能够直接调用Windows API函数。 VBScript唯一真正的好处是它无处不在,但是你可以找到没有安装VB运行时的计算机已经好几年了。更不用说,如果您正在编写需要通用对话框的应用程序,那么您可能正在与用户进行对话:完整VB的表单功能可能在此时开始派上用场。但是,选择这条路线的最大和最重要的优势可能就是你不需要注册(或包含)一个外部“卫星”DLL - 一个简单的VB 6应用程序只能在任何拥有它的计算机上运行EXE。 VB运行时安装,至少包含在Windows 7中。
  3. 最后,如果你对从低级VBScript升级到功能齐全的VB 6感到非常兴奋,我觉得不得不把另一个问题放到这个等式中:为什么不一直向上移动到像VB这样的语言。净?再次,得益于.NET Framework,VB.NET提供了各种新功能,但是对于一个体面的VB / VBScript开发人员来说,开始在VB.NET中编写应用程序感觉很舒服不应该花费几周时间。 。他们可能不会完全理解.NET Framework,他们肯定不会开发出良好的面向对象设计实践,但至少他们会朝着正确的方向前进。几乎所有你可以在VBScript(甚至VB 6)中做的事情都可以在VB.NET中完成。通常,由于.NET Framework提供了巨大的功能,它需要比以前更少的大惊小怪。当然,缺点是您的应用程序现在需要在用户的计算机上安装.NET Framework,这不像VB 6运行时那么普遍(尽管它现在比仅仅几年更常见)前)。

所以我听到你说那些不是你希望听到的变通方法?是的,我也不是。我不是那个告诉人们放弃一切并学习新语言的人。如果VBScript继续为你工作,那就去吧。但是,如果你正处于开始对其局限性产生压力的那一刻,那么可能是时候实现这一目标了。

另一答案

使用VBScript(或VBA或JScript)的公共对话框的秘诀在于您必须在计算机上安装其许可证。某些开发工具(如Visual Basic 6)将安装许可证,但它也由免费的Microsoft HTML帮助编辑器安装(这是一个非常古老的应用程序)。有趣的是,如果您安装然后卸载HTML帮助编辑器,它将保留通用对话许可证。出于这个原因,我认为许可证是免费提供的,因此它将在我的答案中包含它创建的注册表项:

HKLMSoftwareCLASSESLicenses4D553650-6ABE-11cf-8ADB-00AA00C00905,将(Default)条目设置为gfjmrfkfifkmkfffrlmmgmhmnlulkmfmqkqj

一旦到位,您可以使用以下代码在VBScript中创建这些对话框:

Set objDialog = CreateObject("MSComDlg.CommonDialog")

要启动文件保存对话框,请使用此代码中的ShowSave方法:

objDialog.ShowSave

当然,此对象有许多其他方法和属性,您可能希望在启动对话框之前配置适当的属性。例如,您可以设置文件筛选器,以便只在对话框中显示某些文件扩展名。这里有一个很好的参考MSDN网站上的控件:http://msdn.microsoft.com/en-us/library/aa259661%28v=vs.60%29.aspx

希望这可以帮助。如果您有任何疑问,请告诉我。

另一答案

如果您对将要部署它的系统有一定程度的控制,并且可以合理地确定它们安装了Visual Studio或Microsoft HTML帮助,则可以使用如下代码:

function filedialog(filt, def, title, save)
    set dialog = CreateObject("MSComDlg.CommonDialog")
    dialog.MaxFileSize = 256
    if filt = "" then
        dialog.Filter = "All Files (*.*)|*.*"
    else
        dialog.Filter = filt
    end if
    dialog.FilterIndex = 1
    dialog.DialogTitle = title
    dialog.InitDir = CreateObject("WScript.Shell").SpecialFolders("MyDocuments")
    dialog.FileName = ""
    if save = true then
        dialog.DefaultExt = def
        dialog.Flags = &H800 + &H4
        discard = dialog.ShowSave()
    else
        dialog.Flags = &H1000 + &H4 + &H800
        discard = dialog.ShowOpen()
    end if
    filedialog = dialog.FileName
end function

此外,将此问题的其他答案之一调整为VBScript代码(感谢@oddacorn!),如果您不能确定您的用户将拥有VS或HTML帮助,则应添加此功能。在程序启动时调用此函数。如果你已经有钥匙,不要担心;在这种情况下,这没有任何效果。这应该适用于没有管理员权限的标准用户帐户。

'Make the MSComDlg.CommonDialog class available for use. Required for filedialog function.
function registerComDlg
    Set objRegistry = GetObject("winmgmts:\.
ootdefault:StdRegProv")
    objRegistry.CreateKey &H80000001, "SoftwareCLASSESLicenses4D553650-6ABE-11cf-8ADB-00AA00C00905"
    objRegistry.SetStringValue &H80000001, "SoftwareCLASSESLicenses4D553650-6ABE-11cf-8ADB-00AA00C00905", "", "gfjmrfkfifkmkfffrlmmgmhmnlulkmfmqkqj"
end function

请注意,我在HTML here中修改了VBScript代码的“查看源”中的filedialog函数;在现代Web浏览器上,它们用于呈现代码示例的HTML似乎无法正确显示(在IE 8和Chrome上测试)。但幸运的是,代码仍然存在于View Source中。

我发现有一件事对于在Windows 7上完成这项工作至关重要(SP1,完全打补丁);你必须设置dialog.MaxFileSize = 256或者你会得到一个运行时错误。

也就是说,以下代码在Windows 7 SP1上失败,但可能适用于旧版本的Windows:

Set x = CreateObject("MSComDlg.CommonDialog")
x.ShowSave
另一答案

http://blogs.msdn.com/b/gstemp/archive/2004/02/18/75600.aspx上有一种方法描述了如何从VBScript显示另存为对话框。

请注意,根据http://www.eggheadcafe.com/software/aspnet/29155097/safrcfiledlg-has-been-deprecated-by-microsoft.aspx,SAFRCFileDlg已被Microsoft弃用。

另一答案

我刚刚创建了一个shell,将它链接到一个asp网站,让网站读取一个方向标记 - 我将文件位置加载到,并且asp页面立即在该文件位置打开文件对话框,文件名也通过方向标签。保存后,shell就会消失。

如果它是网站direcitonal标签的限制,即(blah.com/temp.aspx?x=0&y=2&z=3)

将信息存储在SQL数据库或平面文件中,有大量的解决方法,但上面说的是真的。 VBS不会在内部削减它。

另一答案

寻找年龄后,我在jsware.net找到了jsShell - Shell Component。该zip文件包含jsShell.dll 176 kB,一个用于注册dll的vbscript,基本上是regsvr32.exe jsShell.dll,演示脚本和清晰的文档。

该DLL在Windows 7中运行良好,并提供了一些有用的方法,包括打开/保存对话框:

Dim jsS, sFileName
jsS = CreateObject("jsShell.Ops")
' Save as dialog
sFileName = jsS.SaveDlg("<title>", "exe") ' Example: Filter by exe files
sFileName = jsS.SaveDlg("<title>", "")    ' Example: No extension filter
' Open dialog
' Example: Filter by exe, initial dir at C:
sFileName = jsS.OpenDlg("<title>", "exe", "C:")

如果未选择任何文件,则sFileName为空字符串。

另一答案
Private Sub cmdB1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdB1.Click
    Dim objExec, strMSHTA, wshShell, SelectFile

    SelectFile = ""

    ' For use in HTAs as well as "plain" VBScript:
    strMSHTA = "mshta.exe ""about:" & "<" & "input type=file id=FILE>" _
             & "<" & "script>FILE.click();new ActiveXObject('Scripting.FileSystemObject')" _
             & ".GetStandardStream(1).WriteLine(FILE.value);close();resizeTo(0,0);" & "<" & "/script>"""

    wshShell = CreateObject("WScript.Shell")
    objExec = wshShell.Exec(strMSHTA)

  

以上是关于VBScript实现浏览文件对话框的主要内容,如果未能解决你的问题,请参考以下文章

vbscript 它只是弹出对话框,允许您指定数据库文本文件和连接字符串/表名的文件路径。

这段程序是用VBScript去取的所选文件的路径对话框,有哪位高手可以让这个对话框可以打开特定的文件夹

如何使用VBScript中的常用“另存为”对话框?

鼠标左键单击的脚本vbscript

vbscript 通过KTM验证表单按钮触发对话框。通过SQLDBQuery填充对话框

asp网页中,如何实现点击按钮弹出对话框,然后点击“确定”关闭窗口,点击“取消”返回?尽快,非常感谢!