お世話になります。
お知恵を拝借できればありがたいです。
殆どのCLSIDキーによる特殊フォルダーの呼出しに於いて「ShellExecute」でも
「ファイル名を指定して実行」でも結果は同じなのですが、一部のキーでは動作
が異なるようです。
例えば「システムアイコン」を表示する
CLSID'{05d7b0f4-2121-4eff-bf6b-ed3f69b894d9}\SystemIcons'なのですが
「ファイル名を指定して実行」で
'shell:::{05d7b0f4-2121-4eff-bf6b-ed3f69b894d9}\SystemIcons'
は「システムアイコン」が正常に表示されます。
ところが「ShellExecute」では表示されません。
procedure TForm1.Button1Click(Sender: TObject);
begin
var StrTxt := 'shell:::{05d7b0f4-2121-4eff-bf6b-ed3f69b894d9} \SystemIcons';
ShellExecute(Self.Handle, '', PChar(StrTxt), nil, nil, SW_SHOW);
//ERROR :2・・・ ERROR_FILE_NOT_FOUND 結果何も表示されません。
end;
パラメータと分けてみます。
procedure TForm1.Button1Click(Sender: TObject);
begin
var StrTxt := 'shell:::{05d7b0f4-2121-4eff-bf6b-ed3f69b894d9}';
var StrPrm := '\SystemIcons';
var nRet := ShellExecute(Self.Handle, '', PChar(StrTxt), PChar(StrPrm), nil, SW_SHOW);
//ERROR :31・・・ SE_ERR_NOASSOC 結果何も表示されません。
end;
コマンドプロンプトでも正常に呼び出せるので、バッチファイルならと試してみました。
procedure TForm1.Button1Click(Sender: TObject);
begin
var StrFileName := 'D:\abc.bat';
var SL := TStringList.Create;
try
SL.Clear;
SL.Add('explorer shell:::{05d7b0f4-2121-4eff-bf6b-ed3f69b894d9} \SystemIcons');
//SL.Add(':Lbl0');
//SL.Add('DEL ' + StrFileName );
//SL.Add('IF EXIST ' + StrFileName + ' GOTO Lbl0' );
SL.SaveToFile(StrFileName);
finally
SL.Free;
end;
ShellExecute(Handle, '', PChar(StrFileName), nil, nil, SW_HIDE);
end;
結果は「Documentフォルダー」が開いてしまいます。
作成されたバッチファイルを直接実行すると「システムアイコン」のフォルダーが
表示されますので問題ないようには思えるのですがよくわかりません。
他、以下のCLSIDでも同様でした。
{ファイアウォール許可されたアプリ}
shell:::{4026492F-2F69-46B8-B9BF-5654FC07E423} -Microsoft.WindowsFirewall\pageConfigureApps
{デスクトップの背景}
shell:::{ED834ED6-4B5A-4bfe-8F11-A626DCB6A921} -Microsoft.Personalization\pageWallpaper
根本的に私が間違っているのか、環境なのかよくわかりません。
何とか、プログラムを通してCLSIDで特殊フォルダーが開ければと思います。
よろしくお願いいたします。
Windows10Pro 22H2
Delphi10,11
CLSIDキーの値を SHGetFolderPathの引数として渡してパスを取得して開く方法はダメでしょうか?
64ビットでコンパイルしたら動くんですけどね。32ビットだと駄目っぽいです。
外していたらすいません。
DEKO様の
【Delphi】WOW64 のリダイレクトを回避するには?
を使用すれば32Bitでも可能かもですね。
https://qiita.com/ht_deko/items/039f03b08ec3f08995b3
Takeさん
ありがとうございます。
SHGetFolderPathは本目的のCLSIDキーと定数が結び付きませんでした。
目的のフォルダーとは違いますが、ShlObjに宣言されている幾つかの定数で試しましたが、
CSIDL_DESKTOPはフォルダーを取得でき表示する事はできましたが、CSIDL_PRINTERSは
フォルダーさえ取得できない結果となってしまいました。
CSIDL_PRINTERSは'Shell:::{A8A91A66-3A7D-4424-8D24-04E180695C7A}'
='\control.exe printers'と勝手に解釈しましたが違うのかな?
よくわかりません。
manさん
ありがとうございます。
正解でございました。
私、32ビットでコンパイルしておりました。
64ビットでコンパイルして正常に「システムアイコン」を表示する事を確認しました。
因みに、DEKOさんのWOW64のリダイレクトを試しましたが、32ビットコンパイラでライブラリ内
の関数(Wow64DisableWow64FsRedirection及びWow64RevertWow64FsRedirection)が呼び出され
ているのは確認できましたが、何故か目的の特殊フォルダーを表示する事はできませんでした。
uses uWOW64;
procedure TForm1.Button1Click(Sender: TObject);
begin
var OldValue: LongBool;
DisableWow64FsRedirection(OldValue);
try
// リダイレクトが予想される処理 (ShellExecute など)
var StrTxt := 'shell:::{05d7b0f4-2121-4eff-bf6b-ed3f69b894d9} \SystemIcons';
ShellExecute(Self.Handle, '', PChar(StrTxt), nil, nil, SW_SHOW);
//32ビットコンパイルではERROR :2・・・ ERROR_FILE_NOT_FOUND
finally
RevertWow64FsRedirection(OldValue);
end;
end;
皆様、お騒がせしました。
また、大変ありがとうございました。
以下のようにすると、DEKO様の「uWOW64」ユニットを使って、32BITでも動作しました。
ご参考まで。
uses uWOW64,ShellAPI;
procedure TForm1.Button1Click(Sender: TObject);
var OldValue: LongBool;
begin
DisableWow64FsRedirection(OldValue);
try
// リダイレクトが予想される処理 (ShellExecute など)
ShellExecute(
Self.Handle, 'open',
'explorer',
'shell:::{05d7b0f4-2121-4eff-bf6b-ed3f69b894d9} \SystemIcons',
nil, SW_SHOW
);
finally
RevertWow64FsRedirection(OldValue);
end;
end;
mamさん、遅くなりました。
Win32で動作確認できました。
私の引数の扱いがよろしくなかったです。
ありがとうございました。
ツイート | ![]() |