フォーラム


ゲスト  

ようこそ ゲスト さん。このフォーラムに投稿するには 登録が必要です。

ページ: [1]
トピック: バッドノウハウ
DEKO
管理者
投稿数: 2691
バッドノウハウ
on: 2013/07/06 09:15 Sat

古い OS (Windows) を対象としたコードは冗長になりがちです。
例えば特殊フォルダ (シェルフォルダ) を得る関数は古い OS を考慮すると以下の URL にあるようなコードになってしまいます。

[シェルフォルダ - Windows Vista対応アプリを作る (Delphi VCL Tips)]
http://ht-deko.minim.ne.jp/tech005.html

// Windowsの特殊フォルダを取得
function GetSpecialFolderPath(hwndOwner: THandle; var Path: String; nFolder: Integer): Boolean;
var
Buf: PChar;
{ _GetSpecialFolderPath begin }
function _GetSpecialFolderPath(hwndOwner: THandle; var lpszPath: PChar; nFolder: Integer; fCreate: Boolean): Boolean;
var
pidl: PItemIDList;
pMalloc: IMalloc;
begin
result := False;
if SHGetMalloc(pMalloc) <> NOERROR then
Exit;
if SHGetSpecialFolderLocation(hwndOwner, nFolder, pidl) = NOERROR then
Exit;
if SHGetPathFromIDList(pidl, lpszPath) then
result := True;
pMalloc.Free(pidl);
end;
{ _GetSpecialFolderPath end }
begin
result := True;
Buf := StrAlloc(MAX_PATH);
try
if SHGetSpecialFolderPath(hwndOwner, Buf, nFolder, False) then
Path := ExcludeTrailingPathDelimiter(StrPas(Buf))
else if _GetSpecialFolderPath(hwndOwner, Buf, nFolder, False) then
Path := ExcludeTrailingPathDelimiter(StrPas(Buf))
else
result := False;
finally
StrDispose(Buf);
end;
end;

 
なんとメンドイ。しかも現在では SHGetSpecialFolderPath() / SHGetSpecialFolderLocation() は非推奨 API となっています。

SHGetSpecialFolderPath() -> ShGetFolderPath()
SHGetSpecialFolderLocation() -> SHGetFolderLocation()

 
今現在ならば、上記コードはシンプルに書けます。

function GetFolderPath(nFolder: Integer): string;
var
LStr: array [0..MAX_PATH] of Char;
begin
SetLastError(ERROR_SUCCESS);
if SHGetFolderPath(0, nFolder, 0, 0, @LStr) = S_OK then
result := LStr;
end;

 
Windows 2000 以降ならこれで OK なハズです。このように、昔の情報のままだとやたらとコードを記述しなくてはならなかったりします。これも所謂バッドノウハウの一種です。

…しかしながら、Vista 以降では SHGetFolderPath() すら SHGetKnownFolderPath() のラッパーとなっています。

SHGetSpecialFolderPath() -> ShGetFolderPath() -> SHGetKnownFolderPath()
SHGetSpecialFolderLocation() -> SHGetFolderLocation() -> SHGetKnownFolderIDList()

 
おいおいってな感じですね。

特殊フォルダ (シェルフォルダ) に関する詳細は Mr.XRAY さんとこの記事をご覧下さい。

See Also:
[460_特殊フォルダのフルパスを取得 (Mr.XRAY)]
http://mrxray.on.coocan.jp/Delphi/plSamples/460_SpecialFolderPath.htm

DEKO
管理者
投稿数: 2691
Re: バッドノウハウ (XP と Vista の違い)
on: 2013/07/06 09:39 Sat

昔書いた記事です (http://ht-deko.minim.ne.jp/ft0702.html#070224)。

・Vista のWindowsAPI
 例えば文字列へのポインタを引数で取る API があったとする。この API は正常終了時に文字列へのポインタ (の示す先) に対して文字列を入れて返す。文字列は空である事もある。この API をループで回して処理する…といった場合、

AAAA
BBBB
(なし)
DDDD

のように文字列が返る…少なくとも XP では。ところが Vista では

AAAA
BBBB
BBBB <-
DDDD

のように、正常終了時で文字列が空の場合には文字列へのポインタ (の示す先) が初期化されない事があるようだ。今後は API 呼び出し前に文字列を必ず初期化した方がよさそうだ。 SHSFP は SHGetFolderPath() で件の現象に遭遇したため、文字列初期化処理を組み込んである。

 
# SHSFP はシェルフォルダを列挙 / 再設定するコンソールアプリケーションです。
# http://ht-deko.minim.ne.jp/junkbox.html#SHSFP

Mr.XRAY
メンバー
投稿数: 192
Re: バッドノウハウ
on: 2013/07/06 18:28 Sat

サイトの記事の紹介サンクスです.
DEKO さんの記事も参考にさせて頂きます.
この文字列の扱いなんですが, 少なくとも SHGetFolderPath は失敗した時は空文字のようです.
わたしのところのコードは,一応空にしてから呼び出していますが.これも含めて,後で細かい修正をと.
なんせ,誤字脱字の修正が最優先なもんですから (^^;

API によって挙動が違うことがあるようなので,わたしゃ確実なことが言えませんです.ハイ.
そうか,SetLastError(ERROR_SUCCESS); を書いておけはいいのか.なるほど.

Mr.XRAY
メンバー
投稿数: 192
Re: バッドノウハウ
on: 2013/07/06 18:32 Sat

Windows API には,やたら非推奨とか,サポート外とかありますが.
Delphi のメソッド,関数類にもありすが,実際には使えますから.
便利なら使った方がいいと思っている私です.

DEKO
管理者
投稿数: 2691
Re: バッドノウハウ
on: 2013/07/06 19:18 Sat

引用 Mr.XRAY on 2013/07/06 18:28 Sat
この文字列の扱いなんですが, 少なくとも SHGetFolderPath は失敗した時は空文字のようです.

 
Vista の SP (或いはホットフィックス) で仕様が XP と同じに戻っているのかもしれませんね。これまた "バッドノウハウ" ですが…(^^;A

DEKO
管理者
投稿数: 2691
Re: バッドノウハウ
on: 2013/07/06 19:24 Sat

引用 Mr.XRAY on 2013/07/06 18:28 Sat
サイトの記事の紹介サンクスです.

 
丁度 GCT.EXE で 特殊フォルダ (シェルフォルダ) を扱ってる時にサイトの記事を更新されていたので、ネタ的にもナイスタイミングだったのです。
# ちなみに、上にある GetFolderPath() は Delphi の GetHomePath() のパクリです (w
# 何故これに相当する関数が用意されていないのか未だに疑問なのですが。

ページ: [1]
WP Forum Server by ForumPress | LucidCrew
バージョン: 1.7.5 ; ページロード: 0.031 sec.