3

I have app1.exe (built with VB6) which takes a bunch of command line parameters. It calls lib1.dll - a C#/.NET interop library which needs access to the command line parameters of the EXE. I use Environment.CommandLine to read the command line params and that works great.

When I am debugging app1.exe in the VB6 IDE, I typically go into project properties, Make tab and set the command line parameters textbox manually. However, the .NET library, when called, doesn't see the command line parameters at all. It just sees that the entire thing is running under the VB6.exe process.

That makes sense (since when debugging, it really does run under VB6.exe), but it makes it difficult to debug, since .NET library never gets access to the actual command line parameters.

My question: short of passing up the command line parameters manually to the .NET lib, is there any other way for it to see them when debugging in the VB6 IDE?

4

2 回答 2

6

这只是 VB6 IDE 设计方式的核心。当您调试 VB6 代码时,您不会运行进程,而是运行解释器。它执行 p 代码,而不是机器代码。这是一个意外的好功能,它允许调试您制作的 VB6 代码和 .NET 代码 [ComVisible]。这通常是不可能的,只能有一个调试器附加到一个进程。这也解释了为什么您的 .NET 调试器会看到 VB6.exe 进程,该进程同时具有解释器和调试器。

因此,当您使用 Environment.CommandLine 时,您实际上是在读取传递给 VB6 IDE 的命令行。通常这是一个空的。

正确的做法是明确的:不要试图通过后门获取信息。只需在对象上设置 VB6 代码集属性即可。

于 2013-04-05T21:49:40.793 回答
1

您可能可以使用您想要进行调试运行的命令行参数来启动 VB6 IDE。虽然看起来很不方便(每次运行之前都必须重新启动 IDE)。如果 .NET 库关心作为命令行一部分的程序名称,它也不应该工作。

替代方法可以是在修改运行 VB6.exe 进程的命令行之后进行。由于命令行在创建时被复制到进程的地址空间中,因此进程可以修改它。理论上。坏消息是,据我所知,没有支持的方法来做到这一点。并且实施不受支持的方式可能很棘手。

另一种选择可能是 .NET 库测试它是否在 VB6.exe 下运行(这应该从命令行清楚),并在这种调试场景中从一些替代存储中获取数据。

编辑

下面的代码改变了GetCommandLine WinAPI 函数返回的内存位置。希望在幕后也能使用同样的函数Environment.CommandLine

我还没有使用 .NET 库测试过代码(还没有),但你还是想试试看。为了尝试这种方法:

使用任意但足够长的命令行参数字符串运行 VB6 IDE (VB6.exe)。安排SetCmdLineWhenRunInVB6IDE在VB6 IDE中运行时执行以下程序。它旨在用项目参数中设置的值替换 IDE 的命令行。GetCmdLine并且SetCmdLine仅仅是促进探索的帮手。

Option Explicit

Private Declare Function GetCommandLine _
    Lib "kernel32" Alias "GetCommandLineW" () As Long
Private Declare Function lstrlen _
    Lib "kernel32" Alias "lstrlenW" (ByVal lpString As Long) As Long
Private Declare Sub CopyMemory _
    Lib "kernel32" Alias "RtlMoveMemory" (ByVal pDst As Any, ByVal pSrc As Any, ByVal ByteLen As Long)

Public Function GetCmdLine() As String
    Dim hStr As Long
    Dim hLen As Long

    hStr = GetCommandLine
    hLen = lstrlen(hStr)
    If hLen > 0 Then
        GetCmdLine = Space$(hLen)
        CopyMemory StrPtr(GetCmdLine), hStr, (hLen) * 2
    End If
End Function

Public Sub SetCmdLine(sNewCmdLine As String)
    Dim hStr As Long
    Dim hLen As Long
    Dim sBuf As String

    hStr = GetCommandLine
    hLen = lstrlen(hStr)
    If hLen > 0 Then
        Dim i As Long, hEndMark As Long

        sBuf = Space$(hLen)
        hEndMark = IIf(Len(sNewCmdLine) < Len(sBuf), Len(sNewCmdLine), Len(sBuf))

        For i = 1 To hEndMark
            Mid$(sBuf, i) = Mid$(sNewCmdLine, i)
        Next i

        CopyMemory ByVal hStr, StrPtr(sBuf), LenB(sBuf)
    End If
End Sub

Public Sub SetCmdLineFromVBACommand()
    Dim sVBACmdLine As String

    sVBACmdLine = """" & App.Path & "\" & App.EXEName & ".exe"" " & VBA.Command$
    SetCmdLine sVBACmdLine
End Sub
于 2013-04-05T23:33:01.573 回答