Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Почему не срабатывает ShellExecute и чем это заменить? [D7, XP]


Andy BitOff ©   (2009-08-25 16:02:00) 

Собственно вот:

program Project1;

uses
 Forms, SysUtils, ShellAPI, Windows,
 Unit1 in 'Unit1.pas' {Form1},
 Unit2 in 'Unit2.pas';

{$R *.res}

var
 mt: TMThread;

begin
 Application.Initialize;
 Application.CreateForm(TForm1, Form1);
 mt := TMThread.Create(False);
 sleep(15000);
 Application.Run;
end.

=======

unit Unit2;

interface

uses
 Classes, ShellAPI, Windows;

type
 TMThread = class(TThread)
 protected
   procedure Execute; override;
 end;

implementation

procedure TMThread.Execute;
begin
 ShellExecute(0, 'open', ' http://www.ya.ru/', nil, nil, SW_SHOWNORMAL);
end;

end.


Так ShellExecute сработает только после sleep(15000);

Однако, если сделать так:

begin
 Application.Initialize;
 Application.CreateForm(TForm1, Form1);
 ShellExecute(0, 'open', ' http://www.ya.ru/', nil, nil, SW_SHOWNORMAL);
 sleep(15000);
 Application.Run;
end.


То сработает сразу.

В чем загвоздка? У как решить эту задачу? Нужно что бы вызов работал именно из потока.


lohnes   (2009-08-27 18:24:00) [1]

Попробуй добавить в поток работу с очередью windows-сообщений, т.е. реализацию метода "Application.ProcessMessages" основного потока.


Andy BitOff   (2009-08-27 09:31:00) [2]


> sniknik ©   (27.08.09 09:15) [15]

Этот вариант описан в [0] как рабочий. Не работает с потоком и, видимо, не могу проверить, с разными браузерами. В частности с оперой у меня не работает.

Сейчас буду пробовать другие варианты, хотя такой у меня тоже не сработал. Точнее сработал с задержкой.
var
 Rlst: LongBool;
 StartUpInfo: TStartUpInfo;
 ProcessInfo: TProcessInformation;
 DBP:string;
///////////////
 function GetDefaultBrowserPath: string;
 begin
   Result := '';
   with TRegistry.Create do begin
     try
       RootKey := HKEY_CLASSES_ROOT;
       if OpenKey('http\shell\open\command', False) then begin
         Result := StringReplace(ReadString(''), '"', '', [rfReplaceAll]);
         CloseKey;
         end;
       end;
     finally
       Free;
     end;
   end;
 end;
/////////////////
Begin
 FillChar(StartUpInfo, SizeOf(TStartUpInfo), 0);
 with StartUpInfo do begin
   cb := SizeOf(TStartUpInfo);
   dwFlags := STARTF_USESHOWWINDOW or STARTF_FORCEONFEEDBACK;
   wShowWindow := SW_SHOWNORMAL;
 end;
 DBP := GetDefaultBrowserPath();
 if DBP <> '' then begin
   CreateProcess(PChar(DBP), ' http://www.ya.ru/', nil, nil, false, NORMAL_PRIORITY_CLASS, nil, nil, StartUpInfo, ProcessInfo);
 end;


sniknik   (2009-08-27 09:19:00) [3]

похоже он просто пытается синхронизироваться с основным потоком, а это без цикла выборки, что в Run; не получается.
используй что-нибудь другое (ShellExecuteEx, CreateProcess, ...).


sniknik   (2009-08-27 09:15:00) [4]

> Юрий, а если перед Run заснуть Sleep(10000);?
да без проблем.
begin
 Application.Initialize;
 Application.CreateForm(TForm1, Form1);
 ShellExecute(0, 'open', ' http://www.ya.ru/', nil, nil, SW_SHOWNORMAL);
 Sleep(10000);
 Application.Run;
end.

> Все летает и никаких проблем.


Andy BitOff   (2009-08-27 08:55:00) [5]


> Юрий Зотов ©   (26.08.09 19:04) [11]

Юрий, а если перед Run заснуть Sleep(10000);?


lohnes   (2009-08-27 01:07:00) [6]

Да, может ShellExecuteEx ведет себя по другому...


lohnes   (2009-08-27 00:50:00) [7]

У меня аналогичная проблема.
Порыл информацию и пришел к выводу, что в ShellExecute используется COM-объект и, если не вдаваться в подробности, взаимодействие с этим COM-объектом внутри потоков осуществляется при помощи windows-сообщений, причем сообщение отсылается тому потоку который создал этот COM-объект.
Возможно у вас при создании формы создается COM-объект использующийся в ShellExecute, в итоге она не срабатывает пока основной поток не запустит цикл обработки сообщений (см. Application.Run).
Почитать про это можно тут: http://www.podgoretsky.com/ftp/Docs/Delphi/DX/COMmodel.html


Юрий Зотов   (2009-08-26 19:04:00) [8]


begin
 Application.Initialize;
 Application.CreateForm(TForm1, Form1);
 with TMyThread.Create(True) do
 begin
   FreeOnTerminate := True;
   Resume
 end;
 Application.Run;
end.

procedure TMyThread.Execute;
begin
 ShellExecute(0, 'open', ' http://www.ya.ru/', nil, nil, SW_SHOWNORMAL)
end;

Все летает и никаких проблем. D7, XP SP3, IE7.


MonoLife   (2009-08-26 18:43:00) [9]

Строки
...
Application.Initialize;
Application.CreateForm(TForm1, Form1);
mt := TMThread.Create(False);
Application.Run;
...
(без sleep) в мозилле открывает мгновенно, ну, или как > Kolan ©   (25.08.09 16:07) [1]


Andy BitOff   (2009-08-26 10:46:00) [10]

Вот ведь... А у меня даже с циклами (без слипа) выполняется только после Application.Run;
D7, XPsp2

Кстати. IE у меня правда не запускается вообще (вываливается с AV), но такое ощущение, что он все-таки действительно пытается запуститься когда надо. Вообще-то я пользуюсь оперой. Видимо Kolan ©   (25.08.09 16:30) [5] прав.
Хотя не понимаю причем тут могут быть браузеры...


Leonid Troyanovsky   (2009-08-26 10:34:00) [11]


> Andy BitOff ©   (26.08.09 10:01) [7]

> Путем всяческих экспериментов выяснилось, что слип тут не
> причем.

У меня код из [0] пускает IE6 без всяких задержек.
Машина, правда, однопроцессорная, 2003 сервер.

--
Regards, LVT.


Andy BitOff   (2009-08-26 10:01:00) [12]

Блин. CreateProcess (во всяком случае с параметрами по умолчанию) ведет себя также. =(
Путем всяческих экспериментов выяснилось, что слип тут не причем. Видимо, ему для запуска действительно нужно выполение Application.Run;
Очень скверно =(


Leonid Troyanovsky   (2009-08-25 19:11:00) [13]


> Andy BitOff ©   (25.08.09 16:02)  

> Так ShellExecute сработает только после sleep(15000);

SE, видимо, непроста, бо может работать и с DDE и другой фигней.
Возможно, что для каждого потока она требует вещей вроде DDEInitialize
&etc и начинает трудиться лишь после таймаута.

Поэтому, CreateProcess - неплохой выбор, но FindExecutable,
на всякий случай, лучше сделать из первичного потока :)

--
Regards, LVT.


Kolan   (2009-08-25 16:30:00) [14]

Интересно, Andy, а не зависит ли время от браузера?


Медвежонок Пятачок   (2009-08-25 16:27:00) [15]

Нужно что бы вызов работал именно из потока.

Зачем?
Чтобы не было задержек с появлением формочки?
ПостМессадж форме и тот же самый код из основного потока.


Andy BitOff   (2009-08-25 16:18:00) [16]


> Медвежонок Пятачок ©   (25.08.09 16:09) [2]

Она не завершается ошибкой.


> Kolan ©   (25.08.09 16:07) [1]

Да, надо попробовать.


Медвежонок Пятачок   (2009-08-25 16:09:00) [17]

If the function fails, the return value is an error value that is less than or equal to 32. The following table lists these error values:
....
....
....


Kolan   (2009-08-25 16:07:00) [18]

Ну заменить можно на CreateProcess.

Но у меня ваш код срабатывает с примерно секундной задержкой. Может это даже нормально, так как в FF открыто куча табов.


Наверх

Титульная страница Поиск, карта сайта Написать письмо