Click to See Complete Forum and Search --> : Telling my other program to do something in run-time...


Atlantisoft
February 27th, 2000, 05:25 PM
Lets say i have 2 instances of my program open. I already know how to tell when this accurs, and have the second instance close, but how can I have the second instance tell the 1st instance to do something? I need to send it a message somehow, without using a timer that constantly checks the registry/a file. Any suggestions?
Thanks in advance,
Atlantis

Johnny101
February 27th, 2000, 07:05 PM
You could use sockets to talk to the other app. Have the app listen on a specific port and then the first app can send a message on the port. There is a third party control that makes this really easy, its called SocketWrench. I can't remember right now who makes it, but i'm sure you could find it on the net. I've seen this done, one exe, two instances and they talk to each other, it's pretty cool and it wasn't that hard to do (at least with the above control, anyway).

There is probably an easier way, but i don't know what it is. :(

Sorry i couldn't help more,

John

John Pirkey
MCSD
www.ShallowWaterSystems.com

Ravi Kiran
February 27th, 2000, 08:10 PM
There are really many ways to do this:
starting with your own suggestion:
Posting Messages:

You can subclass one of the controls (one which has a hwnd or Form) and write a subclass procedure which looks for a specific user defined message. So on the form load of the first instance, it will put this hwnd in the registry ( well, i know you said "no Registry please", here there is no timer!). Or if you subclass the main form, you can get the main window handle of the app by API like enumWindows or some such fn. So when the other instance starts, APP.previnstance is non-null tell you the situation, so that you can post the message with Send/PostMessage API call, to this hwnd

I have done this with dlls, but not very sure if it works w/o glitches cross process!.

Other method is: This is how Explorer works, i am told: You write your app as Active-x exe. all the forms etc are wrapped in a GlobalMultiUse class. you may need another wraper inbetween - called extender classes ( if i am not wrong!).
In the first instance, this class would be created. and would go on to show the form etc. In the second instance, you can assume safely that this class would have been created, so just access this class, and have a function/property through which you tell the other instance ( not an instance in the strict sense ) what to do. (i.e the form has a method like ReloadSOmething, which comes thru this class interface, for the outside world to access)

Anything that can be used for Cross process communiction can also be used. Like events : Create/register an event in the first instance, in the second instance, signal the event. Event handler would know where to get the new info from.
Pipes , Sockets etc can be used too, like the other post suggests. (I haven't tired them.)

RK

Lothar Haensler
February 28th, 2000, 01:58 AM
one of the easiest ways to achieve what you want without going to the API level is: use DDE (dynamic data exchange).
I'm not saying that it is the best way.

I would go the COM way as already suggested.

Atlantisoft
February 28th, 2000, 01:59 PM
where can i get DDE?

Lothar Haensler
February 29th, 2000, 02:15 AM
DDE is part of the operating system.
It's fully integrated into VB.
Search the online help for the LinkPoke method for example.

Atlantisoft
March 2nd, 2000, 06:48 PM
well, all these ideas are great, and I'm gonna learn tons messing around with it, but I was looking for a simpler way to do it, and low and behold, I found it. One problem however...

Here's the situation:

I'm using subclassing (SetWindowLong and CallWindowProc) to check for messages sent to the computer about that program. Then I have it check for prev instances on load up, and send it a message using SendMessageByString. The problem I'm having is the msg has to be a long. Is there any way I can send a string accross?

Aaron Young
March 2nd, 2000, 08:54 PM
You'd probably find it easier to create an ActiveX EXE which can be shared by multiple Applications, here's an example I've put together which demonstrates using an ActiveX EXE to share a CommandLine between Multiple Instances of an Application, it uses No Timers and No Registry/Files:

Create a New ActiveX EXE Project Called AppExtender..

Add a Standard Module..
'Global CommandLine Object
public oCommandLine as CommandLine
'No. of Current Connections
public lConnected as Long


Add a Class Module, Name it CommandLine and set Instancing to [2 - PublicNotCreatable]..
public Event Change()
private sString as string

public property get szString() as string
'Return the Value of the szString property
szString = sString
End property

public property let szString(byval vNewValue as string)
'set the Value of the szString property and Trigger
'the Change Event
sString = vNewValue
RaiseEvent Change
End property


Add another Class Module, Name it Connector and set Instancing to [5 - MultiUse]..
private Sub Class_Initialize()
'If the Global CommandLine Object isn't Initialized, then Initialize it
If oCommandLine is nothing then
set oCommandLine = new CommandLine
End If
'Increment the number of Connections to this Object
lConnected = lConnected + 1
End Sub

private Sub Class_Terminate()
'Decrement the Number of Connections to this Object
lConnected = lConnected - 1
'If the No. of Connections is Zero, Destroy the Global
'Command Line Object, Releasing the ActiveX EXE
If lConnected = 0 then set oCommandLine = nothing
End Sub

public property get CommandLine() as CommandLine
'Return a Reference to the Global CommandLine Object
set CommandLine = oCommandLine
End property



Compile the ActiveX EXE..

Create a new Standard Project, add a Reference to AppExtender and set the Startup Object to Sub Main:

In a Standard Module..
'Create a private Instance of the CommandLine Object
'So that we can still change the Commandline if
'we have to unload this Instance..
private oCommandLine as AppExtender.CommandLine
'Create a public Connector Object, used to get a
'Reference to the Globally Shared CommandLine Object..
public oConnector as new AppExtender.Connector

Sub Main()
'get the CommandLine Object..
set oCommandLine = oConnector.CommandLine
'If this is the 1st Instance, show the Form
If Not App.PrevInstance then Form1.Show
'set the CommandLine Object's szString property to
'this instances CommandLine, Triggering the Change
'Event of the CommandLine Object in the Other Instance.
oCommandLine.szString = Command
End Sub



In Form1, (Add a Textbox)..
'Create a private Instance of the CommandLine Object with
'the Change Event, which will Trigger Each time the szString
'property of the CommandLine Object is Changed, in any App.
private withevents oCommandLine as AppExtender.CommandLine

private Sub Form_Load()
'get the CommandLine Object from the public Connector
set oCommandLine = oConnector.CommandLine
End Sub

private Sub oCommandLine_Change()
'Triggered when the value of szString changes
Text1 = oCommandLine.szString
End Sub


To Test it, Compile the Project then Drag files onto the EXE, you'll Notice the 1st Time a Form is Displayed showing the CommandLine in a Textbox, subsequent times the commandLine of the 1st Form will Change and no more instances of the Form will be loaded, (Sharing the CommandLine).

Aaron Young
Analyst Programmer
ajyoung@pressenter.com
Certified AllExperts Expert: http://www.allexperts.com/displayExpert.asp?Expert=11884

Ravi Kiran
March 4th, 2000, 02:53 AM
IN my asnwer to the earlier post, in the same thread, this is the idea i mentioned. But i couldn't post the code...

Apparently that idea is not all that correct, because you are not using a GlobalMultiUse class. Also i forgot to mention in there that the extender class needs to be MultiUse.

RK