none
OLE com automation, invoke and access violation RRS feed

  • Question

  • Hello,

    We also use OLE Com automation in our XLL, to be precise in our recalculation handler.

    My tewst system is german Windows with installed german office,
    especially not en_us.

    I import the information via

    #import "tlb\office\14\mso.dll" \
    	rename("RGB", "MSORGB") \
    	rename("DocumentProperties","MSODocumentProperties") \
    	rename("xlStackScale", "MSOxlStackScale")  \
    	rename("xlStack", "MSOxlStack") \
    	rename("xlStretch", "MSOxlStretch") \
    	rename("IAccessible", "MSOIAccessible")
    
    using namespace Office;
    
    #import "tlb\office\14\VBE6EXT.OLB"
    
    using namespace VBIDE;
    
    #import "tlb\office\14\Excel.exe" \
    	rename("DialogBox", "ExcelDialogBox") \
    	rename("RGB", "ExcelRGB") \
    	rename("CopyFile", "ExcelCopyFile") \
    	rename("ReplaceText", "ExcelReplaceText") \
    	rename("xlStackScale", "ExcelxlStackScale")  \
    	rename("xlStack", "ExcelxlStack") \
    	rename("xlStretch", "ExcelxlStretch") \
    	rename("xlCommand", "ExcelxlCommand") \
    	rename("xlFunction", "ExcelxlFunction") \
    	rename("xlNotXLM", "ExcelxlNotXLM") \
    	rename("xlHierarchy", "ExcelxlHierarchy") \
    	rename("xlMeasure", "ExcelxlMeasure") \
    	rename("xlSet", "ExcelxlSet") \
    	rename("xlPrompt", "ExcelxlPrompt") \
    	rename("xlConstant", "ExcelxlConstant") \
    	rename("xlRange", "ExcelxlRange") \
    	no_auto_exclude
    

    This automatically generates for Excel:RangePtr

    inline _variant_t Excel::Range::GetNumberFormat ( ) {
    VARIANT _result;
    VariantInit(&_result);
    _com_dispatch_method(this, 0xc1, DISPATCH_PROPERTYGET, VT_VARIANT, (void*)&_result, NULL);
    return _variant_t(_result, false);
    }
    
    inline void Excel::Range::PutNumberFormat(const _variant_t & _arg1) {
    	_com_dispatch_method(this, 0xc1, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL,
    		L"\x000c", &_arg1);
    }
    

    Unfortunatly this returns or espect the numberformat in the nlv (here german) version, and not as I hoped in en_us version.
    So for me it looks like _com_dispatch_method uses LOCALE_SYSTEM_DEFAULT, and not 1033

    So I tried to invoke directly

    inline _variant_t XLCOMRange::MyGetNumberFormat() {
    	VARIANT _result;
    	DISPPARAMS Params;
    
    	Params.cArgs = 0;
    	Params.cNamedArgs = 0;
    	Params.rgdispidNamedArgs = nullptr;
    	Params.rgvarg = nullptr;
    
    	VariantInit(&_result);
    
    	HRESULT hr = this->xRange->Invoke(0xC1, IID_NULL, 1033, DISPATCH_PROPERTYGET, &Params, &_result, NULL, NULL);
    
    	return _variant_t(_result, false);
    }
    

    This really returns the number in en_us, but my problem is now the seeting of a numberformat

    inline  void XLCOMRange::MyPutNumberFormat(wchar_t* format) {
    	DISPPARAMS Params;
    
    	VARIANTARG vformat[1];
    
    	Params.cArgs = 1;
    	Params.cNamedArgs = 0;
    	Params.rgdispidNamedArgs = nullptr;
    	Params.rgvarg = vformat;
    	Params.rgvarg[0].vt = VT_BSTR;
    	Params.rgvarg[0].bstrVal = SysAllocString(format);
    
    	HRESULT hr = this->xRange->Invoke(0xC1, IID_NULL, 1033, DISPATCH_PROPERTYPUT, &Params, NULL, NULL, NULL);
    }
    
    

    Unfortunatly the call to invoke leads to an access violation:

    So what's wrong in this method ?

    tia

      Hendrik Schmieder



    Friday, March 9, 2018 1:43 PM

Answers

  • Sorry for the long delay,
    but I had to work on other topics.

    With the help of
    http://www.cplusplus.com/forum/windows/125996/

    I found the soltuion

    [Note:
    one of the links inside there points to a dead Microsoft side]

    This code works.

    DISPPARAMS Params;
    VARIANT CallArgs[1];
    
    DISPID dispidNamed = DISPID_PROPERTYPUT;
    
    VariantInit(&CallArgs[0]);
    
    CallArgs[0].vt = VT_BSTR;
    CallArgs[0].bstrVal = SysAllocString(format);
    
    Params.rgvarg = CallArgs;
    Params.rgdispidNamedArgs = &dispidNamed;  // <--
    Params.cArgs = 1;
    Params.cNamedArgs = 1;  // <--
    
    HRESULT hr = this->xRange->Invoke(0xc1;, IID_NULL, 1033, DISPATCH_PROPERTYPUT, &Params, NULL, NULL, NULL);
    
    VariantClear(&CallArgs[0]);
    

    where format is of type wchar_t* and this->xRange is of type Excel::RangePtr.

    Important is the handlung of the attributes with 'NamedArgs" in name.

    • Marked as answer by h_schmieder Wednesday, April 3, 2019 11:49 AM
    Thursday, March 28, 2019 10:47 AM

All replies

  • Hi h_schmieder,

    You had mentioned that ,"This really returns the number in en_us, but my problem is now the seeting of a numberformat".

    what kind of number format you want and what number format it returns?

    Can you post the sample project? So that we will make a test with En_US version and try to check the result.

    By this way, We will able to understand the issue in better way.

    Regards

    Deepak


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, March 12, 2018 9:08 AM
    Moderator
  • Sorry for the long delay,
    but I had to work on other topics.

    With the help of
    http://www.cplusplus.com/forum/windows/125996/

    I found the soltuion

    [Note:
    one of the links inside there points to a dead Microsoft side]

    This code works.

    DISPPARAMS Params;
    VARIANT CallArgs[1];
    
    DISPID dispidNamed = DISPID_PROPERTYPUT;
    
    VariantInit(&CallArgs[0]);
    
    CallArgs[0].vt = VT_BSTR;
    CallArgs[0].bstrVal = SysAllocString(format);
    
    Params.rgvarg = CallArgs;
    Params.rgdispidNamedArgs = &dispidNamed;  // <--
    Params.cArgs = 1;
    Params.cNamedArgs = 1;  // <--
    
    HRESULT hr = this->xRange->Invoke(0xc1;, IID_NULL, 1033, DISPATCH_PROPERTYPUT, &Params, NULL, NULL, NULL);
    
    VariantClear(&CallArgs[0]);
    

    where format is of type wchar_t* and this->xRange is of type Excel::RangePtr.

    Important is the handlung of the attributes with 'NamedArgs" in name.

    • Marked as answer by h_schmieder Wednesday, April 3, 2019 11:49 AM
    Thursday, March 28, 2019 10:47 AM