【问题标题】:Why is this call to InvokeVerb ("&Print") not working?为什么对 InvokeVerb ("&Print") 的调用不起作用?
【发布时间】:2015-01-19 15:50:27
【问题描述】:

我只是想批量打印文件夹中的大量文件。该文件夹包含多种文件类型,我只想调用等效于Right-Click > Print 的打印方法。

看来我应该可以使用Shell32.FolderItem 对象的InvokeVerb 方法来做到这一点。 所以,我不知道为什么,当我运行下面的代码时,什么都没有打印出来。

有什么想法吗?

GetFolder 只是 Shell32.BrowseForFolder 函数的包装器,它返回所选文件夹的路径。该函数可以正常工作。对于测试,您只需替换为文件夹的路径即可。)

Sub printFOO()
    Dim shApp           As Shell32.Shell
    Dim srFSO           As Scripting.FileSystemObject
    Dim strPath         As String
    Dim shFIcol         As Shell32.FolderItems
    Dim shFIx           As Shell32.FolderItem
    Dim shFLDx          As Shell32.Folder
    Dim lngX            As Long

    Set shApp = New Shell32.Shell
    Set srFSO = New Scripting.FileSystemObject

    strPath = GetFolder("Choose a folder...")

    Set shFLDx = shApp.NameSpace(strPath)
    Set shFIcol = shFLDx.Items()


    For Each shFIx In shFIcol
            'For lngX = 0 To shFIx.Verbs.Count
                'Debug.Print shFIx.Verbs.ITEM(lngX).Name
            'Next
            'msgbox("printing "&shFIx.name)
            shFIx.InvokeVerb ("&Print")
            DoEvents
    Next
End Sub

【问题讨论】:

  • 如果.InvokeVerb是FileSystemObject的一个方法,那你不需要用那个对象来调用它吗?比如:srFSO.GetFile(strPath & "\" & shFIx.Name).InvokeVerb("&Print")
  • @SO InvokeVerb 方法属于FolderItem 对象,是Shell32 库的一部分。我在最初的问题中输入错误 - 我已编辑以更正此问题。谢谢!! MSDN for InvokeVerb

标签: vba vbscript scripting filesystemobject fso


【解决方案1】:

文件夹浏览对话不需要 FSO。试试 shApp.BrowseForFolder(0, "Select Folder to print from", 0, 0)。通过这种方法,您可以直接获得 shell 文件夹对象。此外,如果是文件或文件夹,您可能需要检查每个文件夹项。

Sub printFgOO()
    Dim shApp           As Shell32.Shell
    Dim shFIcol         As Shell32.FolderItems
    Dim shFIx           As Shell32.FolderItem
    Dim shFLDx          As Shell32.Folder
    Dim lngX            As Long

    Set shApp = New Shell32.Shell
    Set shFLDx = shApp.BrowseForFolder(0, "Select Folder to print from", 0, 0)
    Set shFIcol = shFLDx.Items()

    For Each shFIx In shFIcol
        If Not shFIx.IsFolder Then    ' Print only if is file
            shFIx.InvokeVerb ("&Print")
            DoEvents
        End If
    Next
End Sub

或者按照here 的描述尝试函数 ShellExecute!

【讨论】:

  • 避免使用 FSO 的好建议。由于我已经在使用BrowseForFolder,因此我更改了包装函数以允许它返回文件夹对象本身,而不仅仅是路径。 ShellExecute 是一个选项,我只是希望在不打开的情况下打印。尽管如此,这是使用相同的 InvokeVerb 方法,但它仍然没有打印 - 这就是我想要弄清楚的......为什么 "&Print" 动词似乎不起作用?它列在文件的Verbs 集合中...
【解决方案2】:

好的,所以我仍然没有答案为什么InvokeVerb 方法无法打印,但我现在确实有办法使用ShellExecute 打印文件@Radek 建议的功能。

想我会在这里分享我的工作代码。随时提出改进建议;)

Option Explicit

Public Declare PtrSafe Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteW" (ByVal hWnd As Long, _
                                                                    ByVal lpOperation As LongPtr, _
                                                                    ByVal lpFile As LongPtr, _
                                                                    ByVal lpParameters As LongPtr, _
                                                                    ByVal lpDirectory As LongPtr, _
                                                                    ByVal nShowCmd As Long) As Long


Public Const SW_HIDE As Long = 0
'Hides the window and activates another window.

Public Const SW_MAXIMIZE  As Long = 3
'Maximizes the specified window.

Public Const SW_MINIMIZE  As Long = 6
'Minimizes the specified window and activates the next top-level window in the z-order.

Public Const SW_RESTORE  As Long = 9
'Activates and displays the window. If the window is minimized or maximized, Windows restores it to its original size and position. An application should specify this flag when restoring a minimized window.

Public Const SW_SHOW  As Long = 5
'Activates the window and displays it in its current size and position.

Public Const SW_SHOWDEFAULT  As Long = 10
'Sets the show state based on the SW_ flag specified in the STARTUPINFO structure passed to the CreateProcess function by the program that started the application. An application should call ShowWindow with this flag to set the initial show state of its main window.

Public Const SW_SHOWMAXIMIZED  As Long = 3
'Activates the window and displays it as a maximized window.

Public Const SW_SHOWMINIMIZED  As Long = 2
'Activates the window and displays it as a minimized window.

Public Const SW_SHOWMINNOACTIVE  As Long = 7
'Displays the window as a minimized window. The active window remains active.

Public Const SW_SHOWNA  As Long = 8
'Displays the window in its current state. The active window remains active.

Public Const SW_SHOWNOACTIVATE  As Long = 4
'Displays a window in its most recent size and position. The active window remains active.

Public Const SW_SHOWNORMAL  As Long = 1
'Activates and displays a window. If the window is minimized or maximized, Windows restores it to its original size and position. An application should specify this flag when displaying the window for the first time.

Public Enum shexActions
    shexEDIT
    shexEXPLORE
    shexFIND
    shexOPEN
    shexPRINT
End Enum

Private Function getShellAction(ByRef enACTION As shexActions) As String
    Select Case enACTION
        Case shexActions.shexEDIT
            getShellAction = "EDIT"
        Case shexActions.shexEXPLORE
            getShellAction = "EXPLORE"
        Case shexActions.shexFIND
            getShellAction = "FIND"
        Case shexActions.shexOPEN
            getShellAction = "OPEN"
        Case shexActions.shexprint
            getShellAction = "PRINT"
    End Select
End Function



Public Function ShellEx(ByRef strFILE As String, _
                        Optional ByRef lngWINDOWHANDLE As Long = 0, _
                        Optional ByRef shexACTION As shexActions = (-1), _
                        Optional ByRef strPARAMETERS As String, _
                        Optional ByRef strDIRECTORY As String, _
                        Optional ByRef lngSHOWCOMMAND As Long = 0) As Long

    Dim lngReturnCheck As Long

    lngReturnCheck = (-1)

    lngReturnCheck = ShellExecute(hWnd:=lngWINDOWHANDLE, lpOperation:=StrPtr(getShellAction(shexACTION)), lpFile:=StrPtr(strFILE), lpParameters:=StrPtr(strPARAMETERS), lpDirectory:=StrPtr(strDIRECTORY), nShowCmd:=lngSHOWCOMMAND)

        While lngReturnCheck = (-1)
            DoEvents
        Wend

    ShellEx = lngReturnCheck
End Function

Sub printBAR()
    Dim shFIcol         As Shell32.FolderItems
    Dim shFIx           As Shell32.FolderItem
    Dim shFLDx          As Shell32.Folder
    Dim lngX            As Long

    Set shFLDx = GetFolder("Choose a folder...", True)

    Set shFIcol = shFLDx.Items()

    For Each shFIx In shFIcol
            lngX = ShellEx(shFIx.Path, , shexPRINT)
            Debug.Print lngX
    Next
End Sub

【讨论】:

  • 有趣的是,我把Debug.Print lngX 行放在那里,这样我就可以看到结果了。 Documentation 表示如果成功,该函数将返回一个大于 32 的值。好吧,该函数成功打印了文档,但返回的是29。有点奇怪。为什么会这样?
  • #define SE_ERR_DDEFAIL 29 来自 ShellAPI.h。来自您的文档链接The DDE transaction failed.
  • 是的,我看到了——但我不确定交易的哪一部分失败了——因为文件确实打印了。我不完全确定 ShellExecute 函数的底层代码,所以我不确定它需要哪些步骤或如何解释该错误来修复它。
  • 我怀疑如果 DDEfails 会退回到指定的命令行。
  • 意识到我从未标记过答案 - 这是我最终实施的方法,并且在过去 7 个月中一直在毫无问题地使用。只是想将其标记为答案。
【解决方案3】:

这是一个使用稍微不同的方法执行此操作的程序。它还列出了可用的动词。

HelpMsg = vbcrlf & "  ShVerb" & vbcrlf & vbcrlf & "  David Candy 2014" & vbcrlf & vbcrlf & "  Lists or runs an explorer verb (right click menu) on a file or folder" & vbcrlf  & vbcrlf & "    ShVerb <filename> [verb]" & vbcrlf & vbcrlf & "  Used without a verb it lists the verbs available for the file or folder" & vbcrlf & vbcrlf
HelpMsg = HelpMsg & "  The program lists most verbs but only ones above the first separator" & vbcrlf & "  of the menu work when used this way" & vbcrlf & vbcrlf 
HelpMsg = HelpMsg & "  The Properties verb can be used. However the program has to keep running" & vbcrlf & "  to hold the properties dialog open. It keeps running by displaying" & vbcrlf & "  a message box." 
Set objShell = CreateObject("Shell.Application")
Set Ag = WScript.Arguments 
set WshShell = WScript.CreateObject("WScript.Shell") 
Set fso = CreateObject("Scripting.FileSystemObject")

    If Ag.count = 0 then 
        wscript.echo "  ShVerb - No file specified"
        wscript.echo HelpMsg 
        wscript.quit
    Else If Ag.count = 1 then 
        If LCase(Replace(Ag(0),"-", "/")) = "/h" or Replace(Ag(0),"-", "/") = "/?" then 
            wscript.echo HelpMsg 
            wscript.quit
        End If
    ElseIf Ag.count > 2 then 
        wscript.echo vbcrlf & "  ShVerb - To many parameters" & vbcrlf & "  Use quotes around filenames and verbs containing spaces"  & vbcrlf
        wscript.echo HelpMsg 
        wscript.quit
    End If

    If fso.DriveExists(Ag(0)) = True then
        Set objFolder = objShell.Namespace(fso.GetFileName(Ag(0)))
'       Set objFolderItem = objFolder.ParseName(fso.GetFileName(Ag(0)))
        Set objFolderItem = objFolder.self
        msgbox ag(0)
    ElseIf fso.FolderExists(Ag(0)) = True then
        Set objFolder = objShell.Namespace(fso.GetParentFolderName(Ag(0)))
        Set objFolderItem = objFolder.ParseName(fso.GetFileName(Ag(0)))
    ElseIf fso.fileExists(Ag(0)) = True then
        Set objFolder = objShell.Namespace(fso.GetParentFolderName(Ag(0)))
        Set objFolderItem = objFolder.ParseName(fso.GetFileName(Ag(0)))
    Else
        wscript.echo "  ShVerb - " & Ag(0) & " not found"
        wscript.echo HelpMsg 
        wscript.quit
    End If

    Set objVerbs = objFolderItem.Verbs

    'If only one argument list verbs for that item

    If Ag.count = 1 then
        For Each cmd in objFolderItem.Verbs
            If len(cmd) <> 0 then CmdList = CmdList & vbcrlf & replace(cmd.name, "&", "") 
        Next
        wscript.echo mid(CmdList, 2)

    'If two arguments do verbs for that item

    ElseIf Ag.count = 2 then
        For Each cmd in objFolderItem.Verbs
            If lcase(replace(cmd, "&", "")) = LCase(Ag(1)) then 
                wscript.echo Cmd.doit 
                Exit For
            End If
        Next
    'Properties is special cased. Script has to stay running for Properties dialog to show.
        If Lcase(Ag(1)) = "properties" then
            WSHShell.AppActivate(ObjFolderItem.Name & " Properties")
            msgbox "This message box has to stay open to keep the " & ObjFolderItem.Name & " Properties dialog open."
        End If  
    End If
End If

【讨论】:

  • 这很有趣。编写猫脚本的方法总是不止一种……或类似的东西。 FolderItem.Verb.DoIt
  • 那是因为我一直遇到直接方式的问题。当用作通用脚本时,直接方式有时不起作用。
  • 奇怪。我将不得不尝试.DoIt 方法,看看它是否适合我。我目前正在使用我使用ShellExecute 包装器发布的代码。 .DoIt 方法要简单得多。
【解决方案4】:

如果你愿意使用 powershell 来解决这个问题:

#Save this as Print-Files.ps1
[CmdletBinding()]
param(
    [Property(Mandatory=$true,
        ValueFromPipelineByPropertyName=$true,
        Position=0)]
    [string]$Path)


foreach($file in (Get-ChildItem $path ))
{
    Start-Process –FilePath $file.FullName –Verb Print
}

【讨论】:

    猜你喜欢
    • 2012-07-30
    • 2022-06-29
    • 2011-02-27
    • 1970-01-01
    • 1970-01-01
    • 2011-04-30
    • 1970-01-01
    • 1970-01-01
    • 2011-03-20
    相关资源
    最近更新 更多