首页 > 解决方案 > 如何在 AutoExec 宏中获取 WinWord.exe 的命令行参数?

问题描述

AutoExecWord 的宏中,我想处理一些功能。为此,我需要一个 ID,它在启动 WinWord.exe 时由命令行参数给出。

例子: "C:\Program Files\Microsoft Office\root\Office16\WINWORD.EXE" /MyParam:5

我需要这个5

我怎样才能得到这个?

标签: vbams-word

解决方案


VBA 本身不提供此类信息。有必要利用 Windows API 来获取命令行参数。

下面的代码演示了如何使用GetCommandLineAlstrcpynAAPI 来提取获取完整的命令行。然后对其进行解析以获取每个单独的参数。

Declare Function GetCommandLineA Lib "kernel32" () As Long
Declare Function lstrcpynA Lib "kernel32" ( _
   ByVal pDestination As String, ByVal pSource As Long, _
   ByVal iMaxLength As Integer) As Long

Function GetCmdLineInfo() As String

   ' Pointer to the command line
   ' Which will be passed as pSource to lstrcpynA
   Dim ptrCmdLine As Long
   ' Will hold the command line after the call to lstrcpynA
   ' Pointer to the destination; before being passed...
   ' must first be initialized with enough characters to hold that string
   Dim strCmdLine As String

   ' Get the pointer to the command line string
   ptrCmdLine = GetCommandLineA

   ' Fill the string with enough zeros to make sure there are enough
   ' characters available for the command string (which will replace the content).
   ' 300 is an arbitrary number, more might be necessary.
   strCmdLine = String$(300, vbNullChar)

   ' Copy from the pointer to a VBA-style string
   lstrcpynA strCmdLine, pCmdLine, Len(strCmdLine)

   ' Remove the extra vbNullChar characters at the end of the command line
   strCmdLine = left(strCmdLine, InStr(1, strCmdLine, _
      vbNullChar) - 1)

   GetCmdLineInfo = strCmdLine
End Function

Function GetCmdLineArgs(strCmdLine As String) As String
    Dim lExePos As Long, lSpaceAfterExe As Long
    Dim strArgString As String

    'Get the end of the path to the exe file...
    lExePos = InStr(LCase(strCmdLine), ".exe")
    strArgString = Mid(strCmdLine, lExePos + 4)

    'Move beyond any quote characters and spaces after '.exe'
    'The first argument may be the path to a file or
    'an argument beginning with a forward slash, so get it all.
    lSpaceAfterExe = InStr(strArgString, " ")
    If lSpaceAfterExe > 0 Then
        strArgString = Mid(strArgString, lSpaceAfterExe + 1)
    Else
        strArgString = "No args"
    End If
    GetCmdLineArgs = Trim(strArgString)
End Function

Sub TestCmdLineargs()
    Dim strCmdLine As String
    Dim strCmdArgs

    strCmdLine = GetCmdLineInfo
    strCmdArgs = GetCmdLineArgs(strCmdLine)
    'Debug.Print Len(strCmdLine), strCmdLine, strCmdArgs

   'Extract the individual args to an array
    Dim strArgChar As String
    Dim lFirstArgPos As Long, lNextArgPos As Long
    Dim argsList() As String
    Dim strArgString As String
    Dim argsCounter As Long

    strArgChar = " /"
    argsCounter = 0

    lFirstArgPos = InStr(strCmdArgs, strArgChar)
    'If the first argument is a file path, store that in the array
    If left(strCmdArgs, 1) <> "/" Then
        ReDim Preserve argsList(argsCounter)
        strArgString = Trim(left(strCmdArgs, lFirstArgPos - 2))
        argsList(argsCounter) = strArgString
        argsCounter = argsCounter + 1
    End If

    'Get the rest of the args, that start with a /
    Do While lFirstArgPos > 0
        ReDim Preserve argsList(argsCounter)
        strArgString = Mid(strCmdArgs, lFirstArgPos + 1)
        lNextArgPos = InStr(lFirstArgPos + 2, strCmdArgs, strArgChar)

        'If lNextArgPos is not greater than 0, then there are no more args
        If lNextArgPos <= 0 Then
            argsList(argsCounter) = strArgString
            Exit Do
        Else
            strArgString = Mid(strCmdArgs, lFirstArgPos + 1, lNextArgPos - lFirstArgPos)
            argsList(argsCounter) = strArgString
            argsCounter = argsCounter + 1
            lFirstArgPos = lNextArgPos
        End If
    Loop

    Dim i As Long

    For i = LBound(argsList) To UBound(argsList)
        Debug.Print argsList(i)
    Next
End Sub

推荐阅读