30

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,808
  • 3
  • 20
  • 33

2 Answers2

42

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,240
  • 12
  • 11
itslittlejohn
  • 1,808
  • 3
  • 20
  • 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
0

You can also use regular http communication. And send messages using fetch or other js api. And host app will be regular web api project that runs on localhost. You also will need to enable cors policy in your web app. Maybe it's overkill for some cases and probably not as fast. But it is more transparent for most developers and works great in my project.

Vlad
  • 3
  • 4
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/33174344) – possum Nov 20 '22 at 16:39