[RESOLVED] How to pass values into a running program?
Hello.
I'd like to pass some values into a VB6 application. I know how to do this via the command line, but what if the program is already running?
Is there a way to send command line arguments to a running VB6 program? And if so, how does that work? Or, is there a better way to send the arguments to the running program?
I welcome any comments. I have never tried to do this before so I would like some ideas on the best way to do it.
Thanks.
Re: How to pass values into a running program?
DDE, MAPI, FileMapping, .... any IPC method.
Re: How to pass values into a running program?
DDE, Winsock are good methods as long as you have the source code to both VB6 programs. If not, then, we'll have to figure out some other way
Re: How to pass values into a running program?
The demo project here shows yet another method using the WM_COPYDATA message.
Re: How to pass values into a running program?
TheTrick - I am not familiar with the DDE, MAPI, FileMapping methods. I will have to do a little research to learn about it to see if I can use any of those methods.
jmsrickland - I have the code for the VB.NET source program and the VB6 destination program, so yes, I'm sure we can find something to make it happen.
BonnieWest - I will download and try the demo project. Thank you.
1 Attachment(s)
Re: How to pass values into a running program?
I make simple example using FileMapping. You should compile and launch several instances of application and try to send message.
Code:
Option Explicit
Private Type SharedData
AppCount As Long ' Count of running applications
Counter As Long ' Counter that show how many objects read data
SenderPID As Long ' Sender process id
' String offset ---- 0xc
End Type
Private Declare Function CreateFileMapping Lib "kernel32" _
Alias "CreateFileMappingA" ( _
ByVal hFile As Long, _
ByRef lpFileMappingAttributes As Any, _
ByVal flProtect As Long, _
ByVal dwMaximumSizeHigh As Long, _
ByVal dwMaximumSizeLow As Long, _
ByVal lpName As String) As Long
Private Declare Function MapViewOfFile Lib "kernel32" ( _
ByVal hFileMappingObject As Long, _
ByVal dwDesiredAccess As Long, _
ByVal dwFileOffsetHigh As Long, _
ByVal dwFileOffsetLow As Long, _
ByVal dwNumberOfBytesToMap As Long) As Long
Private Declare Function UnmapViewOfFile Lib "kernel32" ( _
ByVal lpBaseAddress As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" ( _
ByVal hObject As Long) As Long
Private Declare Function CreateMutex Lib "kernel32" _
Alias "CreateMutexA" ( _
ByRef lpMutexAttributes As Any, _
ByVal bInitialOwner As Long, _
ByVal lpName As String) As Long
Private Declare Function WaitForSingleObject Lib "kernel32" ( _
ByVal hHandle As Long, _
ByVal dwMilliseconds As Long) As Long
Private Declare Function ReleaseMutex Lib "kernel32" ( _
ByVal hMutex As Long) As Long
Private Declare Function lstrlen Lib "kernel32" _
Alias "lstrlenA" ( _
ByVal lpString As Any) As Long
Private Declare Function lstrcpyn Lib "kernel32" _
Alias "lstrcpynA" ( _
ByVal lpString1 As Any, _
ByVal lpString2 As Any, _
ByVal iMaxLength As Long) As Long
Private Declare Function GetCurrentProcessId Lib "kernel32" () As Long
Private Declare Sub CopyMemory Lib "kernel32" _
Alias "RtlMoveMemory" ( _
ByRef Destination As Any, _
ByRef Source As Any, _
ByVal Length As Long)
Private Declare Sub ZeroMemory Lib "kernel32" _
Alias "RtlZeroMemory" ( _
ByRef Destination As Any, _
ByVal Length As Long)
Private Const FILE_MAP_WRITE As Long = &H2
Private Const PAGE_READWRITE As Long = 4&
Private Const INVALID_HANDLE_VALUE As Long = -1
Private Const INFINITE As Long = -1&
Private Const ERROR_ALREADY_EXISTS As Long = 183&
Dim lpAddrSharedData As Long ' Address of shared data
Dim hMutex As Long ' Synchronization mutex
Dim IsSending As Boolean
Dim hMap As Long
Private Sub cmdSend_Click()
Dim Dat As SharedData
' Capture mutext
WaitForSingleObject hMutex, INFINITE
CopyMemory Dat, ByVal lpAddrSharedData, Len(Dat)
If Dat.Counter > 0 Then
MsgBox "Sending"
Else
' Exclude itsels
Dat.Counter = Dat.AppCount - 1
Dat.SenderPID = GetCurrentProcessId()
lstrcpyn lpAddrSharedData + &HC, ByVal txtMessage.Text, Len(txtMessage.Text) + 1
CopyMemory ByVal lpAddrSharedData, Dat, Len(Dat)
IsSending = True
End If
' Release mutex
ReleaseMutex hMutex
End Sub
Private Sub Form_Load()
Dim Dat As SharedData
Dim isFirst As Long
hMap = CreateFileMapping(INVALID_HANDLE_VALUE, ByVal 0&, PAGE_READWRITE, 0, &H1000, "MapExample")
If hMap = 0 Then
MsgBox "Unable to create file mapping", vbCritical
End
Else
If Err.LastDllError <> ERROR_ALREADY_EXISTS Then
' First application
isFirst = True
End If
End If
lpAddrSharedData = MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0)
If lpAddrSharedData = 0 Then
MsgBox "Unable to project file mapping", vbCritical
End
Else
If isFirst Then
' Clear all data
ZeroMemory ByVal lpAddrSharedData, &H1000
End If
End If
hMutex = CreateMutex(ByVal 0&, 0, "MapExampleMutex")
If hMutex = 0 Then
MsgBox "Unable to create mutex", vbCritical
UnmapViewOfFile lpAddrSharedData
End
End If
' Capture mutext
WaitForSingleObject hMutex, INFINITE
CopyMemory Dat, ByVal lpAddrSharedData, Len(Dat)
' Add application
Dat.AppCount = Dat.AppCount + 1
CopyMemory ByVal lpAddrSharedData, Dat, Len(Dat)
' Release mutex
ReleaseMutex hMutex
End Sub
Private Sub Form_Unload(Cancel As Integer)
Dim Dat As SharedData
' Capture mutext
WaitForSingleObject hMutex, INFINITE
CopyMemory Dat, ByVal lpAddrSharedData, Len(Dat)
' Delete application
Dat.AppCount = Dat.AppCount - 1
CopyMemory ByVal lpAddrSharedData, Dat, Len(Dat)
' Release mutex
ReleaseMutex hMutex
UnmapViewOfFile lpAddrSharedData
CloseHandle hMap
CloseHandle hMutex
End Sub
Private Sub tmrSurvey_Timer()
Dim Dat As SharedData
Dim SizeOfStr As Long
Dim tmpString As String
Static LastData As Long
' Capture mutext
WaitForSingleObject hMutex, INFINITE
CopyMemory Dat, ByVal lpAddrSharedData, Len(Dat)
' Check sended data
If Dat.Counter > 0 And Not IsSending Then
If LastData = 0 Then
' We hava a new message
SizeOfStr = lstrlen(lpAddrSharedData + &HC) ' Get size of string
tmpString = Space(SizeOfStr) ' Alloc space for string
lstrcpyn ByVal tmpString, lpAddrSharedData + &HC, SizeOfStr + 1 ' Copy shared string to local string
txtMessage = tmpString
lstLog.AddItem "Get string '" & tmpString & "' from " & Dat.SenderPID
' Decrement counter
Dat.Counter = Dat.Counter - 1
CopyMemory ByVal lpAddrSharedData, Dat, Len(Dat)
End If
LastData = Dat.Counter
Else
If Dat.Counter = 0 Then IsSending = False
LastData = 0
End If
' Release mutex
ReleaseMutex hMutex
End Sub
1 Attachment(s)
Re: How to pass values into a running program?
Here's a sample of a very simple DDE demo
1 Attachment(s)
Re: How to pass values into a running program?
Here's another example using Handles
EDIT: Made correction to project
Re: How to pass values into a running program?
Trying to make DDE work in .Net was so clunky Microsoft ended up punting and now refers to DDE as legacy technology and spits on it whenever they can. The old "baby can't eat steak so we all get pablum" syndrome mixed with a lot of sour grapes. But you face this sort of thing whenever you use a foreign layer on top of any OS, and .Net is no exception.
As far as I know it can only be done using a hack like NDde which was never really supported.
So DDE isn't practical if .Net is in the picture, even though it is still widely supported by native applications written in C, C++, VB6, etc. including the MS Office suite.
Re: How to pass values into a running program?
Re: How to pass values into a running program?
That's basically the same thing posted in #8
Re: How to pass values into a running program?
Wow. Thanks!
I had a busy day and was in meetings for most of it. I will have to try to download and try all of these. There are certainly way more options than I expected!
I'll check it out and reply back.
Re: How to pass values into a running program?
I made a correction to project in post 8
Re: How to pass values into a running program?
I was very interested in seeing this work ( app in post #8) but it doesn't seem to for me. At least the way I imaged it would. "Click on App1 Command1' does not appear to work nor does "Click on App1 Command2'. I expected App1 to display "Left command button clicked" and so on. Sending text doesn't appear to work either. I'm on Windows 7 Professional.
One last "anomaly" is clicking App2 "copy picture to App1 Picture1" put the picture in the upper left hand corner of my screen, not on the app.
I was hoping it just worked "out of the box" to show to someone else I thought would be interested. I don't have time to try and debug it myself, at least in the near future.
Edit:
I had the apps split across two monitors and thought that might be it but being on the same one hand the same issues.
Re: How to pass values into a running program?
If you want something that works out of the box, you may use one of my personal simplest methods that does this very elegantly,
by sending input between two applications using PostMessage to a text field, who's handle is sent as a parameter to any application wishing to interact with my form.
if this was Chinese to you check this quick source i wrote here -Attachment Removed by Moderator-
Extract - compile both projects to the same folder - run Project1.exe click buttons on project2's form.
http://i61.tinypic.com/2cmusf4.png
Of course once you get the hang of things, it may be more elegant to fetch the handles via APIs (FindWindow, FindWindowEx) and such, maybe even use hooks on the post_message and instead of sending it to a textbox, send it straight to the form and process it from there, the possibilities are endless.
but the principal is the same.
Re: How to pass values into a running program?
Quote:
Originally Posted by
TysonLPrice
I was very interested in seeing this work ( app in post #8) but it doesn't seem to for me. At least the way I imaged it would. "Click on App1 Command1' does not appear to work nor does "Click on App1 Command2'. I expected App1 to display "Left command button clicked" and so on. Sending text doesn't appear to work either. I'm on Windows 7 Professional.
One last "anomaly" is clicking App2 "copy picture to App1 Picture1" put the picture in the upper left hand corner of my screen, not on the app.
I was hoping it just worked "out of the box" to show to someone else I thought would be interested. I don't have time to try and debug it myself, at least in the near future.
Edit:
I had the apps split across two monitors and thought that might be it but being on the same one hand the same issues.
I do not know if it will work on Windows 7. It works on XP.
The first thing you have to do is to get the handles of App1's objects so you click on 'Get Objects From App1' button. That's it. You should now see the handle numbers of App1's objects in the left view area on App2. Now when you click on the other buttons everything works as it is expected. Make sure App1 is running before you click any buttons on App2 or you will get invalid handle numbers.
I guess if I had given it a little more thought I would have put the 'Get Objects From App1' button code in the Form_Load event. I just thought everyone would know to click that button first. My bad here.
Sorry I don't write perfect code:cry:
Re: How to pass values into a running program?
I'll try this at home but running if at work is generating missing valid digital signature errors and I start it. Thanks for posting.
Re: How to pass values into a running program?
Quote:
Originally Posted by
jmsrickland
That's basically the same thing posted in #8
Yeah, I know. ;) I just thought the OP might be interested in seeing a description of how that simple technique works, hence my link to penagate's short article about it.
Quote:
Originally Posted by
stum
... but the principal is the same.
Yep, posting a WM_CHAR message to a TextBox is doing essentially the same thing as sending a WM_SETTEXT message, which jmsrickland's and penagate's examples were demonstrating. One major difference though, is that the WM_CHAR message is limited to only 1 character code per message while the WM_SETTEXT message can carry far more information.
Re: How to pass values into a running program?
Quote:
Originally Posted by
jmsrickland
I do not know if it will work on Windows 7. It works on XP.
The first thing you have to do is to get the handles of App1's objects so you click on 'Get Objects From App1' button. That's it. You should now see the handle numbers of App1's objects in the left view area on App2. Now when you click on the other buttons everything works as it is expected. Make sure App1 is running before you click any buttons on App2 or you will get invalid handle numbers.
I guess if I had given it a little more thought I would have put the 'Get Objects From App1' button code in the Form_Load event. I just thought everyone would know to click that button first. My bad here.
Sorry I don't write perfect code:cry:
I wish I had just a very small fraction of your skill set :o
Re: How to pass values into a running program?
@stum - I removed you attachment from post 15 as it contained an EXE. Please read the rules regarding attachments here: http://www.vbforums.com/showthread.p...ts-Please-Read
Re: How to pass values into a running program?
I have been reviewing everything, and there is more than enough to keep me busy. I am sure I can use one of these methods. Thanks.
I will mark the thread as resolved, but feel free to continue posting if you have something to add. :)