Link to home
Start Free TrialLog in
Avatar of bobdylan75
bobdylan75Flag for Afghanistan

asked on

How to comunicate from process and main program vb.net

In VB.Net
from an "A application",
using a process I open another vb.net app called "B application".
So, there a Process method, property, to look the progress
of the B application?
Is possible for B application, to write some text that can be
read from the A application in real time while the B application process is running?
Avatar of Mike Tomlinson
Mike Tomlinson
Flag of United States of America image

Many, many ways to do this...

What is the nature of the data being passed from B to A?  Is it really ONLY a string value? How often is the data sent and how much is sent?  Is it simple, plain text?...or do you need to send control characters as well?
...or do you need to pass other types of data?
Would sending ONE numeric value back to A from B after B completes be sufficient?

What VERSION VB.Net are you working with?

Will there be only ONE instance of A running?...or does each spawned instance of B need to be "paired" with the particular instance of A that ran it?

I assume that both A and B are running on the same machine?...

Details, details, details...  =)
Avatar of bobdylan75

ASKER

Vb.net 2005.
I need to pass only a string for each step in a FOR cycle which will execute
some operation (sending emails)
So when it will send an email I want to alert my "A application" which will display on the screen this information.

And at the end, I want to return a Codeexit value,
but for this last issue I know how to do, with process.exitcode property
Will there be only ONE instance of 'A' running?
ASKER CERTIFIED SOLUTION
Avatar of Mike Tomlinson
Mike Tomlinson
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Yes but,
Perhaps I don't understand well,
but:
I have a big "A-application" which is the main application,
In this application I have a Watcher form which has to monitor the situation,
I cannot start A application every time.
Perhaps I could start every time the B-application but it's not my request
I have to read better your solution...
You question was about communication between A-Application and B-Application (two separate applications) but now it looks like you have A-Application and a FORM which is started from A-Application. Is that correct?
"I cannot start A application every time."

'A' is a SINGLE instance application (check the "Make single instance application" in Project --> Properties) so even though we are starting 'A' multiple times there is ONLY one instance ever running.  That ONE running instance gets a StartupNextInstance() event EVERY time that 'B' runs 'A' again.
I have a very beautiful A-Application.
I love it.
My A-application does many things.
One of this things is:
(MAcro code)
For each document in tableDocs
sendemail(document)
Next

Now, the user at the moment has to wait 1 hour
and he can already cancel the process, and he can already view the progress status,
beacuse I used application.doevents function, but the cancel option isn't performant as I want
but if he wants use my A-application for other functions, he cannot do it while
the "sendEmail process" has not ended to send 400 emails and their attachments.

Now, I dont want to open another A-application,

I want to demand the "sendemail process" code to another B-application that I will create,
How to monitor the progress of b-application from a-application without using
a text file? If I will use a process to start b-application I will able to close it in a second if I want.
at the moment I think only the "text file solution" at the moment
In that case, the solutions provided should work. Personally though, I dont think the effort involved in implementing those solutions is worth just to get rid of text file. Do you use a DB in your apps? You can use DB to share info.
"I dont want to open another A-application"

*My approach will still work and it doesn't open another A-application because it has been set to SINGLE INSTANCE.  Create a new project and enable this setting to see how it works.  You can double click the executable all you want and the same instance will stay open with creating new ones.

Communicating via text file is not necessary.  The whole point of my posts was that you can communicate using the built-in abilities of the .Net framework.

Yes, if you relegate the mail sending to B-application you can cancel it as well.  You could do this forcefully by using the Process() instance and issuing a CloseMainWindow() or Kill() command.  You could even use the SAME technique of SINGLE INSTANCE for B-application and send it a command-line parameter to cancel it.

*** BUT *** it really sounds more like you need to better design A-application with MULTI-THREADING in mind.  Instead of maintaining UI responsiveness with DoEvents(), you move the mail sending code to another thread.  The easiest way to do this is through use of the BackgroundWorker() control:
http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx
*That first paragraph should say "without creating new ones" at the end. =\
;) Ok,
I have only to read slowly your solution and so to understand it.
Thanks, See you later ;)
If you want do it all within A-application (without an external B-application) then please let us know.  It may be fairly easy to move the mail sending code to a background thread and provide an easy method to cancel it.

Just show us your existing mail sending code and we should be able to tell pretty quickly if it's worth the effort.
@CodeCruiser...just thought I'd let you know that I tried to follow the tutorial in the first link you posted...and I failed miserably.  I got lots of errors and exceptions...

@Everyone...

I found this tutorial, though, and made a similar version of it in VB.Net:
http://www.codeproject.com/KB/IP/remotinggui.aspx

I created "AppA_Remoting.exe" and "AppB_Remoting.exe", and was able to communicate from B to A via Remoting.

AppA simply had a Label, and AppB simply had a TextBox.  When the TextBox in B changes, the Label in A is updated automatically.  I did note a significant delay when the connection was first made, but afterwards the connection was quite smooth and responsive.

Here is my code for AppA_Remoting:
' Add a Reference to System.Runtime.Remoting (Project --> Add Reference --> .Net Tab)
Imports System.Threading
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Tcp

Public Class Form1

    Private WithEvents mas As MasterAppServer

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ChannelServices.RegisterChannel(New TcpChannel(50050), False)
        mas = New MasterAppServer
        RemotingServices.Marshal(mas, "Master")
    End Sub

    Private Sub mas_SlaveStatus(ByVal status As String) Handles mas.SlaveStatus
        Label1.Text = status
    End Sub

End Class

Public Class MasterAppServer
    Inherits MarshalByRefObject

    Public Event SlaveStatus(ByVal status As String)

    Private SC As WindowsFormsSynchronizationContext

    Public Sub New()
        SC = WindowsFormsSynchronizationContext.Current
    End Sub

    Public Sub UpdateStatus(ByVal status As String)
        If Not IsNothing(SC) Then
            SC.Post(New SendOrPostCallback(AddressOf SynchronizedRaiseEvent), status)
        End If
    End Sub

    Private Sub SynchronizedRaiseEvent(ByVal status As Object)
        ' ... we are already on the main UI thread when we raise the event below ...
        RaiseEvent SlaveStatus(status)
    End Sub

End Class

Open in new window



Here is my code for AppB_Remoting:
*Note at the top that I added a Reference to AppA_Remoting*
' Add a Reference to System.Runtime.Remoting (Project --> Add Reference --> .Net Tab)
' Add a Reference to the "Master" Remoting App (Project --> Add Reference --> Browse Tab)
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Tcp

Public Class Form1

    Private Master As AppA_Remoting.MasterAppServer = Nothing

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        If Process.GetProcessesByName("AppA_Remoting").Length > 0 Then
            ChannelServices.RegisterChannel(New TcpChannel(), False)
            Master = Activator.GetObject(GetType(AppA_Remoting.MasterAppServer), "tcp://localhost:50050/Master")

            ' Replace "localhost" with a computer name to communicate on a LAN!
            ' For example:
            ' Master = Activator.GetObject(GetType(AppA_Remoting.MasterAppServer), "tcp://Mike-Laptop:50050/Master")
            ' The above allowed me to use the Client from another laptop on my LAN...the master app on this laptop responded correctly
        End If
    End Sub

    Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged
        If Not IsNothing(Master) Then
            Try
                Master.UpdateStatus(TextBox1.Text)
            Catch ex As Exception
            End Try
        End If
    End Sub

End Class

Open in new window



Just run 'A' first, then 'B' and start typing in the box.  Hope it helps in your project!
@ Idle_Mind
thank you very much!
Your solution it's excellent!
Sorry but only today I have found time to look at it...
thank you to every body,
I would like to give you 5000 points but it's impossible at the moment ;)
thank you!
Glad you finally were able to get something working.
And it works fine ;)