プロが教えるわが家の防犯対策術!

いつも大変お世話になっております。
VC++初心者です。

前回質問した内容と重複しますが、
改めて質問させて頂きたいと思います。

現在、SHBrowseForFolderを使用すると、
デバグモードで実行すると以下のようなエラーが出力され困っています。
「例外処理 (初回) は XXXX.exe (NTDLL.DLL) にあります: 0xC0000005: Access Violation」
※実行環境:WindowsXp(sp3) VC++6.0(Sp6)
(ちなみ、このエラーは、PCによって発生したりしなかったりしています。)

http://msdn.microsoft.com/ja-jp/library/bb762115 …
を参照すると、「SHBrowseForFolderを使う前に、Component Object Model (COM)を初期化しなければいけません。」と表記されてますが、
初期化処理を行った後、SHBrowseForFolderを実行している
サンプルを見つけられません。

お手数ですが、上記サンプルをご提示して頂けませんでしょうか

現在、ここまで書いたので、ご指摘いただけると幸いです。
(ほとんど、他のページからの転用なのですが、、、)

****************
void CAAAAAA::OnButtonSelectFolder()
{
// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
UpdateData(TRUE);
BROWSEINFO bInfo;
LPITEMIDLIST pIDList;
TCHAR szDisplayName[MAX_PATH];

// BROWSEINFO構造体に値を設定
bInfo.hwndOwner = AfxGetMainWnd()->m_hWnd; // ダイアログの親ウインドウのハンドル
bInfo.pidlRoot = NULL; // ルートフォルダを示すITEMIDLISTのポインタ (NULLの場合デスクトップフォルダが使われます)
bInfo.pszDisplayName = szDisplayName; // 選択されたフォルダ名を受け取るバッファのポインタ
bInfo.lpszTitle = _T("フォルダの選択"); // ツリービューの上部に表示される文字列
bInfo.ulFlags = BIF_RETURNONLYFSDIRS; // 表示されるフォルダの種類を示すフラグ
bInfo.lpfn = NULL; // BrowseCallbackProc関数のポインタ
bInfo.lParam = (LPARAM)0; // コールバック関数に渡す値


// フォルダ選択ダイアログを表示
pIDList = ::SHBrowseForFolder(&bInfo);
if(pIDList == NULL){

// 戻り値がNULLの場合、フォルダが選択されずにダイアログが閉じられたことを意味します。
}else{
// ItemIDListをパス名に変換します
if(!::SHGetPathFromIDList(pIDList, szDisplayName)){
// エラー処理
}
// szDisplayNameに選択されたフォルダのパスが入っています
m_csFolderName = szDisplayName;
// 最後にpIDListのポイントしているメモリを開放します
::CoTaskMemFree( pIDList );
}

UpdateData(FALSE);//データ初期化(反映)

}

A 回答 (5件)

 こんばんは。

お礼頂きました。

・MFCプロジェクトへのCoInitialize()/CoUninitialize()の必要性

 MFCにおいては、必要無い筈です。
 COMを使用する際には必ずCoInitizlize()等による初期化が必要です。
 其のまま使用すると、その場でプログラムがクラッシュしたりするので直ぐに分かります。

 MFCでは初期化無しでも動いたのですから、MFCアプリがスタートする際に、呼び出されている筈です。
 ただし、何処で呼び出されているのかを特定する時間が無かったので、敢えて言及しませんでした。

この回答への補足

御回答、ありがとうございます。

>MFCにおいては、必要無い筈です。
安心しました。
だから、SHBrowseForFolderを説明している他のサイトでも
MFCの場合は、CoInitialize()/CoUninitialize()を使っていないのですね。

あと、もう1つ以下の事を確認させて頂けませんでしょうか。
>・C:\psdk\tmp\setupフォルダ内のPSDK-x86.msiをダブルクリック
と助言頂きましたが、#3の「この回答へのお礼」で書いた
http://www.noppi.jp/diary/?date=20080114
の内容と異なるため、
「C:\psdk\tmp\setupフォルダ内のCoreSDK-x86.msiをダブルクリック」
も上記に加えて実行しました。
PSDK-x86.msiでなく、CoreSDK-x86.msiが正しいのではないのでしょうか。
(せっかく教えて頂いてるのに、すみません。)
(PSDK-x86.msiとCoreSDK-x86.msiで何が違うかまったく理解していませんが、、、)
(しかしながら、結局「Access Violation」が発生しました。)

補足日時:2009/09/30 11:05
    • good
    • 0

 こんばんは。

補足頂きました。

 以下にインストール方法が載っていました(*.msiをダブルクリックするのでは無い見たいです)。
 http://none-real-sidem.spaces.live.com/Blog/cns! …

 昔、当方がインストールしたのはCD版のPSDKでした(自動的に正しくインストールされる)。
 今現在、CD版のPSDKが配布されていない為、.cabファイルを手動インストールするタイプの方を使用するしか道が無いのですが、正直な所、当方も今回が初めてですので、詳しくは分りません。

この回答への補足

ご回答、ありがとうございます。
(返信遅れて、すみませんでした。)

ご紹介頂いたページを確認しました。
教えて頂いた内容を実行すると
#2の「この回答へのお礼」の現象が発生し、
インストールできませんでした。
(しかし、CoreSDK-x86.msiの実行でそれらしいことが
 出来ているので、根拠はありませんが、問題ないのかな、
 とも思っています。)

話を戻して、
「例外処理 (初回) は XXXX.exe (NTDLL.DLL) にあります: 0xC0000005: Access Violation」
というエラーが出ているので、NTDLL.DLLを調べてみました。

まず、自分のPCで「NTDLL.DLL」で検索すると、何個かのNTDLL.DLLが
ヒットしますが、実際に使用されているのは、WINDOWS\system32内の
NTDLL.DLLでしょうか。

また、WINDOWS\system32\NTDLL.DLLのバージョンを調べると
以下のようになりました。
エラーが出ないPCのNTDLL.DLLのバージョン:5.1.2600.2180
エラーが出る PCのNTDLL.DLLのバージョン:5.1.2600.5755
このバージョンの違いは関係あるのでしょうか。

補足日時:2009/10/04 17:04
    • good
    • 0
この回答へのお礼

追伸です。

何台かのPCのNTDLL.DLLのバージョンを調べてみました。
ViolationがでるPC、でないPCのNTDLL.DLLのバージョンは
関係なさそうです。
(5.1.2600.xxxxのxxxxの値がそれぞれのPCで違いましたが、
 値が大きいものでもViolationが発生したり、
 値が小さいものでもViolationが発生しなかったりしています。)

Violationが出るPC、出ないPCに共通する点は、
某セキュリティソフトが起因していそうです。
(出るPCにはみんなそのソフトがインストールされています。)
(これは私の勝手な見解です。)

本件について長い間、ご相談させていただきましたが、
一度こちらの質問を閉じさせて頂きます。
今までご協力して頂きありがとうございました。

お礼日時:2009/10/07 21:00

 こんばんは。

補足頂きました。

 どうやら、PSDKサイト内の説明がおかしい上、ダウンロードしたPSDK-FULL.?.cabファイル群のうちの幾つかの拡張子がhtmになってしまっている様です。

 ・Cドライブにpsdkフォルダを作成する
 ・psdkフォルダ内にtmpフォルダを作成する
 ・psdkフォルダにPSDK-FULL.?.cabを置く(拡張子がおかしくなっている場合は拡張子をcabに直す)
 ・DOSプロンプトを立ち上げる
 ・DOSプロンプトをC:\psdkへ移動
 ・DOSプロンプトからC:\psdk>PSDK-FULL.bat C:\psdk\tmpを実行
 ・C:\psdk\tmp\setupフォルダ内のPSDK-x86.msiをダブルクリック

 で出来ませんか。

・includeとlinkの参照設定について
 此れに関しては、vc6.0で、今まで使用していたインクルードやリンクのパスの代わりに、新しくインストールしたPSDKに対してインクルードやリンクのパスを設定するという事です。

 新しいPSDKを導入してもアクセスバイオレーションが発生したのならば、当方はギブアップという事になります。

この回答への補足

ご回答、ありがとうございます。
早速試してみます。

先の質問に戻りますが、MFCプロジェクトでコーディングしている場合、
CoInitialize()/CoUninitialize()は必要なのでしょうか。
他のサイトを参照すると、必要ないような事が書かれていましたので。
(他のプロジェクト、例えば、「Win32 Application」などを
 使用している場合は必要になるらしいのですが。)

補足日時:2009/09/29 07:35
    • good
    • 0
この回答へのお礼

追伸です。

やはりViolationが発生してしまいました。

ちなみに、includeとlinkの参照設定については、
以下のページを参照させて頂きました。
http://www.noppi.jp/diary/?date=20080114
(もし、設定の仕方が違うようならば、ご指摘いただけると嬉しいです。)

また、今回の場合についてMFCプロジェクトへのCoInitialize()/CoUninitialize()の
必要性も教えて頂きたくお願いします。

当分は、
デバグでもリリースでも、
「Microsoft Foundation Class 」を
「共有のDLLでMFCを使用」から
「MFCスタティックライブラリを使用」に変更して使用していこうと思います。

ご教授、ありがとうございました。

お礼日時:2009/09/29 10:22

 こんにちは。

補足頂きました。
 書いている途中に追伸が着ましたので、先に追伸の方から返答すると、

・「共有のDLLでMFCを使用」から
・「MFCスタティックライブラリを使用」に変更すると出なくなりました。
 確証はありませんが、vc6.0に付属しているPlatform SDKが古くてxpにそぐわないのが理由の様な気がします。

 vbaとxp(sp3)でSHBrowseForFolder()を実行するとアクセスバイオレーションが発生すると言った記事を見ました。
 http://www.eggheadcafe.com/software/aspnet/30395 …

 当方の、
 vc6.0 windows2000(sp4)
 vc2008 windows xp(sp3)
 では実行出来ています。

 以下補足に対してですが、試すとすれば、

 (1)リリースビルドして実行してみる
 (2)UNICODEでビルドしてみる
 (3)Platform SDKをvc6.0が利用出来る中で最新のものにしてみる
  http://ja.wikipedia.org/wiki/Microsoft_Windows_SDK

 位でしょうか。

 (1)は言語が違うのですが、
 http://www.activebasic.com/forum/viewtopic.php?p …

 に因んで、試してみると言う事です。

 (3)は以下のサイトから
 http://www.microsoft.com/msdownload/platformsdk/ …

 を落として来て、vc6.0に付属しているPlatform SDKの代わりに使用します(includeとlinkの参照設定も行います)。

この回答への補足

ご回答、ありがとうございます。

>(1)リリースビルドして実行してみる
エラー(Access Violation)は発生しませんでした。
※一応、実行時、メニューの「デバッグ」、「例外処理」で
 「Access Violation」を「常に停止」に変更しましたが、
 途中で落ちることはありませんでした。

>(2)UNICODEでビルドしてみる
debugビルドで実行:
エラー(Access Violation)は発生しました。
リリースビルドで実行
エラー(Access Violation)は発生しませんでした。

(3)Platform SDKをvc6.0が利用出来る中で最新のものにしてみる
教えて頂いたページの5まで実行しました。
しかし6の「Setup.exe」とは何を指すのでしょうか。
6. Run Setup.exe to install the Platform SDK using the SDK Update interface.

>vc6.0に付属しているPlatform SDKの代わりに使用します(includeとlinkの参照設定も行います)。
とは、具体的にどういうことなのでしょうか。

初歩的な質問ですみません。

補足日時:2009/09/28 12:01
    • good
    • 0
この回答へのお礼

追伸です。
>(1)リリースビルドして実行してみる。
こちらは、メニューの「プロジェクト」、「設定」の
「プロジェクトの設定」画面内の
「設定の対象」を「Win32 Debug」でも「Win32 Release」でも
「Microsoft Foundation Class」を
「共有DLLでMFCを使用」にすると、Violationが発生し、
「MFCのスタティックライブラリを使用」にすると、Violation発生しませんでした。

>(3)Platform SDKをvc6.0が利用出来る中で最新のものにしてみる
>6. Run Setup.exe to install the Platform SDK using the SDK Update interface.
C:\psdk内のSetup.Exeということですね。
(ぼけていました。)
しかし、実行すると、IE8が現れ、インストールできませんでした。
タイトル:
 「IEXPLORE.EXE - アプリケーションエラー」
内容:
 「"0x04ae0068"の命令が"0x04ae0068"のメモリを参照しました。
 メモリが"written"になることはできませんでした。
 プログラムを終了する場合は「OK」をクリックしたください。、、、」

お礼日時:2009/09/28 15:07

 こんばんは。



 CoInitialize()/CoUninitialize()の事ではないでしょうか。

 http://msdn.microsoft.com/en-us/library/ms678543 …
 http://msdn.microsoft.com/en-us/library/ms688715 …

 取り敢えず、C???App::InitInstance()の中に置いて試して見ては如何でしょうか。

BOOL C???App::InitInstance()
{
::CoInitialize(NULL);

//省略
//...
//省略

::CoUninitialize();
return FALSE;
}

この回答への補足

御回答、ありがとうございます。

試してみましたが、まだエラーが出てしまいます。
何か他に、対応策はありませんでしょうか。

補足日時:2009/09/28 09:15
    • good
    • 0
この回答へのお礼

追伸です。

メニューの「プロジェクト」、「設定」で
「プロジェクトの設定」画面を出し、
その中の「一般」タブの「Microsoft Foundation Class 」を
「共有のDLLでMFCを使用」から
「MFCスタティックライブラリを使用」に変更すると出なくなりました。

※しかし、別のPCでは「共有のDLLでMFCを使用」の設定でも
エラーは出力されていません。

これから何か分かりませんでしょうか。

お礼日時:2009/09/28 10:11

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!