3

I have a video kiosk setup in my lobby, it lets people check in and print a badge with their picture, name, etc. There is also a remote support tool that unfortunately crashes sometimes. I have a function on the kiosk that fixes this issue but you must go to the kiosk to trigger it right now.

I have also written a management tool that uses WMI to monitor and manage some other aspects of the kiosk. I would like to be able to trigger this repair function via this application. I have spent countless hours on google trying to figure this out with no luck. Maybe I am not searching for the right things.

My question is this. In C# how can I call the repair function in my kiosk application from the admin application over the network?

BenMorel
  • 34,448
  • 50
  • 182
  • 322
JD Roberson
  • 589
  • 3
  • 7
  • 25
  • I don't have the answer you want. But what about a timer, on the local kiosk, that attempts the repair every.... 5 minutes... 3 minutes... or whatever you need. or what about remote desktop, where you take control of the second computer. – General Grey May 22 '12 at 15:57
  • 1
    I think RMI or WCF might be the things you're looking for: http://stackoverflow.com/questions/1830243/c-sharp-remote-method-invocation-rmi **and** http://stackoverflow.com/questions/3560107/what-the-net-standard-for-remote-method-invocation – Kiril May 22 '12 at 15:58
  • 1
    I'd think a TCP/IP connection would be good for this. Your management application would be the server (listening for messages) and your kiosk would send messages to it. If you want more on this, I'm able to provide a basic example. –  May 22 '12 at 16:02

1 Answers1

2

OK, on my Server form, I have a BackgroundWorker that runs a TcpListener. You will want to put this TcpListener in a BackgroundWorker, otherwise you will never be able to stop it from executing until it accepts a TcpClient.

Also, you will want to process any data you receive from this background thread in the main thread of execution to prevent cross thread exceptions:

private TcpListener _listener;
private const int port = 8000;

private void Worker_TcpListener(object sender, DoWorkEventArgs e) {
  BackgroundWorker worker = sender as BackgroundWorker;
  do {
    try {
      _listener = new TcpListener(IPAddress.Any, port);
      _listener.Start();
      TcpClient client = _listener.AcceptTcpClient(); // waits until data is avaiable
      int MAX = client.ReceiveBufferSize;
      NetworkStream stream = client.GetStream();
      Byte[] buffer = new Byte[MAX];
      int len = stream.Read(buffer, 0, MAX);
      if (0 < len) {
        string data = Encoding.UTF8.GetString(buffer);
        worker.ReportProgress(len, data.Substring(0, len));
      }
      stream.Close();
      client.Close();
    } catch (SocketException) {
      // See MSDN: Windows Sockets V2 API Error Code Doc for details of error code
    } catch (ThreadAbortException) { // If I have to call Abort on this thread
      return;
    } finally {
      _listener.Stop();
    }
  } while (!worker.CancellationPending);
}

This would not be good for large messages (like JPEG files and such), but works great for short strings where I have coded in special data to look for.

This data is sent back to my main thread of execution (using the ReportProcess method) where the data is processed:

private void Worker_TcpListener(object sender, ProgressChangedEventArgs e) {
  if (e.UserState != null) {
    int len = e.ProgressPercentage;
    string data = e.UserState.ToString();
    if (!String.IsNullOrEmpty(data) && (3 < len)) {
      string head = data.Substring(0, 3);
      string item = data.Substring(3);
      if (!String.IsNullOrEmpty(item)) {
        if (head == "BP:") {
          string[] split = data.Split(';');
          if (2 < split.Length) {
            string box = split[0].Substring(3); // Box Number
            string qty = split[1].Substring(2); // Quantity
            string customer = split[2].Substring(2); // Customer Name
            MyRoutine(box, qty, customer);
          }
        }
      }
    }
  }
}

The code above just sits and runs all day long.

Meanwhile, I have about 10 Pocket PC devices in our plant that could send data at any time. The code for them is written in VB, and I really hope I have time to finish my C# version one of these days, but here it is:

Private Sub SendToServer(string serialNum, int qty, string customer)
  Cursor.Current = Cursors.WaitCursor
  Try
    Dim strPacket As String = String.Format("BP:{0};Q:{1};C:{2};", serialNum, qty, customer)
    Dim colon As Integer = p7_txtIPAddress.Text.IndexOf(":")
    Dim host As String = p7_txtIPAddress.Text.Substring(0, colon)
    Dim port As Integer = CInt(p7_txtIPAddress.Text.Substring(colon + 1))
    Dim dataPacket As [Byte]() = Encoding.ASCII.GetBytes(strPacket)
    Using client As New TcpClient(host, port)
      Dim stream As NetworkStream = client.GetStream()
      stream.Write(dataPacket, 0, dataPacket.Length)
    End Using
  Catch err As Exception
    MessageBox.Show(err.Message, "Print To Server TCP Error")
  Finally
    Cursor.Current = Cursors.Default
  End Try
End Function

I don't know if that is what you are trying to do, but it works and is reliable.

Obviously, the code I have in production is larger and includes other things (i.e. employee validation, error loggers, etc.) that you would not find useful. I have cut a lot of those out, and I hope I did not cut out anything necessary.

This should give you an idea of how to move forward, at least.

  • To handle image files (like your kiosk would require), I'd suggest saving those to a known location on your network (ie "Z:\kiosk\images") and just send the image's name over the TcpClient ("IMG0001.JPG"). –  May 22 '12 at 20:53