I need a way to communicate between 2 apps on the same system. One fellow programmer suggested API call SendMessage but how does the receiving app receive the message to write it to a textbox. Any help or example appreciated.
Printable View
I need a way to communicate between 2 apps on the same system. One fellow programmer suggested API call SendMessage but how does the receiving app receive the message to write it to a textbox. Any help or example appreciated.
Sending the message is easy. Just create a message, and send it.
To recieve the message:Code:WM_MYMESSAGE = WM_USER + 100
SendMessage(hwnd_of_window, WM_MYMESSAGE, 0,0)
(Add to a module)
VB Code:
Public Declare Function SetWindowLong& Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long Public Const GWL_WNDPROC = (-4) Public Const WM_USER = &H400 Public Const WM_MYMESSAGE = WM_USER + 100 Public WndProcOld As Long Public Function WindProc(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long If wMsg = WM_MYMESSAGE Then MsgBox "Message recieved" Exit Function End If WindProc = CallWindowProc(WndProcOld&, hwnd&, wMsg&, wParam&, lParam&) End Function Sub SubClassWnd(hwnd As Long) WndProcOld& = SetWindowLong(hwnd, GWL_WNDPROC, AddressOf WindProc) End Sub Sub UnSubclassWnd(hwnd As Long) SetWindowLong hwnd, GWL_WNDPROC, WndProcOld& WndProcOld& = 0 End Sub
Add to a Form:
VB Code:
Private Sub Form_Load() SubClassWnd hwnd End Sub Private Sub Form_Unload(Cancel As Integer) UnSubclassWnd hwnd End Sub
Here's an example I gave a while ago on using an ActiveX EXE to perform cross-application communication.
OK Megatron, Code looks cool, but how do I select the EXE I want to call and pass it my data. Within the SendMessage call? I haven't really ever used that call before so forgive me if I'm missing the obvious here. The other set of code simply listens for a message back from the EXE and displays a message box, do I have that right?
Aaron, I tried you code, but it keeps breaking on compile this line telling me user defined type not defined:
I followed all the instructon, what am I doing wrong?Code:Private WithEvents oCommandLine As AppExtender.CommandLine
First you need to use FindWindow to get the handle of the windowQuote:
Originally posted by docHoliday
OK Megatron, Code looks cool, but how do I select the EXE I want to call and pass it my data. Within the SendMessage call? I haven't really ever used that call before so forgive me if I'm missing the obvious here. The other set of code simply listens for a message back from the EXE and displays a message box, do I have that right?
Code:hwndWin = FindWindow("ThunderRT6Form", "Form caption")
SendMessage hwndWin, WM_MYMESSAGE, 0, 0
You need to make sure the ActiveX EXE is compiled with the correct name and that the modules are named as specified and that the class modules are setup as specified.
Here's a ZIP file containing the complete project files:
Meagtron - What if it doesn;t run within a window but as a background process or application? This exe does not have a GUI. it only performs functions and spits out the output, usually to STDOUT I believe. I'll admit to not knowing much about the process with how it interacts other than it usually does so with a web server.
Megatron, how would you accomplish that as a single application?
Not using two different apps but just using one that finds out if
a previous instance is running and if it does send a message to
it saying something?
Would DDE come into play here?
i was thinking maybe DDE but i wouldn't know how exactly to employ it, any help?
Me neither. I had seen a post in this forum that DDE is a complicated technology that is difficult to implement. I am always up for a challenge, however. :D
Any of the Fanatics know any good resources to look into whether this is the answer to this question.
i was doing what megatron suggested earlier with the messages
but it's very hard to test sometimes as I have two VBs running
concurrently and neither of them know that a "previous instance"
of the program is running. I think i was on the right track but
there has got to be an easier way.
I am actually not looking to communicate between two instance of the same app.
What I am after is being able to communicate between my VB app and another external program that receives input via STDIN and returns output via STDOUT, as I currently believe. I can;t be totally sure. The program interacts with web servers such as Apache and IIS. It receives input in the form of a file, does it's job, and sends it output back to the server to be delivered. I'm hoping to interface with this app somehow. That's the dilema.
In that case, all you need is this:Quote:
Originally posted by noble
Megatron, how would you accomplish that as a single application?
Not using two different apps but just using one that finds out if
a previous instance is running and if it does send a message to
it saying something?
VB Code:
'Put this in the load event If App.PrevInstance Then Unload Me
Megatron, I knew how to do that part but there were some other
dilemmas. Here is what i did.
First of all, my application is MDI. My program also has an
assocation with a certain file type. When more than one file is
selected an opened two instances of my program are shelled
instead of one opened with the files being opened within the
MDI.
Therefore, all of the message sending has to be done in the form
load event. This asks the question: when i check to see if the
app is already running and whether commands() = true, shouldn't
i set the hook after the checking?
Also, I'm sending text as a message so I have to send a byteCode:If App.PrevInstance = True and Commands() <> "" then
'Put Code Here to Send Message
Unload Me
End If
SubClass hwnd
array instead of just numbers too.
Tell me if this sounds correct because I was doing just this but
it wasn't working correctly.
I forgot where I got this code from but this will 'activate' a previous instance of the same application instead of opening a new one.
VB Code:
'in a standard module 'activate previous instance Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long Declare Function GetWindow Lib "user32" (ByVal hWnd As Long, ByVal wCmd As Long) As Long Declare Function OpenIcon Lib "user32" (ByVal hWnd As Long) As Long Declare Function SetForegroundWindow Lib "user32" (ByVal hWnd As Long) As Long Public Const GW_HWNDPREV = 3 Public Sub ShowPrevInstance() On Error Resume Next Dim OldTitle As String Dim ll_WindowHandle As Long 'saving the current title in OldTitle variable 'and changing the application title OldTitle = App.Title App.Title = "New App - This App Will Be Closed" 'finding the previous instance. if you are using VB 5.0, 'change "ThunderRT6Main" to "ThunderRT5Main" ll_WindowHandle = FindWindow("ThunderRT6Main", OldTitle) 'if there is no old instances of your application - exit. If ll_WindowHandle = 0 Then Exit Sub 'Find the window we need to restore ll_WindowHandle = GetWindow(ll_WindowHandle, GW_HWNDPREV) 'Now restore it Call OpenIcon(ll_WindowHandle) 'And Bring it to the foreground Call SetForegroundWindow(ll_WindowHandle) End End Sub Public Sub Main() 'goto prev instance if there is one If App.PrevInstance Then ShowPrevInstance frmPrevInst.Show End Sub
I've done this in many different apps in different ways, the real question is not how but which way would you like to do it. I would recommend direct Named Pipes. it's not extremely difficult and is very fast except can cause system lockups if you're not careful (synchronization issues).
The other way which is difficult but most likely the most efficient way of doing it is MemoryMapped Files. Think of it as shared memory.
The Simplest way is through an ActiveX EXE (always hated that solution). It's the VB solution to the problem, except if speed is not an issue...it's the BEST solution :rolleyes:
Direct process memory reading...NOT RECOMMENDED but produces fabulous CRASHES :) (Open the Process, will involve some NT Security and use Readprocessmemory and WriteprocessMemory...then expect some fireworks)
Another Simple way is to register a windows message and simply send messages...can't be much easier then that except that now both your apps need at least one window handle.
The last way, that I know of,is to use GetProp/SetProp to insert info on a communication method. You can set object pointers and they can retrieve info via the object (COMish solution).
I have examples of a lot of these in my archives...I can try and dig some up if you want...let me know....
Good Luck