C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

ログ内検索
  • キーワードを複数指定する場合は 半角スペース で区切ってください。
  • 検索条件は、(AND)=[A かつ B] (OR)=[A または B] となっています。
  • [返信]をクリックすると返信ページへ移動します。
キーワード/ 検索条件 /
検索範囲/ 強調表示/ ON (自動リンクOFF)
結果表示件数/ 記事No検索/ ON
大文字と小文字を区別する

No.85096 の関連記事表示

<< 0 >>
■85096  Re[7]: 複数ファイルをコピーする時に進捗ダイアログを表示する
□投稿者/ 魔界の仮面弁士 -(2017/09/11(Mon) 13:02:08)
    No85094 (カンガルー さん) に返信
    >>SHFILEOPSTRUCT 構造体のアライメントは、本来は 1 バイトパッキングです。
    >>提示 URL の VBA コードだと fFlags の後続メンバーの配置がずれますのでご注意ください。
    > これってどういう意味ですか?

    紹介した URL で解説していますが、ファイルコピーがユーザによってキャンセルされた場合、
    SHFILEOPSTRUCT の fAnyOperationsAborted メンバーに 1 がセットされる仕様なのです。
    (先のサンプルでは、キャンセルを判定するようなコードにはなっていないですけれどね)

    32bit環境においては、SHFILEOPSTRUCT 構造体のメモリ配置は、
     0x00-0x03 → HWND 型 hWnd
     0x04-0x07 → UINT 型 wFunc
     0x08-0x0B → PCZZTSTR 型 pFrom
     0x0C-0x0F → PCZZTSTR 型 pTo
     0x10-0x11 → FILEOP_FLAGS 型 fFlags
     0x12-0x15 → BOOL 型 fAnyOperationsAborted
     0x16-0x19 → LPVOID 型 hNameMappings
     0x1A-0x1D → PCTSTR 型 lpszProgressTitle
    と並んでいます。


    ところが VBA は、4バイト単位に再配置して呼び出す仕様です。

    0x00、0x04、0x08、0x0C というのは 4 バイト単位の位置に並んでいるので問題ないのですが、
    fAnyOperationsAborted が配置されているのは、「0x10-0x13 の後半」と「0x14-0x17 の前半」に
    またがるメモリ位置になっています。

    そこで VBA は、API の呼び出し時に自動的に 2 バイト分調整し、 No85091 の構造体を
     0x00-0x03 → Long 型 hWnd
     0x04-0x07 → Long 型 wFunc
     0x08-0x0B → String 型 pFrom
     0x0C-0x0F → String 型 pTo
     0x10-0x11 → Integer 型 fFlags
     0x12-0x13 → 【2 バイトのパディング】
     0x14-0x17 → Long 型 fAnyOperationsAborted
     0x18-0x1B → Long 型 hNameMappings
     0x1C-0x1F → String 型 lpszProgressTitle
    のメモリ配置に変換して渡すようになっています。


    ところが、API がキャンセル結果を書き込むのは
    0x12-0x15 のメモリ位置なので、結果を正しく受け取れなくなるわけです。

    受け取れないだけならまだ良いですが、ポインタである
    lpszProgressTitle に文字列を渡してから呼び出せば、
    クラッシュしてしまう可能性すらあるわけです。


    一方 VB.NET の場合は、StructLayoutAttibute 属性を付与することで、
    このアライメント調整を明示的に指定することができるようになっています。


    'SHFileOperationA を呼び出す場合は、CharSet.Ansi をセットします。
    'SHFileOperationW を呼び出す場合は、CharSet.Unicode をセットします。
    <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode, Pack:=1)> _
    Public Structure SHFILEOPSTRUCT
      Public hwnd As IntPtr
      <MarshalAs(UnmanagedType.U4)> Public wFunc As Integer '(Enum FILEOP As Int32)
      <MarshalAs(UnmanagedType.LPWStr)> Public pFrom As String
      <MarshalAs(UnmanagedType.LPWStr)> Public pTo As String
      <MarshalAs(UnmanagedType.U2)> Public fFlags As Short '(Enum FILEOP_FLAGS As Int16)
      <MarshalAs(UnmanagedType.Bool)> Public fAnyOperationsAborted As Boolean
      Public hNameMappings As IntPtr
      <MarshalAs(UnmanagedType.LPWStr)> Public lpszProgressTitle As String
    End Structure
記事No.85029 のレス /過去ログ145より / 関連記事表示
削除チェック/



<< 0 >>

パスワード/

- Child Tree -