Управление форвардом из Си++

Здесь обсуждаются любые продукты компании СофтЛаб-НСК для телевизионного вещания (Форвард Т, Форвард ТС, Форвард Голкипер, Форвард Рефери, Форвард Офис, Форвард Инжест)

Модераторы: ElenVR, Людмила, PR

Ответить
int
Сообщения: 21
Зарегистрирован: 03 июн 2013 14:12

Сообщение int »

Windows 7 32 бита, была установлена одним из инженеров. Зачем и для чего он поставил .NET Framework 4 пока не знаю. Увижу его - спрошу, но к делу это отношения не имеет. Активации компонентов для 3.5 в настройках компонентов Windows были отключены, точно также, как вы описали на сайте для Windows 8. Почему это произошло, тоже понятия не имею. Или Windows 7 так поставилась. Или установка 4-ого фреймворка их отключила.

Попробую еще раз более детально описать проблему.
1. Запускаем Forward, ловим ошибку как на скриншоте. Закрываем ошибку, открывается OnAIR (но без возможности управления им).
2. Проверили галочки в Программы и компоненты, они не стояли. Поставили. До перезагрузки Windows проверили OnAIR - ошибка. Запустил regasm для SLMessageRemote2.dll и regsvr32 для SLMessageQueue2.dll библиотек. Проверили OnAIR - ошибки нет, все работает.
3. Обновили Forward, перезагрузились, ошибка снова появляется. Повторные махинации с regasm и regsvr32 не проходят.
4. Нашли установленным .NET 4. Попробовали его удалить. Удалили, перегрузили, все работает.

Возможных вывода тут 2:
1) Проблема с активациями компонентов есть не только у Windows 8, но иногда (по не до конца ясным причинам) и у Windows 7.
2) Forward MessageServer не очень хочет работать, пока на машине стоит .NET Framework 4. По крайней мере MessegeServer как часть всей системы (хотя его служба все это время была запущена, т.е. скорее всего работала).

Подчеркну, эти выводы мы (я и коллега) сделали на основе опытов, которые вы можете прочитать выше. Механизм возникновения ошибок на уровне какая библиотека какую ошибку вызвала, какая не смогла загрузиться или что там еще могло произойти - я не знаю. Факт в том, что даже моя программа не смогла сделать CoCreateInstance. Сами COM хвосты, по которым библиотека COM находит нужную DLL и подгружает в программу, в реестре были. Я недавно прочитал книгу по COM, дабы заполнить пробелы в этой области, так что, что там должно быть представляю. Т.е. библиотека зарегистрирована, не смотря на код ошибки, но загрузится не смогла.

>Какую версию ПО ставили?
А вот какая есть на сайте, такую и ставили - ForwardTA. Плата FD422.
Даниленко Сергей
Сообщения: 7093
Зарегистрирован: 26 фев 2004 09:53
Откуда: Techsupport SoftLab-NSK

Сообщение Даниленко Сергей »

>Какую версию ПО ставили?
А вот какая есть на сайте, такую и ставили - ForwardTA. Плата FD422.
Хороший ответ. Вам не приходило в голову, что версии ПО на сайте меняются? Толку от вашего ответа нет никакого.
vd
Сообщения: 2311
Зарегистрирован: 05 мар 2003 19:21

Сообщение vd »

Т.е. библиотека зарегистрирована, не смотря на код ошибки, но загрузится не смогла.
А вот это не факт. Если не проходит CoCreateInstance, то библиотека как раз, скорее всего, не зарегистрирована. Особенно если код ошибки "Класс не зарегистрирован". И если ручная регистрация решает проблему - тем более. В реестре библиотека не в одном месте при регистрации прописывается.

А еще у сервиса есть EXE-часть, а есть DLL (прокси). Могут быть и другие причины подобных проблем, при этом обе части зарегистрированы, но класс все равно не создается.
Даниленко Сергей
Сообщения: 7093
Зарегистрирован: 26 фев 2004 09:53
Откуда: Techsupport SoftLab-NSK

Сообщение Даниленко Сергей »

Похоже, что мы разобрались с проблемой.
Дело не в том, что не регистрируются компоненты SLMessageServer. Проблема вовсе не в этом - все компоненты нормально регистрируются.
Проблема в другом. SLMessageServer при своей работе использует другой наш сервис. Может возникнуть ситуация, что к моменту запуска SLMessageServer тот другой сервис ещё не стартовал. В таком случае объекты из SLMessageServer не создаются (хотя они и зарегистрированы в системе правильным образом)
Добавили в SLMessageServer зависимости на другие сервисы.
AntonChik
Сообщения: 83
Зарегистрирован: 16 фев 2010 15:32
Откуда: г. Красноярск

Сообщение AntonChik »

Здравствуйте.
Возник такой вопрос. Имеется проект с одним титровальным объектом, содержащим один элемент, АнимЛого, с загруженным в него файлом анимации (баннер). Не зациклен.
Программно запускаю этот объект. Он нормально отрабатывает.
Но при повторном запуске уже не запускается. Как я понял, потому что задание уже очистилось.
Если при первом запуске успеть(по таймеру, например) остановить этот АнимЛого(например за секунду до его конца), то повторно он запустится (задание не очистится). Но это как-то некрасиво.
Можно конечно программно каждый раз перед запуском загружать ему задание, но интересует именно случай, когда один раз загрузили задание в проекте и все.

Собственно вопрос, возможно ли сделать чтоб задание не очищалось после успешного воспроизведения? Или есть еще какие-то варианты?
Даниленко Сергей
Сообщения: 7093
Зарегистрирован: 26 фев 2004 09:53
Откуда: Techsupport SoftLab-NSK

Сообщение Даниленко Сергей »

Если задание в титровальном элементе не зацикленно, то оно показывается один раз и сбрасывается. Поэтому задание нужно каждый раз грузить перед началом показа.
int
Сообщения: 21
Зарегистрирован: 03 июн 2013 14:12

Сообщение int »

И снова здравствуйте!

Хотелось бы уточнить. Возможно ли контролировать действия совершенные в Forward в другом направлении? Т.е. отправить команду можно, например, "Shedule.Start". А мне нужно наоборот, повесить какой-то цикл обработки сообщений, чтобы туда приходили команды с Forward. Т.е. нажал режиссер на "Shedule.Start" - мне пришло сообщение об этом. На самом деле интересует только "Shedule.Start", другие команды не так нужны.
Игорь Таранцев
Сообщения: 493
Зарегистрирован: 04 янв 2004 12:45
Откуда: СофтЛаб-НСК

Сообщение Игорь Таранцев »

Вариант №1 - использовать команды зеркалирования:
1) Ваше приложение создает очередь для приема сообщений.
2) В OnAir включается отправка команд в эту очередь.
3) Ваше приложение получает все команды, которые были выполнены оператором в OnAir, "отлавливает" нужную команду и что-то делает.

Вариант №2 - поскольку интересует только команда Start, выполняемая режисером, то можно использовать GPI-события. А именно, сделать внешнюю GPI-кнопку, которую режисеру будет очень удобно нажимать :) А уже в OnAir и в Вашем приложении настроить обработку этой кнопки - OnAir должен выполнить команду Start, а Ваше приложение - нужные действия.
int
Сообщения: 21
Зарегистрирован: 03 июн 2013 14:12

Сообщение int »

Как я понял из примера, надо передать манипулятор окна (HWND) при создании очереди, чтобы OnAIR присылал сообщение WM_USER о новом сообщении в очереди. Только вот ничего не приходит. Есть какие-то особые требования к окну и параметрам WParam и LParam?

Добавлено:
Сейчас засунул пару GetCounts и GetMessage (если предыдущая функция вернула что в очереди есть сообщения) в while (GetMessage(&msg, NULL, 0, 0)). Т.е. в основной цикл обработки сообщений. И очередь все время пустая, даже если я делаю, например, запрос "Player.Titling". Т.е. похоже что Forward неправильно настроен. Какие мои действия? В настройках зеркалирования стоит "Принимать и исполнять команды". Даже пробовал "Посылать команды машинам" и указывать в качестве машины "localhost", хотя на сколько я понимаю это для передачи сообщений другому Forward где-то еще.

Не совсем по теме, но хотелось бы отметить, что передача сообщений другому Forward работает. Приложение из примеров на C# (которое про SLMessageServer) не работает и валится с ошибкой "Сбой при получении производства объектов класса COM для компонента с CLSID {F392FA1B-1348-4AAD-8A0E-F1B0FFE6A893} в результате следующей ошибки: 80040154", хотя мое на С++ прекрасно отправляет команду "Shedule.Start" и не жалуется ни на что. А во вкладке RPM (не знаю что, но на всякий случай) при выборе строчки "local" появляется внизу надпись "API error 4 340 (0x80040154): Класс не зарегистрирован". Версия Forward: Forward Tx Lite 1.24.63
vd
Сообщения: 2311
Зарегистрирован: 05 мар 2003 19:21

Сообщение vd »

Приложение из примеров на C# (которое про SLMessageServer) не работает и валится с ошибкой "Сбой при получении производства объектов класса COM для компонента с CLSID {F392FA1B-1348-4AAD-8A0E-F1B0FFE6A893} в результате следующей ошибки: 80040154"
Система используется 32-разрядная или 64-разрядная?
А во вкладке RPM (не знаю что, но на всякий случай) при выборе строчки "local" появляется внизу надпись "API error 4 340 (0x80040154): Класс не зарегистрирован".
Эта вкладка ответственна за воспроизведение фрагментов задержанного видео, записанного в хранилища (система PostPlay, продукт Форвард ТП). В ПО Forward Tx Lite компоненты PostPlay, скорее всего, отсутствуют, поэтому и появляется такая ошибка. К SLMessageServer и обсуждаемым проблемам это никакого отношения не имеет.
Версия Forward: Forward Tx Lite 1.24.63
Что это на номер версии? Версия программы OnAir?

Номер версии ПО смотрится так:
http://www.softlab-nsk.com/rus/forward/qna.html#a2_14
Игорь Таранцев
Сообщения: 493
Зарегистрирован: 04 янв 2004 12:45
Откуда: СофтЛаб-НСК

Сообщение Игорь Таранцев »

int писал(а):Как я понял из примера, надо передать манипулятор окна (HWND) при создании очереди, чтобы OnAIR присылал сообщение WM_USER о новом сообщении в очереди. Только вот ничего не приходит. Есть какие-то особые требования к окну и параметрам WParam и LParam?
Скорее всего проблема с именем Вашей очереди. Как я понимаю очередь создается на том же ПК, где запущен OnAir. В этом случае Вы не сможете создать очередь с тем же номером, что и очередь самого OnAir-а. Вам нужно в OnAir назначить другой номер очереди, а в OnAir настроить передачу команд в номер именно Вашей очереди.
Например, если OnAir имеет индекс #1, то можно создать очередь с именем "FDOnAir2", и в OnAir выбрать сервер "localhost" и индекс очереди "2" (предполагается, что OnAir с индексом #2 не запускается).
int
Сообщения: 21
Зарегистрирован: 03 июн 2013 14:12

Сообщение int »

Сделал так:

Код: Выделить всё


    // create window
    static const wchar_t* class_name = L"VE_FORWARD_HOOK";
    WNDCLASSEX wx = {};
    wx.cbSize = sizeof(WNDCLASSEX);
    wx.lpfnWndProc = WindowProc;
    wx.hInstance = 0;
    wx.lpszClassName = class_name;
    if (RegisterClassEx(&wx)) {
        hWindow = CreateWindowEx(0, class_name, L"forward_hook_wnd", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
    }
...
LRESULT CALLBACK WindowProc
    (
        _In_  HWND /*hwnd*/,
        _In_  UINT uMsg,
        _In_  WPARAM /*wParam*/,
        _In_  LPARAM /*lParam*/
    )

{
    if (uMsg == WM_USER + 100) {
        if (g_windowObject) {
            // отправка сообщения в другой класс, где читается сообщение из очереди - GetMessage
            QEvent *event = new QEvent&#40;static_cast<QEvent&#58;&#58;Type>&#40;QEvent&#58;&#58;User + 1&#41;&#41;;
            QApplication&#58;&#58;postEvent&#40;g_windowObject, static_cast<QEvent*>&#40;event&#41;, 0&#41;;
        &#125; else &#123;
            qDebug&#40;&#41; << "hWnd is not defined!";
        &#125;
    &#125;

    return 0;
&#125;
...
    // create connection
    ISLMSConnection *pConnection;
    HRESULT hr = &#58;&#58;CoCreateInstance&#40;CLSID_SLMSConnection, NULL, CLSCTX_ALL,
                                    IID_ISLMSConnection, &#40;void**&#41;&pConnection&#41;;
    if &#40;FAILED&#40;hr&#41;&#41; &#123;
        err_state = true;
        return;
    &#125;
    // create queue
    SLMSErrorCode ErrorCode;
    HRESULT ResultCode;
    HWND NotifyWindow = hWindow;
    long NotifyCmd = WM_USER + 100, NotifyWParam = 0, NotifyLParam = 0;
    BSTR bstrQName = &#58;&#58;SysAllocString&#40;L"FDOnAir2"&#41;; // IMPORTANT&#58; not "FDOnAir1"
    IUnknown *pUnk = NULL;
    hr = pConnection->CreateQueue&#40;&ErrorCode, &ResultCode, bstrQName,
                                  &#40;long&#41;NotifyWindow, NotifyCmd, NotifyWParam, NotifyLParam, &pUnk&#41;;
    &#58;&#58;SysFreeString&#40;bstrQName&#41;;
В настройках Forward указал отправлять сообщения в окно с ID 2 (localhost #2).
Результата по-прежнему нет. Окно для приема сообщений должно быть видимым?

Добавлено:
Во второй программе, где окно сделал видимым сообщения WM_USER + 100 приходят в окно. Вот такой код:

Код: Выделить всё

case WM_USER + 100&#58;
	&#123;
		long sentLo, sentHi;
		long MessId = 1;
		BSTR bBody, ReplyTo;
		SLMSErrorCode ErrorCode;
		SLMSMessageType MessType;
		HRESULT ResultCode;
		BSTR bToQueue;
		BSTR bSubj;
		BSTR bToMachine;
		pQueue->GetMessage&#40;&ErrorCode, &ResultCode, &MessType, &MessId, &ReplyTo,
			&sentLo, &sentHi, &bToMachine, &bToQueue, &bSubj, &bBody&#41;;
		if &#40;/*res != 0 ||*/ ErrorCode != mcSuccess&#41; &#123;
			// Сообщение не получено, ничего освобождать не надо
			break;
		&#125;
		// проверяем тип сообщения
		if &#40;MessId == mtError&#41; &#123;
			// Сообщение об ошибке
		&#125;
		else if &#40;MessId == mtMessage || MessId == mtNotify&#41; &#123;
			// Сообщение от кого-то
			//Work&#40;FromMachine, FromQueue, Subject, Body&#41;;
			int t = 5 + 7; // махинации для отладочных стопов
			t = 7;
			std&#58;&#58;cout << t;
		&#125;
		else &#123;
			// Служебное сообщение
		&#125;
		break;
	&#125;
Все сообщения приходят с MessId == mtIgnore

Добавлено:
А собственно, и ладно, что mtIgnore. Главное, что тело сообщения содержит нужную команду. Моя проблема была в том, что очередь называлась "TestQueue", сейчас переименовал "FDOnAir2". Не сразу дошло, что моя программа должна притвориться форвардом.
vd
Сообщения: 2311
Зарегистрирован: 05 мар 2003 19:21

Сообщение vd »

Не Форвардом, а программой FDOnAir. Откуда программа FDOnAir сама догадается, что нужно посылать сообщения в очередь с произвольным названием?

С другой стороны, если в текущем SDK ни слова про это нет, то имеет смысл добавить, наверное.
int
Сообщения: 21
Зарегистрирован: 03 июн 2013 14:12

Сообщение int »

Не Форвардом, а программой FDOnAir.
Ну я просто привык так ее называть, названием всего продукта. Извините за неточность.
Откуда программа FDOnAir сама догадается, что нужно посылать сообщения в очередь с произвольным названием?
Сейчас у меня более полное понимание концепции очередей.

А никак нельзя сделать так, чтобы FDOnAir посылал окну NotifyWindow сообщения, с учетом того что оно невидимое? Мне просто очень не хочется доверять режиссерам еще одну программу, которую они могут случайно закрыть или еще что-то с ней сделать. Я не особо помню, да и не все знаю, что касается WinAPI и окон Windows, так что не представляю возможно это или нет. Но вроде есть специальная возможность сделать невидимое окно с родительским HWND_MESSAGE именно для приема сообщений и все.
vd
Сообщения: 2311
Зарегистрирован: 05 мар 2003 19:21

Сообщение vd »

Мне просто очень не хочется доверять режиссерам еще одну программу, которую они могут случайно закрыть или еще что-то с ней сделать.
Перехватите в своей программе все сообщения, ответственные за закрытие окна - WM_CLOSE, например, и в обработке этого сообщения ничего не делайте. Или по этому сообщению делайте minimize окна программы. Также, если это диалоговое приложение, перехватите OnOK и OnCancel и тоже в них ничего не делайте, иначе программу можно будет закрыть случайным нажатием Enter или Esc.

Программу тогда возможно будет закрыть только убиванием ее в списке процессов. То есть, случайно закрыть ее не получится, и даже специально - придется сильно постараться. А режиссерам объясните, что за убивание программ в списке процессов (диспетчере задач) последуют экономические санкции их зарплате от Обамы и Меркель ;-)

Можно при попытке закрытия окна программы вывешивать страшное предупреждающее сообщение (например, про последствия в виде санкций - см. выше). Также сразу после запуска программа может свое окно минимизировать, чтобы не мозолить глаза. Много чего можно придумать, на самом деле.
А никак нельзя сделать так, чтобы FDOnAir посылал окну NotifyWindow сообщения, с учетом того что оно невидимое?
Насколько я знаю, какие-либо переделки SLMessageServer не планируются. Его разработчик сильно занят другими задачами. Во всяком случае, Вам будет на порядок быстрее доработать свою программу (см. выше), чем ждать каких-то доделок от нас. Я точно не знаю, но, подозреваю, отправка сообщений только видимым окнам делается не просто так.
Ответить