Blue Campus
ちょっとした記録

最近 C++/CLI でも Excel を操作したいという質問をよく見ます。
そこでサンプルでも作っておこうかなとおもって、いろいろやってみたのですが、
CLRプロジェクト-Windows フォームアプリケーションのときに、ある条件のときに実行できなくなります。
(コンパイルはできる)

以下そのコードです。Formも立ち上がらずすぐにASSERTします。
(ちなみに、CoInitializeは(何でかはよくわからないけど)不要のようです。)

#import "C:\Program Files\Common Files\Microsoft Shared\OFFICE11\MSO.DLL" \
    no_namespace rename("DocumentProperties", "DocumentPropertiesXL") \ 
    rename("RGB", "MSO_RGBXL")
#import "C:\Program Files\Common Files\Microsoft Shared\VBA\VBA6\VBE6EXT.OLB" \
    no_namespace
#import "D:\Program Files\Microsoft Office\OFFICE11\EXCEL.EXE" \
    rename("ReplaceText", "ReplaceTexXL") rename("CopyFile", "CopyFileXL") \
    rename("DialogBox", "DialogBoxXL" ) rename("RGB", "RGBXL")\
    rename("DocumentProperties", "DocumentPropertiesXL") \
    exclude("IFont") exclude("IPicture") no_dual_interfaces

HRESULT ExcelTest()
{
    HRESULT hr = S_OK;
    Excel::_ApplicationPtr pApp = NULL;
    try
    {
        hr = pApp.CreateInstance(L"Excel.Application");
        if (FAILED(hr)) _com_issue_error(hr);
        Excel::WorkbooksPtr pWorkbooks = pApp->GetWorkbooks();
        if (pWorkbooks)
        { 
            Excel::_WorkbookPtr pWorkbook = pWorkbooks->Add();
            if (pWorkbook)
                pWorkbook->Close();
        }
        pApp->Quit();
    }
    catch (_com_error& e)
    {
        hr = e.Error();
    }
    if (pApp) pApp.Release();
    return hr;
}

環境:Visual Studio 2005 Pro SP1/Windows Xp Pro SP2/Excel 2003 Personal SP2
オプション:Unicode 文字セットを使用する, 共通言語ランタイム サポート (/clr)
(一応ソースは分けてあります。(ExcelTest.cpp))

これをCLRコンソールアプリケーションで記述し動かしても何も問題ありません。
で、本題の
>ある条件のときに
とは、引数省略時のvtMissingではなかろうか?と思っています。
上のコードの Excel::Workbooks::Add と Excel::Workbook::Close をコメントアウトすると正常に実行できます。
また、
>Excel::_WorkbookPtr pWorkbook = pWorkbooks->Add();

Excel::_WorkbookPtr pWorkbook = pWorkbooks->Add(Excel::xlWBATWorksheet);
にして、Excel::Workbook::Close をコメントアウトしても正常に実行できます。

>pWorkbook->Close();

_variant_t v;
pWorkbook->Close(v);
としても実行できません。

ASSERTは
D:\Program Files\Microsoft Visual Studio 8\VC\crt\src\dbgheap.c の 1473 で発生し、ちょっと理解しにくそうなものです。
>_ASSERTE(_CrtIsValidHeapPointer(pUserData));

一応、#pragma unmanged とか、試してみたけど意味なしっぽく、お手上げ状態です、、、
もう少しやってみて、だめなら掲示板にスレたてますかな。

投稿日時 : 2007年1月16日 1:53
コメント
  • # re: [C++/CLI]Windows フォームアプリケーションでタイプライブラリを使ってExcelを操作できない
    Blue
    Posted @ 2007/01/16 8:42
    よくかんがえてみると、Excel::Workbook::Close の認識が間違っているっぽい。
    (手元にVS2005がないので試せないけど)
    Excel::xlWBATWorksheetのように既定値をいれてみるとうまくいくかも。
  • # re: [C++/CLI]Windows フォームアプリケーションでタイプライブラリを使ってExcelを操作できない
    シャノン
    Posted @ 2007/01/16 9:30
    > (ちなみに、CoInitializeは(何でかはよくわからないけど)不要のようです。)

    CLRが勝手に初期化してくれます。
  • # re: [C++/CLI]Windows フォームアプリケーションでタイプライブラリを使ってExcelを操作できない
    Blue
    Posted @ 2007/01/16 14:07
    > CLRが勝手に初期化してくれます。
    情報ありがとうございます。

    http://msdn2.microsoft.com/ja-jp/library/ms173265(VS.80).aspx
    の「COM の初期化」のところに記述されていましたね。
    ちゃんと確認すべきでした。
  • # re: [C++/CLI]Windows フォームアプリケーションでタイプライブラリを使ってExcelを操作できない
    Blue
    Posted @ 2007/01/16 19:35
    試してみました。

    pWorkbook->Close(VARIANT_FALSE, L"", VARIANT_FALSE);

    と、vtMissingをつかわない記述をすればASSERTはおきずに実行できるようです。

    ということで、省略引数はすべてOUTで砂。
    でもなんぜコンソールアプリはOKなんだろ?
  • # re: [C++/CLI]Windows フォームアプリケーションでタイプライブラリを使ってExcelを操作できない
    Blue
    Posted @ 2007/01/17 0:43
    ちなみに

    _variant_t v;
    pWorkbook->Close(v, v, v);

    でOKそうです。
    やはりvtMissingを使うような場合NGのような気がします。
  • # C++/CLIでタイプライブラリを使ってExcelを操作できない その2
    Blue Campus
    Posted @ 2007/01/19 1:15
    C++/CLIでタイプライブラリを使ってExcelを操作できない その2
  • # re: [C++/CLI]Windows フォームアプリケーションでタイプライブラリを使ってExcelを操作できない
    Blue
    Posted @ 2007/06/23 0:16
    >_variant_t v;
    >pWorkbook->Close(v, v, v);
    は間違いですね。

    Closeメソッドの場合はたまたまうまくいっていたようで、
    ディスパッチポインタを渡すところでは例外が発生してしまいます。

    vtMissingと等価にするには

    _variant_t v(DISP_E_PARAMNOTFOUND, VT_ERROR);

    とした値を使わないといけませんでした。
  • # re: [C++/CLI]Windows フォームアプリケーションでタイプライブラリを使ってExcelを操作できない
    ひらしょー
    Posted @ 2007/07/01 22:28
    通りすがりの者です。

    http://www.thescripts.com/forum/thread642179.html

    に解決策が載っている問題かもしれません。
    もしそうならばプロジェクトのプロパティのリンカの詳細の
    エントリポイントをデフォルトのmainから
    ?mainCRTStartupStrArray@@$$FYMHP$01AP$AABString@System@@@Z

    にすると動くと思われます。
    デフォルトで用意されるmainからはじめてしまう
    とCランタイムの初期化を経由せず、
    static変数その他の初期化でメモリを破壊して
    しまう、というようなことだそうです。
  • # re: [C++/CLI]Windows フォームアプリケーションでタイプライブラリを使ってExcelを操作できない
    Blue
    Posted @ 2007/07/03 1:06
    > プロジェクトのプロパティのリンカの詳細の
    エントリポイントをデフォルトのmainから
    >?mainCRTStartupStrArray@@$$FYMHP$01AP$AABString@System@@@Z
    として、main関数を
    int
    __clrcall mainCRTStartupStrArray(cli::array<class System::String ^ >^)
    に変更しましたが、やはり実行時にASSERTが発生し
    実行できませんでした。

    >デフォルトで用意されるmainからはじめてしまう
    とCランタイムの初期化を経由せず、
    >static変数その他の初期化でメモリを破壊して
    しまう
    はなるほどですね。
    本気で英語を読まないといけなさそう(汗)
  • # re: [C++/CLI]Windows フォームアプリケーションでタイプライブラリを使ってExcelを操作できない
    Blue
    Posted @ 2007/07/07 1:41
    とりあえず、

    http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=99693
    より

    >2w.) /clr - /SYSTEM:WINDOWS - [w]WinMain(<unmanaged args>) - [w]WinMainCRTStartup();
    (タイプライブラリを使うので/clr)
    で、/ENTRYは[w]WinMainCRTStartupにして、

    int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd)
    {
    return main(gcnew array<System::String^>(0));
    }

    てなコードをかましたところ動くには動きました。
  • # re: [C++/CLI]Windows フォームアプリケーションでタイプライブラリを使ってExcelを操作できない
    Blue
    Posted @ 2007/07/07 1:49
    >return main(gcnew array<System::String^>(0));

    return main(System::Environment::GetCommandLineArgs());
    でよさげ。
  • # re: [C++/CLI]Windows フォームアプリケーションでタイプライブラリを使ってExcelを操作できない
    Ivan
    Posted @ 2007/09/26 13:24
    Nice
  • # re: [C++/CLI]Windows フォームアプリケーションでタイプライブラリを使ってExcelを操作できない
    Blue
    Posted @ 2008/03/25 1:19
    一応リンクはっとこ。
    http://forums.microsoft.com/msdn-ja/ShowPost.aspx?PostID=2651529&SiteID=7
タイトル  
名前  
Url
コメント