> Hello,
> We successfully compiled (on .NET 2003) and ran a MFC application
[quoted text clipped - 5 lines]
> Thanks in advance,
> Kaixin
hmmm, this is not simple to track down.
You see, once a thread joins a COM apartment (by calling CoInituializeEx) it
does so for life/ If you call CoInituializeEx on the same thread to join a
different apartment, you'll get the error you are seeing.
.NET will call CoIninitalizeEx automatically just before the first time that
a thread accesses COM. By default a .NET thread will join the MTA, but you
can use the [STAThread] attribute on a method to indicate that *if*
CoInituializeEx is called then the thread should be STA. Another was to do
this is to call
System.Threading.Thread.CurrentThread.ApartmentState = ApartmentState.STA;
> when calling HRESULT hr(::CoInitialize(NULL));.
Are you suggesting that the error happens on this line? If so, then I
suspect .NET has already initialized the thread to join another apartment.
You should have a look at the .NET code and see what it does, and perhaps
see if you can get the .NET code called *after* the MFC initialization has
occurred.
I have seen problems due to using .NET web services (there's some COM calls
somewhere in the .NET web services client code). Also, if you use .NET forms
you may have some issues because .NET forms are COM servers (to support drag
and drop).
Richard

Signature
my email evpuneqt@zicf.bet is encrypted with ROT13 (www.rot13.org)
sign up for my free .NET newsletter at
http://www.wd-mag.com/newsletters/
Kaixin - 19 Feb 2004 00:26 GMT
Hello Dr Grimes, is this you? You are famous! And thanks for your help!
I added some code to test the thread apartment state, prior calling HRESULT
hr(::CoInitialize(NULL)); in C++ as the following. And this piece of code is
called by almost every windows service or app we develop.
if(Thread::CurrentThread->ApartmentState == ApartmentState::STA)
{Thread::CurrentThread->ApartmentState = ApartmentState::MTA;}
else if(Thread::CurrentThread->ApartmentState == ApartmentState::MTA)
{Thread::CurrentThread->ApartmentState = ApartmentState::STA;}
else{Thread::CurrentThread->ApartmentState = ApartmentState::Unknown;}
HRESULT hr;
hr = ::CoInitialize(NULL);
Below are my observations today:
- If I compile and start a windows service (compiled with /clr) with 'debug'
as start parameter in Services Manager, Apartment state is STA; CoInitialize
returns S_FALSE, which is ok, since it is not considered as FAILED. Our
service started.
- If I compile and start a windows MFC app (compiled with /clr) with
'/winapp' as Debugging Command Argument from Visual Studio, Apartment state
is set to MTA; CoInitialize throws the excpetion not able to change thread
mode. Our app failed to start.
I believe that the thread is considered to be managed in both cases.
Although in my code, I tried to manipulate the apartment state, it had no
effect when calling CoInitialize. In fact, "Once the concurrency model for a
thread is set, it cannot be changed. ", quoted from MSDN COM CoInitializeEx.
Since our code does not control the .NET call to CoInitializeEx, my quest
would be to find a way to somehow change from a MTA appartment to a STA one
for our apps to run, if this is feasible. Do you agree? Or you can point me
out to a different direction?
Thanks,
Kaixin