Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.10.03;
Скачать: CL | DM;

Вниз

Диалог свойств файла (ShellExecuteEx)   Найти похожие ветки 

 
R1   (2004-08-18 17:38) [0]

Написал элементарную программку для показа диалога свойств файла, переданного в командной строке:

program showprop;

uses
 ShellApi;

var
 ShellExecuteInfo: TShellExecuteInfo;
begin
 if ParamCount <> 1 then
   WriteLn("One and only parameter expected.")
 else
 begin
   FillChar(ShellExecuteInfo, SizeOf(ShellExecuteInfo), 0);
   ShellExecuteInfo.cbSize := SizeOf(ShellExecuteInfo);
   ShellExecuteInfo.lpFile := PChar(ParamStr(1));
   ShellExecuteInfo.lpVerb := "properties";
   ShellExecuteInfo.fMask := SEE_MASK_INVOKEIDLIST;
   ShellExecuteEx(@ShellExecuteInfo);
 end;
end.

Однако при запуске:
showprop.exe c:\autoexec.bat
результатов работы программки (диалога свойств файла autoexec.bat) не наблюдается.

После небольшой добавки, а именно вставки вызова MessageBox сразу после ShellExecuteEx(@ShellExecuteInfo):

program showprop;

uses
 ShellApi, Windows;

var
 ShellExecuteInfo: TShellExecuteInfo;
begin
 if ParamCount <> 1 then
   WriteLn("One and only parameter expected.")
 else
 begin
   FillChar(ShellExecuteInfo, SizeOf(ShellExecuteInfo), 0);
   ShellExecuteInfo.cbSize := SizeOf(ShellExecuteInfo);
   ShellExecuteInfo.lpFile := PChar(ParamStr(1));
   ShellExecuteInfo.lpVerb := "properties";
   ShellExecuteInfo.fMask := SEE_MASK_INVOKEIDLIST;
   ShellExecuteEx(@ShellExecuteInfo);
   MessageBox(0, "qwerty", "qwerty", MB_OK);
 end;
end.

желаемое окно свойств файла появляется, причем через некоторое время после (!) MessageBox"а. А после нажатия на ОК MessageBox"а окно свойств исчезает.

Что и как надо делать, чтобы вывести окно свойств файла (и только его) и чтобы оно не исчезало самопроизвольно, а только когда я сам его закрою?


 
simpson ©   (2004-08-18 18:20) [1]

Попробуй так:


unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls;

const
 SHOP_PRINTERNAME = 1;
 SHOP_FILEPATH = 2;
 SHOP_VOLUMEGUID = 4;

type
 TForm1 = class(TForm)
   Button1: TButton;
   Edit1: TEdit;
   procedure Button1Click(Sender: TObject);
   procedure FormCreate(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

function SHObjectProperties(hOwnerWnd: HWND; dwType: DWORD;
 szObject, szPage: PWideChar): LongBool; stdcall;

implementation

function SHObjectProperties(hOwnerWnd: HWND; dwType: DWORD;
 szObject, szPage: PWideChar): LongBool;
 external "shell32.dll" name "SHObjectProperties";

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
 S: WideString;
begin
 S := Edit1.Text;
 if not SHObjectProperties(Application.Handle, SHOP_FILEPATH, PWideChar(S), nil) then
   ShowMessage("sorry...");
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 Edit1.Text := ParamStr(0);
end;

end.


 
simpson ©   (2004-08-18 18:40) [2]

Извиняюсь... просмотрел, что приложение консольное.
Тогда все в порядке вещей - завершается приложение, закрывается окно свойств.


 
R1   (2004-08-18 20:02) [3]

Как говорится, "все в порядке, идем ко дну, т. капитан!" :)

Вот как раз и хочется, чтобы диалог свойств файла оставался, пока лично его не закроют.

Кстати, о SHObjectProperties... Это какая-то странная функция, вообще... Сначала была совсем уж недокументирована, начиная с 5-ой версии shell32.dll она документирована, но по имени не вызывается, только по ординалу 178... В общем, вариант:

program showprop;

function SHObjectProperties(hWnd: LongWord; dwType: LongWord; szObject: Pointer;
 szPage: Pointer): LongBool; external "shell32.dll" index 178;

const
 SHOP_FILEPATH = 2;

begin
 if ParamCount <> 1 then
   WriteLn("One and only parameter expected.")
 else
   SHObjectProperties(0, SHOP_FILEPATH, PChar(ParamStr(1)), nil);

   { // тот же результат, что и строчкой выше...
   SHObjectProperties(Windows.FindWindow("Progman", "Program Manager"),
     SHOP_FILEPATH, PChar(ParamStr(1)), nil);
   }
end.

показывает диалог свойств какого-то неизвестного мне тома винчестера (с заголовком "Свойства: Том без метки", неизвестной файловой системой и с нулевыми емкостями)... Сам процесс showprop.exe при этом работает (в смысле, висит - в хорошем смысле - в памяти), пока этот диалог не закроют.

Таки как вызвать диалог свойств файла, закрыться - и чтоб этот диалог потом остался?


 
R1   (2004-08-18 20:06) [4]

Оговорюсь - 1) на дуракоустойчивость пока забил, допустим, showprop.exe всегда вызывается с ровно одним параметром; 2) программа не обязательно консольная (на WriteLn просьба пристальное внимание не обращать :)).


 
nikkie ©   (2004-08-19 02:30) [5]

я посмотрел Spy++ - диалог принадлежит нашему процессу, просто создан он другим потоком. варианта вижу два - либо прицепиться к чужому процессу (идеально explorer.exe - и вызвать ShellExecute в его контексте), либо банально считать количество потоков при завершении программы и не выходить, пока их больше, чем 1.


 
R1   (2004-08-19 15:20) [6]

nikkie ©   (19.08.04 02:30) [5]

> прицепиться к чужому процессу (идеально explorer.exe - и вызвать ShellExecute в его контексте)

Прошу прощения за возможную наивность, но как это сделать - вызвать ShellExecuteEx в контексте другого процесса, в частности, explorer.exe?

Очередной вариант:

program showprop;

uses
 ShellApi, Windows;

var
 ShellExecuteInfo: TShellExecuteInfo;
 ParentProcessID: THandle;
begin
 if ParamCount = 1 then
 begin
   FillChar(ShellExecuteInfo, SizeOf(ShellExecuteInfo), 0);
   ShellExecuteInfo.cbSize := SizeOf(ShellExecuteInfo);
   ShellExecuteInfo.lpFile := PChar(ParamStr(1));
   ShellExecuteInfo.lpVerb := "properties";
   ShellExecuteInfo.fMask := SEE_MASK_INVOKEIDLIST;
   GetWindowThreadProcessId(FindWindow("TAppBuilder", "Delphi 5 - showprop"),
     @ParentProcessID);
   ShellExecuteInfo.hProcess := ParentProcessID;
   ShellExecuteEx(@ShellExecuteInfo);
   MessageBox(0, "qwerty", "qwerty", MB_OK);
 end; // else
end.

не канает с тем же результатом - окно свойств живет только до нажатия на ОК MessageBox"а...


 
nikkie ©   (2004-08-19 15:39) [7]

поищи по этому форуму - обсуждается периодически внедрение в чужой процесс. обычно к Рихтеру отсылают. я все варианты не скажу, только что вспоминается: AppInitDLL, глобальный хук, CreateRemoteThread на NT-системах. но городить это ради того, чтобы диалог не закрывался - овчинка выделки не стоит. другое дело, если твое приложение можно реализовать как shell extension dll, например. тогда уже автоматически в процессе explorer-a окажешься.


 
R1   (2004-08-20 17:02) [8]

Понятно. Овчинка, действительно, выделки не стоит.

Вопрос остается открытым: таки как показать диалог свойств файла, закрыться, а диалог чтобы остался? Ведь если в проводнике вызвать "Свойства", потом закрыть проводник - диалог-то остается...


 
nikkie ©   (2004-08-20 17:36) [9]

>Ведь если в проводнике вызвать "Свойства", потом закрыть проводник - диалог-то остается...
это ты не проводник закрываешь, а одно из его окошек.
попробуй explorer.exe через TaskManager снять.

Вопрос остается открытым
>банально считать количество потоков при завершении программы и не выходить, пока их больше, чем 1.


 
R1   (2004-08-20 20:01) [10]

1) У меня вообще explorer.exe отсутствует в диспетчере задач. У меня Aston. :) Но мысль понятна, все верно. Да, действительно, при снятии explorer.exe, все открытые в нем окна свойств закрываются. Так как же он их так запускает?

2) Возникает другой вопрос - а как узнать количество потоков, запущеных процессом?

Можно, конечно, узнать количество дескрипторов - GetProcessHandleCount - и на этом как-то основываться, но, может быть, я чего-то в хелпе не заметил и можно легко узнать количество потоков?

И потом... Мне кажется, это тоже не выход. Сейчас попытаюсь объяснить...

Очередной вариант:

program showprop;

uses
 ShellApi, Windows, SysUtils;

function WaitingThreadFunc(PropCaption: PChar): DWORD; stdcall;
begin
 while FindWindow("#32770 (Dialog)", PropCaption) <> 0 do
   ;
 Result := 0;
end;

var
 ShellExecuteInfo: TShellExecuteInfo;
 ThreadHandle: THandle;
 szCaption: PChar;
 ThreadID: DWORD;
 S: string;
begin
 if ParamCount = 1 then
 begin
   FillChar(ShellExecuteInfo, SizeOf(ShellExecuteInfo), 0);
   ShellExecuteInfo.cbSize := SizeOf(ShellExecuteInfo);
   ShellExecuteInfo.lpFile := PChar(ParamStr(1));
   ShellExecuteInfo.lpVerb := "properties";
   ShellExecuteInfo.fMask := SEE_MASK_INVOKEIDLIST;
   ShellExecuteEx(@ShellExecuteInfo);

   GetMem(szCaption, 80);
   S := "&#209;&#226;&#238;&#233;&#241;&#242;&#226;&#224;: " + ParamStr(1);
   StrCopy(szCaption, PChar(S));
   ThreadHandle := CreateThread(nil, 0, @WaitingThreadFunc,
     szCaption, 0 {CREATE_SUSPENDED}, ThreadID);
   //SetThreadPriority(ThreadHandle, THREAD_PRIORITY_IDLE);
   //ResumeThread(ThreadHandle);
   WaitForSingleObject(ThreadHandle, INFINITE);
   CloseHandle(ThreadHandle);
   FreeMem(szCaption);
 end;
end.

не проканал, т.к. на момент, когда поток (WaitingThreadFunc) получает управление, окно свойств еще не создано, и он честным образом тут же возвращает ноль - приложение закрывается, окна свойств я так и не увидел. (Если в потоке вместо FindWindow поставить MessageBox, то сначала появляется он, а уж после него - окно свойств файла.) Мне кажется, что вариант с подсчетом количества потоков отработает по той же схеме. Ну не создасться окно свойств, пока прога хоть чем-то занимается...

Все ж таки, всемогущий ALL - как показать окно свойств и чтоб оно не исчезло, пока его не закроют?

Может быть, запускать процесс explorer.exe с какими-нибудь параметрами?



Страницы: 1 вся ветка

Текущий архив: 2004.10.03;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.083 c
14-1095152916
ikivio
2004-09-14 13:08
2004.10.03
Странная строка в реестре: BootExecute=autocheck autochk *,,


14-1095159096
Лиса
2004-09-14 14:51
2004.10.03
Как поздравить-порадовать сисадмина? Скоро у него День рождения!


8-1088677157
leonidus
2004-07-01 14:19
2004.10.03
Как извлечь информацию из ID тэгов mp3-файлов


1-1095244558
Максим
2004-09-15 14:35
2004.10.03
DBGrid c FixedCols


1-1095092611
Yanis
2004-09-13 20:23
2004.10.03
Frame