Private Declare Function lstrlenW Lib "kernel32" (ByVal lpString As Long) As Long
Private Declare Function GetCommandLineW Lib "kernel32" () As Long
Private Declare Function CommandLineToArgvW Lib "shell32" (ByVal lpCmdLine As Long, ByVal pnNumArgs As Long) As Long
Private Declare Function LocalFree Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Sub PutMem4 Lib "msvbvm60" (ByVal Ptr As Long, ByVal NewVal As Long)
Private Declare Sub GetMem4 Lib "msvbvm60" (ByVal Ptr As Long, Ret As Any)
Private Declare Sub MemCopy Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private CmdArgv() As String '命令行列表: 用数组便于插入/删除等编辑操作
Private CmdArgc As Long '命令行列表的有效数量(k) (不是很有必要 先用着)
''返回命令行信息:
''Index = -1 输出 命令行参数(全部) 的空格分隔字符串(带前导空格,不包括执行文件名)
''Index = 0 输出 执行文件名 如果本身没有引号,附加首尾的引号
''Index < k 输出 命令行参数(单项)
Public Function Commandw(Optional ByVal Index As Long = -1) As String
If CmdArgc <= 0 Then GetCommands CmdArgv(), CmdArgc
If Index < 0 Then '已经有命令行解析列表,取数据就好
Dim w As Long '数组下标0元素暂时置为"",用完再恢复
GetMem4 VarPtr(CmdArgv(0)), w: PutMem4 VarPtr(CmdArgv(0)), 0&
Commandw = Join(CmdArgv, " "): PutMem4 VarPtr(CmdArgv(0)), w
ElseIf Index < CmdArgc Then
Commandw = CmdArgv(Index) '输出 执行文件名 或 命令行参数(单项)
End If '否则返回 ""
End Function
Private Sub GetCommands(CmdArgv() As String, ByRef CmdArgc As Long)
Dim w As Long: w = GetCommandLineW(): If w = 0 Then Exit Sub
Dim i As Long, k As Long, m() As Integer
k = lstrlenW(w): ReDim m(0 To k) '复制 命令行文本 到缓存区
MemCopy m(0), ByVal w, k * 2: m(k) = 0: w = 0
For i = 0 To k - 1 '预处理 保留命令行中的双引号
Select Case m(i)
Case 34: w = Not w: m(i) = &HFFFF '引号 替换为 &HFFFF
Case 32, 9: If w Then m(i) = &HFFFE '空格 替换为 &HFFFE
End Select
Next
Dim Argv As Long, Argc As Long '调用 API 解析命令行
Argv = CommandLineToArgvW(VarPtr(m(0)), VarPtr(Argc))
If Argv Then
ReDim CmdArgv(0 To Argc - 1): CmdArgc = Argc
GetMem4 Argv, w
MemCopy m(0), ByVal w, k * 2 '复制 解析后的数据 到缓存区
LocalFree Argv: Argv = 0 '释放 系统内存的引用
w = 0: i = 0: k = 0
Do
Select Case m(i)
Case 0 '遇到截止符 复制 命令行数据
CmdArgv(k) = String(i - w, 0)
MemCopy ByVal StrPtr(CmdArgv(k)), m(w), LenB(CmdArgv(k))
k = k + 1: w = i + 1
Case &HFFFF: m(i) = 34 '&HFFFF 恢复为 引号
Case &HFFFE: m(i) = 32 '&HFFFE 恢复为 空格
End Select: i = i + 1
Loop Until (k = Argc) '计数器到了 结束扫描
If Mid(CmdArgv(0), 1, 1) <> Chr(34) Then
CmdArgv(0) = Chr(34) & CmdArgv(0) & Chr(34)
End If
End If
End Sub