All. Firstly I am aware of the question Send data back to .exe from dll, however the answers there leave too many open ends for me and as I have no experience of what I am attempting I feel a new question is warranted.
I have an existing C# [All WinForms here] app that heavily relies on SQL. We have been asked (by clients) to provide an SQL Editor and library that can be used to develop and test SQL, but that can also be used to paste directly back in to the main application. The new SQLEditor is a multi-threaded application that parses and executes TSQL. I now have some things to consider; what is the best way to launch this second application from the main application::
Make the second app into a DLL and load into the main project, call the second app as a new form (SqlEditor sqlEd = new SqlEditor() etc.)? What are the implication in terms of thread bombardment, would I need [STAThread] - as I want both multithreaded apps to be available and active at the same time.
To launch as a separate .exe from the main application?
Depending on you advice; in either of the above cases - what is the best way I can pass information back to the main application from a click event in the second application whilst they are still both running and active [WCF, ApplicationDomains etc.]? Would the Observer design pattern come in to play here?
To make this question a little more appealing, here is the SQL Editor:
I plan to have a button which pastes the selected SQL back into the main application.
I am also aware that there are multiple questions here - which I apologise for. Thanks very much for your time.
If you need a simple way to do an outproc communication of two WinForms applications, then why don't you use the Clipboard with a custom format?
In the source application:
// copy the data to the clipboard in a custom format
Clipboard.SetData( "custom", "foo" );
In the destination application, create a timer to peek the clipboard:
private void timer1_Tick( object sender, EventArgs e )
{
// peek the data of a custom type
object o = Clipboard.GetData( "custom" );
if ( o != null )
{
// do whatever you want with the data
textBox1.Text = o.ToString();
// clear the clipboard
Clipboard.Clear();
}
}
This should fit your needs and it's still really simple as it doesn't require any heavyweight outproc communication mechanisms.
Another way of accomplishing intra-app communication is with the use of Windows messages. You define a global windows message id and use Windows API calls such as SendMessage and PostMessage.
Here's a simple article that explains how:
Ryan Farley's article "Communication between applications via Windows Messages"
This is in effect the observer pattern, receiving all the Windows messages being directed at the current Window and picking out the one you're listening out for.
In my experience this is definitely less flaky than the clipboard approach.
You have multiple choices for IPC(Inter Process Communication) such as:
Mailslot, NamedPipe, Memory Mapped File, Socket, Windows Messaging, COM objects, Remoting, WCF...
http://msdn.microsoft.com/en-us/library/windows/desktop/aa365574(v=vs.85).aspx
http://en.wikipedia.org/wiki/Inter-process_communication
Some of them provide two-way communication, some needs considaration about system security(antivirus & firewall restrictions, you need to add the application as an exception in their settings).
Sending message through WM_COPYDATA can be done just by SendMessage, PostMessage is not supported, it means that the communication is sync.
Using outproc singleton COM object is another way, its not as simple as the other ways and both app. must be run on the same security context to access the same COM object.
Launching a separate application can coz some restrictions in communication methods or types of data you can pass, but separation of them will also protect them from their failures(App. crash will not close the other one).
If the two parts are always run on the same PC, using one of them as dll[inproc] is simpler. Using other techniques such as Socket, Remoting, WCF will provide you with more flexibility for communication, i.e. the two parts can run in different PCs with minor modifications...
Related
I have a problem, have not much experience in C #, so I did a lot of research and I'm stuck.
I have to make two applications C #, the first applications is windows forms, the second runs in the background, so that the first applications will be a (POS) sales point that need to communicate with the application background for information as (products, customers, etc ...) and send data, so do not want to use web service for problems like timeouts, so anyone can help me with some idea to perform this task?
it is important to mention that the application in background will be just one while the POS applcations wich will communicate with it will be a lot (n number of apps).
There is a myriad of ways of doing interprocess communication. As the question is so generic, I will point out some more common ways.
The background process can be a windows service which updates the DB and POS systems query the DB to retrieve what they need. Even if the background process reads from the same DB, you can have a separate table which has "finished" information ready for the POS piece to pick up. Now you can use a file instead of a DB to store this finished results too, but most folks prefer DB.
You can use WCF channel to establish communication between the POS piece and the background process.
You can convert your background process to a web-service and let your POS piece communicate using XML. I don't think any time-out issue should be a problem. You will have to explain better what time-out issue causes you to not use this option.
You can convert the whole piece into a web-site and the POS will simply be a browser then
You can use a bus like Tibco or MQ to pass data.
Or you can go the old fashioned way of TCP sockets.
The most preferred way is usually the web-servcie or web-site way depending on your constraints.
Typically you'll use a message queue for something like this. They are a component in ensuring clean separation of concerns reducing and cross-application coupling and are meant to receive messages by some publisher (thus freeing the publisher of any further responsibility), and pushing messages to some subscriber.
RabbitMQ is a popular framework: https://www.rabbitmq.com/
(note that RabbitMQ (and other ready-built frameworks) can sometimes be daunting for new application programmers as they handle a great many use cases. However the underlying concept of writing to a queue from one application and reading from the queue in the other application is really the key here... feel free to implement a small utility of your own as a learning experience, but I do recommend an pre-existing framework if you're comfortable using such)
One method is to use named pipes for such communications between different programs.
How to: Use Named Pipes for Network Interprocess Communication
If you do not want to use web service (based on soap protocol),
you could attempt to use web api. In this way, you could build rest based interfaces with json (json streaming between computers is faster than xml streaming).
I think the following link can be usefull to you:
http://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api/using-web-api-with-aspnet-web-forms
This may seem very elementary, but I don't really have any experience in this realm - all my experience has been on the web side of things.
I need to create a process of some sort that will repeatedly query an API (around 5 times a second), get the results from the API (in JSON format), and then my process will do what it needs to do with the results (in my case, insert them into a SQL database). These details don't really matter to the scope of the question I have, I just want to give you an idea on what I'm trying to achieve in case someone wants to recommend a better way of doing it.
My first thought was to create a console app that basically never quits (unless I specifically tell it to). Is a console app the way to go for this? The idea is I'll have a VM set up which will host my solution, including this "process" I create. I'm not all too familiar with Windows Services, or Windows Tasks, but I probably need to write some custom code so therefore I imagine I can't use the Windows Task Scheduler, am I right?
Once options would be to create a Windows Service which is the OS-level implementation of a long running process. To do so in C# you may wish to read through some tutorials online, perhaps starting with the MSDN Walkthrough. You should also read about Windows Services in general and the differences between a service and a regular user process (mainly the fact that services have no UI and can't interact with the user directly, and some of the other security considerations).
Other options may be to leverage a framework such as WCF or similar.
It's my first post on StackOverflow, so please be patient with me :)
I'm looking out for a way to pass a value to an already running application. The application should be able to accept this value and use it for further operations during its lifetime. I'd prefer not to logoff/restart the application in order to use the updated value.
The scenario would be something like this:
The application uses MachineName to initialize and populate some objects while it is being instantiated. Once it is up and running, I would like to pass a different workstation name to the application (possibly from command line) and the application should be able to use this MachineName and use it further down the line. I dont mind if I have perform same operations again to initialize the required objects with new MachineName name.
The application in question is a WPF app with C#. It's also using some WCF services as well. I was thinking to use a common registry key to store the workstation name and this registry key needs to be used/updated in the application. So it should be the first point of contact. But I'm not sure if this is a better approach. Any ideas please?
It's pretty easy to watch a file on disk using a FileSystemWatcher. When your app gets a change notification, re-read the contents of the file and update your app state.
The application listen to a socket port or watch a shared file when it starts up, if the application is called again with parameter, just open the socket port or write the command to the file, the first application can do the re-initialization .
First off, I think you might be over-complicating things a bit. If all you need to do is give your application a new string "MachineName", then you have several options (this is certainly not all of your options, just a few to think about):
Since this is a WPF application, we can assume some user is interacting with it...otherwise it may as well just be a console app. If this is the case, create a view giving the user the ability to change the MachineName. Perhaps a ComboBox listing all available MachineNames and a button to begin the re-initialization you need.
You apparently already have the plumbing in place for service calls. You could have your application act as both a client AND a service, allowing you to remotely (read: outside of this application) update your MachineName.
You can set this application up to monitor a specific directory or file (as pointed out by #jlew) and when some change occurs to that file, your application will read the change (the new MachineName) and begin it's re-initialization routine.
I don't know your full set of requirements, but I would probably set it up for both 1 and 2, which will give you a little more flexibility.
Is it possible to write custom events that can be handled by 3rd party applications?
We have an existing app and we're finding that many people that use the app are using sql triggers to custom-write functionality of their own certain when things happen in our app.
This has led to some instances where our own processes have slowed down due to shoddy 3rd party Triggers that block our app.
I was thinking we could make this easier for 3rd party devs if we could raise events that they could handle in their own services or apps instead of having to use triggers.
That way we'd lose the blocking because we can just fire the event and continue. Also their slowness/potential crashes would happen outside of our process.
A) is this a reasonable approach?
B) Is this possible? Can I scope an event beyond the scope of my app?
EDIT
I have since found other related questions to be of interest:
wcf cross application communication
Interprocess pubsub without network dependency
Listen for events in another application (This seems very close to what I'm after)
I guess I'm looking for the simplest approach but if we wanted to adopt this method across a number of other apps within our company we'd have some further challenges:
We have some older apps in vb6 and delphi - from those I'd just like to be able to listen for their events in my (or 3rd party) newer C# apps or services.
For now, I'll look at:
Managed Spy and http://pubsub.codeplex.com
No, events are only usable by code that's loaded into your own process. If you don't trust these people now, you really don't want to expose yourself to shoddy code that you load into your own process and throws unhandled exceptions that terminate your app. You'll get the phone call, not them. Besides, they'll use such an event to run code that slows down your app.
In general, anything you do with a dbase will run with an entirely unpredictable amount of overhead. Not just because of triggers added by others, the dbase server could simply be bogged down by other work and naturally slow down over time as it stores more and more data. Make sure that doesn't make your app difficult or unpleasant to use, dbase operations typically must run on a worker thread or be done asynchronously with, say, BeginExecuteXxxx(). And make it obvious in your UI that progress is stalled by the dbase server, not by any code that you wrote. Saves you from having to do a lot of explaining.
What you're looking to do is basically to send messages to other processes. For this, you need some sort of IPC mechanism. Since it sounds like you'll have multiple listeners to each message, a mailslot is probably the best way. Unfortunately, .NET doesn't have built-in support for mailslots, so you'll have to use P/Invoke.
If you're looking for a built-in solution, then you could use named pipes, WCF, .NET Remoting, or bare TCP or UDP. With any of these, though, you'll have to loop through all of your listeners and send the message one at a time to each of them, which is not that big of a deal, but maintaining the separate connections is a little more of a hassle.
Note that with WCF and .NET Remoting, you're pretty much limiting your clients to using .NET as well. If your clients might be native or some other platform, then mailslots, named pipes, and TCP/IP are your best bet.
Suppose I have two applications written in C#. The first is a third party application that raises an event called "OnEmailSent".
The second is a custom app that I've written that I would like to somehow subscribe to the "OnEmailSent" even of the first application.
Is there any way that I could somehow attach the second application to an instance of the first application to listen for "OnEmailSent" event?
So for further clarification, my specific scenario is that we have a custom third party application written in c# that raises an "OnEmailSent" event. We can see the event exists using reflector.
What we want to do is have some other actions take place when this component sends an email.
The most efficient way we can think of would be to be able to use some form of IPC as anders has suggested and listen for the OnEmailSent event being raised by the third party component.
Because the component is written in C# we are toying with the idea of writing another C# application that can attach itself to the executing process and when it detect the OnEmailSent event has been raise it will execute it's own event handling code.
I might be missing something, but from what I understand of how remoting works is that there would need to be a server defining some sort of contract that the client can subscribe to.
I was more thinking about a scenario where someone has written a standalone application like outlook for example, that exposes events that I would like to subscribe to from another application.
I guess the scenario I'm thinking of is the .net debugger and how it can attach to executing assemblies to inspect the code whilst it's running.
In order for two applications (separate processes) to exchange events, they must agree on how these events are communicated. There are many different ways of doing this, and exactly which method to use may depend on architecture and context. The general term for this kind of information exchange between processes is Inter-process Communication (IPC). There exists many standard ways of doing IPC, the most common being files, pipes, (network) sockets, remote procedure calls (RPC) and shared memory. On Windows it's also common to use window messages.
I am not sure how this works for .NET/C# applications on Windows, but in native Win32 applications you can hook on to the message loop of external processes and "spy" on the messages they are sending. If your program generates a message event when the desired function is called, this could be a way to detect it.
If you are implementing both applications yourself you can chose to use any IPC method you prefer. Network sockets and higher-level socket-based protocols like HTTP, XML-RPC and SOAP are very popular these days, as they allow you do run the applications on different physical machines as well (given that they are connected via a network).
You can try Managed Spy and for programmatic access ManagedSpyLib
ManagedSpyLib introduces a class
called ControlProxy. A ControlProxy is
a representation of a
System.Windows.Forms.Control in
another process. ControlProxy allows
you to get or set properties and
subscribe to events as if you were
running inside the destination
process. Use ManagedSpyLib for
automation testing, event logging for
compatibility, cross process
communication, or whitebox testing.
But this might not work for you, depends whether ControlProxy can somehow access the event you're after within your third-party application.
You could also use Reflexil
Reflexil allows
IL modifications by using the powerful
Mono.Cecil library written by Jb
EVAIN. Reflexil runs as Reflector plug-in and
is directed especially towards IL code
handling. It accomplishes this by
proposing a complete instruction
editor and by allowing C#/VB.NET code
injection.
You can either use remoting or WCF. See http://msdn.microsoft.com/en-us/library/aa730857(VS.80).aspx#netremotewcf_topic7.
What's the nature of that OnEmailSent event from that third party application? I mean, how do you know the application is triggering such an event?
If you are planning on doing interprocess communication, the first question you should ask yourself is: Is it really necessary?
Without questioning your motives, if you really need to do interprocess communication, you will need some sort of mechanism. The list is long, very long. From simple WM_DATA messages to custom TCP protocols to very complex Web services requiring additional infrastructures.
This brings the question, what is it you are trying to do exactly? What is this third party application you have no control over?
Also, the debugger has a very invasive way of debugging processes. Don't expect that to be the standard interprocess mechanism used by all other applications. As a matter of fact, it isn't.
You can implement a similar scenario with SQL Server 2005 query change notifications by maintaing a persistent SqlConnection with a .NET application that blocks until data changes in the database.
See http://www.code-magazine.com/article.aspx?quickid=0605061.
also WM_COPYDATA might be possible, see https://social.msdn.microsoft.com/Forums/en-US/eb5dab00-b596-49ad-92b0-b8dee90e24c8/wmcopydata-event-to-receive-data-in-form-application?forum=winforms
I'm using it for similar Purose (to notify that options have been changed)
In our C++/Cli-scenario (MFC-)programs communicate vith WM_COPYDATA with Information-String in COPYDATASTRUCT-Member lpData
(Parameterlist like "Caller=xyz Receiver=abc Job=dosomething"). also a C#-App can receive WM_COPYDATA-messages as shown in the link. Sending WM_COPYDATA from C# (to known Mainframe-Handle) is done by a cpp/cli-Assembly, (I didnt proove how sending WMCOPYDATA can bei done in C#).
PS in Cpp/Cli we send AfxGetMainWnd()->m_hWnd as WPARAM of WMCOPYDATA-Message and in C# (WndProc) m.WParam can be used as adress to send WM_COPYDATA