Chrome Native Messaging API chrome.runtime.connectNative is not a function
Asked Answered
V

4

10

I am looking to manipulate the content page that's currently on the tab in Chrome and if this below can not do that then I need to find the way in order to do that!

Hey all I am trying to get this new chrome extension working with my C# program to pass messages back and forth. I've seen a lot of demos of code on stackoverflow and that's mainly what I've been going by but it seems that all the examples are not working on my end.

The issue I am having is I am getting the error of:

Connecting to native messaging host com.google.chrome.example.echo
Uncaught TypeError: chrome.runtime.connectNative is not a function

enter image description here

Whenever I try to "connect" to the port.

Not sure what I am doing wrong since I have followed other tetorials on here and they all seem to state it works....

The JS main.js:

var port = null;
var getKeys = function (obj) {
    var keys = [];
    for (var key in obj) {
        keys.push(key);
    }
    return keys;
}
function appendMessage(text) {
    document.getElementById('response').innerHTML += "<p>" + text + "</p>";
}
function updateUiState() {
    if (port) {
        document.getElementById('connect-button').style.display = 'none';
        document.getElementById('input-text').style.display = 'block';
        document.getElementById('send-message-button').style.display = 'block';
    } else {
        document.getElementById('connect-button').style.display = 'block';
        document.getElementById('input-text').style.display = 'none';
        document.getElementById('send-message-button').style.display = 'none';
    }
}
function sendNativeMessage() {
    message = { "text": document.getElementById('input-text').value };
    port.postMessage(message);
    appendMessage("Sent message: <b>" + JSON.stringify(message) + "</b>");
}
function onNativeMessage(message) {
    appendMessage("Received message: <b>" + JSON.stringify(message) + "</b>");
}
function onDisconnected() {
    appendMessage("Failed to connect: " + chrome.runtime.lastError.message);
    port = null;
    updateUiState();
}
function connect() {
    var hostName = "com.google.chrome.example.echo";
    appendMessage("Connecting to native messaging host <b>" + hostName + "</b>")
    console.log("Connecting to native messaging host " + hostName);
    port = chrome.runtime.connectNative(hostName);
    port.onMessage.addListener(onNativeMessage);
    port.onDisconnect.addListener(onDisconnected);
    updateUiState();
}
document.addEventListener('DOMContentLoaded', function () {
    document.getElementById('connect-button').addEventListener(
        'click', connect);
    document.getElementById('send-message-button').addEventListener(
        'click', sendNativeMessage);
    updateUiState();
});

The manifest.json:

{
  // Extension ID: knldjmfmopnpolahpmmgbagdohdnhkik
  "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDcBHwzDvyBQ6bDppkIs9MP4ksKqCMyXQ/A52JivHZKh4YO/9vJsT3oaYhSpDCE9RPocOEQvwsHsFReW2nUEc6OLLyoCFFxIb7KkLGsmfakkut/fFdNJYh0xOTbSN8YvLWcqph09XAY2Y/f0AL7vfO1cuCqtkMt8hFrBGWxDdf9CQIDAQAB",
  "name": "Native Messaging Example",
  "version": "1.0",
  "manifest_version": 2,
  "description": "Send a message to a native application.",
  "app": {
    "launch": {
      "local_path": "main.html"
    }
  },
  "icons": {
    "128": "icon-128.png"
  },
  "permissions": [
    "nativeMessaging"
  ]
}

The Registry:

REG ADD "HKCU\Software\Google\Chrome\NativeMessagingHosts\com.google.chrome.example.echo" /ve /t REG_SZ /d "%~dp0com.google.chrome.example.echo-win.json" /f

C# code:

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace talkWithChromeCSharp
{
    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["message"].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))["data"];
        }

        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();
        }
    }
}

com.google.chrome.example.echo-win.json file:

{
  "name": "com.google.chrome.example.echo",
  "description": "Chrome Native Messaging API Example Host",
  "path": "native-messaging-example-host.bat",
  "type": "stdio",
  "allowed_origins": [
    "chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/"
  ]
}

HTML main.html:

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <script src='main.js'></script>
</head>
<body>
    <button id='connect-button'>Connect</button>
    <input id='input-text' type='text' />
    <button id='send-message-button'>Send</button>
    <div id='response'></div>
</body>
</html>

My directory structure in Visual Studio:

C:\Users\t||||||\Documents\Visual Studio 2012\Projects\talkWithChromeCSharp\talkWithChromeCSharp
   -APP
     |-icon-128.png
     |-main.html
     |-main.js
     |-manifest.json
   -bin
     |-Debug
        |-Newtonsoft.Json.dll
        |-talkWithChromeCSharp.exe
        |-etc etc...
     |-Release
   -obj
   -Properties
   -regs
     |-com.google.chrome.example.echo-win.json
     |-install_host.bat
     |-etc etc...

After starting VS debug I install the plugin and load up the main.html file on the chrome browser and click the "connect" button. That's when I get that error.

What am I missing?

UPDATE

That is the correct ID for it. I kept it that way since i'm guessing the "KEY" is what determines the ID.

enter image description here enter image description here

Veta answered 9/10, 2015 at 14:55 Comment(8)
" "allowed_origins": [ "chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/" ]" -> that is a copy paste from the example page .. what is your extension id? try using the right oneNorth
@DanielBatkilin thats incorrect. Its the correct ID for that Key.Veta
@Teepeemm I have changed the tag. Thanks for pointing that out.Veta
Please add the output of console.log("" + Object.getOwnPropertyNames(chrome.runtime)); , while running through your main.html pageNorth
@DanielBatkilin PlatformOs,PlatformArch,PlatformNaclArch,RequestUpdateCheckStatus,OnInstalledReason,OnRestartRequiredReason,connect,sendMessageVeta
Try running the command from your background page .. seems you really don't have the permission set for this ( I'm not sure why ) -> sometimes google does massive changes to the API between chrome versions without prior noticeNorth
@StealthRT: i.imgur.com/LMEYNoZ.png - i used your C# code, but when i launch it it crash. see screenshot can you explain why crashing? Visual studio 2013, Windows 8.1, Browser Google chrome version 46, 47, 48, 50..Emmen
This code works for sending the Native application text to Chrome app: gist.github.com/hubplace/9465a081c786fa0f685eEmmen
I
10

Too many confusions and not well explained which really worked for me. Therefore, here i am trying to make a ``idiot proof` doc. (Please improve this version)

Goal: Windows OS, Google chrome till version 50 tested, communicate to Native application


Step 1:


Download: https://developer.chrome.com/extensions/examples/api/nativeMessaging/app.zip

Step 2:


Load the downloaded app to Google chrome

enter image description here

Step 3:


a) add the registry key

REG ADD "HKLM\Software\Google\Chrome\NativeMessagingHosts\com.google.chrome.example.echo" /ve /t REG_SZ /d "C:\\run-my-exe\\manifest.json" /f

enter image description here

b) To make a custom chrome executer, copy the following into C:\run-my-exe\run-chrome.bat:

"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --enable--native-messaging --native-messaging-hosts="com.google.chrome.example.echo=C:\\run-my-exe\\manifest.json"

Step 4: Host


a) put following to C:\run-my-exe\manifest.json

{
  "name": "com.google.chrome.example.echo",
  "description": "Chrome Native Messaging API Example Host",
  "path": "native-messaging-example-host.bat",
  "type": "stdio",
  "allowed_origins": [
    "chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/"
  ]
}

b) put following to C:\run-my-exe\native-messaging-example-host.bat

@echo off
cd %windir%\system32
start calc.exe

Step 5: How do i now run it?


a) open chrome with this script: C:\\run-my-exe\\run-chrome.bat

b) in the chrome go to chrome://apps

c) launch

via the icon

enter image description here

not as below:

enter image description here

Final Output:

enter image description here

Indophenol answered 9/10, 2015 at 14:55 Comment(8)
Thanks for these instructions. At first it wasn't working for me, but it is now. I had previously tried the app and had the same registry key in current user as well as local machine. The current user key was invalid. After deleting and re-running I have the calc popping up. One question, is there any way to call the exe with a parameter?Weisburgh
@YumYumYum, But wait, isn't Google going to remove Chrome Apps from Chrome by 2018? See blog.chromium.org/2016/08/from-chrome-apps-to-web.html so in other words, this is not going to work any more in the future? I've submitted a request at docs.google.com/forms/d/e/… to request it for inclusion in the future, but we need more people telling the Chrome team that native messaging is Important.Amphi
NO - lets shutdown the Chrome apps from Google Chrome, they are scaring the planet, as community we should rule Google chrome not Google chrome should rule us.Emmen
@YumYumYum, We need people to spam this form docs.google.com/forms/d/e/… and tell them to include the connectNative functions, otherwise the Chrome team would go ahead and ignore us again.Amphi
Btw step 3b is not needed. I've tried without --enable--native-messaging and without --native-messaging-hosts and it works. The only thing that is required is the registry installation.Amphi
@YumYumYum, Dam, it seems like this answer no longer works anymore. I get ERROR:native_process_launcher.cc(147) Failed to load manifest for native messaging host com.google.chrome.example.echo: Invalid value for name.. For your environment does the steps outlined in this answer still work?Amphi
Which version you used? maybe Google Chrome removed it. Can you try Chromium version 46 or Chromium older?Emmen
Best example there is. Step 2 could be more detailed, i.e. type chrome://extensions in the url to get to the extensions tab, then press the Load Unpacked Extensions button, then select the app folder in your solution (the app folder includes the main.js, main.html and manifest.json).Byers
S
1

You are not supposed to open main.html directly, but rather from Chrome's App Launcher at chrome://apps/

Silvereye answered 9/10, 2015 at 15:25 Comment(3)
YES - launching from chrome://apps/ it worked. But how can i launch it like http://localhost or https://myserver.com/sameapp and connect same way?Emmen
I am not completely sure, but I think you add the app to the Chrome Web Store and people install it locally.Silvereye
See that is the problem, it was never well documented how to use it from http:// or https:// . i need to use it not using chrome://apps concept.Emmen
N
0

Beware copy-paste !

https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/docs/examples/api/nativeMessaging/app/manifest.json

I would assume that's where you got your manifest. Replace the "key" with the proper one

and in "allowed_origins" use your actual extension id instead of the one from the example

https://developer.chrome.com/apps/manifest/key

There may be more errors there, but those are just the ones I catch in a first look.

North answered 9/10, 2015 at 15:50 Comment(0)
M
0

Since you are using C# project which generate an exe file as its output, the file of native-messaging-example-host.bat should not be like original example that was sth like this:

python "%~dp0/native-messaging-example-host" %*

Instead, the batch file should change as follows:

@echo off
Pushd C:\Users\h.aghajani\Desktop\host  /*Path directory of your exe*/
start native-messaging-example-host.exe /*Name of the execution file*/
Mize answered 15/11, 2015 at 6:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.