![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Почему не срабатывает 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 открыто куча табов.