CLSIDでの呼び出しで「ShellExecute」と「ファイル名を指定して実行」で結果が異なる

解決


Yoshi_K  2023-10-03 01:45:37  No: 151149  IP: [192.*.*.*]

お世話になります。
お知恵を拝借できればありがたいです。

殆どの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

編集 削除
take  2023-10-03 02:52:08  No: 151150  IP: [192.*.*.*]

CLSIDキーの値を SHGetFolderPathの引数として渡してパスを取得して開く方法はダメでしょうか?

編集 削除
mam  2023-10-03 04:07:00  No: 151151  IP: [192.*.*.*]

64ビットでコンパイルしたら動くんですけどね。32ビットだと駄目っぽいです。

外していたらすいません。

編集 削除
mam  2023-10-03 04:15:05  No: 151152  IP: [192.*.*.*]

DEKO様の
【Delphi】WOW64 のリダイレクトを回避するには?
を使用すれば32Bitでも可能かもですね。

https://qiita.com/ht_deko/items/039f03b08ec3f08995b3

編集 削除
Yoshi_K  2023-10-03 06:07:24  No: 151158  IP: [192.*.*.*]

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;

皆様、お騒がせしました。
また、大変ありがとうございました。

編集 削除
mam  2023-10-05 01:18:51  No: 151163  IP: [192.*.*.*]

以下のようにすると、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;

編集 削除
Yoshi_K  2023-10-20 02:17:11  No: 151190  IP: [192.*.*.*]

mamさん、遅くなりました。
Win32で動作確認できました。
私の引数の扱いがよろしくなかったです。
ありがとうございました。

編集 削除