本文事例工程源码面积分下载地址:http://download.csdn.net/detail/zy_dreamer/5321760
介绍:
这个事例演示了如何写C++代码来创建并操作一个Microsoft步骤2.打开Windows资源管理器(Ctrl+Shift+Esc),确保没有winword.exe在运行。
步骤3.运行程序,如果没有任何错误抛出的话,它应该打印下列内容。然后你就会看见在程序目录下生成两个新文档:Sample1.docx和Sample2.docx。每个文档都有如下内容
步骤4.打开任务管理器确保没有winword.exe进程,并且Word实例正常退出清理。1.使用#import指令引入需要使用的包含COM服务的库文件
C# code snippet -
#import "libid:2DF8D04C-5BFA-101B-BDE5-00AA0044DE52" \
rename("RGB", "MSORGB") \
rename("DocumentProperties", "MSODocumentProperties")
// [-or-]
//#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\MSO.DLL" \
// rename("RGB", "MSORGB") \
// rename("DocumentProperties", "MSODocumentProperties")
using namespace Office;
#import "libid:0002E157-0000-0000-C000-000000000046"
// [-or-]
//#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB"
using namespace VBIDE;
#import "libid:00020905-0000-0000-C000-000000000046" \
rename("ExitWindows", "WordExitWindows") \
rename("FindText", "WordFindText")
// [-or-]
//#import "C:\\Program Files\\Microsoft Office\\Office12\\MSWORD.OLB" \
// rename("ExitWindows", "WordExitWindows")
// rename("FindText", "WordFindText")
- end -
2.编译工程,如果成功,工程中会生成一个.tlh的文件,它包装了刚才引入的COM服务。它以一个包装类的形势供我们使用,我们可以通过它创建COM类并使用成员,方法等。Solution1.h
/****************************** Module Header ******************************\
* Module Name: Solution1.h
* Project: CppAutomateWord
* Copyright (c) Microsoft Corporation.
*
* The code in Solution1.h/cpp demonstrates the use of #import to automate
* Word. #import (http://msdn.microsoft.com/en-us/library/8etzzkb6.aspx),
* a new directive that became available with Visual C++ 5.0, creates VC++
* "smart pointers" from a specified type library. It is very powerful, but
* often not recommended because of reference-counting problems that typically
* occur when used with the Microsoft Office applications. Unlike the direct
* API approach in Solution2.h/cpp, smart pointers enable us to benefit from
* the type info to early/late bind the object. #import takes care of adding
* the messy guids to the project and the COM APIs are encapsulated in custom
* classes that the #import directive generates.
*
* This source is subject to the Microsoft Public License.
* See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL.
* All other rights reserved.
*
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
\***************************************************************************/
#pragma once
//
// FUNCTION: AutomateWordByImport(LPVOID)
//
// PURPOSE: Automate Microsoft Word using the #import directive and smart
// pointers.
//
// PARAMETERS:
// * lpParam - The thread data passed to the function using the
// lpParameter parameter when creating a thread.
// (http://msdn.microsoft.com/en-us/library/ms686736.aspx)
//
// RETURN VALUE: The return value indicates the success or failure of the
// function.
//
DWORD WINAPI AutomateWordByImport(LPVOID lpParam);
/****************************** Module Header ******************************\
* Module Name: Solution2.h
* Project: CppAutomateWord
* Copyright (c) Microsoft Corporation.
*
* The code in Solution2.h/cpp demonstrates the use of C/C++ and the COM APIs
* to automate Word. The raw automation is much more difficult, but it is
* sometimes necessary to avoid the overhead with MFC, or problems with
* #import. Basically, you work with such APIs as CoCreateInstance(), and COM
* interfaces such as IDispatch and IUnknown.
*
* This source is subject to the Microsoft Public License.
* See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL.
* All other rights reserved.
*
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
\***************************************************************************/
#pragma once
//
// FUNCTION: AutomateWordByCOMAPI(LPVOID)
//
// PURPOSE: Automate Microsoft Word using C++ and the COM APIs.
//
// PARAMETERS:
// * lpParam - The thread data passed to the function using the
// lpParameter parameter when creating a thread.
// (http://msdn.microsoft.com/en-us/library/ms686736.aspx)
//
// RETURN VALUE: The return value indicates the success or failure of the
// function.
//
DWORD WINAPI AutomateWordByCOMAPI(LPVOID lpParam);
/****************************** Module Header ******************************\
* Module Name: Solution1.cpp
* Project: CppAutomateWord
* Copyright (c) Microsoft Corporation.
*
* The code in Solution1.h/cpp demonstrates the use of #import to automate
* Word. #import (http://msdn.microsoft.com/en-us/library/8etzzkb6.aspx),
* a new directive that became available with Visual C++ 5.0, creates VC++
* "smart pointers" from a specified type library. It is very powerful, but
* often not recommended because of reference-counting problems that typically
* occur when used with the Microsoft Office applications. Unlike the direct
* API approach in Solution2.h/cpp, smart pointers enable us to benefit from
* the type info to early/late bind the object. #import takes care of adding
* the messy guids to the project and the COM APIs are encapsulated in custom
* classes that the #import directive generates.
*
* This source is subject to the Microsoft Public License.
* See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL.
* All other rights reserved.
*
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
\***************************************************************************/
#pragma region Includes
#include
#include
#include "Solution1.h"
#pragma endregion
#pragma region Import the type libraries
#import "libid:2DF8D04C-5BFA-101B-BDE5-00AA0044DE52" \
rename("RGB", "MSORGB") \
rename("DocumentProperties", "MSODocumentProperties")
// [-or-]
//#import "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE12\\MSO.DLL" \
// rename("RGB", "MSORGB") \
// rename("DocumentProperties", "MSODocumentProperties")
using namespace Office;
#import "libid:0002E157-0000-0000-C000-000000000046"
// [-or-]
//#import "C:\\Program Files\\Common Files\\Microsoft Shared\\VBA\\VBA6\\VBE6EXT.OLB"
using namespace VBIDE;
#import "libid:00020905-0000-0000-C000-000000000046" \
rename("ExitWindows", "WordExitWindows") \
rename("FindText", "WordFindText")
// [-or-]
//#import "C:\\Program Files\\Microsoft Office\\Office12\\MSWORD.OLB" \
// rename("ExitWindows", "WordExitWindows") \
// rename("FindText", "WordFindText")
#pragma endregion
//
// FUNCTION: GetModuleDirectory(LPWSTR, DWORD);
//
// PURPOSE: This is a helper function in this sample. It retrieves the
// fully-qualified path for the directory that contains the executable
// file of the current process. For example, "D:\Samples\".
//
// PARAMETERS:
// * pszDir - A pointer to a buffer that receives the fully-qualified
// path for the directory taht contains the executable file of the
// current process. If the length of the path is less than the size that
// the nSize parameter specifies, the function succeeds and the path is
// returned as a null-terminated string.
// * nSize - The size of the lpFilename buffer, in characters.
//
// RETURN VALUE: If the function succeeds, the return value is the length
// of the string that is copied to the buffer, in characters, not
// including the terminating null character. If the buffer is too small
// to hold the directory name, the function returns 0 and sets the last
// error to ERROR_INSUFFICIENT_BUFFER. If the function fails, the return
// value is 0 (zero). To get extended error information, call
// GetLastError.
//
DWORD GetModuleDirectory(LPWSTR pszDir, DWORD nSize);
//
// FUNCTION: AutomateWordByImport(LPVOID)
//
// PURPOSE: Automate Microsoft Word using the #import directive and smart
// pointers.
//
DWORD WINAPI AutomateWordByImport(LPVOID lpParam)
{
// Initializes the COM library on the current thread and identifies the
// concurrency model as single-thread apartment (STA).
// [-or-] CoInitialize(NULL);
// [-or-] CoCreateInstance(NULL);
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
try
{
/////////////////////////////////////////////////////////////////////
// Create the Word.Application COM object using the #import directive
// and smart pointers.
//
// Option 1) Create the object using the smart pointer's constructor
// _ApplicationPtr is the original interface name, _Application, with a
// "Ptr" suffix.
//Word::_ApplicationPtr spWordApp(
// __uuidof(Word::Application) // CLSID of the component
// );
// [-or-]
// Option 2) Create the object using the smart pointer's function,
// CreateInstance
Word::_ApplicationPtr spWordApp;
HRESULT hr = spWordApp.CreateInstance(__uuidof(Word::Application));
if (FAILED(hr))
{
wprintf(L"CreateInstance failed w/err 0x%08lx\n", hr);
return 1;
}
_putws(L"Word.Application is started");
/////////////////////////////////////////////////////////////////////
// Make Word invisible. (i.e. Application.Visible = 0)
//
spWordApp->Visible = VARIANT_FALSE;
/////////////////////////////////////////////////////////////////////
// Create a new Document. (i.e. Application.Documents.Add)
//
Word::DocumentsPtr spDocs = spWordApp->Documents;
Word::_DocumentPtr spDoc = spDocs->Add();
_putws(L"A new document is created");
/////////////////////////////////////////////////////////////////////
// Insert a paragraph.
//
_putws(L"Insert a paragraph");
Word::ParagraphsPtr spParas = spDoc->Paragraphs;
Word::ParagraphPtr spPara = spParas->Add();
Word::RangePtr spParaRng = spPara->Range;
spParaRng->Text = _bstr_t(L"Heading 1");
Word::_FontPtr spFont = spParaRng->Font;
spFont->Bold = 1;
spParaRng->InsertParagraphAfter();
/////////////////////////////////////////////////////////////////////
// Save the document as a docx file and close it.
//
_putws(L"Save and close the document");
// Make the file name
// Get the directory of the current exe.
wchar_t szFileName[MAX_PATH];
if (!GetModuleDirectory(szFileName, ARRAYSIZE(szFileName)))
{
_putws(L"GetModuleDirectory failed");
return 1;
}
// Concat "Sample1.docx" to the directory
wcsncat_s(szFileName, ARRAYSIZE(szFileName), L"Sample1.docx", 12);
// Convert the NULL-terminated string to BSTR
variant_t vtFileName(szFileName);
spDoc->SaveAs(&vtFileName);
spDoc->Close();
/////////////////////////////////////////////////////////////////////
// Quit the Word application.
//
_putws(L"Quit the Word application");
spWordApp->Quit();
/////////////////////////////////////////////////////////////////////
// Release the COM objects.
//
// Releasing the references is not necessary for the smart pointers
// ...
// spWordApp.Release();
// ...
}
catch (_com_error &err)
{
wprintf(L"Word throws the error: %s\n", err.ErrorMessage());
wprintf(L"Description: %s\n", (LPCWSTR) err.Description());
}
// Uninitialize COM for this thread
CoUninitialize();
return 0;
}
/****************************** Module Header ******************************\
* Module Name: Solution2.cpp
* Project: CppAutomateWord
* Copyright (c) Microsoft Corporation.
*
* The code in Solution2.h/cpp demonstrates the use of C/C++ and the COM APIs
* to automate Word. The raw automation is much more difficult, but it is
* sometimes necessary to avoid the overhead with MFC, or problems with
* #import. Basically, you work with such APIs as CoCreateInstance(), and COM
* interfaces such as IDispatch and IUnknown.
*
* This source is subject to the Microsoft Public License.
* See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL.
* All other rights reserved.
*
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
\***************************************************************************/
#pragma region Includes
#include
#include
#include "Solution2.h"
#pragma endregion
//
// FUNCTION: AutoWrap(int, VARIANT*, IDispatch*, LPOLESTR, int,...)
//
// PURPOSE: Automation helper function. It simplifies most of the low-level
// details involved with using IDispatch directly. Feel free to use it
// in your own implementations. One caveat is that if you pass multiple
// parameters, they need to be passed in reverse-order.
//
// PARAMETERS:
// * autoType - Could be one of these values: DISPATCH_PROPERTYGET,
// DISPATCH_PROPERTYPUT, DISPATCH_PROPERTYPUTREF, DISPATCH_METHOD.
// * pvResult - Holds the return value in a VARIANT.
// * pDisp - The IDispatch interface.
// * ptName - The property/method name exposed by the interface.
// * cArgs - The count of the arguments.
//
// RETURN VALUE: An HRESULT value indicating whether the function succeeds
// or not.
//
// EXAMPLE:
// AutoWrap(DISPATCH_METHOD, NULL, pDisp, L"call", 2, parm[1], parm[0]);
//
HRESULT AutoWrap(int autoType, VARIANT *pvResult, IDispatch *pDisp,
LPOLESTR ptName, int cArgs...)
{
// Begin variable-argument list
va_list marker;
va_start(marker, cArgs);
if (!pDisp)
{
_putws(L"NULL IDispatch passed to AutoWrap()");
_exit(0);
return E_INVALIDARG;
}
// Variables used
DISPPARAMS dp = { NULL, NULL, 0, 0 };
DISPID dispidNamed = DISPID_PROPERTYPUT;
DISPID dispID;
HRESULT hr;
// Get DISPID for name passed
hr = pDisp->GetIDsOfNames(IID_NULL, &ptName, 1, LOCALE_USER_DEFAULT, &dispID);
if (FAILED(hr))
{
wprintf(L"IDispatch::GetIDsOfNames(\"%s\") failed w/err 0x%08lx\n",
ptName, hr);
_exit(0);
return hr;
}
// Allocate memory for arguments
VARIANT *pArgs = new VARIANT[cArgs + 1];
// Extract arguments...
for(int i=0; i < cArgs; i++)
{
pArgs[i] = va_arg(marker, VARIANT);
}
// Build DISPPARAMS
dp.cArgs = cArgs;
dp.rgvarg = pArgs;
// Handle special-case for property-puts
if (autoType & DISPATCH_PROPERTYPUT)
{
dp.cNamedArgs = 1;
dp.rgdispidNamedArgs = &dispidNamed;
}
// Make the call
hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT,
autoType, &dp, pvResult, NULL, NULL);
if (FAILED(hr))
{
wprintf(L"IDispatch::Invoke(\"%s\"=%08lx) failed w/err 0x%08lx\n",
ptName, dispID, hr);
_exit(0);
return hr;
}
// End variable-argument section
va_end(marker);
delete[] pArgs;
return hr;
}
//
// FUNCTION: GetModuleDirectory(LPWSTR, DWORD);
//
// PURPOSE: This is a helper function in this sample. It retrieves the
// fully-qualified path for the directory that contains the executable
// file of the current process. For example, "D:\Samples\".
//
// PARAMETERS:
// * pszDir - A pointer to a buffer that receives the fully-qualified
// path for the directory taht contains the executable file of the
// current process. If the length of the path is less than the size that
// the nSize parameter specifies, the function succeeds and the path is
// returned as a null-terminated string.
// * nSize - The size of the lpFilename buffer, in characters.
//
// RETURN VALUE: If the function succeeds, the return value is the length
// of the string that is copied to the buffer, in characters, not
// including the terminating null character. If the buffer is too small
// to hold the directory name, the function returns 0 and sets the last
// error to ERROR_INSUFFICIENT_BUFFER. If the function fails, the return
// value is 0 (zero). To get extended error information, call
// GetLastError.
//
DWORD GetModuleDirectory(LPWSTR pszDir, DWORD nSize);
//
// FUNCTION: AutomateWordByCOMAPI(LPVOID)
//
// PURPOSE: Automate Microsoft Word using C++ and the COM APIs.
//
DWORD WINAPI AutomateWordByCOMAPI(LPVOID lpParam)
{
// Initializes the COM library on the current thread and identifies the
// concurrency model as single-thread apartment (STA).
// [-or-] CoInitialize(NULL);
// [-or-] CoCreateInstance(NULL);
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
/////////////////////////////////////////////////////////////////////////
// Create the Word.Application COM object using C++ and the COM APIs.
//
// Get CLSID of the server
CLSID clsid;
HRESULT hr;
// Option 1. Get CLSID from ProgID using CLSIDFromProgID.
LPCOLESTR progID = L"Word.Application";
hr = CLSIDFromProgID(progID, &clsid);
if (FAILED(hr))
{
wprintf(L"CLSIDFromProgID(\"%s\") failed w/err 0x%08lx\n", progID, hr);
return 1;
}
// Option 2. Build the CLSID directly.
/*const IID CLSID_Application =
{0x000209FF,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
clsid = CLSID_Application;*/
// Start the server and get the IDispatch interface
IDispatch *pWordApp = NULL;
hr = CoCreateInstance( // [-or-] CoCreateInstanceEx, CoGetObject
clsid, // CLSID of the server
NULL,
CLSCTX_LOCAL_SERVER, // Word.Application is a local server
IID_IDispatch, // Query the IDispatch interface
(void **)&pWordApp); // Output
if (FAILED(hr))
{
wprintf(L"Word is not registered properly w/err 0x%08lx\n", hr);
return 1;
}
_putws(L"Word.Application is started");
/////////////////////////////////////////////////////////////////////////
// Make Word invisible. (i.e. Application.Visible = 0)
//
{
VARIANT x;
x.vt = VT_I4;
x.lVal = 0;
AutoWrap(DISPATCH_PROPERTYPUT, NULL, pWordApp, L"Visible", 1, x);
}
/////////////////////////////////////////////////////////////////////////
// Create a new Document. (i.e. Application.Documents.Add)
//
// Get the Documents collection
IDispatch *pDocs = NULL;
{
VARIANT result;
VariantInit(&result);
AutoWrap(DISPATCH_PROPERTYGET, &result, pWordApp, L"Documents", 0);
pDocs = result.pdispVal;
}
// Call Documents.Add() to get a new document
IDispatch *pDoc = NULL;
{
VARIANT result;
VariantInit(&result);
AutoWrap(DISPATCH_METHOD, &result, pDocs, L"Add", 0);
pDoc = result.pdispVal;
}
_putws(L"A new document is created");
/////////////////////////////////////////////////////////////////////////
// Insert a paragraph.
//
_putws(L"Insert a paragraph");
// pParas = pDoc->Paragraphs
IDispatch *pParas = NULL;
{
VARIANT result;
VariantInit(&result);
AutoWrap(DISPATCH_PROPERTYGET, &result, pDoc, L"Paragraphs", 0);
pParas = result.pdispVal;
}
// pPara = pParas->Add
IDispatch *pPara = NULL;
{
VARIANT result;
VariantInit(&result);
AutoWrap(DISPATCH_METHOD, &result, pParas, L"Add", 0);
pPara = result.pdispVal;
}
// pParaRng = pPara->Range
IDispatch *pParaRng = NULL;
{
VARIANT result;
VariantInit(&result);
AutoWrap(DISPATCH_PROPERTYGET, &result, pPara, L"Range", 0);
pParaRng = result.pdispVal;
}
// pParaRng->Text = "Heading 1"
{
VARIANT x;
x.vt = VT_BSTR;
x.bstrVal = ::SysAllocString(L"Heading 1");
AutoWrap(DISPATCH_PROPERTYPUT, NULL, pParaRng, L"Text", 1, x);
VariantClear(&x);
}
// pFont = pParaRng->Font
IDispatch *pFont = NULL;
{
VARIANT result;
VariantInit(&result);
AutoWrap(DISPATCH_PROPERTYGET, &result, pParaRng, L"Font", 0);
pFont = result.pdispVal;
}
// pFont->Bold = 1
{
VARIANT x;
x.vt = VT_I4;
x.lVal = 1;
AutoWrap(DISPATCH_PROPERTYPUT, NULL, pFont, L"Bold", 1, x);
}
// pParaRng->InsertParagraphAfter();
AutoWrap(DISPATCH_METHOD, NULL, pParaRng, L"InsertParagraphAfter", 0);
/////////////////////////////////////////////////////////////////////////
// Save the document as a docx file and close it.
//
_putws(L"Save and close the document");
// pDoc->SaveAs
{
// Make the file name
// Get the directory of the current exe.
wchar_t szFileName[MAX_PATH];
if (!GetModuleDirectory(szFileName, ARRAYSIZE(szFileName)))
{
_putws(L"GetModuleDirectory failed");
return 1;
}
// Concat "Sample2.docx" to the directory.
wcsncat_s(szFileName, ARRAYSIZE(szFileName), L"Sample2.docx", 12);
// Convert the NULL-terminated string to BSTR.
VARIANT vtFileName;
vtFileName.vt = VT_BSTR;
vtFileName.bstrVal = SysAllocString(szFileName);
AutoWrap(DISPATCH_METHOD, NULL, pDoc, L"SaveAs", 1, vtFileName);
VariantClear(&vtFileName);
}
// pDoc->Close()
AutoWrap(DISPATCH_METHOD, NULL, pDoc, L"Close", 0);
/////////////////////////////////////////////////////////////////////////
// Quit the Word application. (i.e. Application.Quit())
//
_putws(L"Quit the Word application");
AutoWrap(DISPATCH_METHOD, NULL, pWordApp, L"Quit", 0);
/////////////////////////////////////////////////////////////////////////
// Release the COM objects.
//
if (pFont != NULL)
{
pFont->Release();
}
if (pParaRng != NULL)
{
pParaRng->Release();
}
if (pPara != NULL)
{
pPara->Release();
}
if (pParas != NULL)
{
pParas->Release();
}
if (pDoc != NULL)
{
pDoc->Release();
}
if (pDocs != NULL)
{
pDocs->Release();
}
if (pWordApp != NULL)
{
pWordApp->Release();
}
// Uninitialize COM for this thread.
CoUninitialize();
return 0;
}
CppAutomateWord.cpp
/****************************** Module Header ******************************\
* Module Name: CppAutomateWord.cpp
* Project: CppAutomateWord
* Copyright (c) Microsoft Corporation.
*
* The CppAutomateWord example demonstrates how to write VC++ code to create a
* Microsoft Word instance, create a new document, insert a paragraph, save
* the document, close the Microsoft Word application and then clean up
* unmanaged COM resources.
*
* There are three basic ways you can write VC++ automation codes:
*
* 1. Automating Word using the #import directive and smart pointers
* (Solution1.h/cpp)
* 2. Automating Word using C++ and the COM APIs (Solution2.h/cpp)
* 3. Automating Word using MFC (This is not covered in this sample)
*
* This source is subject to the Microsoft Public License.
* See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL.
* All other rights reserved.
*
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
\***************************************************************************/
#pragma region Includes
#include
#include
#include "Solution1.h" // The example of using the #import directive
// and smart pointers to automate Word
#include "Solution2.h" // The example of using the raw COM API to
// automate Word
#pragma endregion
int wmain(int argc, wchar_t* argv[])
{
HANDLE hThread;
// Demonstrate automating Word using the #import directive and smart
// pointers in a separate thread.
hThread = CreateThread(NULL, 0, AutomateWordByImport, NULL, 0, NULL);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
_putws(L"");
// Demonstrate automating Word using C++ and the COM APIs in a separate
// thread.
hThread = CreateThread(NULL, 0, AutomateWordByCOMAPI, NULL, 0, NULL);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
return 0;
}
//
// FUNCTION: GetModuleDirectory(LPWSTR, DWORD);
//
// PURPOSE: This is a helper function in this sample. It retrieves the
// fully-qualified path for the directory that contains the executable
// file of the current process. For example, "D:\Samples\".
//
// PARAMETERS:
// * pszDir - A pointer to a buffer that receives the fully-qualified
// path for the directory taht contains the executable file of the
// current process. If the length of the path is less than the size that
// the nSize parameter specifies, the function succeeds and the path is
// returned as a null-terminated string.
// * nSize - The size of the lpFilename buffer, in characters.
//
// RETURN VALUE: If the function succeeds, the return value is the length
// of the string that is copied to the buffer, in characters, not
// including the terminating null character. If the buffer is too small
// to hold the directory name, the function returns 0 and sets the last
// error to ERROR_INSUFFICIENT_BUFFER. If the function fails, the return
// value is 0 (zero). To get extended error information, call
// GetLastError.
//
DWORD GetModuleDirectory(LPWSTR pszDir, DWORD nSize)
{
// Retrieve the path of the executable file of the current process.
nSize = GetModuleFileName(NULL, pszDir, nSize);
if (!nSize || GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
*pszDir = L'\0'; // Ensure it's NULL terminated
return 0;
}
// Run through looking for the last slash in the file path.
// When we find it, NULL it to truncate the following filename part.
for (int i = nSize - 1; i >= 0; i--)
{
if (pszDir[i] == L'\\' || pszDir[i] == L'/')
{
pszDir[i + 1] = L'\0';
nSize = i + 1;
break;
}
}
return nSize;
}