简体   繁体   English

如何读取.NET库中从VB6 IDE传递的命令行参数?

[英]How to read command line parameters passed from VB6 IDE in a .NET library?

I have app1.exe (built with VB6) which takes a bunch of command line parameters. 我有app1.exe(用VB6构建),它需要一堆命令行参数。 It calls lib1.dll - a C#/.NET interop library which needs access to the command line parameters of the EXE. 它调用lib1.dll - 一个C#/ .net互操作库,需要访问EXE的命令行参数。 I use Environment.CommandLine to read the command line params and that works great. 我使用Environment.CommandLine来读取命令行参数,这很有用。

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. 当我在VB6 IDE中调试app1.exe时,我通常会进入项目属性,Make选项卡并手动设置命令行参数文本框。 However, the .NET library, when called, doesn't see the command line parameters at all. 但是,.NET库在调用时根本看不到命令​​行参数。 It just sees that the entire thing is running under the VB6.exe process. 它只是看到整个事情在VB6.exe进程下运行。

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. 这是有道理的(因为在调试时,它确实在VB6.exe下运行),但它使调试变得困难,因为.NET库永远不会访问实际的命令行参数。

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? 我的问题:没有手动将命令行参数传递给.NET lib,在VB6 IDE中进行调试时,有没有其他方法可以看到它们?

This is just core to the way the VB6 IDE is designed. 这只是VB6 IDE设计方式的核心。 When you debug VB6 code then you don't run a process, you run an interpreter. 当您调试VB6代码然后您不运行进程时,您运行解释器。 Which executes p-code, not machine code. 它执行p代码,而不是机器代码。 It is an accidentally nice feature, it allows debugging both VB6 code and .NET code that you made [ComVisible]. 这是一个意外的好功能,它允许调试你做的[ComVisible]的VB6代码和.NET代码。 That would not normally be possible, there can only be one debugger attached to a process. 这通常是不可能的,只有一个调试器附加到进程。 This also explains why your .NET debugger sees the VB6.exe process, that's the process that has both the interpreter and the debugger. 这也解释了为什么你的.NET调试器看到VB6.exe进程,这是同时拥有解释器和调试器的进程。

So when you are using Environment.CommandLine, you are actually reading the command line that was passed to the VB6 IDE. 因此,当您使用Environment.CommandLine时,实际上是在读取传递给VB6 IDE的命令行。 Normally that's an empty one. 通常这是空的。

The proper approach is a clear one: don't try to obtain information through a back-door. 正确的方法是明确的:不要试图通过后门获取信息。 Just have your VB6 code set properties on your object. 只需在对象上拥有VB6代码集属性即可。

You could probably start VB6 IDE with command line arguments you'd like for a debug run. 您可以使用命令行参数启动VB6 IDE,以便进行调试运行。 Although it looks inconvenient (one has to restart IDE before each run). 虽然看起来不方便(每次运行之前必须重新启动IDE)。 It also shouldn't work if .NET library cares about program name which is part of command line. 如果.NET库关心作为命令行一部分的程序名,它也应该不起作用。

Alternative could be to go after modifying command line of running VB6.exe process then. 替代方法可能是修改运行VB6.exe进程的命令行后再去。 Since the command line is copied into the process's address space on its creation, the process can modify it. 由于命令行在创建时被复制到进程的地址空间中,因此进程可以对其进行修改。 In theory. 理论上。 Bad news is that there's no supported way to do this, to my knowledge. 据我所知,坏消息是没有支持的方法来做到这一点。 And implementing unsupported way may be tricky to do. 实施不受支持的方式可能很棘手。

Yet another alternative could be for the .NET library to test if it runs under VB6.exe (this should be clear from command line), and obtain data from some alternative storage in such debug scenario. 另一种替代方法是.NET库可以测试它是否在VB6.exe下运行(这应该在命令行中清楚),并从这种调试方案中的某些备用存储中获取数据。

Edit 编辑

The code below alters memory location returned by GetCommandLine WinAPI func. 下面的代码改变了GetCommandLine WinAPI函数返回的内存位置。 Hopefully, this same func is used by Environment.CommandLine under the hood. 希望这个相同的函数由Environment.CommandLine在引擎盖下使用。

I have not tested the code with .NET library (yet), but you may wish to try it out anyway. 我还没有使用.NET库测试代码,但您可能希望尝试一下。 In order to give this method a try: 为了尝试这个方法:

Run VB6 IDE (VB6.exe) with arbitrary, but sufficiently long, string of command line arguments. 使用任意但足够长的命令行参数字符串运行VB6 IDE(VB6.exe)。 Arrange to execute SetCmdLineWhenRunInVB6IDE procedure below when running in VB6 IDE. 安排在VB6 IDE中运行时执行下面的SetCmdLineWhenRunInVB6IDE过程。 It is intended to replace IDE's command line with values one set up in project parameters. 它旨在用项目参数中设置的值替换IDE的命令行。 GetCmdLine and SetCmdLine are mere helpers to facilitate exploration. GetCmdLineSetCmdLine仅仅是帮助探索的助手。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM