Creating the Text Interpreter Project
Create a new ATL COM server project for the text interpreter.
To create the text interpreter project
From the File menu, click New Project.
On the left, click the Visual C++ category. On the right, click ATL Project as the project type, type TextInterpreter as the name of the project, and specify where the project is to be placed. Click OK.
In the ATL Project Wizard that appears, click Next.
Clear the Attributed option.
Change the Server Type to Executable.
Click Finish, and the New Project Wizard creates the skeleton project for you. You can build the skeleton project at this point, if you choose, although it won’t do anything.
Open the TextInterpreter.cpp file and insert the following helper items before the _tWinMain function:
const DWORD dwPause = 1000; // time to wait for threads to finish up LPCTSTR FindOneOf(LPCTSTR p1, LPCTSTR p2) { while (p1 != NULL && *p1 != NULL) { LPCTSTR p = p2; while (p != NULL && *p != NULL) { if (*p1 == *p) return CharNext(p1); p = CharNext(p); } p1 = CharNext(p1); } return NULL; }
Replace _tWinMain (TextInterpreter uses different parameters than the default) with the following:
extern "C" int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpCmdLine, int /*nShowCmd*/) { lpCmdLine = GetCommandLine(); //this line necessary for _ATL_MIN_CRT #if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED) HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED); #else HRESULT hRes = CoInitialize(NULL); #endif _ASSERTE(SUCCEEDED(hRes)); TCHAR szTokens[] = _T("-/"); int nRet = 0; BOOL bRun = TRUE; LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens); while (lpszToken != NULL) { if (lstrcmpi(lpszToken, _T("UnregServer"))==0) { _AtlModule.UpdateRegistryFromResource(IDR_TEXTINTERPRETER, FALSE); nRet = _AtlModule.UnregisterServer(TRUE); bRun = FALSE; break; } if (lstrcmpi(lpszToken, _T("RegServer"))==0) { _AtlModule.UpdateRegistryFromResource(IDR_TEXTINTERPRETER, TRUE); nRet = _AtlModule.RegisterServer(TRUE); bRun = FALSE; break; } lpszToken = FindOneOf(lpszToken, szTokens); } if (bRun) { _AtlModule.StartMonitor(); #if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED) hRes = _AtlModule.RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED); _ASSERTE(SUCCEEDED(hRes)); hRes = CoResumeClassObjects(); #else hRes = _AtlModule.RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE); #endif _ASSERTE(SUCCEEDED(hRes)); MSG msg; while (GetMessage(&msg, 0, 0, 0)) DispatchMessage(&msg); _AtlModule.RevokeClassObjects(); Sleep(dwPause); //wait for any threads to finish } _AtlModule.Term(); CoUninitialize(); return nRet; }
Build the project to make sure there are no errors.
You can run the TextInterpreter project at this point (by either pressing F5 or selecting Start from the Debug menu): the program executes and waits forever because of the loop using GetMessage in _tWinMain. This behavior is the same in all of the following steps; the only way to see TextInterpreter in action is to install it in Visual Studio (which is done in the very last step, Starting the Text Interpreter Program, after the entire debug engine is complete). Stop TextInterpreter by clicking Stop Debugging on the Debug menu.