Проблемы с СОМ...

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

bunt_pupsikov
Сообщения: 6
Зарегистрирован: 16 июл 2007, 13:11

16 июл 2007, 13:24

Добрый день! С СОМ столкнулась первый раз...


есть такая часть программы:

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

     double f2;

     f2 = nwa.GetGStop();      
     this->UpdateData(FALSE);
    
     m_KSV_1 = nwa.GetChValue(4, f2);     
     this->UpdateData(FALSE);    

где nwa - объект автоматизации..

далее есть еще вот такая часть:

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


double IAutomation::GetGStop()
{
    double result;
    InvokeHelper(0x7, DISPATCH_PROPERTYGET, VT_R8, (void*)&result, NULL);
    return result;
}

double IAutomation::GetChValue(long Channel, double Frequency)
{
    double result;
    static BYTE parms[] =
        VTS_I4 VTS_R8;
    InvokeHelper(0x20, DISPATCH_PROPERTYGET, VT_R8, (void*)&result, parms,
        Channel, Frequency);
    return result;
}


функция GetGStop() обрабатывается нормально и выдает правильный результат.
А вот функция GetChValue(long Channel, double Frequency) работать не хочет.... В процессе работы переменная result получает определенное значение, но оно не возвращается... Возникает какая-то ошибка..... Выдается сообщение "EAссess Violation", а когда при отлаживании закрываешь программу, выдается собщение "Unhandled exeption in Planar.exe (OLE32.DLL):0xC000005: Access Violatoin."
Бьюсь над этим уже неделю.... Помогите, пожалуйста, разобраться что за ошибки и как их исправить...
Заранее спасибо...
Владимир
Сообщения: 56
Зарегистрирован: 25 апр 2005, 13:57

17 июл 2007, 10:08

Мне кажется, что проблема с массивом parms, по описанию из MSDN это должна быть строка байт, завершающаяся нулем("Pointer to a null-terminated string of bytes specifying the types of the parameters..."). Добавь завершающий 0 и вроде как должно помочь

Сорри, почитал внимательнее MSDN и понял, что ответил не по делу. Единственно, в примерах к MSDN, нашел что там используется такая конструкция
static BYTE BASED_CODE parms[] = VTS_I2 VTS_I2 VTS_BSTR; Но по описанию макрос BASED_CODE только для обратной совместимости с 16-bit MFC и под Win32 ничего не значит.
bunt_pupsikov
Сообщения: 6
Зарегистрирован: 16 июл 2007, 13:11

17 июл 2007, 12:12

MSDN тоже излазила вдоль и поперек..... Ничего ообо интересного не нашла....
А эта ошибка не может быть связана с проблемой подключения библиотек? Просто у меня стоит XP, а эту прогу пишу на VC++5.0..... Они могут, например, "не понимать" друг друга?....
Владимир
Сообщения: 56
Зарегистрирован: 25 апр 2005, 13:57

17 июл 2007, 15:00

Не пробовала использовать try catch и проанализировать возникающее исключение. Может проблемы с передаваемыми параметрами методу(например местами перепутаны) или номер искомого метода не тот и по номеру 0x20 вызывается совсем другой с другой сигнатурой
bunt_pupsikov
Сообщения: 6
Зарегистрирован: 16 июл 2007, 13:11

17 июл 2007, 16:13

имена правильные.... и методы вызываются вроде те.....
bunt_pupsikov
Сообщения: 6
Зарегистрирован: 16 июл 2007, 13:11

18 июл 2007, 11:48

Проблемы возникают в этой функции

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

double IAutomation::GetChValue(long Channel, double Frequency)
{    
double result;    
static BYTE parms[] =        
VTS_I4 VTS_R8;    
InvokeHelper(0x20, DISPATCH_PROPERTYGET, VT_R8, (void*)&result, parms,        
Channel, Frequency);    
return result;
}
а конкретно - при обработке исключения....
пишет сообщения про нарушение доступа к исключению и сбой при удаленном вызове процедуры....
в отладчике из строки InvokeHelper(.....) выкидывает в WINCORE.CPP в процедуру

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

LRESULT AFXAPI AfxCallWndProc(CWnd* pWnd, HWND hWnd, UINT nMsg,
	WPARAM wParam = 0, LPARAM lParam = 0)
конкретно в часть

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

CATCH_ALL(e)
	{
	lResult = AfxGetThread()->ProcessWndProcException(e, &pThreadState->m_lastSentMsg);
		TRACE1("Warning: Uncaught exception in WindowProc (returning %ld).\n",
			lResult);
	DELETE_EXCEPTION(e);
	}
	END_CATCH_ALL
и на первой же строке lResult = ... отладчик подвисает....
Владимир
Сообщения: 56
Зарегистрирован: 25 апр 2005, 13:57

18 июл 2007, 13:59

С COMом под MFC никогда дела не имел, ATL пользовался. Попробуй заменить вызов метода InvokeHelper(0x20, DISPATCH_PROPERTYGET, VT_R8, (void*)&result, parms,
Channel, Frequency) на вызов метода IDispatch интерфейса Invoke(), в конечном итоге InvokeHelper вызывает этот метод. Может тогда что нить проясниться. А прошагать InvokeHelper не дало прояснения? (Реализация метода находится в OLEDISP2.CPP)
bunt_pupsikov
Сообщения: 6
Зарегистрирован: 16 июл 2007, 13:11

18 июл 2007, 14:31

прошагала все, что можно....
Пишу все по порядку....
Есть прибор, есть для него ПО, написанное, как СОМ сервер... Мне нужно написать ПО клиента... Класс IAutomation формируется из файла *.tlb, который идет в комплекте с ПО к прибору...
Что представляет из себя ПО сервера могу тока догадываться... никакого описания нет...

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

void CPlanarDlg::OnPusk() //обработка нажатия кнопки CButton
{
BOOL result = nwa.CreateDispatch("Obzor102.Automation"); //Подключение к серверу 
if(result!=TRUE) AfxMessageBox("COM-object didn't create");//и запуск приложения 

Obzor103.exe nwa.Minimize(); //Минимизация окна приложения Obzor103.exe 
BOOL connect = nwa.GetConnected();//Проверка включения прибора и его готовности к работе 
UpdateData(FALSE);
} 

void CPlanarDlg::OnScan() //обработка нажатия кнопки CButton
{ 
//ЧИСЛО ТОЧЕК СКАНИРОВАНИЯ 
CString str; 

CWnd* pWnd = GetDlgItem(IDC_POINTS_SCAN); 
pWnd->EnableWindow(TRUE);  

pWnd->GetWindowText(str); // берем данные из окна IDC_POINTS_SCAN и передаем переменной str
this->UpdateData(TRUE);	// присваиваем переменной str значение 

pWnd  long nResult = atol(str);// конвертируем данные из типа CString  в тип long
this->UpdateData(FALSE);	 

nwa.SetGPoints(nResult);//передаем значение nResult объекту автоматизации
this->UpdateData(FALSE);	 

 //ПЕРВАЯ ЧАСТОТА 
CString str_freq_1; 

CWnd* pWnd1 = GetDlgItem(IDC_FREQ_1); 
pWnd1->EnableWindow(TRUE); 

pWnd1->GetWindowText(str_freq_1); // берем данные из окна IDC_FREQ_1и передаем переменной str_freq_1
this->UpdateData(TRUE);
	 
long nFreq_1 = atol(str_freq_1);// конвертируем данные из типа CString  в тип long
this->UpdateData(FALSE);	  

nwa.SetGStart(nFreq_1);//начальная частота сканирования (передаем объекту автомат.)
nwa.SetGStop(nFreq_1);//конечная частота сканирования (передаем объекту автомат.)
this->UpdateData(FALSE);	  

CWnd* pWnd2 = GetDlgItem(IDC_KSV_1); 
pWnd2->EnableWindow(TRUE); 

double f2; 

f2 = nwa.GetGStop();
this->UpdateData(FALSE); 

m_KSV_1 = nwa.GetChValue(4, f2); 
this->UpdateData(FALSE);	 
}
nwa - глобальная переменная класса IAutomation.

из строки

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

f2 = nwa.GetGStop();
из класса CPlanarDlg скачем в класс IAuromation в функцию

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

double IAutomation::GetGStop()
{    
double result;    
InvokeHelper(0x7, DISPATCH_PROPERTYGET, VT_R8, (void*)&result, NULL);    
return result;
}
из этой функции в OLEDISP2.CPP в

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

void AFX_CDECL COleDispatchDriver::InvokeHelper(DISPID dwDispID, WORD wFlags,	
                                                        VARTYPE vtRet, void* pvRet, const BYTE* pbParamInfo, ...)
{	
va_list argList;	
va_start(argList, pbParamInfo); 	
InvokeHelperV(dwDispID, wFlags, vtRet, pvRet, pbParamInfo, argList); 	
va_end(argList);
}
все прекрасно обрабатывается, скачет в класс IAutomation, возвращает результат, скачет в CPlanarDlg и выдает данные в нужное место (переменная или окошечко моей диалоговой панели)...

На следующей строке

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

m_KSV_1 = nwa.GetChValue(4, f2); 
мы опять же из класса CPlanarDlg скачем в класс IAuromation, но в функцию

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

double IAutomation::GetChValue(long Channel, double Frequency)
{
double result;
static BYTE parms[] =    
VTS_I4 VTS_R8;
InvokeHelper(0x20, DISPATCH_PROPERTYGET, VT_R8, (void*)&result, parms, 	
                    Channel, Frequency);
return result;
}
здесь, похоже, возникает какая-то проблема с объявлением массива static BYTE parms[] =VTS_I4 VTS_R8; т.к. отладчик эту строку просто проскакивает и сразу переходит к InvokeHelper(...), а из InvokeHelper скачет в тот же OLEDISP2.CPP, но уже в функцию

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

void AFX_CDECL COleDispatchDriver::InvokeHelper(DISPID dwDispID, WORD wFlags,	
                                                        VARTYPE vtRet, void* pvRet, const BYTE* pbParamInfo, ...)
{	
va_list argList;	
va_start(argList, pbParamInfo); 	
InvokeHelperV(dwDispID, wFlags, vtRet, pvRet, pbParamInfo, argList); 	
va_end(argList);
}
а из этой функции при обработке InvokeHelperV, а именно параметра pbParamInfo выкидывает в этот самый WINCORE.CPP

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

LRESULT lResult;
TRY
{
...
}
CATCH_ALL(e)	
{	
lResult = AfxGetThread()->ProcessWndProcException(e, &pThreadState->m_lastSentMsg);
TRACE1("Warning: Uncaught exception in WindowProc (returning %ld).\n",			           
            lResult);	
DELETE_EXCEPTION(e);	
}	
END_CATCH_ALL
где на первой строке lResult =... отладчик подвисает....
Владимир
Сообщения: 56
Зарегистрирован: 25 апр 2005, 13:57

18 июл 2007, 14:50

Ну дык замени вызов nwa.GetChValue(4, f2) на свой код, а именно от nwa получи указатель на IDispatch и сама сделай вызов метода № 0x20 через Invoke(), что этому методу и как передается посмотри в реализации InvokeHelperV()
bunt_pupsikov
Сообщения: 6
Зарегистрирован: 16 июл 2007, 13:11

18 июл 2007, 15:07

сорри... не поняла....
мне ж надо получить данные с сервера..., а конкретно из функции

double IAutomation::GetChValue(long Channel, double Frequency)

если я заменю вызов nwa.GetChValue(4, f2) на свой код, получится, что я обойду сервер.... и какой-тоды смысл??... или я чего-то не понимаю?.... :confused:
Ответить