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

Jay*_*ayK 18 vbscript common-dialog savefiledialog

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

使用此代码:

Dim sfd
Set sfd = CreateObject("UserAccounts.CommonDialog")
sfd.ShowOpen
Run Code Online (Sandbox Code Playgroud)

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

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

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

odd*_*orn 11

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

HKLM\Software\CLASSES\Licenses\4D553650-6ABE-11cf-8ADB-00AA00C00905,将(Default)条目设置为gfjmrfkfifkmkfffrlmmgmhmnlulkmfmqkqj.

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

Set objDialog = CreateObject("MSComDlg.CommonDialog")
Run Code Online (Sandbox Code Playgroud)

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

objDialog.ShowSave
Run Code Online (Sandbox Code Playgroud)

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

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


Cod*_*ray 8

我可以明确地说,没有解决方案在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公开的常用对话框函数,而不是依赖comdlg32.ocxVisual Basic提供的公共对话框OCX().它在Windows 7中存在一些问题,并且它不会为您提供Windows现在提供的华丽的新对话框.在VBnet上可以找到一篇优秀的文章,解释您需要了解的有关Open和Save Common Dialog API以及如何在VB 6中使用它们的所有信息.当然,如果你真的想要全力以赴,那么你可以用常见的对话框做很多有趣的事情,所有这些都在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继续为你工作,那就去吧.但是,如果你正处于开始对其局限性产生压力的那一刻,那么可能是时候实现这一目标了.


all*_*tic 5

如果您对要部署此系统的系统有一定程度的控制,并且可以合理确定它们安装了 Visual StudioMicrosoft 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
Run Code Online (Sandbox Code Playgroud)

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

'Make the MSComDlg.CommonDialog class available for use. Required for filedialog function.
function registerComDlg
    Set objRegistry = GetObject("winmgmts:\\.\root\default:StdRegProv")
    objRegistry.CreateKey &H80000001, "Software\CLASSES\Licenses\4D553650-6ABE-11cf-8ADB-00AA00C00905"
    objRegistry.SetStringValue &H80000001, "Software\CLASSES\Licenses\4D553650-6ABE-11cf-8ADB-00AA00C00905", "", "gfjmrfkfifkmkfffrlmmgmhmnlulkmfmqkqj"
end function
Run Code Online (Sandbox Code Playgroud)

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

我发现一件事对于在 Windows 7(SP1,已完全修补)上运行至关重要;必须设置dialog.MaxFileSize = 256,否则您将收到运行时错误。

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

Set x = CreateObject("MSComDlg.CommonDialog")
x.ShowSave
Run Code Online (Sandbox Code Playgroud)