VC ソースコンバートトラブルを解説
中井技術工房
VC6→VC2005 移行トラブル
May.01,2019 改正
トップ>
ここ
■
VC2005 移行トラブル
当方が公開しているソフトをVC6 から VC2005 へ移行するときに出くわしたトラブルについて解説します。
解決策についてもできるだけ概説します。
Microsoft め、いいかげんな製品をだすな!と何回もののしりました。
[ トラブルリスト ]
- 1) WinExec でアプリを引数付きで呼び出せない
- 2) sprintf_s,strcpy_s で文字化けする
- 3) 変数の初期化をしないようだ
- 4) 自動的な変数の型変換をしないようだ
- 5) オーバーロード関数〜のエラーが出る
- 6) MDI アプリのアイコンが自動で置換されない
- 7) トラブル7−−デスクトップアイコンが古いままになる
- 8) コンボボックスでリストゾーン定義手順が変わった
- 9) Manifestの埋め込みに失敗する。
- 10) リソースファイルが「他のエディタで使用中」で開けない
以下、項目別に詳細に示します。
●
トラブル1−−WinExec でアプリを引数付きで呼び出せない
[ 現象 ]
当方で公開しているソフトから印刷プログラムを起動するときに、これまで WinExec 関数を使って次のようにPrnF.exe を引数付きで呼び出していました。
- sprintf_s(msg,sizeof(msg),"PrnF.exe F=%s PF=%s CV=0",szDFinclrslt,DFinclrslt_dflt);
- UINT wReturn = ::WinExec(msg,SW_SHOW);
- if( wReturn<32 ) {
- sprintf_s(msg,sizeof(msg),"印刷プログラムの起動に失敗:エラーコード=%d",wReturn);
- MessageBox(msg,"確認要求",MB_OK | MB_ICONEXCLAMATION);
- }
これはエラー中断するようになりました。正確に言うと起動途中で消えてなくなり、エラーも追跡できません。
確かに、WinExec は古く、CreateProcess を使うように Microsoft が推奨しているのは知ってはいたが??
[ 解決案1−−失敗 ]
そこで、引数を別個に指定できる ShellExecute 関数を使用することにし、次のようにコーディングしました。
- sprintf_s(msg,sizeof(msg),"F=%s PF=%s CV=0",szDFinclrslt,DFinclrslt_dflt);
HINSTANCE ret=::ShellExecute(m_hWnd,NULL,"PrnF.exeのフルパス",msg,NULL,SW_SHOW);
if( (int)ret<32 ) {
- sprintf_s(msg,sizeof(msg),"印刷プログラムの起動に失敗:エラーコード=%d",(int)ret);
- MessageBox(msg,"確認要求",MB_OK | MB_ICONEXCLAMATION);
}
これで確かに PrnF.exe は呼び出されましたが、やはり起動途中で消えてなくなります。
デバッグモードで、途中でいろいろ止めて観察すると、第3引数(上例では msg のところ) を、実行ディレクトリにくっつけて処理しています。
MSDN ではここは引数のみを記述することになっているんじゃが?
[ 解決案2−−成功 ]
そこで、次のように引数の先頭に PrnF.exe を再度記述することにしました。
- sprintf_s(msg,sizeof(msg),
"PrnF.exe
F=%s PF=%s CV=0",szDFinclrslt,DFinclrslt_dflt);
HINSTANCE ret=::ShellExecute(m_hWnd,NULL,"PrnF.exeのフルパス",msg,NULL,SW_SHOW);
if( (int)ret<32 ) {
- sprintf_s(msg,sizeof(msg),"印刷プログラムの起動に失敗:エラーコード=%d",(int)ret);
- MessageBox(msg,"確認要求",MB_OK | MB_ICONEXCLAMATION);
}
これで無事動くようになりました。
ああ、疲れた!
●
トラブル2−−sprintf_s,strcpy_s で文字化けする
[ 現象 ]
1行文字列を合成するために、いったんスペースで埋めて、文字列途中に別文字列を埋めると、その前後に 0xfd とか 0x00 の想定外のキャラクタが現れる。
しかもネットで調べると
デバッグモードだけ現れる
現象のようだ。
コーディングは次の例を参照ください。どこも欠点はないと思うが?
- char msg[256];
- memset(msg,0x20,55);
- sprintf_s(&msg[ 3],sizeof(msg)-3,"No");
- sprintf_s(&msg[13],sizeof(msg)-13," 幅");
- sprintf_s(&msg[24],sizeof(msg)-24,"深さ");
- sprintf_s(&msg[39],sizeof(msg)-39,"中心座標");
- sprintf_s(&msg[55],sizeof(msg)-55,"剪断フラグ\r\n");
下図は結果サンプルです。左が Release モードで正常だが、右側の Debug モードではところどころ不要なキャラが出ていることがわかる。
[ 解決案−−成功? ]
リリースモードにすると正常に動作しました。
非常に気持ちが悪いが、このままにすることにした。
●
トラブル3−−変数の初期化をしないようだ
[ 現象 ]
初期化していない変数があると、動作がおかしい。初期化処理をしないようだ。(昔のIBM 汎用機がこうだった。)
たとえばクラス変数を使うと、コンストラクタなどで初期化するのを忘れることがある。
VC6 ではクリアされていたものがクリアされないので、変な動作をする。
[ 妙案はない ]
初期化忘れはちょっと判定しにくい。こまめにチェックするしかない。
●
トラブル4−−自動的な変数の型変換をしないようだ
[ 現象 ]
たとえば、
- CString m_Str;
- m_Str= (int 変数);
-
というのも VC6 では問題なく通っていた。
[ 厳密にやるしかない ]
この件については別に MS に文句はないが。
●
トラブル5−−オーバーロード関数〜のエラーが出る
[ 現象 ]
VC6 で開発した関数を不用意に組み込むと、
- オーバーロード関数が定義されていません。
とかのエラーメッセージに引っかかる。
VC6 では無事通っていたのに〜おかしい、おかしいとさんざん悩んだ。
[ 文字コードをマルチバイトに ]
VC2005 はデフォルトで Unicode を適用する。
したがって関数の引数に文字列を採用していると上記のトラブルが発生する。
プロジェクトを作って、VC6 の関数をコピーする前に必ず、
「プロジェクト」→「プロパティ」→「構成プロパティ」→「全般」→「文字セット」にて
「マルチバイト文字〜」
を選択してください。
●
トラブル6−−MDI アプリのアイコンが自動で置換されない
[ 現象 ]
VC6 のMDI プロジェクトでは、アプリのアイコンはリソース→Icon→ IDR_MAINFRAME で定義したアイコンがそのままアプリのアイコンとして採用されていた。
でもこのアプリをWin7 でデスクトップにショートカットで引き出すと、デフォルトアイコン(ブロック積みみたいなやつ)になってしまう。
ネットで調べても情報不足でさんざん悩んだ。
[ エクスプローラで置換した ]
アプリのアイコンは、IDR_MAINFRAME ではなく、ソリューションエクスプローラのリソースファイルの
(プロジェクト名).ico
のようだ。(下図参照)
しかもこのファイルをこのソリューションエクスプローラ上で、コピーとか削除とかするといろいろ問題があるようだ。
結局、アイコンを別に作って、エクスプローラで同名ファイルに置換したらうまくいった。
●
トラブル7−−デスクトップアイコンが古いままになる
[ 現象 ]
アイコンを修正してEXE を作りなおすと、エクスプローラでの表示は新しいアイコンに変わる。
しかし、このEXE のアイコンをデスクトップへショートカットを作ると古いアイコンのままになってしまい、いくらやっても更新されない。
[ キャッシュを消した ]
ネットで調べると、デスクトップのアイコンは、なんとキャッシュが効いているそうな。
だからソフトをいくら更新してもデスクトップへ引き出すと古いままになる。
いったんソフトを消しても、キャッシュが残るようだ。なんだ仕様は!
ユーザーディレクトリにある隠しファイルIconCache.db を消してから再立ち上げするとキャッシュが消えて解決する。
詳しくは、
http://support.microsoft.com/kb/958740/ja
を参照ください。ソフト側ばっかり考えて疲れたぞ!
[ ファイル名を変更しても可 ]
当該ファイル名を変更してから、デスクトップへショートカットをいったん作り、デスクトップのアイコンのファイル名を元名に変更します。
これでも逃れられます。
キャッシュを消すのもあまり効かんかった。
[ セーフモード起動で直る ]
いくらやっても直らないことがあり、ネットで調べると、いったんセーフモードで起動してみる、というのが有効であることがわかりました。
これがお勧め。(2019/5/1)
●
トラブル8−−コンボボックスでリストゾーン定義手順が変わった
[ 現象 ]
これまでコンボボックスをリストボックスで使用する場合、いったん「TYPE=標準」にして左下図のようにドロップダウンゾーンを指定してから「TYPE=ドロップダウンリスト」へ変更していました。
でもVC2005 になってこのゾーン指定は、ドロップダウンリストには無効で、下向きボタンをクリックしてもリスト表示しなくなりました。
この方法は昔何かの本で読んで何年も使っていたので本当に悩んでしまいました。
[ 解決策 ]
あらためてガイド本を読み、右下図のようにドロップダウンリスト選択状態で、下向きボタンをクリックしてゾーンを修正しました。
これが本来の手続きみたいです。
それまでは、TYPE に関係なく同じゾーンが適用されていたようです。
●
トラブル9−−Manifest 埋め込みに失敗する
[ 現象 ]
リンク時に「 Failed to write the updated manifest 〜 」とかのメッセージで止まる。
[ 解決策 ]
ネットで原因をさがすと、どうもウイルス対策ソフトのせいのようだ。
Cディスクはウイルスチェックなしで使用するのはこわいので、サブディスクにソフトをおいて、ウイルス対策ソフトにこのディスクをチェックしないように設定すると、回避できるようになった。
●
トラブル10−−「他のエディタで使用中」でリソースが開けない
[ 現象 ]
リソースファイル(プロジェクト名.rc)ファイルをリソースビューで開こうとすると
他のエディタで使用中
というメッセージが出て開けない。
この現象はリソースファイルを汎用エディタで改正してから再読込みをすると起きるようだ。さらに改正直後は起きず、PCを再立ち上げしたあとに起きやすいようだ。
[ 解決策 ]
どうもバグくさいが、2回この現象にでくわし、さんざんネットで調べても原因、対策はわからなかった。
で、何をしたら解決したかといえば
開いているソース類を全部クローズ
したら直った。
これだけでよい。
いったんVisual Studio をクローズする必要がある場合もあります。
それでもなったら、いったん rc ファイルを1行直して再読み込みすればOKです。
この現象は非常にショッキングでした。作り直さんといかんのかい、と思わず叫んでしまった。
トップ >
頁トップ