When you try to run a Managed C++ application that has
Component Object Model (COM) initialization on the main thread, you may receive
the following error message at run time:
HRESULT -
0x80010106 - Cannot change thread mode after it is set.
Setting the apartment state on the main thread is not
reliable.
The main function is not the real managed entry point. The
real managed entry point is the C Run-Time Libraries (CRT) entry point. To
resolve this problem, write the managed entry point and manually
initialize the CRT as follows:
#define _WIN32_WINNT 0x501
#include <objbase.h>
#include <stdio.h>
#using <mscorlib.dll>
using namespace System;
extern "C" void mainCRTStartup();
[System::STAThread]
int mymain() //the new entry point
{
//Initialize COM
HRESULT hr = CoInitialize(0);
//Initialize the CRT
mainCRTStartup();
//uninit
CoUninitialize();
return 0;
}
int main()
{
/*
Do the application work
that you would do in your main thread
*/
}Explicitly specify the entry point to the
mymain function. To do this, follow these steps:
- Click Project, and then click Properties.
- In the Property Pages dialog box, expand Linker under Configuration Properties, and then click to select Advanced.
- In the Entry Point text box, type mymain, and then click OK.
Microsoft has confirmed that this is a bug in the Microsoft products that are
listed at the beginning of this article.
When the common language runtime must use the Component Object Model (COM) any time before the user application starts,
the common language runtime calls the
CoInitializeEx method to initialize the main thread to the
multi-threaded apartment (MTA). However, the common language runtime calls the
CoInitializeEx method only as
required. The common language runtime is not deterministic. Typically, applications that require
a single-threaded apartment (STA) for the main thread must instead apply the
STAThread attribute at the entry point. Also, in C++ the user entry point
(main method and its variants) is not a true managed entry point. The C Run-Time Libraries supply the entry points for console applications and for windows
applications.
Steps to Reproduce the Behavior 1
- Start Microsoft Visual Studio .NET 2003.
- On the File menu, point to
New, and then click Project.
- Expand Visual C++ Projects under Project Types, click
MFC, and then click MFC
Application under Templates.
- Type MFCTest in the
Name text box, type C:\ in
the Location text box, and then click
OK.
- In the MFC Application wizard, click
Compound Document Support.
- Under Compound Document Support, click to select Container/Full server, and
then click Finish.
- In Solution Explorer, right-click MFCTest, and then click Properties.
- In the Property Pages dialog box, expand
C/C++ under
Configuration Properties.
- Set the Debug Information Format
property to Disabled.
- Expand Code Generation,
and then set the following properties:
- Set the Basic Runtime Checks property
to Default.
- Set the Enable Minimal Rebuild
property to No.
- Expand Command Line,
and then type /clr in the Additional
Options text box.
- Click Apply, and then click
OK.
- Build the application.
- On the Debug menu, click
Start to debug the application. You may receive the error message that is described in the "Symptoms" section of this article.
Steps to Reproduce the Behavior 2
- Start Visual Studio .NET 2003.
- On the File menu, point to
New, and then click Project.
- Expand Visual C++ Projects under Project Types, click
.NET, and then click
Console Application (.NET) under Templates.
- Type TestProject in the
Name text box, type C:\ in
the Location text box, and then click
OK.
- In Solution Explorer, double-click TestProject.cpp, and then replace the existing code with the
following code:
#include "stdafx.h"
#define _WIN32_WINNT 0x501
#include <objbase.h>
#include <stdio.h>
#using <mscorlib.dll>
using namespace System;
int main()
{
HRESULT hr = CoInitialize(0);
printf("hr in main thread is %d \n",hr);
} - Build, and then run the project. You may receive the run-time
error that is described in the "Symptoms" section of this article.
This problem may also occur in Managed C++
applications under the following scenarios:
- When the application must call the
CoInitializeEx method to initialize the main thread to the STA.
- When you compile MFC OLE based applications by using the /clr
option.
- When you run a Wizard-generated Windows Forms application.