Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / PowerBuilder Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 PBNI Wizard  [new]
AIS
Member

Откуда:
Сообщений: 1695
Есть PBNIWizard (в комплекте PB10.5), но как понимаю старый, т.к. инстал при старте выдает ошибку:
---------------------------
Windows Script Host
---------------------------
Сценарий: C:\Program Files (x86)\Sybase\PowerBuilder 10.5\SDK\PBNI\Wizards\VCWizards\PBNIWizard8\install.wsf
Строка: 7
Символ: 8
Ошибка: Неверная ссылка на корень в разделе реестра "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\8.0\Setup\VC\ProductDir".
Код: 80070002
Источник: WshShell.RegRead
-------------------------

На ПК VS2017, NET 4.6, W7 (64).

Что сделать, чтобы установить PBNIWizard и пользоваться?
27 июл 17, 11:03    [20678933]     Ответить | Цитировать Сообщить модератору
 Re: PBNI Wizard  [new]
spas2001
Member

Откуда: Тамбов--->Москва-->Тамбов-->Москва-->Тамбов
Сообщений: 2010
Он на директорию похоже ругается
Попробуйте поставить в корень диска C:
27 июл 17, 11:58    [20679225]     Ответить | Цитировать Сообщить модератору
 Re: PBNI Wizard  [new]
AIS
Member

Откуда:
Сообщений: 1695
spas2001
Он на директорию похоже ругается
Попробуйте поставить в корень диска C:

Эт я понимаю.
Возможно будет достаточно в файлах deploy.bat и install.wsf скорректировать соответствующие названия и значения переменных, по аналогии различий между одноименными файлами в каталогах PBNIWizard (7.0) и PBNIWizard8 (8.0).
В первом ссылка на:
"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\7.0\Setup\VC\ProductDir"
а во втором ссылка на:
"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\8.0\Setup\VC\ProductDir"

Но у меня VS2017 (15.0) и W7 (64) и такого раздела реестра нет.

К тому же, в обоих вариантах файлов указывается соответственно:
"C:\Program Files\Microsoft Visual Studio 7"
"C:\Program Files\Microsoft Visual Studio 8"
а у меня скорее всего надо указать:
"C:\Program Files (x86)\Microsoft Visual Studio"
а может и продолжить путь по имеющейся цепочке:
"C:\Program Files (x86)\Microsoft Visual Studio\2017"
т.к. другого не вижу.
27 июл 17, 12:22    [20679340]     Ответить | Цитировать Сообщить модератору
 Re: PBNI Wizard  [new]
Hennadiy
Member

Откуда:
Сообщений: 8
AIS, возможно я не прав, но судя по всему проблема в несовместимости 32/64 битных приложений. Как вариант, смоделировать ситуатуцию на 32 виртуалке.
27 июл 17, 17:14    [20680571]     Ответить | Цитировать Сообщить модератору
 Re: PBNI Wizard  [new]
spas2001
Member

Откуда: Тамбов--->Москва-->Тамбов-->Москва-->Тамбов
Сообщений: 2010
Сам создай ключи, в чем проблема?
Ну и поставить соота=ветственно VC 7.0 и 8.0
27 июл 17, 21:13    [20680984]     Ответить | Цитировать Сообщить модератору
 Re: PBNI Wizard  [new]
AIS
Member

Откуда:
Сообщений: 1695
spas2001
Сам создай ключи, в чем проблема?
Ну и поставить соота=ветственно VC 7.0 и 8.0

Проблема в том, что для VS2017 не знаю куда, что прописывать, чтобы была "правильная" связь с РВ (установка PBNI).
Задачу решил установкой VS2015. Хотя для него чуть пришлось пути допилить (таки W7 и х64 в тандеме дали свое Г), но все получилось.
ПС. Конечно жалко, что такое с VS2017 не получилось, да и хрен с ним.
27 июл 17, 22:45    [20681111]     Ответить | Цитировать Сообщить модератору
 Re: PBNI Wizard  [new]
AIS
Member

Откуда:
Сообщений: 1695
Подниму тему, нужен совет или комментарий по опыту.
Сделал внешнее решение одной и той же задачи при помощи DLL с экспортированной функцией и через PBX. И то и другое работает. Возник вопрос:
Что предподчительней использовать в проекте DLL или PBX?
26 мар 18, 12:46    [21285959]     Ответить | Цитировать Сообщить модератору
 Re: PBNI Wizard  [new]
Anatoly Moskovsky
Member

Откуда: Odessa
Сообщений: 6610
AIS,

C PBNI больше возможностей. Например можно напрямую обращаться к объектам и вызывать функции ПБ из С++.
Но с ним больше мороки по поддержке при выходе новых версий ПБ.
Так что если возможностей DLL хватает то есть смысл именно этот вариант использовать, а перейти на PBNI только когда вознитнет необходимость.
26 мар 18, 16:37    [21287010]     Ответить | Цитировать Сообщить модератору
 Re: PBNI Wizard  [new]
AIS
Member

Откуда:
Сообщений: 1695
Anatoly Moskovsky,

Спасибо за совет. Да, согласен, с PBX хлопот больше, но есть и не малые плюсы.
На счет проблем с выходом новых версий РВ, то это наверное решающий фактор, т.к. в последних версиях PBX уже не идет в комплекте, а ориентир на VS, если я не ошибаюсь.

А если смотреть с точки зрения защиты кода, т.е. спрятать, то DLL снова проигрывает, или без разницы?
26 мар 18, 17:20    [21287208]     Ответить | Цитировать Сообщить модератору
 Re: PBNI Wizard  [new]
Anatoly Moskovsky
Member

Откуда: Odessa
Сообщений: 6610
AIS
А если смотреть с точки зрения защиты кода, т.е. спрятать, то DLL снова проигрывает, или без разницы?

Без разницы. И то и то - DLL
26 мар 18, 21:48    [21287804]     Ответить | Цитировать Сообщить модератору
 Re: PBNI Wizard  [new]
AIS
Member

Откуда:
Сообщений: 1695
Anatoly Moskovsky
AIS
А если смотреть с точки зрения защиты кода, т.е. спрятать, то DLL снова проигрывает, или без разницы?

Без разницы. И то и то - DLL

С этим, конечно, не спорю. Но если только просто поверхностно взглянуть на экспортируемые функции DLL и PBX, то это большая разница: у DLL - все как на ладони*, а у PBX - уй поймешь* о чем они. Не правда ли?
26 мар 18, 22:52    [21287976]     Ответить | Цитировать Сообщить модератору
 Re: PBNI Wizard  [new]
AIS
Member

Откуда:
Сообщений: 1695
Создаю в PBX функцию вычисления MD5 из переданного строкового аргумента:
+ MD5 не работает с входящим аргументом
HCRYPTPROV CryptProv;
HCRYPTHASH CryptHash;
BYTE BytesHash[16];
DWORD dwHashLen = 16;
_TCHAR theOut[MAX_PATH];

/* если задаю аргумент так, работает правильно */
// char *data = "test f_md5";
/* если беру входящий аргумент "test f_md5" из функции f_md5(ref string), то не работает правильно */
////////
char *data;
LPCTSTR lptheInput = NULL;
pbstring val = ci->pArgs->GetAt(0)->GetString();
lptheInput = m_pSession->GetString(val);
data = (LPSTR)lptheInput;
///////

BYTE *pbBuffer = (BYTE*)data;
DWORD dwBufferLen = strlen(data);
if (CryptAcquireContext(&CryptProv,
	NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET))
	{
		if (CryptCreateHash(CryptProv, CALG_MD5, 0, 0, &CryptHash))
		{
			if (CryptHashData(CryptHash, pbBuffer, dwBufferLen, 0))
			{
				if (CryptGetHashParam(CryptHash, HP_HASHVAL, BytesHash, &dwHashLen, 0))
				{
					CHAR hexcharset[] = "0123456789abcdef";
					for (int j = 0; j < dwHashLen; j++)
					{
						theOut[j*2] = hexcharset[BytesHash[j] >> 4];
						theOut[(j*2)+1] = hexcharset[BytesHash[j] & 0x0F];
					}

				}
				else {
					//"Error CryptGetHashParam";
				}
			}
			else {
				//"Error CryptHashData";
			}
		}
		else {
			//"Error CryptCreateHash";
		}
	}
	else {
		//"Error CryptAcquireContext";
	}
	CryptDestroyHash(CryptHash);
	CryptReleaseContext(CryptProv, 0);

         ci->returnValue->SetString(theOut);

}
return pbxr;

Где ошибка или как правильно сделать?
29 мар 18, 10:40    [21295290]     Ответить | Цитировать Сообщить модератору
 Re: PBNI Wizard  [new]
Anatoly Moskovsky
Member

Откуда: Odessa
Сообщений: 6610
AIS
data = (LPSTR)lptheInput;

data - указатель на строку в кодировке ANSI
lptheInput - указатель на строку в кодировке Unicode (UTF-16)

Во-первых, нельзя так принудительно менять тип, не преобразовав данные (там потом следующий strlen() неверно отрабатывает, и может еще какие-то эффекты).
Во-вторых, вам надо решить в каком формате вы будете строку передавать в MD5 (UTF-16 или UTF-8). ANSI - не всегда годится, т.к. будут потери символов не входящих в текущую кодовую страницу.
В-третьих, надо помнимать что MD5 от одной и той же строки в ANSI, UTF-16 и в UTF-8 будут разные.
Эта тема уже обсуждалась где-то здесь. Мое мнение - если MD5 потом передается в третьи приложения, то лучше UTF-8, т.к. для английского текста ANSI и UTF-8 совпадают, т.е. больше вероятность совместимости.
В любом случае предлагаю преобразование кодировки делать на стороне ПБ функцией Blob() со вторым параметром - кодировкой. А в модуль передавать blob и его длину, и уже его хешировать.
29 мар 18, 12:34    [21295769]     Ответить | Цитировать Сообщить модератору
 Re: PBNI Wizard  [new]
AIS
Member

Откуда:
Сообщений: 1695
Anatoly Moskovsky,

премного благодарен, таки да, с blob и UTF-8 все встало на свои места.
Еще буквально недавно Вы мне это же советовали в другой ситуации, видать не внял, все string примеряю...))
Спасибо за помощь.
29 мар 18, 18:02    [21297286]     Ответить | Цитировать Сообщить модератору
 Re: PBNI Wizard  [new]
AIS
Member

Откуда:
Сообщений: 1695
Еще вопрос, на который не могу найти ответа.

Получаю в PB экземпляр класса и передаю его в PBNI:
/* например */
ClassDefinition lcd 
lcd = nuo_test.ClassDefinition 

а как потом получить свойства класса на стороне PBNI? Например, lcd.LibraryName.
31 мар 18, 11:53    [21301683]     Ответить | Цитировать Сообщить модератору
 Re: PBNI Wizard  [new]
avs63
Member

Откуда:
Сообщений: 69
См. документацию по PBNI:

cls = session-> GetClass(dwobj);
   fid = session-> GetFieldID(cls, "visible");
   if (fid == kUndefinedFieldID) 
      return;
   isTrue = session-> GetBoolField(dwobj, fid, isNull); 
   if (isTrue)
      session -> SetBoolField(dwobj, fid, false);
    else
      session -> SetBoolField(dwobj, fid, true);
    return ;
2 апр 18, 09:18    [21303838]     Ответить | Цитировать Сообщить модератору
 Re: PBNI Wizard  [new]
AIS
Member

Откуда:
Сообщений: 1695
avs63
См. документацию по PBNI:

cls = session-> GetClass(dwobj);
   fid = session-> GetFieldID(cls, "visible");
   if (fid == kUndefinedFieldID) 
      return;
   isTrue = session-> GetBoolField(dwobj, fid, isNull); 
   if (isTrue)
      session -> SetBoolField(dwobj, fid, false);
    else
      session -> SetBoolField(dwobj, fid, true);
    return ;

Да вроде читал...
Для начала у меня не получается даже fid получить. Так как в доках выдает ошибку, а если так:
...
fid = session-> GetFieldID(cls, (LPCTSTR) "visible");
...
то получаю UndefinedFieldID.
В чем причина?

РВ10.5
2 апр 18, 11:21    [21304290]     Ответить | Цитировать Сообщить модератору
 Re: PBNI Wizard  [new]
AIS
Member

Откуда:
Сообщений: 1695
Упс, нашел ошибку. Все работает. Всем спасибо.
2 апр 18, 12:19    [21304676]     Ответить | Цитировать Сообщить модератору
 Re: PBNI Wizard  [new]
AIS
Member

Откуда:
Сообщений: 1695
AIS
Еще вопрос, на который не могу найти ответа.

Получаю в PB экземпляр класса и передаю его в PBNI:
/* например */
ClassDefinition lcd 
lcd = nuo_test.ClassDefinition 

а как потом получить свойства класса на стороне PBNI? Например, lcd.LibraryName.

Да, если передаю в PBNI параметром lcd, то могу получить lcd.LibraryName.
А как получить LibraryName ничего вообще не передавая на PBNI?
Вот например:
...
LPCTSTR GroupName = (LPCTSTR) "test_app"; /* AppName */
pbgroup group = session->FindGroup(GroupName, pbgroup_application);
if (group == NULL) {
   ci->returnValue->SetString(_T("Group is NULL"));
} else {
   /* получаю класс в текущей библиотеке */
   pbclass cls = session->FindClass(group, GroupName); 
   if (cls == NULL) {
      ci->returnValue->SetString(_T("Class is NULL"));
   } else {
      LPCTSTR FieldName = (LPCTSTR)"classdefinition";
      pbfieldID fid = session->GetFieldID(cls, FieldName);
      if (session->IsFieldObject(cls, fid)) {
         /* сюда не проходит, хотя ClassDefinition должен быть PowerObject */
      } else {
         ci->returnValue->SetString(_T("NOT IsFieldObject"));
      }
   }
}

Что не так? Можно ли таким способом получить LibraryName?
2 апр 18, 22:41    [21306678]     Ответить | Цитировать Сообщить модератору
 Re: PBNI Wizard  [new]
Anatoly Moskovsky
Member

Откуда: Odessa
Сообщений: 6610
AIS
Что не так?

Вот так нельзя делать:
(LPCTSTR) "строка"

Все такие места в коде надо заменить на
_T("строка")


И вообще, если у вас в коде есть конструкция (тип) перед выражением, то там скореее всего проблема. Лучше заменить ее на конструкцию static_cast<тип>(выражение).
Тогда компилятор сам подскажет вам когда нельзя так делать ))
3 апр 18, 13:37    [21308157]     Ответить | Цитировать Сообщить модератору
 Re: PBNI Wizard  [new]
AIS
Member

Откуда:
Сообщений: 1695
Anatoly Moskovsky,

спасибо за помощь, поменял.
Теперь получилось получить, например, значение свойства "displayname" приложения.
А вот дальше не могу понять, что делать, чтобы получить свойство "classdefinition" приложения, которое является объектом, и далее получить из него значение LibraryName.
Если есть возможность, то подскажите хоть схематически, как это делается.
3 апр 18, 14:38    [21308495]     Ответить | Цитировать Сообщить модератору
 Re: PBNI Wizard  [new]
Anatoly Moskovsky
Member

Откуда: Odessa
Сообщений: 6610
AIS,

Что-то типа этого. (Только добавить проверки на успешность выполнения)
pbclass cls = session->FindClass(group, GroupName)
pbfieldID fid = session->GetFieldID(cls, _T("classdefinition"));
pbobject clsdef = session->GetObjectField(cls, fid, isNull);


Если это не сработает, то приведите ваш код - может по нему что-то будет видно.
У меня нет Винды с ПБ под рукой, поэтому больше ничем помочь не могу, кроме проверки вашего кода в форуме )).
3 апр 18, 19:30    [21309633]     Ответить | Цитировать Сообщить модератору
 Re: PBNI Wizard  [new]
Anatoly Moskovsky
Member

Откуда: Odessa
Сообщений: 6610
А вообще, classdefinition это же свойство объекта, а не класса.
Поэтому вам надо этот объект (приложение?) передать в pbni, и для него вызывать
GetFieldID и GetObjectField
3 апр 18, 19:35    [21309644]     Ответить | Цитировать Сообщить модератору
 Re: PBNI Wizard  [new]
AIS
Member

Откуда:
Сообщений: 1695
Anatoly Moskovsky,
+ PB: событие "open" приложения
string ls_rtn
ls_rtn = f_test(this) /* вызов функции PBX */
MessageBox("test", ls_rtn)

+ PBX: после корректировки
...
pbboolean isNull;
/* передаю параметр - объект приложения */
pbobject obj = ci->pArgs->GetAt(0)->GetObject();
pbclass cls = ci->pArgs->GetAt(0)->GetClass();
if (cls == NULL) {
   ci->returnValue->SetString(_T("Class is NULL"));
}
else {
   LPCTSTR FieldName = _T("classdefinition");
   pbfieldID fid = session->GetFieldID(cls, FieldName);
   if (fidcls == kUndefinedFieldID) {
      ci->returnValue->SetString(_T("Undefined FieldID"));
   }
   else {
      /* в GetObjectField нужен таки объект, а не класс */
      pbobject objclsdef = m_pSession->GetObjectField(obj, fid, isNull);
      if (objclsdef == NULL) {
	 ci->returnValue->SetString(_T("ObjectField is NULL"));
      }
      else {
	 ci->returnValue->SetString(_T("ObjectField is NOT NULL")); /* сюда доходит */
      }
   }
}

А дальше не пойму как получить из PBX значение libraryname, который в РВ в событии "open" приложения можно получить так:
ClassDefinition lcd
lcd = this.ClassDefinition
ls_Fullpath = lcd.LibraryName
4 апр 18, 10:06    [21310540]     Ответить | Цитировать Сообщить модератору
 Re: PBNI Wizard  [new]
Anatoly Moskovsky
Member

Откуда: Odessa
Сообщений: 6610
AIS,
pbobject objclsdef = session->GetObjectField(obj, fid, isNull);  // это у вас уже есть
pbclass clsdefcls = objclsdef->GetClass();
pbfieldID library_fid = session->GetFieldID(clsdefcls, _T("libraryname"));
pbstring lirary_name = session->GetStringField(objclsdef, library_fid, isNull);
4 апр 18, 15:53    [21312140]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / PowerBuilder Ответить