replacing MarshalByRefObject with safer option in C# - c#

I've tried to find a solution at stackoverflow but can't seem to find one quite like mine so here it goes. I have a computer in the lab that is connected to various devices like pan/tilt units, cameras, and light sensors and has all their drivers installed. I have C# code on the lab computer that knows how to talk to the hardware. The C# code can set an exposure time, ask for a picture, get one back, and display it in a picture box. I can tell the pan/tilt to move to a location and have it respond when done. If I am in the lab, it all works just the way I want.
The problem is that I want it to feel like I am at the lab computer when I am really at another computer. Most likely, I will be running the code that is on the non lab computer from inside Visual Studio. The program running in the lab will not be running from Visual Studio. With Remoting, this is a piece of cake. Put the code that talks to the hardware into a class, use MarshalByRefObject along with an interface I create, add RegisterWellKnownServiceType and presto I can use GetObject to get a reference and control it like I was sitting at the computer in the lab. So I know that remoting will work.
However, remoting is being phased out for WCF not to mention its not real safe out in the real world. It appears to me that WCF is going to make a local copy (by value) of the remote object which means it will not be on the lab computer and therefore unable to interact with the hardware that is attached. Someday this lab computer and all the sensor equipment is going to be moved away and I will have to access it remotely using the internet. A couple of years ago I did this exact thing but I was using remoting. Since remoting is so insecure, how do I do this without using remoting? Does WCF not have something equivalent to MarshalByRefObject? If WCF only uses by value, then it seems like they are phasing something out without providing functionality to replace it. Is there a way to use remoting that is not insecure? Is there something else besides WCF I should use?
This may be long winded but I see lots of people get dinged for asking questions that aren't very clear so I am trying to be clear. If there is already a post that truly provides me the best answer to my question, I must first apologize for not finding it myself but ask that a link be provided so I can get the answer there.

It appears to me that WCF is going to make a local copy (by value) of
the remote object which means it will not be on the lab computer and
therefore unable to interact with the hardware that is attached
This is almost entirely incorrect. There is no "copying" being done across machines. In fact the whole terminology around the "remote object" no longer has much meaning with WCF.
There is no remote object, simply a service. The service exposes operations across it's boundary. Service consumers can call those operations. When a consumer calls an operation, that call passes into the service and can cause the state of the service to change (for example, to talk to some hardware devices).
The service can also send a response to the caller, which can then cause the caller state to change (for example, to display output from the hardware device).
In order to make this happen you first need to create a service definition. Then you need to host your service on the lab machine. Then you need to create a service client, which you can then use on your local machine to call the service operations.
(How to) handle the situation where the port connected to the hardware
on the lab computer fires a DataReceived event that needs to be picked
up by my application
This is a more complex requirement but yes, WCF supports duplex communications with it's clients.
When you are defining your service contract you can specify that consuming clients implement a callback contract. This forces clients to define a callback operation which is exposed over the communication channel between service and client, and which the service can then call to "push" information to the client.
You should have your service use the WSDualHttpBinding WCF channel binding, which will use port 80 in both directions, allowing this to go across the internet.

Related

Best Practices: Adding a CLI to Existing Windows Service in .NET / Core

I'm wondering if anyone has any recommendations for the best way to implement a command line interface to an existing Windows service.
Ideally, the following requirements can be met:
Supports .Net Core and works cross platform
Is self hosted (ie not a separate executable)
Is registered globally and available in any terminal (ie. > myApp doThis -please --prettyplease)
Can be piped through to a web interface for remote terminal access via existing web app
Is available via terminals on other local network devices
The big requirement is that this works cross platform and is not tied to Windows. Any recommendations are very much appreciated!!!
Questions that feature the phrase "what is the best" typically aren't a good fit for stackoverflow as they're subjective - there may be no right answer to your query, but maybe there will be some good ones.
One option that I've employed several times in the past is to implement something like a simple shell/command prompt, accessed via telnet. You simply open a listening socket (TcpListener) and accept text commands sent to it/write text to it, something like your first day's of programming, with console in and out stream printing. There are bucketloads of examples on the web of simple tcp servers so I won't provide any code here. In terms of your points:
Supports .Net Core and works cross platform
It's tcp based, this is intrinsic
Is self hosted (ie not a separate executable)
Starts when the app starts, hosted by the app, doesn't need any complex IPc
Is registered globally and available in any terminal (ie. > myApp doThis -please --prettyplease)
The firewall is probably the only thing stopping your remote device communicating
Call be piped through to a web interface for remote terminal access via existing web app
html5/web based implementations of telnet exist. Could also make a simple web interface out of it (treat the browser like telnet; Here's little difference between them, they both read and write tcp sockets, just the browser adds more text from the http protocol. You can filter that out and just get the interesting bit the user can vary (the URL))
Is available via terminals on other local network devices
Covered above
The last time I implemented this was on a server that was used by credit card terminals. It already had a listening socket and clients followed a strict protocol, so it was easy to detect when a message didn't match protocol and treat it as a command instead. The system grew to the point where the server was full remotely configurable via a simple telnet interface, new credit card ranges and routings could be added,debug printouts could be enabled and all traffic would be sent to the telnet client, certain card terminals could be monitored etc; it was nothin more than compsci101 stuff of command = streamreader.ReadLine(), if(command == "debug") Global.DebugLoggingStream = tcpWriterStream
It had a web interface too, based on HttpListener, that just provided a nicely formatted list of the most recent errors, some config settings etc.. some stuff is better on a web page in a table than in an 80char column format. Eventually I upgraded this to be more like the terminal; the user could end the URL with a command, the command would be carried out and the result put in an array. Each time the page was served he array was dumped, so it became a sort of command shell in itself, not requiring telnet. I kept the telnet interface because it was good for realtime debugging, watching messages as they happened etc but if you wanted to get really fancy, websockets exists today for that sort of thing.
Another thought struck me; perhaps most of this hard work has been done for you, if you can find a c# implementation of an irc server, paired with a web based irc client, it would provide a way to "chat" with your service (which is pretty much all a command shell is; a human having a text chat with a program)

How to connect multiple clients to multiple servers and send alerts from servers based on certain events?

Background
I have multiple servers that I currently connect to remotely to run a number of different commands/scripts to obtain information about the servers and/or applications running on the servers.
I'd like to automate running the commands/scripts (or the code contained in the scripts converted to C#/.NET) and have the server send alerts/notifications/messages to a client (basically a Windows Form) running on multiple workstations, but need some guidance.
For reference, I have limited experience creating Windows Services, but feel fairly confident in being able to create them on the server to handle to command/script automation, which I'm assuming would be the best way to go about handling the command/script automation on the server (since the commands/scripts would need to be run all the time or at set intervals).
Question
How can I connect multiple servers to multiple clients so that the server sends alerts/notifications/messages to the client when a command/script or even an event occurs on the server?
For instance, if an application on the server has a built-in command that can be run to determine the status of the application (up, down, limbo, etc.), I would like the Windows Form on the client to receive an alert from the server when the command returns "down" or "limbo" when it is run, presumably from a Windows Service. The alerts would be displayed on the Windows Form that would be setup basically as a dashboard for the servers that the client can connect to.
An even better outcome would be that the client runs as a background application and a notification appears similar to how Microsoft Outlook displays a notification when new email messages arrive (although these notifications would likely require user interaction to close instead of fading out like the Outlook notifications).
I would also like for the client to use a configuration file that has the connection information for the servers in it so that the servers being used can be changed quickly new servers are added or existing servers are decommissioned.
Research (so far)
I've read about WCF and duplex contracts, and how WCF can be hosted in Windows Services. From what I've read, this seems promising. However, I'm not quite sure how I would set this up so that the client can connect to a WCF service on multiple servers.
One thing that I'm concerned about with WCF is that in all of the WCF examples (which implement a calculator-type service) I've seen the client has to initiate the communication with the server in order to receive a message through a callback. In the calculator service examples, the client sends numbers to the service and the result is provided in the callback. I've also seen an asynchronous example, but in that example the client initiated a single, long running request and the callback returned a single response when it was finished processing.
And, just so I'm clear about bindings in WCF, it is possible to create and use bindings for multiple servers using a configuration file without having to use SvcUtil.exe to generate the code, correct? The reason I ask is because the servers that will be configured will likely be change for different users, so the client needs to be flexible when connecting to the services.
I've just now started looking at Sockets, but I'm not familiar enough with them to know if this would be the better option to achieve my objective.
Summary
I'm just looking for guidance, so if you can help direct me to some resources that will help me achieve my objective, I would appreciate it. I've searched extensively, but the majority of my searching either doesn't apply to my scenario, it is limited to a single server/client interaction, or it is limited to a single server with multiple clients.
Since I'm not sure what direction to go in, I don't have any code examples, although I have implemented the examples in the following Microsoft article: Windows Communication Foundation - Getting Started Tutorial
So you want to build a system of
multiple servers which execute commands on the computer they are running on
multiple clients which will receive the status of the commands executed on server or such information from the server
This would be my advice
Servers can be implemented as windows service. You will be able to administrate them easily this way using the services console or the scm. Checkout this link for a creating a simple C# service How do you write and use a Windows Service in C#?
Also, you can set the service to run as an in-built service user with different levels of permissions in addition to regular user accounts.
I have not used WCF, but usually clients connect to the server; this is a pretty common model, and hence all samples are such. Initiating connection from server is not a big deal (at least in a socket program), but just a bad model. You have to ask yourself, if no client is connected to your servers, how can they relay a status to the end user. You have to think clearly about the communication model. I would suggest a central repository of messages. It can be a file on a shared file system or a database or any such entity which can act as a data repository. This way all servers can convey there messages without caring if a client is connected or not. You can use Sockets to achieve what you want to do. Check the asychronous socket server sample from MSDN to understand how to do it.
Making the client run in the background and just have a notification area icon is also easy in c#. You can use NotifyIcon Class for that. This CodeProject article (Formless System Tray Application) demonstrates its usage. To show notification a la outlook style, you can refer to the following post: How to create form popup from from system tray on windows application (not web) with c#. Look at not only the accepted answer but other answers too; there are lot of useful links in it.
So far we have windows service talking over sockets, storing messages in a central repository and capable of handling multiple clients with toast style pops for client side notification.
You need a far richer client side GUI so the end users can take actions on the messages sent from the server. You can maintain a list of servers in app.config for the client that the client connects on startup. You should to provide a GUI for users to manage all servers and their connections.
Lat but not least, by building such a client server model, you are effectively building a security loophole in your systems. You should implement a good authorization mechanism. Checkout the following post: Authenticate user in WinForms (Nothing to do with ASP.Net)
EDIT:
You can also implement your server to accept "custom command" when you implement it as a service. This way, your client server communication will be standardized by using ServiceController to pass the command. This post might help: How to send a custom command to a .NET windows Service from .NET code?.
Don't get confused in the "command" terminology here. ServiceController issues standard commands to a service for start, stop, pause, resume and restart the service. These are the same items you see on the context menu when you right click a service in the services.msc snap-in. The same way a service can respond to custom commands. In your case the custom command maybe a request to execute a process.
Note that some mechanisms I have described are geared towards an intranet setup while others scale fine on both intranet and internet

Android app disconnects from WCF web service randomly

We have designed an Android and iOS application for a client using their WCF created backend.
We have a method that allows users to checkin for their appointments if they are with in a certain geo location.
Both apps are able to find the server and grab data however the android application only works about 50% of the time (the iOS version works 100%). I have tried on Wifi and Cellular and get the same results.
The biggest issue is I can't even determine if the issue is with the client or server or how should i handle it?
I have read that it could be due to an unclosed httpURLConnection but thats my only real lead at the moment.
Please help!!!
Thanks
Since it works half of the time on android and for iOS always, the problem can be only the network problem by my opinion. It just happens in some network environments and on some of the devices or on some of the device with certain android-java version. I think you will not be able to do anything.
When I started to have those problems, I just always bumped into a simple fact about fallacy of network programming and CAP theorem: Network is reliable. So the fact is that network is NOT reliable and you should consider it in your solutions.
http://en.wikipedia.org/wiki/Fallacies_of_Distributed_Computing
http://en.wikipedia.org/wiki/CAP_theorem
It could be that this problem sometimes gets also into succeeded request but no response problem. Again almost the same network failure problem as above and what you can do is handle the possible timeout exceptions etc. and handle it appropriately on the server and client. So in case of having methods like submittingSomePayment, not use a normal WCF methods, but use enterprise service buses which store the messages into queues and process them and then have additional call that checks the results. See CQRS pattern for example.
http://msdn.microsoft.com/en-us/library/jj591573.aspx
Not very helpful, I know. But a possible answer and my thought about it. Because it annoyed me too. So it could be that you will not be able to do anything about it (except end users handling their network issue by themselves).
I would also log the request in the core beginning of the WCF service method call to exclude any internal WCF behavior (to exclude guessing is a problem in your code). All possible Logging on server and client would be a possible way to go in case you are still convinced the problem is in a code. And also see is this happening on all android devices (LG,... etc.) or only certain with certain java versions.

How to control settings of Windows Service from GUI?

I have this Windows Service that communicates with TCP/IP.
What I want to know is a method for a Windows Form Application to able to modify the setting of this service, such as remote host address and port to connect, timeout length, and log settings.
I have researched about NamedPipe, WCF Service, and IPC, but I can't decide what matches my scenario the best.
Will be nice to able to change the service settings by doing something like this from the client side.
[Service].SetTimeout(3000);
Any suggestions?
If you want that kind of programmatic control, then WCF is your best bet. With WCF, you get to define the API yourself, e.g., what methods to call, what messages to pass, etc. The WCF framework takes care of exchanging the data for you. And with the WCF config files, changing the back-end data exchange mechanism is trivial. For example, you could replace a NetNamedPipeBinding used for same-machine communication with a NetTcpBinding for cross-machine communication simply by modifying the config file(s). Full disclosure, though, if you haven't done WCF before, my experience was that the barrier to entry was pretty high. Of course, I took my lumps with Visual Studio 2008. It might be much easier in a more recent version. Here's an answer I gave a while back with some tutorials that helped me.
For me personally, I've replaced the early WCF implementation with a TCP-based version over localhost in the project I work on. The front-end application receives constant information from the Windows service when things are "running," and at the time of our decision, WCF streaming was not documented very well. We also saw evidence of problems, although that might simply be because we did it wrong. In any case, I'm very pleased with the solution we've come up with.
I can't speak to named pipes directly, but from what I've read, they're easy to use.
HTH.

Do I want to use Remoting or just a Socket connection

I'm writing code for a project that was initially written in VB6 and my partner and I are trying to slowly migrate it to .NET. In the mean time I need some feedback on how I should go about doing the following:
My users can run several instances the same program to help split several specific Messages sent to a server; a server that will IP Ban you if you send to many messages at one time. What I want to do is share these messages sent between the programs so that we can build a distributed messaging system to prevent an IP Ban - these programs are running on the same machine at the present. I'm trying to get my feet wet, so I've done several (no joke...) days worth of research and I came to the conclusion that I could write a DLL in C# .NET, incorporate the needed Interop to support COM, and have that DLL store commonly used Functions, Arrays, Etc. The function would also raise events on the VB6 program to send its messages which then the client program would send to the server its connected to.
My partner says I'm going about this the wrong way and that I should to create a Sever application that loads when the first stances of my program starts and distribute messages between my clients via Socket. This process seems like a lot of work.
I'm finding it all the more difficult because samples I've found on MSDN won't compile. If you know of a great example I'd really appreciate you posting it.
Don't use Remoting for new development. It has been deprecated in favor of WCF.
Use WCF instead. You can host a WCF service in any application, and it can communicate quite quickly and efficiently using binary over TCP/IP.

Categories

Resources