让一个.NET应用程序和一个VB6应用程序互相通信的方法是什么?

3

我有几个相互依赖的应用程序。其中之一是一个强大的VB6应用程序,另一个是备受期待的、采用隐蔽技术、很可能获得奥斯卡奖的.NET(2.0)系统托盘应用程序。VB6应用程序启动了系统托盘应用程序。如果VB6应用程序关闭,则系统托盘应用程序将关闭自身,假设它没有其他的工作要做(它的工作是将文档保存到数据库中)。

我唯一剩下的担忧是,如果系统托盘应用程序崩溃或由于某些致命错误无法完成工作,会发生什么情况。这种情况的一个可能结果是我弹出一个模态对话框,告诉用户“立即联系支持人员,因为您不能再保存文档了”。

我认为这里最坏的情况是,每当在vb6应用程序中处理文档时(即,用户完成文档,并将其组件压缩并保存在本地),我都必须检查并查看系统托盘应用程序是否正在运行。我不知道,这似乎有点繁琐。有更优雅的方法吗?有没有办法“发出信号”让我的VB6应用程序/让我的VB6应用程序监听这样的信号呢?


1
在 .Net 中做的任何事情都不算隐秘。你需要额外的(而且非常臃肿的)运行时,并且反编译也很容易。 - Bob77
检查一下你的讽刺仪。 - Erix
我在想这里的“隐身”是什么意思。 - Bob77
他在谈论那种过度臃肿的讽刺 :-)) - wqw
隐秘评论,就像“奥斯卡获奖”评论一样,是叙事口味和愚蠢的体现。 - peacedog
5个回答

3

我过去所做的是一个在.NET中暴露为COM对象的类库(在程序集信息中,将ComVisible属性设置为true)。

这样,在VB6中,您可以调用从.NET类库导出的方法,在C#中,您可以获得处理情况所需的所有代码。

这样,我在VB6中编写的代码更少,而在C#中编写的代码更多,我们可以受益于更好的异常处理(try-catch-finally),像Log4Net这样的日志框架等等...

迄今为止,这对我非常有效。


你也可以添加一个名为 Ping 的方法!(只是为了使所有其他回答此问题的答案都过时) - wqw

0

您可以使用类似以下代码的 WMI 来轻松检查它是否正在运行:

dim foundIt
For Each Process in GetObject( "winmgmts://." ).InstancesOf( "win32_process" )
    If UCase( Process.name ) = "MYDOTNET.EXE" Then
        foundIt = true 
    End If
Next
if not foundIt then
    msgbox( "It's not running, so start the process")
end if

请注意,上述代码是用VBscript编写的,但我认为它应该也可以作为VB6代码运行。

1
WMI 不应在应用程序中使用。它是一个管理员工具,可能会在某个 Windows 安装中被禁用或根本不存在。 - Bob77
@bob:这取决于应用程序以及它是为谁而设计的。如果是面向家庭消费者的应用程序,我会避免使用WMI,但如果是公司内部或类似情况下使用的应用程序(我假设是这样,但这可能不是事实),那么他可以问管理员WMI是否可用,这样就不会有问题。 - Hans Olsson

0

我手头没有详情,但我过去使用过Windows消息发送WM_NULL。这相当于一个ping消息。因此,VB6应用程序向系统托盘应用程序发送定期ping。如果系统托盘应用程序未能及时响应ping,则VB6应用程序会知道它已挂起或未运行。


-1

我的第一次猜测是介绍两者之间的互通。让VB6应用程序在定义的时间间隔内发送PING请求。然后,如果VB6应用程序没有收到响应或请求超时,则执行所需操作。


在同一台机器上向另一个应用程序发送PING请求? - Matt Wilko
为什么不呢?我觉得你把我的PING当成一个命令行PING了吧?我只是在谈论心跳保持。这种情况经常发生,尤其是在相互依赖的应用程序之间。仅仅因为这些应用程序在同一台机器上并不意味着它们不能相互通信。这与一个监视由其他应用程序创建的文件没有区别。我曾在几家大型工程公司工作过,他们都使用了这种方法。这比查找窗口或监视正在运行的可执行文件的进程更高效。它还允许应用程序在需要在单独的计算机上运行时具有灵活性。 - Josh
对于大多数人来说,PING可能意味着shell命令PING。我可以建议您编辑您的答案,使其更清晰,可能附带一些示例代码吗? - Matt Wilko

-1
我建议在计时器上使用类似以下函数的东西:
'declaration for FindWindow API
Private Declare Function FindWindow _
        Lib "user32" _
        Alias "FindWindowA" _
       (ByVal lpClassName As String, _
        ByVal lpWindowName As String) As Long



'Call the following on a timer with the Tray icon form caption
'when it goes False unleash hell
Private Function IsWindowLoaded(ByVal strWindowCaption As String) As Boolean
    Dim lHwnd As Long
    lHwnd = FindWindow(strWindowCaption, vbNullString)
    If lHwnd <> 0 Then
        IsWindowLoaded = True
    Else
        IsWindowLoaded = False
    End If
End Function

你正在做我下面建议的同样的事情,但是开销更大。如果你读了Kevin Gale上面的帖子,他也说了同样的话。你会因为他使用了真实世界的场景而对他投反对票吗? - Josh
@Josh - Kevin Gales的回答提到了Windows消息传递 - 我只是认为你可以编辑一下你的回答,让意思更清晰。不过现在肯定也可以删掉了,因为Kebin Gale已经说了同样的话。 - Matt Wilko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接