I have a few questions on good programming design. I'm going to first describe the project I'm building so you are better equipped to help me out.
I am coding a Remote Assistance Tool similar to TeamViewer, Microsoft Remote Desktop, CrossLoop. It will incorporate concepts like UDP networking (using Lidgren networking library), NAT traversal (since many computers are invisible behind routers nowadays), Mirror Drivers (using DFMirage's Mirror Driver (http://www.demoforge.com/dfmirage.htm) for realtime screen grabbing on the remote computer).
That being said, this program has a concept of being a client-server architecture, but I made only one program with both the functionality of client and server. That way, when the user runs my program, they can switch between giving assistance and receiving assistance without having to download a separate client or server module.
I have a Windows Form that allows the user to choose between giving assistance and receiving assistance. I have another Windows Form for a file explorer module. I have another Windows Form for a chat module. I have another Windows Form form for a registry editor module. I have another Windows Form for the live control module. So I've got a Form for each module, which raises the first question:
1. Should I process module-specific commands inside the code of the respective Windows Form? Meaning, let's say I get a command with some data that enumerates the remote user's files for a specific directory. Obviously, I would have to update this on the File Explorer Windows Form and add the entries to the ListView. Should I be processing this code inside the Windows Form though? Or should I be handling this in another class (although I have to eventually pass the data to the Form to draw, of course). Or is it like a hybrid in which I process most of the data in another class and pass the final result to the Form to draw?
So I've got like 5-6 forms, one for each module. The user starts up my program, enters the remote machine's ID (not IP, ID, because we are registering with an intermediary server to enable NAT traversal), their password, and connects. Now let's suppose the connection is successful. Then the user is presented with a form with all the different modules. So he can open up a File Explorer, or he can mess with the Registry Editor, or he can choose to Chat with his buddy. So now the program is sort of idle, just waiting for the user to do something. If the user opens up Live Control, then the program will be spending most of it's time receiving packets from the remote machine and drawing them to the form to provide a 'live' view.
2. Second design question. A spin off question #1. How would I pass module-specific commands to their respective Windows Forms? What I mean is, I have a class like "NetworkHandler.cs" that checks for messages from the remote machine. NetworkHandler.cs is a static class globally accessible. So let's say I get a command that enumerates the remote user's files for a specific directory. How would I "give" that command to the File Explorer Form. I was thinking of making an OnCommandReceivedEvent inside NetworkHandler, and having each form register to that event. When the NetworkHandler received a command, it would raise the event, all forms would check it to see if it was relevant, and the appropriate form would take action. Is this an appropriate/the best solution available?
3. The networking library I'm using, Lidgren, provides two options for checking networking messages. One can either poll ReadMessage() to return null or a message, or one can use an AutoResetEvent OnMessageReceived (I'm guessing this is like an event). Which one is more appropriate?
Put as little code as possible in the form. You should create a seperate class/set of classes to handle this and make the form use them to draw.
An event seems like a good idea. I wouldn't let the form subscribe, but have another class do the processing and just pass the processed data to the form (through another event).
I would use the event, because it probably checks async, which is what you want. You do not want to lock the form while waiting on messages.
Related
I have been charged with the task to send data from COM 1 to COM 2 in Windows CE 4.2. A running application takes data from COM 1 and displays it to the user in a form (textbox I assume). I then have to take that data and send it out COM 2. COM 1 is being used by the program displaying the data and I know of no way to hijack COM 1.
I figure trying to do a screen scrap would be the next step. Unfortunately this is compact framework and an old version at that and from a lot of research it seems managed code is out of the question . Many of the API functions I would use are not available; FindWindowEx for example.
Here is where I am at now. I have created two projects. One runs with a TextBox and some wording. A separate application runs and tries to read the text in that TextBox. I have been able to find the running process based off the name of the form using FindWindow API. Using code I have found on this site I have even been able to enumerate through the controls of the form. However my TextBox is never found and many of the controls that are found where never placed on the form by myself (listbox, button). I assume those are the form's initial controls.
Does anyone have any experience with this? Currently this is in C# but VB or Visual C++ will be fine. Even if you have any ideas on a third party application. BTW I am not given the option to upgrade to a higher version of compact framework.
Thank you.
An update I just found out about. It does not look like I only screen scrape only new data but instead have to screen scrape the entire screen and send it out COM2. Someone will scan a barcode and I will send out all screen data through COM2. The data may include a picture etc.
For a native C application I have one sceleton that enumerates all child windows and controls inside a dialog: http://code.google.com/p/rdp-auto-login/source/browse/trunk/rdp-auto-login/tscDialog.cpp. See ScanTSCWindow and the results found in the comment "TSC dialog elements".
I started with remote spy and looked thru the RDM window to find the CtrlID values. There is also a nice tool called zDump (http://www.hjgode.de/wp/2009/06/11/zdump-take-a-look-inside-windows-ce/) that runs on device and enables you to look at window elements.
The theory is that every element in Windows (either Mobile or desktop) is a window. Windows are accesible by there window handle. The handle is assign by the OS during CreateWindow/Ex. Inside dialogs, elements can be identified by there control ID (a resource value), the window class (ie "EDIT", "LISTBOX") and window text and internally by the window handle at creation.
The problem with Compact Framework apps is that they hide many of these basics and dialog (Form) elements can not be easily identified from another process.
As you say you are not able to capture COM1, what is, if you stop the application and then open COM1? As knonw, normally on one application can access a serial port at the same time. You can then read the serial data directly and do not need to access a foreign window.
There are also drivers that enable port mirroring or multiple access. Even for Windows CE based OS (ie http://www.virtual-serial-port.org/products/serial-splitter-mobile/).
If the application is a compact framework one you can take a look inside the code using .Net Reflector or similar .Net decompilers. I use that often to mimik or learn from other apps.
You say "I have been charged with the task to send data from COM 1 to COM 2 in Windows CE 4.2. A running application takes data from COM 1 and displays it to the user in a form (textbox I assume). I then have to take that data and send it out COM 2. COM 1 is being used by the program displaying the data and I know of no way to hijack COM 1." and if you do not start the other app you can write your own and do not need to parse the foreign app.
Possibly you can post the other app or more details of what it does what you can not do.
EDIT/UPDATE:
as we now know it is Intermec TE2000 (terminal emulation) the answer is to use the XMLRPC interface provided by TE2000. The interface is able to call back a function hosted by an xmlrpc server and send all screen content (text, fields and attributes) on screen changes. I have working c++ stl windowsce code for that.
If the device is connected via network, the xmlrpc server can even run on a PC.
As TE2000 does use native drwastring API you will not success in reading texts from the window. If you screen capture the window, you will have to do OCR on the image. XMLRPC does avoid all this.
UPDATE2:
I finished a class lib to get async screen updates using TE2000 xmlrpc: see https://github.com/hjgode/ITE_xml_rpc/tree/master/XmlRpcCS/XmlRpcCF
and http://community.intermec.com/t5/Thin-Client-Based-Development/Printing-CV60-Screen-Windows-CE-4-2/m-p/28663/highlight/false#M473
I'm not going to go into details why am trying to do this, instead of making the main application do the work. I think it's currently easier for me. But I'm not going to use this technique in the future.
In my case, the main form has a button that opens another form. In the second one for you can adjust the amount, pause, resume and stop the work of the console application (sound totally useless (and maybe stupid), but, like I said, I'm not going to go into details why). This means that the application must have access to all the variables and resources of the whole program and vise versa.
I know how to launch a new form trough a main form, but I don't know how to launch a console application.
EDIT:
I forgot to mention, that the console application is a part of the solution.
Your requirement is a bit vague; "the application must have access to all the variables and resources of the whole program and vise versa". 'Variables and resources' cannot be shared across processes, you will instead need interprocess communication of some form.
If your console app merely needs to communicate back to the calling forms app that a RPC has succeeded then use exit codes in the console app, see: How do I return a value from a console application to a service in .NET?
Otherwise this has been answered before: Getting the ouput from Console window into Winform application
You'll need to either create a console emulator (time consuming and difficult to get right), or fire up cmd.exe in another process and use remote procedure calls (or another inter process communication method) to communicate between the two processes
If you want to communicate between the two processes, take a look at this library here:
https://github.com/TheCodeKing/XDMessaging.Net
It allows you to send messages from one app to the other. For example, App1 sends a message "stop" on the channel "randomkey" to ConsoleApp1, ConsoleApp1 can listen on the channel "randomkey" and intercept the "stop" message and stop its current processing.
If you wanted to just open the console window, just use System.Diagnostics.Process.Start();
You can just call Main directly. Beware of doing this on the UI thread directly though!
SomeConsoleApp.Main(new string[]{"-O", "File 1.txt", "-some-parameter"});
Or if you only have an exe, you can do:
System.Diagnostics.Process.Start("someconsoleapp.exe");
I have this program that several users on the same computer is using (windows 2008 server environment with remote desktop clients).
When the program is ended normally, it deletes a special file in its working directory.
I need to be able to send all instances of this program a command to cleanly shut down (so that it deletes the file at exit).
What would be the best way to do this, and how?
I assume getting the pids for each instance is a start, but then what?
Anyone have any good ideas?
Edit: Forgot to mention, it's a WinForm (not a command line) program.
Edit2: My comment was too long, so I guess it's best to just edit the question instead...
The file it's deleting is actually a file containing it's pid.
The reason for having this file is to make sure that the user doesn't attempt to start the program twice with the same arguments (login information).
The main program (control center) that is actually starting the client program is keeping track of the pidfile in the users directory.
If it discovers the file it reads the pid and tries to see if the pid exists.
If not, it actually does delete the file and is letting the user start the client window.
I guess by using that procedure, I simply could make it look for all pids asociated with my application and simply kill them, ut I'd prefere to be able to send a shutdown command, as that would also notify the user in an IM that the program is shutting down for whatever the reason given. (Client initiated, remote server initiated, or, as in this case "Local server initiated").
A Mutex is something that represents mutual exclusion. I don't think that is really what you want in this case. It's not really modelling what you want; plus only one application at time would be able to shut down. I would recommend using a named EventWaitHandle to model one application sending events (shutdown events) to other applications. If you use a manual reset event (by using EventResetMode.ManualReset when you create an EventWaitHandle object.
You would do this on a background thread that, when signalled, would marshal something over to the UI thread (via Control.BeginInvoke) to communicate to the main form that it needs to shut down.
You could use a system wide event by using a Mutex
See the example on the linked page in the MSDN
I have a web-based picking/packing solution for delivering orders (asp.net/c#). Orders are marked as packed in the browser and then immediately the label information is added to our database, ready for the next part...
The label printing is done via a Windows application (written in C#) and was done this way because I couldn't find a way of getting the browser to print the label automatically (i.e. without the user having to click Print/OK, etc.)
The problem:
The Windows application polls every 10 seconds (subject to change) to see if there are any new labels for that picker/packer. Now, if I could get the browser to communicate with the label application then the polling would be unnecessary, since the picker/packer would have just clicked "Ready to Ship" and the label data would be created.
The data that is pulled down by the polling process isn't vast, but I'm concerned that as we add more picker/packer stations the polling process could have a knock on effect to the web server/database (since all stations would be polling). Also, pickers/packers don't want to wait around waiting for labels, so extending the polling time isn't possible (if anything I'd like it as quick as possible)
Solutions?
So, ideally, I'd like a way of communicating between the browser and the application (if possible). Or any method that removes the need for polling. Perhaps something akin to Comet, that allows the server to send a message to the application when a new label is added.
Ideally, a solution that wouldn't require a specific browser. But this may be asking too much.
A long-term solution would be to move the web-based picking-packing solution into the label application, but that would be a lot of work!
I hope that's clear and not too wordy. Let me know if I can add any other details in here. Thanks in advance.
Edit
Am looking into websockets as an idea. Any advice will be more than welcome!
Update
Thanks for all comments. I've now got a few ideas on how to solve the problem:
Websockets. May be problematic with firewall issues since I don't have easy access to the system (geographical distance)
Read browser cookies from the application. Possible solution http://www.codeproject.com/Articles/330142/Cookie-Quest-A-Quest-to-Read-Cookies-from-Four-Pop. This covers all the browsers that are in use in the warehouse. I can poll the local cookie values and see if any new labels have been created, then download them. Therefore no polling on the database server.
ActiveX control. Limited to IE and perhaps there'd be some security/setup issues with installing this on each PC.
Leave the code as is. Gauge whether the load on the database server is too much or ok.
You could create a local WebSocket server in your C# application and then make the browser connect to it and send the data you need to print.
I'm not sure, though, that this is what you need. As I see it you need to pass graphical data to your application, which could be really tricky to do using only javascript.
The appropriate way to achieve the communication between a web application and a desktop application would be to go through a server both apps talk to.
You can get any web-server (e.g. node.js nodejs.org that will let you use the same javascript you use for the web-app on the server) and interact with it. How you talk with the server from the desktop app depends on its technology. However all languages have some way to do http communications like SOAP.
Or you can try to make:
Both apps talk to the server using socket.io. You can borrow code from the following project.
Create an MSMQ (or a queue implementation of your choice) and host a WCF service in your windows application that polls the MSMQ.
Have your ASP.NET application write any relevant information to this queue so that the WCF service in the windows app that pulls this information will know what to make of it and print your labels.
The reason I mention a queue is for reliability, if your windows app goes down for any reason, the queue will at least be preserved and waiting for you to bring the windows application back up.
Although there is a bit of polling involved, it is very quick and almost neglibible. Implementing it is automatic with NetMsmqBinding, it's all taken care of. All you need to do is configure it.
If you go for a non-MSMQ queue, then I don't know whether you can still use NetMsmqBinding, you may have to create your own.
I'm not sure, but it seems like your application is polling a filesystem for these new labels to print? Have you considered using a FileSystemWatcher in your application? You can set that to watch a directory and be notified of anything new.
I am trying to create a window service to create a small keylogger application. I am new to Windows services and my sole purpose is to learn.
How can I obtain all the events that are available in Winforms, but in a Windows service?
I've tried searching on Google, but I'm unable to find out how to do this. I'm getting many references to keyhook DLLs.
Windows Services are not form based therefore you cannot do it that way.... Have a look here for an example of how to create a Windows Service that kills other windows.
A window service is not an ideal spot to place a form on... think of a daemon under Linux/Unix variants - they do not have a graphical display nor interact with the user as such and hence would be 'headless' for want a word for it as there's no interaction whatsoever, and furthermore, a service would be running under a system service account....
Speaking of Keyloggers, it does not work like that - you need to hook into the global keyboard hook and intercept the keys, an example of such a thing is here.
But then the question will arise for what purpose, gather data, etc - possibly AV's will flag them as malware... If you are doing it for yourself - that's good...but to maliciously place it on another computer without that user knowing about it is very iffy and could end up in court for invasion of privacy, in terms of local laws etc.