Кросс-браузер, кроссплатформенный собственный обмен сообщениями с использованием Xamarin Ma c, C# - PullRequest
7 голосов
/ 11 февраля 2020

Я попытался воссоздать пример для подключения к моему приложению Xamarin Ma c с использованием расширения chrome, которое я буду использовать в качестве магистрали для всех других браузеров, но оно не работало со следующей ошибкой:

Ошибка при взаимодействии с собственным хостом обмена сообщениями.

Документация кажется простой на бумаге, но не так проста в реальной жизни.

Вот мои Функции чтения и прослушивания (отличные примеры, https://github.com/anewtonlevey/NativeMessaging):

    public void Listen()
    {

        JObject data;
        while ((data = Read()) != null)
        {
            ProcessReceivedMessage(data);
        }

    }




    private JObject Read()
    {
        try
        {
            Stream stdin = Console.OpenStandardInput();


            byte[] lengthBytes = new byte[4];
            stdin.Read(lengthBytes, 0, 4);


            var buffer = new char[BitConverter.ToInt32(lengthBytes, 0)];

            using (var reader = new StreamReader(stdin)) while (reader.Peek() >= 0) reader.Read(buffer, 0, buffer.Length);
            return JsonConvert.DeserializeObject<JObject>(new string(buffer));


        }
        catch (Exception e)
        {
            Console.WriteLine("Read error: {0}", e);
            return null;
        }
    }

Из моей основной функции я вызываю их с помощью следующего:

        host = new ExtendedHost();


        host.Listen();

Отметим, что я использую собственный обмен сообщениями из форм Xamarin для приложения macOS, поскольку, с моей точки зрения, это может быть порядком байтов, как предполагает следующая документация:

Ошибка при взаимодействии с собственным хостом обмена сообщениями:

https://developer.chrome.com/extensions/nativeMessaging#native -messaging-host-protocol

Похоже, что открывается другое окно моего приложения C#, когда я отправляю сообщение с веб-расширения , жадный При этом, кажется, что ошибка возникает на этапе чтения.

Помощь очень ценится.

Спасибо.

Редактировать:

Я предложил порядковый номер, поскольку документация предполагает, что ответ также должен быть правильным или сделает весь процесс поврежденным, как предложено в Собственный протокол обмена сообщениями делает c, но это не проблема, так как я все еще могу анализировать отправленные данные:

https://developer.chrome.com/apps/nativeMessaging#native -messaging-host- протокол

Я видел, что ответ имеет какое-то отношение к нему, и что функция, используемая для отправки сообщения (как и предполагалось, ошибка в ответе может вызвать общую ошибку), может вызвать проблему, или что Console.StandardInput () не работает так, как предлагается, но я так не думаю.

Я думаю, что попытка подключиться к работающему приложению вызвала проблему, так как я использовал ps aux | grep app_name и поместите путь в файл хоста.

Вот упоминание в протоколе:

Собственный протокол обмена сообщениями Chrome запускает каждый собственный хост обмена сообщениями в отдельный процесс и связывается с ним с помощью стандартного ввода (stdin) и стандартного вывода (stdout).

Я также видел этот ответ от Xan в другом посте, который собственный обмен сообщениями не может прикрепить к запущенным процессам и Chrome должен запустить процесс:

Поговорить с приложением MacOSX из Chrome Расширение

Не забывайте, что я использую собственный API обмена сообщениями с Xamarin macOS в Режим отладки, и что мое приложение является приложением MacOS.

По этому вопросу приветствуется дополнительная информация, например:

  • способ получить путь к приложению, который Chrome может использовать с его собственным API обмена сообщениями
  • решение для получения этого пути программно, которое будет работать на всех платформах, если это возможно, как Console.WriteLine (Path.Combine (Assembly.GetExecutingAssembly (). Location)); не добились цели.

Конечно, если это то, что, как вы думаете, вызывает проблему.

Заранее спасибо!

РЕДАКТИРОВАТЬ:

При отправке вывода в stderr я получил следующую ошибку:

Ошибка чтения: System.NotSupportedException: поток не поддерживает чтение в System.IO.FileStream.Read (массив System.Byte [], смещение System.Int32, System. Число Int32) [0x0002e] в /Library/Frameworks/Xamarin.Mac.framework/Versions/Current/src/Xamarin.Mac/mcs/class/corlib/System.IO/FileStream.cs:493

Может быть, Console.OpenStandardInput не работает кроссплатформенно? И если да, то какой может быть другой метод для анализа стандартного ввода, поскольку я видел, что каналы могут работать, но я не уверен, могут ли они быть развернуты кроссплатформенным способом.

Я не получил любая ошибка или вывод при чтении, только вышеуказанная ошибка при запуске приложения. Для меня OpenStandardInput кажется виновником.

Любые мысли приветствуются! Спасибо

1 Ответ

0 голосов
/ 15 февраля 2020

По сути, первые 32 бита, отправленные с расширения, соответствуют длине сообщения в собственном порядке.

Поскольку первые 32 бита имеют тип int, и я попытался проанализировать JSON объекты, Ошибка при обмене данными с собственным хостом обмена сообщениями . В документации упоминается, что проблема связана с нарушением протокола Native Messaging.

Хуже всего то, что я видел это на примере Python, но подумал, что это было реализовано программистом, который это сделал.

Я наткнулся на этот поток в переполнении стека, что помогло подтвердить, (Chrome Приложение не может связаться с собственным хостом на windows).

Для отладки Chrome гораздо более многословно, запустите Chrome с - enable-logging = stderr --v = 1 в командной строке, и все stderr будут выведены туда.

в документации упоминается об этом, но примеры, найденные здесь и там с использованием C#, не включают их.

Если у меня будет время, я подтвердлю эту проблему, отредактировав этот ответ, и предоставлю код для заставить это работать в Visual Studio для macOS.

Edit

Мне удалось заставить это работать несколько дней go. Я изменил код так, чтобы он работал без l oop, так как StreamReader читает stdin до конца, таким образом, не запрашивая некоторое время l oop (это привело к зависанию моего предыдущего кода). Метод SendMessage также отличается от других, которые можно увидеть в других примерах. Меньше строк и работает просто отлично.

Мой рабочий пример:

public void Listen()
{


    JObject data;

    //while ((data = Read()) != null)
    //{
    //    ProcessReceivedMessage(data);
    //}

    if((data = Read()) != null)
    {
        string message = ProcessReceivedMessage(data);
        SendMessage(message);
    }
}


    private JObject Read()
    {

        Stream stdin = Console.OpenStandardInput();

        byte[] lengthBytes = new byte[4];
        stdin.Read(lengthBytes, 0, lengthBytes.Length);

        char[] buffer = new char[BitConverter.ToInt32(lengthBytes, 0)];

        var reader = new StreamReader(stdin);
        //int messageLength =
        reader.Read(buffer, 0, buffer.Length);

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





    public void SendMessage(JToken data)
    {
        var bytes = Encoding.UTF8.GetBytes(data.ToString(Formatting.None));
        var lengthBytes = BitConverter.GetBytes(bytes.Length);
        var stdout = Console.OpenStandardOutput();

        stdout.Write(lengthBytes, 0, 4);
        stdout.Write(bytes, 0, bytes.Length);
        stdout.Flush();
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...