问题
We are upgrading a suite of data acquisition and analysis routines from VB6 programs to a mixture of VB.NET, VB6, and Matlab programs. We want to keep the system modular (separate EXEs) so we can easily create specialized stand-alone analysis programs without having to constantly upgrade one massive application. We have used MBInterProcess to send messages between EXEs when all the programs were written in VB6 and this worked perfectly for us (e.g., to have the data acquisition EXE send the latest file name to a stand-alone data display program). Unfortunately, this ActiveX cannot be used within Matlab or VB.NET to receive messages. We are wondering what is the simplest string message passing system (pipes, registered messages, etc) that we could adopt. Right now we are just polling to see if new file was written in a specific folder, which can't be the best solution. Our ideal solution would not require a huge investment in time learning nuances of Windows (we are biologists, not full-time programmers) and would work in both WinXP and 64-bit versions of Windows.
In response to the queries, we have wrapped the entire Matlab session within a VB6 program that has the MBInterProcess ActiveX control. That works but is not a great solution for us since it will probably lock us into WinXP forever (and certainly will prevent us from using the 64-bit version of Matlab). The latest version of Matlab (2009a) can access .NET functions directly, so we assume one solution might be to use the .NET library to implement pipes (or something similar) across programs. We would like to recreate the elegantly simple syntax of the MBInterProcess ActiveX and have a piece of code that listens for a message with that program's top-level Windows name, and then call a specific Matlab m-file, or VB.NET function, with the string data (e.g., file name) as an argument.
回答1:
Could you create an ActiveX EXE in VB6 to simply forward messages between the different parties? When anyone called it, it would raise an event with the parameters passed to the call. Your VB6 and VB.NET code could establish a reference to the ActiveX exe to call it and sink its events. I'm not familiar with Matlab so I don't know whether it would be accessible there.
EDIT: you've written that Matlab 2009a can access .NET directly. If it can sink .NET events, you could also have a .NET wrapper on the VB6 ActiveX EXE.
Here's some sample code I knocked up quickly.
VB6 ActiveX EXE project with project name VB6MatlabMessenger. Each message has a text string Destination (that somehow identifies the intended recipient) and a string with the message.
'MultiUse class VB6Messenger
Option Explicit
Public Event MessageReceived(ByVal Destination As String, ByVal Message As String)
Public Sub SendMessage(ByVal Destination As String, ByVal Message As String)
Call Manager.RaiseEvents(Destination, Message)
End Sub
Private Sub Class_Initialize()
Call Manager.AddMessenger(Me)
End Sub
Friend Sub RaiseTheEvent(ByVal Destination As String, ByVal Message As String)
RaiseEvent MessageReceived(Destination, Message)
End Sub
'BAS module called Manager
Option Explicit
Private colMessengers As New Collection
Sub AddMessenger(obj As VB6Messenger)
colMessengers.Add obj
End Sub
Sub RaiseEvents(ByVal Destination As String, ByVal Message As String)
Dim obj As VB6Messenger
For Each obj In colMessengers
Call obj.RaiseTheEvent(Destination, Message)
Next obj
End Sub
And a test VB6 normal exe, with a reference to the VB6MatlabMessenger. Here is the whole frm file. Build this as an exe, run a few copies. Fill in the destination and message text fields and click the button - you will see that the messages are received in all the exes (reported in the listboxes).
VERSION 5.00
Begin VB.Form Form1
Caption = "Form1"
ClientHeight = 3090
ClientLeft = 60
ClientTop = 450
ClientWidth = 4680
LinkTopic = "Form1"
ScaleHeight = 3090
ScaleWidth = 4680
StartUpPosition = 3 'Windows Default
Begin VB.ListBox lstEvents
Height = 1620
Left = 120
TabIndex = 3
Top = 1320
Width = 4455
End
Begin VB.TextBox txtMessage
Height = 375
Left = 120
TabIndex = 2
Text = "Message"
Top = 840
Width = 2295
End
Begin VB.TextBox txtDestination
Height = 375
Left = 120
TabIndex = 1
Text = "Destination"
Top = 240
Width = 2295
End
Begin VB.CommandButton cmdSendMessage
Caption = "Send Message"
Height = 495
Left = 2640
TabIndex = 0
Top = 360
Width = 1575
End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Option Explicit
Private WithEvents objMessenger As VB6MatlabMessenger.VB6Messenger
Private Sub cmdSendMessage_Click()
objMessenger.SendMessage txtDestination, txtMessage.Text
End Sub
Private Sub Form_Load()
Set objMessenger = New VB6MatlabMessenger.VB6Messenger
End Sub
Private Sub objMessenger_MessageReceived(ByVal Destination As String, ByVal Message As String)
lstEvents.AddItem Now() & " RECEIVED - " & Destination & ", " & Message
End Sub
I started writing a VB.NET class library that wraps the VB6 to make it accessible to .NET. I haven't tested this one. It has a reference to the VB6MatLabMessenger.
Public Class VBNETMatlabMessenger
Private WithEvents objVB6Messenger As VB6MatlabMessenger.VB6Messenger
Public Event MessageReceived(ByVal Destination As String, ByVal Message As String)
Public Sub SendMessage(ByVal Destination As String, ByVal Message As String)
objVB6Messenger.SendMessage(Destination, Message)
End Sub
Public Sub New()
objVB6Messenger = New VB6MatlabMessenger.VB6Messenger
End Sub
Private Sub objVB6Messenger_MessageReceived(ByVal Destination As String, ByVal Message As String) Handles objVB6Messenger.MessageReceived
RaiseEvent MessageReceived(Destination, Message)
End Sub
End Class
This might get you started. Note that the VB6 messenger objects will live forever because the messenger keeps a reference to them internally, so COM will never tidy them up. If this becomes a problem (if many messages are sent without rebooting the PC) you could add a method to the VB6 messenger which instructs it to removed the messenger object from its collection,
回答2:
I've used the Matlab dos command to execute a Java program on the commandline, it waits for the commandline to complete before returning control to Matlab. This worked fine for me, after my Matlab program regained control I read the output file from the Java.
I've used compiled Matlab programs (i.e. exe's), these work okay but they spray files around when they execute - I believe it's possible to pass in commandline arguments to a compiled executable. Assuming VB.NET is like C# .NET you could execute your exe from code using something like the Process object.
Alternatively there are ways to compile to .dll which are accessible via .NET see here:
http://www.codeproject.com/KB/dotnet/matlabeng.aspx
for an explanation. I've never tried this...
来源:https://stackoverflow.com/questions/872469/simplest-way-to-send-messages-between-matlab-vb6-and-vb-net-programs