- PR -

SHGetFIleInfoでファイルの種類を取得

1
投稿者投稿内容
カズ
会議室デビュー日: 2004/02/20
投稿数: 9
投稿日時: 2005-03-22 10:13
WIN32APIのSHGetFileInfoを使用して、ファイルの種類を取得したいのですがうまくいきません。
どこがおかしいのかわからない状態です。誰か助けてください。

[StructLayout(LayoutKind.Sequential,CharSet = CharSet.Auto)]
public struct SHFILEINFO{
  public IntPtr hIcon;
  public int iIcon;
  public uint dwAttribute;
  [MarshalAs(UnmanagedType.ByValTStr,SizeConst = 260)]public string szDisplayName;
  [MarshalAs(UnmanagedType.ByValTStr,SizeConst = 80)]public string szTypeName;
}

[DllImport("shell32.dll",EntryPoint = "SHGetFileInfo")]
private static extern IntPtr SHGetFileInfo(
  [MarshalAs(UnmanagedType.LPStr)]string pszPath,
  uint dwFileAttributes,
  out SHFILEINFO psfi,
  uint cbFileInfo,
  uint uFlags
);

[Flags()]public enum SHGFI:uint{
  Icon = 0x100,
  DisplayName = 0x200,
  TypeName = 0x400,
  LargeIcon = 0x0,
  SmallIcon = 0x1,
  OpenIcon = 0x2,
  UseFileAttribute = 0x10
}
public string GetFileType(string path){
  SHFILEINFO sfi = new SHFILEINFO();
  if(FileSystemUtil.SHGetFileInfo(path,
    0,
    out sfi,
    (uint)Marshal.SizeOf(sfi),
    (uint)(SHGFI.DisplayName | SHGFI.UseFileAttribute)).Equals(IntPtr.Zero)){
    throw new ApplicationException("ファイルタイプの取得に失敗しました。");
  }
  return (string)sfi.szDisplayName;
}
Hongliang
ぬし
会議室デビュー日: 2004/12/25
投稿数: 576
投稿日時: 2005-03-22 11:37
具体的にどううまくいかないのかを書いて下さいね。

入力したパスがそのまま返ってきているのなら、このコードから見て
SHFGI.DisplayNameを取得させているからではないですか?
ファイルの種類ならSHFGI.TypeNameを使ってSHFILEINFO.szTypeNameを取得しなければなりません。

/* 追加 */
それから、SHGetFileInfoのpszPathパラメータはLPCTSTRですから、
DllImport属性にCharSet=CharSet.Autoを追加し、
pszPathパラメータのMarshalAs属性は無しにすべきです。
またSHFILEINFO構造体の文字列もTCHARですから、
StructLayout属性にもCharSet=CharSet.Autoを追加します。
/* ここまで */

以下、余談です。
折角SHFGIのメンバを.NETらしくしてるのですから、SHFGIという列挙体名そのもの、
SHFILEINFOとそのメンバ、SHGetFileInfoのパラメータもついでに.NETらしくするのはどうでしょう。

それから、SHGetFileInfoのなかでuFlagsパラメータがuintで宣言されていますが、
これは列挙体を使っているならそのままSHFGI型で宣言して構いません。

[ メッセージ編集済み 編集者: Hongliang 編集日時 2005-03-22 11:57 ]
カズ
会議室デビュー日: 2004/02/20
投稿数: 9
投稿日時: 2005-03-22 20:30
引用:

入力したパスがそのまま返ってきているのなら、このコードから見て
SHFGI.DisplayNameを取得させているからではないですか?
ファイルの種類ならSHFGI.TypeNameを使ってSHFILEINFO.szTypeNameを取得しなければなりません。

/* 追加 */
それから、SHGetFileInfoのpszPathパラメータはLPCTSTRですから、
DllImport属性にCharSet=CharSet.Autoを追加し、
pszPathパラメータのMarshalAs属性は無しにすべきです。
またSHFILEINFO構造体の文字列もTCHARですから、
StructLayout属性にもCharSet=CharSet.Autoを追加します。
/* ここまで */

以下、余談です。
折角SHFGIのメンバを.NETらしくしてるのですから、SHFGIという列挙体名そのもの、
SHFILEINFOとそのメンバ、SHGetFileInfoのパラメータもついでに.NETらしくするのはどうでしょう。

それから、SHGetFileInfoのなかでuFlagsパラメータがuintで宣言されていますが、
これは列挙体を使っているならそのままSHFGI型で宣言して構いません。



すいません間違えました。SHFILEINFO.szTypeNameを取得すべきでした。
SHFILEINFO.szTypeNameを取得しても空の文字列しか返ってきていなかったんです。
Hongliangさんの言うとおり、API宣言を修正したら直りました。

名前に関してはその場しのぎでAPIから直接参考にしてました。
.NETらしく変えておこうと思います。
Hongliangさんありがとうございました。
1

スキルアップ/キャリアアップ(JOB@IT)