Форум: "WinAPI";
Текущий архив: 2005.11.13;
Скачать: [xml.tar.bz2];
ВнизПри выходе из скринсейвера Винда закрывает запущенные им процессы Найти похожие ветки
← →
Barvetal (2005-08-26 17:16) [0]Всем привет!
Пишу скринсейвер. Скринсейвер должен работать следующим образом:
После запуске, в нем можно работать мышкой. То-есть, при дергании мышкой из скринсейвера выхода не должно происходить. Скринсейвер должен содержать ряд интернет-ссылок. При щелчке мышкой на любую ссылку скринсейвер открывает браузер и загружает ссылку, после чего должен выгружаться.
Так вот. Проблема в чем. Если запускать скринсейвер вручную (двойным щелчком или нажатием на кнопку Preview в диалоге Display панели управления), то все отрабатывает как нужно. Но. Если выставить диапазон запуска (например, 1 минуту), то после нажатия на ссылочку открывается браузер, и через секунду закрывается, сразу после закрытия скринсейвера (это при условии, что ни одного экземпляра браузера не было запущено). Таким образом, выходит, что винда (Вин2000) после выгрузки скринсейвера убивает все созданные им процессы.
И еще такой момент, если был запущен хоть один экземпляр Интернет Эксплорера, то при описанном выходе из скринсейвера вновь открытый экземпляр Интернет Эксплорера не закрывается, и все работает как нужно.
Решил проверить, дело только в интернет-эксплорере, или нет. Написал скринсейвер, который запускается, и в процессе своего запуска запускает еще и Ворд. Так вот, если ни одного экземпляра ворда не было запущено до запуска скринсейвера, то ворд при закрытии скринсейвера тоже закрывается. Если хоть один экземпляр ворда был, то не закрывается. То-есть, ситуация полностью идентична предыдущей.
Таким образом, вопрос. Как сделать, чтобы при выходе из скринсейвера, запущенного согласно периоду ожидания, винда не закрывала запущенные скринсейвером процессы?
Всем заранее спасибо за ответы!!
← →
DeadMeat © (2005-08-26 18:25) [1]А если проверить тоже самое на блокноте?
---
...Death Is Only The Begining...
← →
alpet © (2005-08-26 18:27) [2]Правильно система поступает - когда завершается скринсейвер - она переключает десктоп из Screen-Saver на Default. Запущенные программы, остаются изолированными в десктопе "Screen-Saver". По идее, под скринсейвером ничего лишнего (как и под Winlogon) выполнятся не должно.
← →
Barvetal (2005-08-26 19:26) [3]2 alpet и всем остальным:
Вот, сделал код активации скринсейвера следующим:procedure TScrForm.FormActivate(Sender: TObject);
var
si : TSTARTUPINFO;
ProcInfo : TProcessInformation;
begin
FillChar(si, SizeOf(si), 0);
FillChar(ProcInfo, SizeOf(ProcInfo), 0);
si.wShowWindow := SW_SHOWNORMAL;
si.dwFlags := STARTF_USESHOWWINDOW;
si.lpDesktop := PChar("default");
Result := DWORD(CreateProcess(nil, PChar("D:\Program Files\Microsoft Office\OFFICE11\WINWORD.EXE"), nil, nil, false, 0, nil, nil, si, ProcInfo));
CloseHandle(ProcInfo.hThread);
CloseHandle(ProcInfo.hProcess);
end;
То-есть, в параметр lpDesktop структуры StartupInfo загнал значение "default". Пробовал до этого еще и "WinSta0\Default". Проблема та же. При завершении скринсейвера Ворд также пропадает с экрана :(
Скажите пожалуйста, что же я не так делаю?? Получается, несмотря на мой код, ворд все равно не запускается на десктопе default... :(
← →
alpet © (2005-08-26 19:38) [4]lpDesktop
For CreateProcess and CreateProcessAsUser, if this member is NULL, the new process inherits the desktop and window station of its parent process. If this member is an empty string, the process does not inherit the desktop and window station of its parent process; instead, the system determines if a new desktop and window station need to be created. If the impersonated user already has a desktop, the system uses the existing desktop.
Для функции CreateProcess видимо других вариантов быть не может, указывать конкретный декстоп следует при использовании CreateProcessWithLogonW.
Попробуй значит пустую строку - Word должен запустится на десктопе, но при этом он будет не виден из скринсейвера.
Так чтобы запущенная программа была видна там и там, нужно достаточно сложную задачу решить - при переключении десктопов заставить потоки этой программы, выполнить SetThreadDesktop. И то не факт, что удастся так сделать.
Единственно что, такой скринсейвер лучше не запускать как logon-screen saver (logon.scr), поскольку это одна большая дыра.
← →
Barvetal (2005-08-26 20:25) [5]неа, не помогает :( Сделал пустую строку - то же самое, ворд пропадает с экрана после выключения скринсейвера.
← →
alpet © (2005-08-26 20:32) [6]Barvetal (26.08.05 20:25) [5]
Видимо этот десктоп достаточно изолирован, дабы небыло попыток из-него заразу какую-нибудь запустить. Изучай возможность переключения декстопа (OpenDesktop, SetThreadDesktop), перед запуском процесса, может это поможет (вероятно таки потребуется использовать CreateProcessAsUser)...
← →
Deka © (2005-08-29 14:26) [7]Какой-то навороченный скрин-сейвер. Может все сделать просто приложением? Прикрутить к нему таймер, пускай само-себе будет скрин-сейвером. Тогда через определенные промежутки времени (таймер истек) запускается полноэкранный режим и все работает. Т.е. эмуляция скрин-сейвера. Уйдут проблемы прибивания процессов. Правда родной скрин-сейвер придется запретить ;)
← →
Barvetal (2005-08-29 17:39) [8]Так получается, что это должен быть коммерческий скринсейвер... И он должен управляться из Панель управления-->Дисплей-->Заставка. Нужно, чтобы оттуда он мог настраиваться через "Настройка". Запускаться через "Просмотр" и запускаться по интервалу ожидания, указанному на этой панели. Кроме того, при нажатии галочки "выход по паролю" (или как-там она) нужно сделать, чтобы в виндовс можно было входить только по паролю... Сложно это сделать в простом приложении, без скринсейвера...
← →
alpet © (2005-08-29 17:44) [9]Barvetal (29.08.05 17:39) [8]
Да и не нужно выдумывать. Запускать чего-либо в десктопе Screen-saver не рекомендуется, так что может лучше встроить в прогу просмотр web-страниц. А то после запуска IE, знающие люди из него смогут и без ввода пароля натворить проблем на компе.
← →
Barvetal (2005-08-29 18:01) [10]2alpet:
Так нужно, чтобы при щелчке на ссылке закрывался скринсейвер и открывался браузер. Это требование заказчика... Поэтому ищу способ запустить браузер в отличном, от screen-saver, десктопе.
← →
alpet © (2005-08-29 18:07) [11]Barvetal (29.08.05 18:01) [10]
Тогда лучше так - некоторая программа запускается из Автозапуска (или реестра), и ждет события (глобального, что важно!) от скринсавера. Скринсавер после нажатия на ссылку, записывает ее в некоторый файл, устанавливает событие в сигнальное состояние, и завершается. Программа же реагируя на событие - читает файл, и запускает по ссылке ослика (IE).
← →
DeadMeat © (2005-08-30 00:54) [12]Вы эта.. Казанову тока дождитесь. Он вам расскажет как такие вещи делаются.
---
...Death Is Only The Begining...
← →
Barvetal (2005-08-30 13:53) [13]2DeadMeat:
Расшифруйте пожалуйста, что Вы сказали... Казанова - это гуру на этом форуме? А когда он должен быть?
Заранее спасибо...
← →
Deka © (2005-08-30 14:11) [14]Мне так кажется что aplet в [11] прав. Сделать скринсейвер двухкомпанентным. При этом та часть что реальный скринсейвер выполняет исключительно сигнальные функции. Таким образом можно "шагать" между разными десктопами. Конечно это не совсем скринсейвер получается, но и скринсейвер не для этого придумывали.
← →
alpet © (2005-08-30 15:30) [15]component1 - server:
uses Windows, Messages, ShellApi;
var hCmdFile: HFILE;
msg: tagMSG;
dwWait, reads: DWORD;
hEvent: THandle;
fBreak: Boolean = false;
command: array [BYTE] of CHAR;
evAttr: SECURITY_ATTRIBUTES;
cmdstr: String;
begin
hEvent := CreateEvent (@evAttr, true, false, "Global\ssaver-event");
if GetLastError <> 0 then exit;
hCmdFile := CreateFile ("command.txt", GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_WRITE or FILE_SHARE_READ, nil,
OPEN_ALWAYS, 0, 0);
evAttr.nLength := sizeof (evAttr);
evAttr.lpSecurityDescriptor := nil;
evAttr.bInheritHandle := false;
if (hEvent <> 0) and (hCmdFile <> INVALID_HANDLE_VALUE) then
repeat
SetFilePointer (hCmdFile, 0, nil, FILE_BEGIN);
SetEndOfFile (hCmdFile);
// Message Loop for perform normal process termination
repeat
if PeekMessage (msg, 0, 0, 0, PM_REMOVE) then
fBreak := msg.message = WM_QUIT;
dwWait := WaitForSingleObject (hEvent, 91);
until (fBreak or (dwWait <> WAIT_TIMEOUT));
fBreak := fBreak or (dwWait <> WAIT_OBJECT_0);
if not fBreak then
begin
ReadFile (hCmdFile, command, 256, reads, nil);
cmdstr := "http://www.google.ru/" + command;
ShellExecute (0, nil, PChar(cmdstr), "", nil, SW_SHOW);
ResetEvent (hEvent);
end;
until fBreak;
CloseHandle (hCmdFile);
CloseHandle (hEvent);
end.
component2 - saver (primitive):
uses Windows, Messages;
var hEvent: THandle;
function RegClassEx (name: PAnsiChar; wFunc: Pointer; style: dword): Boolean;
var
wclass: WNDCLASSEXA;
begin
result := true;
fillchar (wclass, sizeof (wclass), 0);
wclass.cbSize := sizeof (wclass);
if not GetClassInfoEx (hInstance, PChar (name), wclass) then
begin
wclass.cbSize := sizeof (wclass);
wclass.lpszClassName := name;
wclass.lpfnWndProc := wFunc;
wclass.style := style;
wclass.hInstance := hInstance;
wclass.hbrBackground := GetSysColorBrush (COLOR_BTNFACE);
wclass.hCursor := LoadCursor (0, IDC_ARROW);
result := RegisterClassEx (wclass) <> 0;
end;
end;
function SSaverProc (hWnd: THandle; msg: DWORD; wParam, lParam: Integer): LongInt; stdcall;
var
hFile: THandle;
sLink: string;
written: DWORD;
begin
result := 0;
case msg of
WM_LBUTTONDOWN:
begin
sLink := "search?hl=ru&q=123&btnG=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA&lr=";
hFile := CreateFile ("command.txt", GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_WRITE or FILE_SHARE_READ, nil,
OPEN_ALWAYS, 0, 0);
WriteFile (hFile, PChar (sLink)^, Length (sLink) + 1, written, nil);
CloseHandle (hFile);
SetEvent (hEvent);
end;
WM_SYSCOMMAND:
if wParam <> SC_SCREENSAVE then
result := DefWindowProc (hWnd, Msg, wParam, lParam);
else result := DefWindowProc (hWnd, Msg, wParam, lParam);
end;
end;
exports
SSaverProc name "ScreenSaverProc";
var
hWnd: THandle = 0;
msg: tagMSG;
begin
hEvent := OpenEvent (EVENT_MODIFY_STATE, false, "Global\ssaver-event");
if hEvent <> 0 then // Server part has runed
begin
if RegClassEx ("WC2SSAVER1", @SSaverProc,
CS_VREDRAW or CS_HREDRAW or CS_SAVEBITS or CS_DBLCLKS)
then hWnd := CreateWindowEx (0, "WC2SSAVER1", "Main", WS_VISIBLE,
0, 0,
GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN),
0, 0, hInstance, nil);
while IsWindow (hWnd) and
GetMessage (Msg, hWnd, 0, 0) do
begin
TranslateMessage (Msg);
DispatchMessage (Msg);
end;
end;
CloseHandle (hEvent);
end.
← →
Barvetal (2005-08-30 15:36) [16]Значит так...
Кой чего прояснилось насчет десктопов... Оказалось, что десктопы тут совершенно ни при чем. Запускаю скринсейвер согласно интервалу ожидания, определяю, на каком десктопе он запущен: Default !!!!! А вот если я ставлю галочку "Password protected", то скринсейвер запускается на десктопе Screen-saver .
Так вот, несмотря на том, что скринсейвер запускается на десктопе Default, процессы, запущенные им, все равно убиваются после завершения скринсейвера :(
На параллельном форуме было высказано предположение:
[quot]Дело в том что Windows запускает screensaver не просто так, а в Job-е и этому Job-у даны такие настройки, что из него нельзя вырваться используя CREATE_BREAKAWAY_FROM_JOB и все процессы запущенные в нём уничтожаются при закрытии screensaver-а[/quot]
Так вот, посоветуйте пожалуйста, как можно обойти эту проблему? Может, можно создать из скринсейвера другой джоб, который запустит интернет эксплорер? Или изменить параметры скринсейверного джоба? Или, может есть более лучший способ?
Помогите пожалуйста, сроки горят, начальство злится...
← →
Игорь Шевченко © (2005-08-30 15:44) [17]Barvetal (30.08.05 15:36) [16]
Правильно сказали на другом форуме, процесс ScreenSaver"а запускается в Job.
По сабжу - не страдай ерундой.
← →
alpet © (2005-08-30 16:11) [18]Игорь Шевченко © (30.08.05 15:44) [17]
Что-же это тогда получается, и предложенный способ не будет работать?
P.S: В [15](2) не ScreenSaver, а просто процесс написан. Таки не ясно, получит ли настоящий ScreenSaver доступ к объекту события или нет.
← →
Игорь Шевченко © (2005-08-30 16:37) [19]alpet © (30.08.05 16:11) [18]
> Что-же это тогда получается, и предложенный способ не будет
> работать?
Практика - критерий истины
← →
alpet © (2005-08-30 16:58) [20]Мне лениво ScreenSaver целый писать, пускай автор попробует. Но по идее, не видно особых противопоказаний работоспособности способа.
← →
Barvetal (2005-09-08 14:14) [21]Значит так... Реализовал таки. Все работает.
итак, по порядку.
Скринсейвер запускается в отдельном джоб обжекте. Значит, все процессы, которые он плодит, также запускаются в этом джоб обжекте. И при завершении скринсейвера винда закрывает джоб обжект, а вместе с ним и все процессы, порожденные скринсейвером.
Поэтому, я создал локальный СОМ-сервер (в ехе-файле), с методом, который открывает указанную ссылку в дефолтовом браузере. При щелчке на урл в скринсейвере я в коде скринсейвера создаю этот СОМ-объект, и вызываю его метод для открытия браузера. Когда запускается локальный СОМ-сервер, он не является дочерним процессом скринсейвера, так как запускается из-под logon. Поэтому после завершения скринсейверного джоб-обжекта браузер не закрывается!
Однако тут есть еще один момент. Если в Вин2000/ХР запускается скринсейвер при установленной галочке "password protected", то скринсейвер запускается на desktop под названием screen-saver, а не default, как в случае, когда галочка отключена. И поэтому браузер виден только тогда, пока запущен скринсейвер, даже если браузер запускается непосредственно из-под COM-сервера.
Поэтому реализацию метода СОМ-сервера я сделал следующим образом. Создал еще одно приложение, которое непосредственно открывает дефолтовый браузер через ShellExecute. В СОМ-сервере в методе открытия урл я запускаю это приложение, при этом в параметрах функции CreateProcess указываю использовать desktop по-умолчанию. Таким образом, у меня браузер всегда будет запускаться на десктопе по-умолчанию, внезависимости от того, на каком desktop был запущен скринсейвер.
Всем спасибо за помощь и поддержку!!
← →
alpet © (2005-09-08 18:31) [22]Barvetal (08.09.05 14:14) [21]
Поздравляю, но как сложно. Более простой и очевидный способ написать было горазо быстрее можно без использования COM, тем более что заготовку я кинул.
← →
Barvetal (2005-09-09 17:29) [23]да, но у тебя был сервер, процесс которого постоянно должен был висеть в оперативке и которого нужно было стартовать при каждом старте винды.
Мой же запускается по требованию, и сразу же завершается. И никакого его автостарта при старте винды не нужно.
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2005.11.13;
Скачать: [xml.tar.bz2];
Память: 0.54 MB
Время: 0.037 c