none
FormatMessageで不明なエラー「System.Runtime.InteropServices.MarshalDirectiveException: 'parameter #7' をマーシャリングできません: ポインタはマーシャリングされた構造体を参照できません。ByRef を使用してください。」 RRS feed

  • 質問

  • エラーメッセージを表示するために以下のコードをネットを参考にして試した。
    Microsoft Visual C++ 2008 on Visual Studio 2008 over Vista

    LPVOID lpMsgBuf;
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|FORMAT_MESSAGE_ARGUMENT_ARRAY,
                           NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL);

    そうするとコンパイルは無事通るが実行時に「 'parameter #7' をマーシャリングできません: ポインタはマーシャリング。。。」というエラーが出る。
    MSDNのサンプルでもNULLとなっているのに7番目のパラメータにアクセスしようと知るようだ。アクセスしてもNULLなら何も無いで処理されるのでは?

    配列を定義して(va_list*)で配列を修飾しても結果は変わらない。

    一体何が必要なのか?By Refでやれとはポインタ処理するようにということ同じでは?

    ネット検索しても同じキーワードにはヒットしない。
    2009年11月7日 5:51

回答

  • これにこだわっている理由はWindowsの対話画面からパラメータ入力をベースにCLIでないコンソールアプリケーションを実行して結果を画面で確認するという一連の作業を実行することを目的として始めました。このとき、実行時のエラーを捕捉して確認したいのでFormatMessageを使用し、結果をポップアップで表示することにしたのがことの発端です。

    そういう意味では簡単に対話画面作成することからC++/CLIを利用しているということです。Windowsでのプログラム開発はVBAくらいしか必要に迫られたことが無かったのですが、CDから蓄積したMedia PlayerライブラリのWindows Media Format内容を確認する個人的な必要からWMD SDKにあるC++のサンプルコードを改良して情報取得をするようになり。次いで、バッチ画面で一々入力するのも手間なので画面からの処理を考えたのですが、FlexではWindowsのコマンド処理を発見できなかったのでWindows開発ならとVisual Studio 2008を利用することになり、ここに至るという経緯です。

    そういった意味ではWindowsでの開発は全くの初心者といってもかまいませんので、ご迷惑おかけしています。
    C++言語の知識を既にお持ちで使用している環境がExpress Editionでないのなら、わざわざC++/CLIでフォームアプリを作成するより
    C++言語でMFCを使ったMFCアプリケーションを作成した方がWeb上に参考例も多いですし、無難だと思います。
    書かれている内容からするとダイアログベースのアプリで十分そうですから、そこまでハードルは高く無いと思いますし。
    C++/CLIは、名前にC++がついているので誤解されやすいですが、C++言語とは全くの別物です。
    なのでC++言語を知っていてもかなり違いがあるので色々勉強する必要があります。
    メモリ管理等も異なりますから、似て非なるものというレベルの違いでは無いと思います。

    あと、Win32APIのFormatMessageを使うだけならコンソールプログラムでも使えるはずです。
    表示をするだけならprintfで画面に出しても良いわけですし。
    最終的にはWindowを使ったGUIアプリを作る事が目的であれば良いのですが、Windowsでの開発が初めてでGUIアプリを作成する事になると
    結構、覚えないといけない事が多いのでエラー表示をする為だけにやるには少々ハードルが高いように思います。

    このフォーラムに書き込まれているのでExpress Editionでは無いと思いますが、質問の際にはEditionまで書いておくと
    不明確な点が減るので良いと思います。あと、できれば御本人がどの程度の知識を持っているのかまで最初から書いておくと
    さらに良いと思います。C++言語でオリジナルのクラスを作成し、それを使ってアプリが作成できるとか具体的にどういう事ができるかを
    書いておくと書き込まれるアドバイスがより適切な物になると思いますよ。


    解決した時は、参考になったレスポンスの所にある[回答としてマーク]ボタンをクリックしてスレッドを締めましょう。
    2009年11月20日 4:31

すべての返信

  • まず確認です。
    一般的なC++ではなく、C++/CLIという特殊な環境を使用されていますが、そのことは認識されていますか?
    MSDNのサンプルやネット検索で見つかる情報は同じく一般的なC++向けの情報です。ですのでそれらの情報はC++/CLIには当てはまらない部分があります。

    ソースコードの記述を見る限り意図せずC++/CLIを使っているように見受けられますので、C++/CLIのまま解決したい or C++/CLIをやめC++を使用したい のどちらでしょうか?
    2009年11月7日 7:41
  • 早速のコメントありがとうございます。

    ご指摘の件、一切意識していませんでした。
    但し、C++に関してはこの環境以外で開発予定はないのでC++/CLIのまま解決できればと考えています。

    以上、よろしくお願いします。
    2009年11月7日 9:06
  • C++の記述をC++/CLIで解釈させるのは茨の道ですよ…。
    面倒なので当該コードを含む関数を

    #pragma managed(push, off)
    ~関数~
    #pragma managed(pop)
    

    でくくってしまってはどうでしょう?
    2009年11月7日 9:21
  • 試してみました。
    関数の前後に入れて見ました。

    1>c:\users\tsuyoshi\documents\visual studio 2008\projects\test2\test2\Form1.h(278) : error C3295: '#pragma managed' は、グローバルまたは名前空間スコープでのみ使用できます

    というコンパイルエラーとなります。

    結構違いがあるようですね。
    2009年11月7日 10:37
  • FormatMessage 関数を呼ぶところを別関数に切り出して、マネージクラスの中から分離してみませんか?
    できれば、cpp ファイルを別にしてしまって、ネイティブでコンパイルされるように cpp ファイルの個別の設定を変えて、ネイティブコードとしてコンパイルされるようにすると良いかもしれません。(試していません)

    cpp 個別に /CLR あり、なしが設定できます。
    この際のトラブルとしてよくあるのが、プリコンパイル済みヘッダーを /CLR の有無によって分けないといけないことでしょうか。


    # もっと楽な方法があるかもしれませんが、今は出先のため、経験的なところで回答しています。


    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    2009年11月8日 1:33
    モデレータ
  • 以下試してみました。

    個別プロジェクトでCLRでなくコンパイル実行すると確かに何のエラーも-無くメッセージ変換します。

    指摘のとおり別CPPとして記述しコンパイルすると有効でないPCHと言うことでコンパイルできません。PCHを作成するに変更するとコンパイルは通ります。ビルドすると「fatal error LNK1313: ijw/native モジュールが検出されました。pure モジュールとリンクできません。」となりリンクが出来ずに先に進めません。別プロジェクトにしてソリューションレベルでビルドすれば可能なのでしょうか?

    上記の内容で検索したら一件ヒットしましたが、書かれている内容からは適切な対応策を読み取れませんでした。

    その後ランタイムオプションをCLRのみとすればこのエラーは発生せず、最初に記述したエラーも発生しません。

    成功したCPPの内容
    void MsgFmt::Formatting(DWORD errNO)
    {
        LPVOID lpMsgBuf;
        long rslt = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|FORMAT_MESSAGE_ARGUMENT_ARRAY,
                                    NULL, errNO, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL);
        MessageBox(NULL, (LPCWSTR)lpMsgBuf, NULL, MB_OK);
    }

    これを参考に
    MessageBox::Show( (LPCWSTR)lpMsgBuf, L"Last Error Message", MessageBoxButtons::OK, MessageBoxIcon::Exclamation);

    としたらLPCWSTRが適用できないようでエラー「オーバーロードのどれも、すべての引数の型を変換できませんでした」となります。

    何か、適当な方法は考えられますか?

    2009年11月17日 5:24
  • 茨の道を更に突き進んでますね。
    Win32 APIのFormatMessage()関数を使うなら同じくWin32 APIのMessageBox()関数を使うのかと思っていました。
    ここでいきなり.NETのMessageBoxクラスを使うのはかなりハードルが高いです。
    .NETクラスメンバを呼び出す場合、その引数は.NET型である必要があります。LPCWSTRはnativeな型ですが、ここでは.NETのstring型が求められています。

    最初に聞きましたが、C++/CLIを使用する意義を確認したいです。
    使用されるのであれば、上記の通り、変数にはnativeな型と.NET型がありますので、関数呼び出しなどを考慮して、どこまでをnative変数+Win32 APIで実装し、どこから.NET型+.NETクラスで実装するのか、ご自身の中で境界線をはっきり持ってください。
    2009年11月17日 12:01
  • エラーメッセージからするとString^を期待しているようなのでこれへの変換を実現できればと探しているとC++ /CLI Tips : 文字列操作 に探し物が見つかった。下記の要領でString^に変換したものを使えば無事思い通りの結果が得られました。

    String^ textString = gcnew String((LPCWSTR)lpMsgBuf);

    これにこだわっている理由はWindowsの対話画面からパラメータ入力をベースにCLIでないコンソールアプリケーションを実行して結果を画面で確認するという一連の作業を実行することを目的として始めました。このとき、実行時のエラーを捕捉して確認したいのでFormatMessageを使用し、結果をポップアップで表示することにしたのがことの発端です。

    そういう意味では簡単に対話画面作成することからC++/CLIを利用しているということです。Windowsでのプログラム開発はVBAくらいしか必要に迫られたことが無かったのですが、CDから蓄積したMedia PlayerライブラリのWindows Media Format内容を確認する個人的な必要からWMD SDKにあるC++のサンプルコードを改良して情報取得をするようになり。次いで、バッチ画面で一々入力するのも手間なので画面からの処理を考えたのですが、FlexではWindowsのコマンド処理を発見できなかったのでWindows開発ならとVisual Studio 2008を利用することになり、ここに至るという経緯です。

    そういった意味ではWindowsでの開発は全くの初心者といってもかまいませんので、ご迷惑おかけしています。
    2009年11月17日 15:53
  • これにこだわっている理由はWindowsの対話画面からパラメータ入力をベースにCLIでないコンソールアプリケーションを実行して結果を画面で確認するという一連の作業を実行することを目的として始めました。このとき、実行時のエラーを捕捉して確認したいのでFormatMessageを使用し、結果をポップアップで表示することにしたのがことの発端です。

    そういう意味では簡単に対話画面作成することからC++/CLIを利用しているということです。Windowsでのプログラム開発はVBAくらいしか必要に迫られたことが無かったのですが、CDから蓄積したMedia PlayerライブラリのWindows Media Format内容を確認する個人的な必要からWMD SDKにあるC++のサンプルコードを改良して情報取得をするようになり。次いで、バッチ画面で一々入力するのも手間なので画面からの処理を考えたのですが、FlexではWindowsのコマンド処理を発見できなかったのでWindows開発ならとVisual Studio 2008を利用することになり、ここに至るという経緯です。

    そういった意味ではWindowsでの開発は全くの初心者といってもかまいませんので、ご迷惑おかけしています。
    C++言語の知識を既にお持ちで使用している環境がExpress Editionでないのなら、わざわざC++/CLIでフォームアプリを作成するより
    C++言語でMFCを使ったMFCアプリケーションを作成した方がWeb上に参考例も多いですし、無難だと思います。
    書かれている内容からするとダイアログベースのアプリで十分そうですから、そこまでハードルは高く無いと思いますし。
    C++/CLIは、名前にC++がついているので誤解されやすいですが、C++言語とは全くの別物です。
    なのでC++言語を知っていてもかなり違いがあるので色々勉強する必要があります。
    メモリ管理等も異なりますから、似て非なるものというレベルの違いでは無いと思います。

    あと、Win32APIのFormatMessageを使うだけならコンソールプログラムでも使えるはずです。
    表示をするだけならprintfで画面に出しても良いわけですし。
    最終的にはWindowを使ったGUIアプリを作る事が目的であれば良いのですが、Windowsでの開発が初めてでGUIアプリを作成する事になると
    結構、覚えないといけない事が多いのでエラー表示をする為だけにやるには少々ハードルが高いように思います。

    このフォーラムに書き込まれているのでExpress Editionでは無いと思いますが、質問の際にはEditionまで書いておくと
    不明確な点が減るので良いと思います。あと、できれば御本人がどの程度の知識を持っているのかまで最初から書いておくと
    さらに良いと思います。C++言語でオリジナルのクラスを作成し、それを使ってアプリが作成できるとか具体的にどういう事ができるかを
    書いておくと書き込まれるアドバイスがより適切な物になると思いますよ。


    解決した時は、参考になったレスポンスの所にある[回答としてマーク]ボタンをクリックしてスレッドを締めましょう。
    2009年11月20日 4:31