18

我想让我的 VBScript 显示 Windows 另存为对话框,但我不知道如何去做。

使用此代码:

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

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

我搜索了 StackOverflow 并在 Google 上搜索了“[vbscript] 保存对话框”(以及“Windows 脚本主机”),但我只找到了有关从网页访问常用对话框和对话框解决方案的线程,BrowseForFolder而没有真正调用保存对话框。

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

4

9 回答 9

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")

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

objDialog.ShowSave

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

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

于 2010-12-16T18:51:10.533 回答
8

我可以肯定地说,没有解决方案可以在 XP 以外的 Windows 版本下从 VBScript 显示“另存为”对话框,而无需依赖您必须自己安装和注册的一些外部依赖项。除了对脚本的简单拖放部署造成明显干扰之外,它还带来了许多与安全和权限相关的其他问题,特别是绕过客户端机器上的 UAC 进行安装并注册一个依赖 DLL。

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

而且由于您不能从 VBScript 直接调用 Windows API(它非常方便地包括这样的另存为对话框)(不仅因为它会带来安全风险,而且还因为 VBScript 的松散 [缺乏?] 打字),这几乎让任何想在寒冷中这样做的人。同样,如问题中所建议的,无法进行 API 调用也排除了使用任何技巧,例如调用SetWindowText来更改“打开”对话框的标题。

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

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

  1. 如果您倾向于接受任何已经建议的答案,那么您已经决定在您的 VBScript 部署中引入对 DLL 文件的外部依赖。一旦实现了这一飞跃,为什么还要“借用”或以其他方式从其他来源劫持 DLL?自己做一次。使用 Visual Basic 6 将 Windows API 提供的本机通用对话框函数包装到 ActiveX DLL 中很简单,然后您的 VBScript 可以调用该 DLL。风险很小,因为几乎任何现代版本的 Windows 都可以预期已经安装了 Visual Basic 运行时,并且由于您可能已经了解 VBScript,因此在 VB 6 中编写一些代码应该不是一件非常困难的事情。您可以包含任何您想要的自定义功能,最重要的是,您 将完全掌控。您不必担心其他应用程序的卸载程序会删除您的脚本所需的 DLL,您不必费心安装和卸载一些随机的、已弃用的应用程序,您也不必只是祈祷。我们知道,作为程序员,这绝不是一个好的选择。

    是的,我建议实际包装由 Windows API 公开的常用对话框函数,而不是依赖于comdlg32.ocxVisual Basic 提供的常用对话框 OCX ( )。它在 Windows 7 中存在一些问题,并且不会为您提供 Windows 的更高版本现在提供的华丽的新对话框。VBnet 上提供了一篇出色的文章,解释了您需要了解的有关打开和保存通用对话框 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 框架,VB.NET 中提供了各种新功能,但是对于一个体面的 VB/VBScript 开发人员来说,在几周内就可以开始熟悉在 VB.NET 中编写应用程序了. 他们可能不会对 .NET Framework 有充分的了解,当然也不会开发出良好的面向对象设计实践,但至少他们会朝着正确的方向前进。您可以在 VBScript(甚至 VB 6)中执行的几乎所有操作,都可以在 VB.NET 中执行。一般来说,它比以前需要更少的大惊小怪,感谢 .NET Framework 提供的巨大功能。当然,缺点是您的应用程序现在需要在用户的计算机上安装 .NET Framework,它不像 VB 6 运行时那样普遍(尽管现在比几年前更普遍)前)。

所以我听到你说这些不是你希望听到的解决方法?是的,我也没有。我不是那种告诉人们放弃一切并学习一门新语言的人。如果 VBScript 继续为您工作,那就去吧。但是,如果您在那个时候开始对其限制感到紧张,那么可能是时候实现飞跃了。

于 2010-12-19T10:32:11.480 回答
4

如果您对要部署它的系统有一定程度的控制,并且可以合理地确定它们安装了 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

此外,将此问题的其他答案之一改编为 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

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

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

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

Set x = CreateObject("MSComDlg.CommonDialog")
x.ShowSave
于 2013-08-01T15:00:27.920 回答
0

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 弃用。

于 2010-12-13T23:13:13.357 回答
0

我刚刚制作了一个外壳,将其链接到一个 asp 网站,使网站读取了一个定向标签——我将文件位置加载到该标签中,然后 asp 页面立即在该文件位置内打开文件对话框,文件名也通过指定定向标签。一旦保存,外壳就会消失。

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

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

于 2011-11-11T19:36:04.080 回答
0

在找了很久之后,我在 jsware.net 找到了 jsShell - Shell 组件。zip 文件包含jsShell.dll 176 kB 、一个基本regsvr32.exe jsShell.dll注册 dll 的 vbscript 、演示脚本和清晰的文档

该 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是一个空字符串。

于 2012-06-09T17:56:42.977 回答
0
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)

    SelectFile = objExec.StdOut.ReadLine()
    Me.txtT0.Text = SelectFile
    objExec = Nothing
    wshShell = Nothing
    strMSHTA = Nothing
End Sub
于 2014-09-25T05:53:39.857 回答
-1

我刚刚在 这个网站上找到了一个解决方案 它有完整的评论并且在 Windows 10 中运行良好

这是将文件夹作为字符串返回的代码(我在三个不同的起始文件夹中尝试过):

Option Explicit

WScript.Echo BrowseFolder( "C:\Program Files", True )
WScript.Echo BrowseFolder( "My Computer", False )
WScript.Echo BrowseFolder( "", False )


Function BrowseFolder( myStartLocation, blnSimpleDialog )
' This function generates a Browse Folder dialog
' and returns the selected folder as a string.
'
' Arguments:
' myStartLocation   [string]  start folder for dialog, or "My Computer", or
'                             empty string to open in "Desktop\My Documents"
' blnSimpleDialog   [boolean] if False, an additional text field will be
'                             displayed where the folder can be selected
'                             by typing the fully qualified path
'
' Returns:          [string]  the fully qualified path to the selected folder
'
' Based on the Hey Scripting Guys article
' "How Can I Show Users a Dialog Box That Only Lets Them Select Folders?"
' http://www.microsoft.com/technet/scriptcenter/resources/qanda/jun05/hey0617.mspx
'
' Function written by Rob van der Woude
' http://www.robvanderwoude.com
    Const MY_COMPUTER   = &H11&
    Const WINDOW_HANDLE = 0 ' Must ALWAYS be 0

    Dim numOptions, objFolder, objFolderItem
    Dim objPath, objShell, strPath, strPrompt

    ' Set the options for the dialog window
    strPrompt = "Select a folder:"
    If blnSimpleDialog = True Then
        numOptions = 0      ' Simple dialog
    Else
        numOptions = &H10&  ' Additional text field to type folder path
    End If

    ' Create a Windows Shell object
    Set objShell = CreateObject( "Shell.Application" )

    ' If specified, convert "My Computer" to a valid
    ' path for the Windows Shell's BrowseFolder method
    If UCase( myStartLocation ) = "MY COMPUTER" Then
        Set objFolder = objShell.Namespace( MY_COMPUTER )
        Set objFolderItem = objFolder.Self
        strPath = objFolderItem.Path
    Else
        strPath = myStartLocation
    End If

    Set objFolder = objShell.BrowseForFolder( WINDOW_HANDLE, strPrompt, _
                                              numOptions, strPath )

    ' Quit if no folder was selected
    If objFolder Is Nothing Then
        BrowseFolder = ""
        Exit Function
    End If

    ' Retrieve the path of the selected folder
    Set objFolderItem = objFolder.Self
    objPath = objFolderItem.Path

    ' Return the path of the selected folder
    BrowseFolder = objPath
End Function
于 2019-04-22T10:21:19.273 回答
-2
Set objDialog = CreateObject( "SAFRCFileDlg.FileSave" )

' Note: If no path is specified, the "current" directory will
'       be the one remembered from the last "SAFRCFileDlg.FileOpen"
'       or "SAFRCFileDlg.FileSave" dialog!
objDialog.FileName = "test_save.vbs"
' Note: The FileType property is cosmetic only, it doesn't
'       automatically append the right file extension!
'       So make sure you type the extension yourself!
objDialog.FileType = "VBScript Script"
If objDialog.OpenFileSaveDlg Then
    WScript.Echo "objDialog.FileName = " & objDialog.FileName
End If
于 2011-05-06T02:05:21.007 回答