Problem with COM usage in .NET

voron999
Уже с Приветом
Posts: 358
Joined: 20 May 2001 09:01
Location: Урал --> Москва --> Midwest USA

Problem with COM usage in .NET

Post by voron999 »

Вот такая проблема - в одной программке референсе на COM обьект работает, a в другой рядышком нет. Обе компилирются на моей машине, а когда устанавливаю на сервер, одна работает, а другая нет (обьект _objDM не создается).

Вот ето работает (Windows forms app):

public class Form1 : System.Windows.Forms.Form
{.........

private KDIDataManager2.CDataManagerClass _objDM;
......

_objDM = new KDIDataManager2.CDataManagerClass();

this.Text += "[" + _objDM.GetCurrentDBName() + "]" + "[" + _sCurrentIP + "]";
....
}


А тут же рядышком, в другой программке, уже не работает (Windows service):

public class JobCacheCleaner : System.ServiceProcess.ServiceBase
{......

private KDIDataManager2.CDataManagerClass _objDM;

.........

_objDM = new KDIDataManager2.CDataManagerClass();
_objDM.CheckConnection();
sConnString = _objDM.sDBNETString.ToString();
_objDM.CloseDBConnection();
_objDM = null;
...
}

Ошибка:

1/7/2004 11:36 AM System.InvalidCastException: QueryInterface for interface KDIDataManager2._CDataManager failed.
at KDIDataManager2.CDataManagerClass.CheckConnection()
at JobCacheCleaner.JobCacheCleaner.InsertJobsDB(FileInfo[] arrFileInfos) in c:\code.net\jobcachecleaner\jobcachecleaner.c


В обоих программках использутся early binding с СОМ обьектом. Методы вызываются разные, но в принципе и тот и другой должны работать.

Какие будут советы?
Спасибо.
Bobo
Уже с Приветом
Posts: 518
Joined: 04 Jun 2002 01:40
Location: CA, USA

Post by Bobo »

Possible reasons:

1. The service is running under an account with insufficient priveledges.

2. The service thread can't enter the STA apartment and cannot marshal the obj across apartments. I never wrote service in .net, but I would guess they use the MTA model, unlike WinForms that are always STA.
Possible solutions:
a) register the tlb on your server. This will allow marshaling across apartments.
b) make your service STA either by placing [STAThread] somewhere or setting Thread.CurrentThread.ApartmentState = STA.
If (b) works at all it should work faster than (a).
voron999
Уже с Приветом
Posts: 358
Joined: 20 May 2001 09:01
Location: Урал --> Москва --> Midwest USA

Post by voron999 »

Oh! Many thanks!
I knew someone here would have suggestions.
Will try and report later on findings.
voron999
Уже с Приветом
Posts: 358
Joined: 20 May 2001 09:01
Location: Урал --> Москва --> Midwest USA

Post by voron999 »

Попробовал вариант (б) - не работает.
Не знаю как быть с вариантом (а). СОМ обьект написан в VB6, там вроде бы tlb информация находится в самом обьекте. Не нужно иметь отдельный tlb file. Да и как его вытащить из VB6 СОМ DLL? Ну и другие программки как-то работают с этим обьектом без проблем. Но они все Windows Forms или ASP.NET....
Не знаю как быть короче. Просто hardcoded (как это по русски?) нужную информацию пока... :oops:
Bobo
Уже с Приветом
Posts: 518
Joined: 04 Jun 2002 01:40
Location: CA, USA

Post by Bobo »

А как пробовали (б) - атрибутом или кодом?
Дело в том, что это дело надо устанавливать до того, как первый раз вызывается CoInitialize. А где он вызывается - никто не знает.
Я игрался с этим в WinForms. Там оно работает только когда навешен атрибут на Main(). (Visual Studio сама его навешивает).
Но раз вы говорите, что это VB obj, то проблема наверно не в этом.

Да, а когда вы его из ASP.Net вызываете, вы включаете ASPCompat, или как его там, атрибут в <@page>, который делает то же самое, что [STAThread]?
Если работает без этого атрибута, то проблема точно НЕ в threading.
Если работает с этим атрибутом, попробуйте его убрать. Если перестанет работать - проблема почти точно в threading. :wink:
Кстати, если работает и так и так, то надо его включить - будет быстрее работать

Если это не threading, то проверьте еще раз permissions.
Если обьект крутится в MTS - проверьте permissions и там.

Другие обьекты пробовали вызывать?
diam
Уже с Приветом
Posts: 107
Joined: 25 Jun 1999 09:01
Location: Russia

Post by diam »

voron999 wrote:Попробовал вариант (б) - не работает.

А вариант в пп.1 by Bobo пробовал?
Сервис запускается с правами "LocalSystem", который не входит даже в "Everyone". Думаю, что проблема с правами доступа (кстати, никак нельзя получить код ошибки?), если простые приложения нормально работают. Попробуй запустить сервис, указав ему имя и пароль пользователя, под которым работает то самое Windows forms app.
diam
Уже с Приветом
Posts: 107
Joined: 25 Jun 1999 09:01
Location: Russia

Post by diam »

Bobo wrote:Если это не threading, то проверьте еще раз permissions.
Если обьект крутится в MTS - проверьте permissions и там.

Вот-вот. Я несколько раз наступал на подобные грабли. Теперь первым делом проверяю permissions. :)
voron999
Уже с Приветом
Posts: 358
Joined: 20 May 2001 09:01
Location: Урал --> Москва --> Midwest USA

Post by voron999 »

diam wrote: Попробуй запустить сервис, указав ему имя и пароль пользователя, под которым работает то самое Windows forms app.


Это проверено. Сервис работает под именем/паролем пользователя с самого начала. С permissions вроде все ОК. Это уже вошло в привычку после нескольких разов.


Также пробовал это:

Thread.CurrentThread.ApartmentState = STA прямо в том методе где обьект вызывается. Еще попробую прямо в Маин() вставить.

А куда [STAThread] вставить - так и не разобрался толком, честно говоря.

Будет время - попробую еще раз с "нитками" разобраться. ДоложУ.

Спасибо всем.
Bobo
Уже с Приветом
Posts: 518
Joined: 04 Jun 2002 01:40
Location: CA, USA

Post by Bobo »

voron999 wrote:А куда [STAThread] вставить - так и не разобрался толком, честно говоря.

Перед Main() вставить. Что, никогда не видели этот атрибут в WinForms?
[STAThread]
public static void Main()
voron999
Уже с Приветом
Posts: 358
Joined: 20 May 2001 09:01
Location: Урал --> Москва --> Midwest USA

Post by voron999 »

Bobo wrote:
voron999 wrote:А куда [STAThread] вставить - так и не разобрался толком, честно говоря.

Перед Main() вставить. Что, никогда не видели этот атрибут в WinForms?
[STAThread]
public static void Main()


Спасибо.

Попробовал.

Не работает.

Return to “Вопросы и новости IT”