Author Topic: 64 Bit COM C++ Code Works With Out Of Process 32 Bit Servers ...  (Read 1513 times)

0 Members and 1 Guest are viewing this topic.

Offline Frederick J. Harris

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1005
  • Gender: Male
    • Frederick J. Harris
64 Bit COM C++ Code Works With Out Of Process 32 Bit Servers ...
« on: February 12, 2015, 08:42:08 PM »
...such as MS Excel.  Hadn't really thought of that scenario!  Of course, we all know of the dll situation where 32 bit code needs 32 bit dlls and 64 bit code needs 64 bits dlls, but the out of process server thing appears to be something of a wrinkle.  Here is some C++ code that opens an Excel file for me created with 32 bit Excel and 32 bit Excel is what is running on my 64 Bit Windows.  The file is C:\Tallies\Documents\01200206.xls and it successfully reads 10 rows of data and prints it to the console window.  Some of these wrappers some might find useful.  Oh!  I'm using my String Class instead of the C++ one so you would have to change that.  Shouldn't be a biggie.  Was using 64 bit Mingw GNU C++ ...

Code: [Select]
#ifndef   UNICODE
#define   UNICODE
#endif
#ifndef   _UNICODE
#define   _UNICODE
#endif
#include <windows.h>
#include <cstdio>
#include "Strings.h"
const CLSID CLSID_XLApplication = {0x00024500,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
const IID   IID_Application     = {0x000208D5,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};


String GetXLCell(IDispatch* pXLWorksheet, LCID& lcid, String& strRange)
{
 DISPPARAMS      NoArgs         = {NULL,NULL,0,0};
 IDispatch*      pXLRange       = NULL;
 VARIANT         vArgArray[1];
 VARIANT         vResult;
 DISPPARAMS      DispParams;
 HRESULT         hr;
 String          strCell;

 VariantInit(&vResult);
 vArgArray[0].vt                = VT_BSTR,
 vArgArray[0].bstrVal           = SysAllocString(strRange.lpStr());
 DispParams.rgvarg              = vArgArray;
 DispParams.rgdispidNamedArgs   = 0;
 DispParams.cArgs               = 1;  // Try to get Range
 DispParams.cNamedArgs          = 0;  // Invoke _Worksheet::Range("A1")  << returns IDispatch** to dispinterface Range
 hr=pXLWorksheet->Invoke(197,IID_NULL,lcid,DISPATCH_PROPERTYGET,&DispParams,&vResult,NULL,NULL);
 if(FAILED(hr))
    return strCell;
 pXLRange=vResult.pdispVal;

 //Member Get Value <6> () As Variant
 VariantClear(&vArgArray[0]);
 hr=pXLRange->Invoke(6,IID_NULL,lcid,DISPATCH_PROPERTYGET,&NoArgs,&vResult,NULL,NULL);
 if(SUCCEEDED(hr))
 {
    strCell=vResult.bstrVal;
    VariantClear(&vResult);
 }

 return strCell;
}


IDispatch* ptrSetWorkSheet(IDispatch* pXLWorksheets, LCID& lcid, String& strSheet, BOOL& blnSuccess)
{
 VARIANT         vResult;
 HRESULT         hr;
 VARIANT         vArgArray[1];
 DISPPARAMS      DispParams;
 DISPID          dispidNamed;
 IDispatch*      pXLWorksheet   = NULL;

 // Member Get Item <170> (In Index As Variant<0>) As IDispatch  >> Gets pXLWorksheet
 // [id(0x000000aa), propget, helpcontext(0x000100aa)] IDispatch* Item([in] VARIANT Index);
 VariantInit(&vResult);
 vArgArray[0].vt                = VT_BSTR;
 vArgArray[0].bstrVal           = SysAllocString(strSheet.lpStr());
 DispParams.rgvarg              = vArgArray;
 DispParams.rgdispidNamedArgs   = &dispidNamed;
 DispParams.cArgs               = 1;
 DispParams.cNamedArgs          = 0;
 hr=pXLWorksheets->Invoke(0xAA,IID_NULL,lcid,DISPATCH_PROPERTYGET,&DispParams,&vResult,NULL,NULL);
 if(FAILED(hr))
    return NULL;
 pXLWorksheet=vResult.pdispVal;
 SysFreeString(vArgArray[0].bstrVal);

 // Worksheet::Select()
 VariantInit(&vResult);
 VARIANT varReplace;
 varReplace.vt                  = VT_BOOL;
 varReplace.boolVal             = VARIANT_TRUE;
 dispidNamed                    = 0;
 DispParams.rgvarg              = &varReplace;
 DispParams.rgdispidNamedArgs   = &dispidNamed;
 DispParams.cArgs               = 1;
 DispParams.cNamedArgs          = 1;
 hr=pXLWorksheet->Invoke(0xEB,IID_NULL,lcid,DISPATCH_METHOD,&DispParams,&vResult,NULL,NULL);
 if(SUCCEEDED(hr))
    blnSuccess=TRUE;
 else
    blnSuccess=FALSE;

 return pXLWorksheet;
}


IDispatch* ptrXLWorkBook(IDispatch* pXLWorkbooks, LCID& lcid, String& strWorkBookPath, BOOL& blnSuccess)
{
 IDispatch*      pXLWorkbook   = NULL;
 VARIANT         vResult;
 VARIANT         vArgArray[1];
 DISPPARAMS      DispParams;
 DISPID          dispidNamed;
 HRESULT         hr;

 VariantInit(&vResult);         // Call Workbooks::Open() - 682  >> Gets pXLWorkbook
 vArgArray[0].vt                = VT_BSTR;
 vArgArray[0].bstrVal           = SysAllocString(strWorkBookPath.lpStr());
 DispParams.rgvarg              = vArgArray;
 DispParams.rgdispidNamedArgs   = &dispidNamed;
 DispParams.cArgs               = 1;
 DispParams.cNamedArgs          = 0;
 hr=pXLWorkbooks->Invoke(682,IID_NULL,lcid,DISPATCH_METHOD,&DispParams,&vResult,NULL,NULL);
 if(FAILED(hr))
 {
    blnSuccess=FALSE;
    return NULL;
 }
 SysFreeString(vArgArray[0].bstrVal);
 pXLWorkbook=vResult.pdispVal;
 blnSuccess=TRUE;

 return pXLWorkbook;
}


int main()
{
 DISPPARAMS NoArgs         = {NULL,NULL,0,0};
 IDispatch* pXLApp         = NULL;
 IDispatch* pXLWorkbooks   = NULL;
 IDispatch* pXLWorkbook    = NULL;
 IDispatch* pXLWorksheets  = NULL;
 IDispatch* pXLWorksheet   = NULL;
 IDispatch* pXLRange       = NULL;
 String strParam,strNum;
 VARIANT vResult;
 BOOL blnSuccess;
 HRESULT hr;
 LCID lcid;

 CoInitialize(NULL);
 hr=CoCreateInstance(CLSID_XLApplication, NULL, CLSCTX_LOCAL_SERVER, IID_Application, (void**)&pXLApp);
 if(FAILED(hr))
    goto Sad_Ending;
 printf("CoCreateInstance() Succeeded!  pXLApp = %u\n",(unsigned)pXLApp);
 lcid=GetUserDefaultLCID();
 VariantInit(&vResult);  //572 Get _Application::Workbooks  >> Gets pXLWorkbooks
 hr=pXLApp->Invoke(572,IID_NULL,lcid,DISPATCH_PROPERTYGET,&NoArgs,&vResult,NULL,NULL);
 if(FAILED(hr))
    goto Sad_Ending;
 pXLWorkbooks=vResult.pdispVal;
 strParam=L"C:\\Tallies\\Documents\\01200206.xls";
 pXLWorkbook=ptrXLWorkBook(pXLWorkbooks, lcid, strParam, blnSuccess);
 if(!pXLWorkbook)
    goto Sad_Ending;
 if(!blnSuccess)
    goto Sad_Ending;
 VariantInit(&vResult);
 hr=pXLWorkbook->Invoke(494,IID_NULL,lcid,DISPATCH_PROPERTYGET,&NoArgs,&vResult,NULL,NULL);
 if(FAILED(hr))
    goto Sad_Ending;
 pXLWorksheets=vResult.pdispVal;
 blnSuccess=FALSE, strParam=L"FMT-19";
 pXLWorksheet=ptrSetWorkSheet(pXLWorksheets, lcid, strParam, blnSuccess);
 if(!pXLWorksheet)
    goto Sad_Ending;
 if(!blnSuccess)
    goto Sad_Ending;
 for(int i=16; i<=25; i++)
 {
     strParam=L"K", strNum=i;
     strParam=strParam+strNum;
     //strCell=GetXLCell(pXLWorksheet, lcid, strParam);
     wprintf(L"%s\n",GetXLCell(pXLWorksheet, lcid, strParam).lpStr());
 }
 pXLApp->Invoke(0x0000012e,IID_NULL,LOCALE_USER_DEFAULT,DISPATCH_METHOD,&NoArgs,NULL,NULL,NULL); // pXLApp->Quit() 0x12E

 Sad_Ending: // Workbooks::Close() 277
 if(pXLRange)
    pXLRange->Release();
 if(pXLWorksheet)
    pXLWorksheet->Release();
 if(pXLWorksheets)
    pXLWorksheets->Release();
 if(pXLWorkbook)
    pXLWorkbook->Release();
 if(pXLWorkbooks)
    pXLWorkbooks->Release();
 if(pXLApp)
    pXLApp->Release();
 CoUninitialize();
 getchar();

 return 0;
}

// Call Workbook::Worksheets()  //Member Get Worksheets  <494> () As XLSheets  >> Gets pXLWorksheets
// Call Workbook::Sheets()      //Member Get Sheets      <485> () As XLSheets
//[id(0x000001e5), propget, helpcontext(0x000101e5)] HRESULT Sheets([out, retval] Sheets** RHS);
//[id(0x000001ee), propget, helpcontext(0x000101ee)] HRESULT Worksheets([out, retval] Sheets** RHS);