28

I spent a few hours today researching how to get Chrome native messaging working with a C# native host. Conceptually it was quite simple, but there were a few snags that I resolved with help (in part) from these other questions:

Native Messaging Chrome
Native messaging from chrome extension to native host written in C#
Very Slow to pass "large" amount of data from Chrome Extension to Host (written in C#)

My solution is posted below.

Community
  • 1
  • 1
itslittlejohn
  • 1,708
  • 2
  • 18
  • 33

1 Answers1

40

Assuming the manifest is set up properly, here is a complete example for talking to a C# host using the "port" method:

using System;
using System.IO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace NativeMessagingHost
{
   class Program
   {
      public static void Main(string[] args)
      {
         JObject data;
         while ((data = Read()) != null)
         {
            var processed = ProcessMessage(data);
            Write(processed);
            if (processed == "exit")
            {
               return;
            }
         }
      }

      public static string ProcessMessage(JObject data)
      {
         var message = data["text"].Value<string>();
         switch (message)
         {
            case "test":
               return "testing!";
            case "exit":
               return "exit";
            default:
               return "echo: " + message;
         }
      }

      public static JObject Read()
      {
         var stdin = Console.OpenStandardInput();
         var length = 0;

         var lengthBytes = new byte[4];
         stdin.Read(lengthBytes, 0, 4);
         length = BitConverter.ToInt32(lengthBytes, 0);

         var buffer = new char[length];
         using (var reader = new StreamReader(stdin))
         {
            while (reader.Peek() >= 0)
            {
               reader.Read(buffer, 0, buffer.Length);
            }
         }

         return (JObject)JsonConvert.DeserializeObject<JObject>(new string(buffer));
      }

      public static void Write(JToken data)
      {
         var json = new JObject();
         json["data"] = data;

         var bytes = System.Text.Encoding.UTF8.GetBytes(json.ToString(Formatting.None));

         var stdout = Console.OpenStandardOutput();
         stdout.WriteByte((byte)((bytes.Length >> 0) & 0xFF));
         stdout.WriteByte((byte)((bytes.Length >> 8) & 0xFF));
         stdout.WriteByte((byte)((bytes.Length >> 16) & 0xFF));
         stdout.WriteByte((byte)((bytes.Length >> 24) & 0xFF));
         stdout.Write(bytes, 0, bytes.Length);
         stdout.Flush();
      }
   }
}

If you don't need to actively communicate with the host, using runtime.sendNativeMessage will work fine. To prevent the host from hanging, simply remove the while loop and do Read/Write once.

To test this, I used the example project provided by Google here: https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/docs/examples/api/nativeMessaging

Note: I'm using Json.NET to simplify the json serialization/de-serialization process.

I hope this is helpful to somebody!

Sebastian Ax
  • 1,110
  • 10
  • 11
itslittlejohn
  • 1,708
  • 2
  • 18
  • 33
  • I'm searching this for Java but I can't find anywhere :/ – omerfarukdogan Jul 03 '15 at 23:15
  • @farukdgn Specifically, what is proving difficult to find? A Java implementation should be fairly similar. – itslittlejohn Jul 04 '15 at 16:25
  • 1
    Where's the connect? i tried to run it and the extension gives me "Native host has exited." – ArielB Nov 07 '17 at 10:30
  • 1
    When initializing the connection from background script (chrome extension) - connection fails even though the host.exe opens up. "Failed to connect: Error when communicating with the native messaging host. " According to Google [link](https://developer.chrome.com/extensions/nativeMessaging) it is because of wrong serialization/size declaration. Any clue? – David D. Jan 02 '18 at 10:19
  • 2
    Why not just create a StreamWriter and write the string.Length and string? Why do you have to use WriteByte to write the int? – Robert Chitoiu Jan 22 '19 at 22:20
  • Actually, why not just do `stdout.Write(BitConverter.GetBytes(bytes.Length));`? – Robert Chitoiu Jan 22 '19 at 22:26
  • Just adding it here. Is there a way(an example) to communicate with multiple loaded chrome extension under chrome user profiles? Thanks in advanced. – Ishan Pandya Mar 31 '21 at 12:34