ЛОЦМАН и C# плагин

Автор OrdinaryMOTH, 29.04.14, 19:18:39

« назад - далее »

0 Пользователи и 1 гость просматривают эту тему.

OrdinaryMOTH

Помогите, пожалуйста, разобраться с плагином для Лоцман на C#?
Может, есть у кого готовый пример, чтоб хотя бы посмотреть как он должен выглядеть и где я ошибаюсь? (как плагин на delphi работает - знаю, но нужно именно на C# и с использованием MS VS 2010)

А если нет, то, дорогие форумчане, пожалуйста, объясните, как бороться с ошибкой invalid data packet?

Chaa

Посмотрите тему Написание плагинов Лоцмана на VB.NET и примеры на http://code.google.com/p/loodsmanthings/

Только учтите, что там все про довольно старый Лоцман. В новых (комплекс 2013-2014) многое по-другому. Подробнее http://achechulin.blogspot.ru/2014/04/plugin-v14.html

ЦитироватьА если нет, то, дорогие форумчане, пожалуйста, объясните, как бороться с ошибкой invalid data packet?
Ошибка означает, что вы пытаетесь создать датасет из того, что не является данными датасета. Покажите ваш код, поищем ошибку.
+ Благодарностей: 2

z-arthur

Плагин из ссылки http://code.google.com/p/loodsmanthings/ получается сложным, по-моему.
Есть шаблон проекта для Visual studio (во вложении). Его нужно поместить в папку C:\Users\<Пользователь>\Documents\Visual Studio <Версия>\Templates\ProjectTemplates, не распаковывая сам шаблон. Т.е. нужно копировать сам архив.
Он основан на утилите https://sites.google.com/site/robertgiesecke/, который позволяет подключать .Net библиотеки как обычные нативные dll-ки. И работает на .Net Framework 3.5. Чтобы заработал на других версиях, по-моему, нужно перекомпилировать исходники из ссылки в нужной версии .Net.

В ЛОЦМАН нужно подключать файл LoodsmanPluginV2 3.51 x86.dll, а не LoodsmanPluginV2 3.51.dll или LoodsmanPluginV2 3.51 x64.dll
+ Благодарностей: 5

OrdinaryMOTH

Спасибо большое за отзывчивость! С ошибкой разобралась, плагин заработал. По ссылкам еще не ходила, но попробую разобраться. Еще раз благодарю

OrdinaryMOTH

>
Цитата: z-arthur от 30.04.14, 11:49:22
>Плагин из ссылки http://code.google.com/p/loodsmanthings/ получается сложным, по-моему.
>Есть шаблон проекта для Visual studio (во вложении).

>В ЛОЦМАН нужно подключать файл LoodsmanPluginV2 3.51 x86.dll, а не LoodsmanPluginV2 3.51.dll или LoodsmanPluginV2 3.51 x64.dll
>

Очень полезный шаблон оказался, спасибо большое! А не подскажете, умный человек, как в этом плагине делать больше одного пункта меню? (т.е., меню и, допустим, 2 подменю)??


z-arthur

Не уверен, что будет работать. Но примерный код должен быть таким:

Цитировать
[DllExport("InitUserDLLCom", CallingConvention.StdCall)]
public static int InitUserDLLCom(IntPtr value)
{
  if (value != IntPtr.Zero)
  {
    byte[] menu = Encoding.GetEncoding(1251).GetBytes("1-й пункт меню\u0000");
    byte[] function = Encoding.GetEncoding(1251).GetBytes("RunModule\u0000");

    Marshal.Copy(menu, 0, value, menu.Length);
    Marshal.Copy(function, 0, (IntPtr)((int)value + 255), function.Length);

    value = value + 255*2;

    menu = Encoding.GetEncoding(1251).GetBytes("2-й пункт меню\u0000");
    function = Encoding.GetEncoding(1251).GetBytes("RunModule\u0000");

    Marshal.Copy(menu, 0, value, menu.Length);
    Marshal.Copy(function, 0, (IntPtr)((int)value + 255), function.Length);
  }
  return 2;
}
+ Благодарностей: 1

OrdinaryMOTH


спасибо, заработало!

код:

DllExport("InitUserDLLCom", CallingConvention.StdCall)]
public static int InitUserDLLCom(IntPtr value)
{
  if (value != IntPtr.Zero)
  {
    byte[] menu = Encoding.GetEncoding(1251).GetBytes("меню#1-й пункт меню\u0000");
    byte[] function = Encoding.GetEncoding(1251).GetBytes("RunModule\u0000");

    Marshal.Copy(menu, 0, value, menu.Length);
    Marshal.Copy(function, 0, (IntPtr)((int)value + 255), function.Length);

    value = (IntPtr)((int)value + 255*2);

    menu1 = Encoding.GetEncoding(1251).GetBytes("меню#2-й пункт меню\u0000");
    function1 = Encoding.GetEncoding(1251).GetBytes("RunModule1\u0000");

    Marshal.Copy(menu1, 0, value, menu.Length);
    Marshal.Copy(function, 0, (IntPtr)((int)value + 255), function1.Length);
  }
  return 2;
}

once

Здравствуйте, собираюсь разработать плагин для ЛОЦМАН на C#, делаю это впервые, так что не судите строго. Я прочитал темы форума про работу с плагинами, скачал пример плагина с http://forum.ascon.ru/index.php?PHPSESSID=jehb0jrec2emb2oqn7l7hsnkg4&action=dlattach;topic=26111.0;attach=52516 (Закирова Артура) и у меня возникло пара вопросов:
1) После подключения плагина выскакивает ошибка "Не удается привести прозрачный прокси к типу "ASCON.Loodsman.PluginDomainWorker". System.InvalidCastException", она исчезает, как только перестаешь использовать класс PluginDomainWorker для выполнения методов плагина в отдельном домене приложений. Однако при этом ЛОЦМАН начинает ругаться на строчке IPluginCall pc = (IPluginCall)Marshal.GetTypedObjectForIUnknown(IPC, typeof(IPluginCall));, т.е. если функция RunModule содержит только вывод MessageBox, то все работает. Подскажите, пожалуйста, в чем проблема.

2) Как выполнить debug проекта плагина? Срада разработки Visual Studio 2012. Я в свойствах проекта на закладке "отладка" указываю в качестве внешней программы запуск клиента ЛОЦМАН (исполняемый файл Loodsman.exe), но ни одна точка останова не срабатывает, что я делаю не так?

z-arthur

Цитировать1) После подключения плагина выскакивает ошибка "Не удается привести прозрачный прокси к типу "ASCON.Loodsman.PluginDomainWorker". System.InvalidCastException"
Я забыл написать, что файл "LoodsmanPluginV2 3.5 x86.dll" нужно переименовать в "LoodsmanPluginV2 3.5.dll", чтобы имя подключаемого файла совпадало с именем сборки. Имя сборки используется в методе CreatePluginDomain при создании отдельного домена.
Для удобства я добавлял в свойствах проекта в поле "Командная строка события после построения" следующую строку
copy "$(TargetDir)\LoodsmanPluginV2 3.5 x86.dll" "D:\sources\LoodsmanPluginV2 3.5.dll"
И добавлял ту же самую команду для всех зависимостей (Ask.dll, BOSimple.dll, LoodsmanDotNet.dll, PDMObjects.dll и др.).
Отказываться от отдельного домена приложений не стоит, т.к. в этом случае для плагина текущей папкой будет папка, где находится Loodsman.exe и в этой папке должны будут находиться все завимости. Но возможно есть другое решение (не отдельный домен).

Цитировать2) Как выполнить debug проекта плагина? Срада разработки Visual Studio 2012. Я в свойствах проекта на закладке "отладка" указываю в качестве внешней программы запуск клиента ЛОЦМАН (исполняемый файл Loodsman.exe), но ни одна точка останова не срабатывает, что я делаю не так?
Тут не смогу подсказать. Выбираю команду в Visual Studio "Отладка"->"Присоединиться к процессу...", выбираю Loodsman.exe и все точки останова срабатывают. Даже если файл называется LoodsmanPluginV2 3.5 x86.dll

once

Спасибо, Ваш плагин заработал. Не могли бы пояснить что делает утилита dllexport и почему нельзя получить сразу сборку без каких-либо переименований.

z-arthur

Потому что сборка на .Net компилируется в байт-код, а не в машинный код :) А так лучше почитать по ссылке https://sites.google.com/site/robertgiesecke/ и литературу какую-нибудь
+ Благодарностей: 1

sashka8884

Здравствуйте, подскажите пожалуйста. Я использую плагин http://forum.ascon.ru/index.php?PHPSESSID=jehb0jrec2emb2oqn7l7hsnkg4&action=dlattach;topic=26111.0;attach=52516 (Закирова Артура) и у меня такой вопрос - мне необходимо в Лоцмане считать данные из одной БД и тут же записать в другую БД. Как прописать в коде, чтобы поменять БД?

bbb

Здравствуйте, подскажите пожалуйста правильный синтаксис RunMethod.

Пишу так
var data= pc.RunMethod("CurrentUser", new []{""}); так работает, а вот где несколько параметров и разного типа не получается пробую так например
var data= pc.RunMethod("GetDBList", new []{"",""}); пишет неверное количество аргументов, пробовал по разному записывать...

z-arthur

ЦитироватьЗдравствуйте, подскажите пожалуйста правильный синтаксис RunMethod.
Попробуйте совсем без параметров. Типа такого:
var data= pc.RunMethod("GetDBList", new []{""});
Насколько я помню метод GetDBList принимает параметры errCode и errMessage.
Если не помогает попробуйте еще передать эти параметры:

int errCode = 0;
string errMess = "";
var data= pc.RunMethod("GetDBList", new []{errCode,errMess});

К сожалению, сейчас не могу это проверить.

bbb

#14
Цитата: z-arthur от 18.07.16, 11:02:48
Попробуйте совсем без параметров. Типа такого:
var data= pc.RunMethod("GetDBList", new []{""});
Насколько я помню метод GetDBList принимает параметры errCode и errMessage.
Если не помогает попробуйте еще передать эти параметры:

int errCode = 0;
string errMess = "";
var data= pc.RunMethod("GetDBList", new []{errCode,errMess});

К сожалению, сейчас не могу это проверить.
Нет так не получится. В первом случае неверное кол-во аргументов, во втором ошибка компиляции - это же массив с динамической типизацией, он не может содержать элементы разных типов.

Пробую так

int errCode=0;
string errMess="";
ArrayList pars = new ArrayList();
pars.Add(errCode);
pars.Add(errMess);
var data = pc.RunMethod("GetDBList", pars);


Ошибка "Invalid argument"


z-arthur

ЦитироватьНет так не получится. В первом случае неверное кол-во аргументов, во втором ошибка компиляции - это же массив с динамической типизацией, он не может содержать элементы разных типов.
Ой, я ошибся. Тут нужно писать так:

var data= pc.RunMethod("GetDBList", new object[] { });
+ Благодарностей: 1

bbb

Цитата: z-arthur от 18.07.16, 13:57:22
Ой, я ошибся. Тут нужно писать так:

var data= pc.RunMethod("GetDBList", new object[] { });

Спасибо. А как обратиться к полям результата?
Например функция GetInfoAboutCurrentUser возвращает набор полей, как получить значения этих полей?

z-arthur

ЦитироватьСпасибо. А как обратиться к полям результата?
Например функция GetInfoAboutUser возвращает набор полей, как получить значения этих полей?
Вы используете шаблон LoodsmanPluginV2 3.5 из вложения выше?
Кроме метода RunMethod() есть еще метод GetDataSet(). Он должен возвращать объект, который реализует интерфейс IDataSet. С ним можно работать так:

public static string GetLastVersion(string typeName, string designation)
{
    var versions = pc.GetDataSet("GetVersionList", new object[] { typeName, designation }) as IDataSet;

    if (versions.RecordCount > 0)
    {
        versions.IndexFieldNames = "_VERSION";
        versions.Last();
        return versions.ValueAsString("_VERSION");
    }
    return null;
}

Только я не уверен, возможно нужно использовать: pc.RunMethod(...) as IDataSet. Код выше использовался для работы с ЛОЦМАН без использования LoodsmanPluginV2 3.5. Нужно проверять.
На сколько я помню RunMethod() можно использовать, когда API-метод не возвращает значение или когда возвращает строку.

bbb

Цитата: z-arthur от 18.07.16, 14:32:28
Вы используете шаблон LoodsmanPluginV2 3.5 из вложения выше?
Кроме метода RunMethod() есть еще метод GetDataSet(). Он должен возвращать объект, который реализует интерфейс IDataSet. С ним можно работать так:

public static string GetLastVersion(string typeName, string designation)
{
    var versions = pc.GetDataSet("GetVersionList", new object[] { typeName, designation }) as IDataSet;

    if (versions.RecordCount > 0)
    {
        versions.IndexFieldNames = "_VERSION";
        versions.Last();
        return versions.ValueAsString("_VERSION");
    }
    return null;
}

Только я не уверен, возможно нужно использовать: pc.RunMethod(...) as IDataSet. Код выше использовался для работы с ЛОЦМАН без использования LoodsmanPluginV2 3.5. Нужно проверять.
На сколько я помню RunMethod() можно использовать, когда API-метод не возвращает значение или когда возвращает строку.
Да я использую шаблон LoodsmanPluginV2 3.5.
Попробовал  так var versions = pc.GetDataSet("GetVersionList", new object[] { typeName, designation }) as IDataSet;
не находит определение интерфейса IDataSet

z-arthur

Он находится в каком то из dll. По-моему в PDMObjects.dll. Нужно добавить его в проект и добавить namespace с помощью using. Возможно вам еще нужно будет пересоздать эти dll. Так как, для разных версий ЛОЦМАН они разные, могут появиться новые методы и интерфейсы.