![]() |
Добро пожаловать, гость ( Вход | Регистрация )
![]() ![]() |
![]() |
-=CHE@TER=- |
![]()
Сообщение
#1
|
Walter Sullivan ![]() ![]() ![]() Группа: Root Admin Сообщений: 1,360 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 313 раз(а) ![]() |
Delphi programs in API.
На английском. Очень подробно всё описано, плюс есть исходные коды готовых юнитов. Например SmallUtil, в котором есть все частоиспользуемые подпрограммы, и который в размере меньше, чем SysUtils (автор так утверждает - я не проверял). |
Siberian GRemlin |
![]()
Сообщение
#2
|
![]() Advanced Member ![]() ![]() ![]() Группа: CTPAX-X Сообщений: 537 Регистрация: 4-February 08 Пользователь №: 2 Спасибо сказали: 221 раз(а) ![]() |
Может не в тему, но не решился создавать новую тему. Как в Delphi для указанного EXE выставить в WinXP совместимость с той или иной виндой?
|
-=CHE@TER=- |
![]()
Сообщение
#3
|
Walter Sullivan ![]() ![]() ![]() Группа: Root Admin Сообщений: 1,360 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 313 раз(а) ![]() |
Может не в тему, но не решился создавать новую тему. Как в Delphi для указанного EXE выставить в WinXP совместимость с той или иной виндой? Например так: CODE [HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers] "C:\GAMES\MYGAME\MAINFILE.EXE"="WIN95" А вообще - поставь на .EXE какую хочешь совместимость (или там 256 цветов) и в этой ветке смотри, что за ключи будут появляться. |
-=CHE@TER=- |
![]()
Сообщение
#4
|
Walter Sullivan ![]() ![]() ![]() Группа: Root Admin Сообщений: 1,360 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 313 раз(а) ![]() |
Вопрос - кто знает, как по MUTEX'у процесса получить его путь и имя файла? Что-то типа ParamStr(0), только у другого процесса...
Суть в чём: при перезапуске моей программы, нужно чтобы она завершила свою старую копию (если есть) перед загрузкой, чтобы не убивать процесс вручную в TaskManager'е и затем снова запускать. Для убиения процесса используется такая, вот, нелёгкая процедура (потому что TerminateProcess() оставляет иконку в трее - т.е. она просто хлопает процесс, а мне нужно, чтобы он корректно завершился): CODE Function EnumThreadWndProc(Handle: Cardinal; lParam: Integer): LongBool; stdcall; Begin SendMessage(Handle, $0010{WM_CLOSE}, 0, 0); Result:=(lParam<>0); End; Function ProcessClose(FileName: String; bCloseAll: Boolean): Boolean; Var ThreadSearch, ModuleSearch: Cardinal; ThreadEntry: TThreadEntry32; ModuleEntry: TModuleEntry32; Begin result:=False; FileName:=ExtractFileName(FileName); ThreadSearch:=CreateToolHelp32Snapshot(TH32CS_SNAPTHREAD, 0); If ThreadSearch > 0 Then Begin ThreadEntry.dwSize:=SizeOf(TThreadEntry32); If Thread32First(ThreadSearch, ThreadEntry) Then Repeat ModuleSearch:=CreateToolHelp32Snapshot(TH32CS_SNAPMODULE, ThreadEntry.th32OwnerProcessID); If ModuleSearch > 0 Then Begin ModuleEntry.dwSize:=SizeOf(TModuleEntry32); If Module32First(ModuleSearch, ModuleEntry) Then Repeat If lstrcmpi(PChar(ExtractFileName(ModuleEntry.szExePath)), PChar(FileName)) = 0 Then Begin EnumThreadWindows(ThreadEntry.th32ThreadID, @EnumThreadWndProc, Integer(bCloseAll)); result:=True; End; Until (Not Module32Next(ModuleSearch, ModuleEntry)) Or (result); CloseHandle(ModuleSearch); End; Until (Not Thread32Next(ThreadSearch, ThreadEntry)) Or (result); CloseHandle(ThreadSearch); End; End; Имя файла нужно для сравнения с ModuleEntry.szExePath - вдруг, мою программу, переименовали, так что я не могу спускать в функцию ParamStr(0) от текущего процесса. Т.е. была, скажем, программа "A1.EXE", сделали копию "A2.EXE". Теперь пускают "A1.EXE", затем "A2.EXE" - т.к. MUTEX у них один, то вторая должна как-то (т.к. имя уже не совпадает) зная только MUTEX завершить предыдущую. Вообще, пытаюсь сделать такой алгоритм: 1) Производится попытка создать MUTEX с определённым именем 2) Если пришла ошибка GetLastError = ERROR_ALREADY_EXISTS, то убить этот процесс (корректно, как в коде выше, через посылание WM_CLOSE, иначе иконка в трее останется) Кто-нибудь знает как или, возможно, более простой путь решения?.. |
jTommy |
![]()
Сообщение
#5
|
Наблюдающий ![]() ![]() ![]() Группа: CTPAX-X Сообщений: 197 Регистрация: 4-February 08 Из: деревня Москва Пользователь №: 6 Спасибо сказали: 19 раз(а) ![]() |
Вопрос - кто знает, как по MUTEX'у процесса получить его путь и имя файла? Что-то типа ParamStr(0), только у другого процесса... Если я правильно понял ситуация такая: загружена твоя программа, пользователь изменил, например, настройки и надо перезагрузить программу, так?Суть в чём: при перезапуске моей программы, нужно чтобы она завершила свою старую копию (если есть) перед загрузкой, чтобы не убивать процесс вручную в TaskManager'е и затем снова запускать. В таком случае, может-быть так: пользователь жмет "применить", программа создает mutex, запускает второй экземпляр и заканчивает работу (при завершении, в самом конце удаляет mutex). Второй экземпляр находит mutex и ждет, пока он не пропадет. P.S.: А закрыть (корректно) процесс наверное можно, если послать ему сообщение WM_CLOSE или WM_DESTROY. В этом я не уверен - надо проверять. P.P.S.: Кажется я вернулся ![]() |
-=CHE@TER=- |
![]()
Сообщение
#6
|
Walter Sullivan ![]() ![]() ![]() Группа: Root Admin Сообщений: 1,360 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 313 раз(а) ![]() |
Если я правильно понял ситуация такая: загружена твоя программа, пользователь изменил, например, настройки и надо перезагрузить программу, так? Нет, всё гораздо хуже - программа при загрузке компьютера загружается и "садится" в SystemTray. А из-за чего я делаю такую хрень с её перезагрузкой - так это из-за того, что при загрузке компа, иногда, проявляется такой баг: программа загрузилась, в процессах есть, а в трее иконки нет. Х.з. из-за чего это. Приходится её перезапускать. В принципе, если бы всё было нормально и иконка всегда появлялась, то с перезагрузкой проги бы проблем не было - я бы просто не давал запускать ещё одну копию и сразу выходил. У меня есть подозрение, что это из-за того, что я держу автозапуск "Run" в HKCU, а не в HKLM, однако, ставить программу на автозапуск для всех пользователей - тупо. Каждый сам должен выбирать нужна она ему или нет.P.S.: А закрыть (корректно) процесс наверное можно, если послать ему сообщение WM_CLOSE или WM_DESTROY. В этом я не уверен - надо проверять. Handle'у процесса посылал WM_CLOSE - без толку. Это только формам посылать надо - как я сейчас и делаю. WM_DESTROY не пробовал.P.P.S.: Кажется я вернулся Welcome back! Хорошо отдохнул? (*улыбается*)![]() |
jTommy |
![]()
Сообщение
#7
|
Наблюдающий ![]() ![]() ![]() Группа: CTPAX-X Сообщений: 197 Регистрация: 4-February 08 Из: деревня Москва Пользователь №: 6 Спасибо сказали: 19 раз(а) ![]() |
Нет, всё гораздо хуже - программа при загрузке компьютера загружается и "садится" в SystemTray. А из-за чего я делаю такую хрень с её перезагрузкой - так это из-за того, что при загрузке компа, иногда, проявляется такой баг: программа загрузилась, в процессах есть, а в трее иконки нет. Бардак на корабле! © Попугай из Пиратов Карибского моря. ![]() Надо разбираться, так не должно быть. У меня есть подозрение, что это из-за того, что я держу автозапуск "Run" в HKCU, а не в HKLM, однако, ставить программу на автозапуск для всех пользователей - тупо. Каждый сам должен выбирать нужна она ему или нет. Из-за этого маловероятно, но и проверить это легко - поробуй позапускать программу из HKLM.Handle'у процесса посылал WM_CLOSE - без толку. Это только формам посылать надо - как я сейчас и делаю. WM_DESTROY не пробовал. Но винда как-то умудряется корректно закрывать приложения...Welcome back! Хорошо отдохнул? (*улыбается*) Да я не отдыхал, лень такая жуткая навалилась, в ресурсокопании ничего не получается + комп новый собирал. |
Xplorer |
![]()
Сообщение
#8
|
Advanced Member ![]() ![]() ![]() Группа: CTPAX-X Сообщений: 52 Регистрация: 4-February 08 Пользователь №: 8 Спасибо сказали: 30 раз(а) ![]() |
Handle'у процесса посылал WM_CLOSE - без толку. Это только формам посылать надо - как я сейчас и делаю. WM_DESTROY не пробовал. Все сообщения посылаются только окнам (HWND). Достаточно послать WM_CLOSE только главному окну. WM_DESTROY посылает сама Windows при уничтожении окна.Но винда как-то умудряется корректно закрывать приложения... Есть сообщения WM_QUERYENDSESSION и WM_ENDSESSION.-=CHE@TER=- Попробуй такой вариант: CODE program Project1; uses Windows, Messages, Forms, Unit1 in 'Unit1.pas' {Form1}; {$R *.res} var Mutex: THandle; Wnd: hWnd; procedure ErrHalt(const Msg: string); begin MessageBox(0, PChar(Msg), 'Error', MB_ICONHAND or MB_OK); Halt; end; begin Mutex := OpenMutex(MUTEX_ALL_ACCESS, false, '851137EC-3D96-4EA6-817B-30969CCF477B'); if Mutex <> 0 then begin Wnd := FindWindow('AFDF47C5-D586-47F2-8091-C6FBAEF8780A', nil); if Wnd = 0 then ErrHalt('Window not found'); SendMessage(Wnd, WMU_MYCLOSE, 0, 0); repeat CloseHandle(Mutex); Mutex := OpenMutex(MUTEX_ALL_ACCESS, false, '851137EC-3D96-4EA6-817B-30969CCF477B'); until Mutex = 0; end; Mutex := CreateMutex(nil, false, '851137EC-3D96-4EA6-817B-30969CCF477B'); if Mutex = 0 then ErrHalt('CreateMutex failed'); if GetLastError = ERROR_ALREADY_EXISTS then ErrHalt('Mutex already exists'); Application.Initialize; Application.CreateForm(TForm1, Form1); Application.Run; CloseHandle(Mutex); end. CODE unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; const WMU_MYCLOSE = WM_USER + 1; type TForm1 = class(TForm) Label1: TLabel; Label2: TLabel; procedure FormCreate(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); private procedure wmuMyClose(var Msg: TMessage); message WMU_MYCLOSE; protected procedure CreateParams(var Params: TCreateParams); override; end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.CreateParams(var Params: TCreateParams); begin inherited; Params.WinClassName := 'AFDF47C5-D586-47F2-8091-C6FBAEF8780A'; end; procedure TForm1.FormCreate(Sender: TObject); begin Label1.Caption := ParamStr(0); Label2.Caption := FormatDateTime('d-mm-yyyy hh:mm:ss.zzz', now); end; procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin Sleep(1000); end; procedure TForm1.wmuMyClose(var Msg: TMessage); begin Application.Terminate; end; end. |
-=CHE@TER=- |
![]()
Сообщение
#9
|
Walter Sullivan ![]() ![]() ![]() Группа: Root Admin Сообщений: 1,360 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 313 раз(а) ![]() |
Бардак на корабле! © Попугай из Пиратов Карибского моря. Угу. Я тоже так думаю. Пока что идей нет.![]() Надо разбираться, так не должно быть. Из-за этого маловероятно, но и проверить это легко - поробуй позапускать программу из HKLM. Попробовал этот вариант - не помогло...Да я не отдыхал, лень такая жуткая навалилась, в ресурсокопании ничего не получается + комп новый собирал. Ну, тоже надо. (*улыбается*)Все сообщения посылаются только окнам (HWND). Достаточно послать WM_CLOSE только главному окну. WM_DESTROY посылает сама Windows при уничтожении окна. А вот, кстати, интересный тогда впорос возникает - если у меня главная форма отлавливает ON_CLOSE событие и вместо закрытия сворачивается в трей - то что делать?Есть сообщения WM_QUERYENDSESSION и WM_ENDSESSION. Кстати, может быть тогда их попробовать? И кому их отсылать?-=CHE@TER=-Попробуй такой вариант: О спасибо тебе большое - работает!Тогда сразу напрашивается пара вопросов: 1) Mutex нигде не закрывается? Это вообще хорошо? Я у себя в главном .DPR файле в конце, перед "END." делал так: CODE ReleaseMutex(Handle); CloseHandle(Handle); Тут тоже так делать? Или см. 2) 2) Я так понял, что программа убивается, посылкой WM_CLOSE - вопрос, а MUTEX, что-ли, передаётся той копии, которая запустилась?.. Или что вообще происходит я не понял... 3) MUTEX обязательно должен называться '851137EC-3D96-4EA6-817B-30969CCF477B' или можно своё имя сунуть?.. |
Xplorer |
![]()
Сообщение
#10
|
Advanced Member ![]() ![]() ![]() Группа: CTPAX-X Сообщений: 52 Регистрация: 4-February 08 Пользователь №: 8 Спасибо сказали: 30 раз(а) ![]() |
Я изменил код.
А вот, кстати, интересный тогда впорос возникает - если у меня главная форма отлавливает ON_CLOSE событие и вместо закрытия сворачивается в трей - то что делать? Смотри в коде.Кстати, может быть тогда их попробовать? И кому их отсылать? Эти сообщения посылает Windows при Log off/Turn off.1) Mutex нигде не закрывается? Это вообще хорошо? Я у себя в главном .DPR файле в конце, перед "END." делал так: ReleaseMutex вызывать не надо, т.к. мьютекс не был захвачен. При завершении процесса мьютекс автоматически закрывается.CODE ReleaseMutex(Handle); CloseHandle(Handle); 3) MUTEX обязательно должен называться '851137EC-3D96-4EA6-817B-30969CCF477B' или можно своё имя сунуть?.. Можно и своё. |
-=CHE@TER=- |
![]()
Сообщение
#11
|
Walter Sullivan ![]() ![]() ![]() Группа: Root Admin Сообщений: 1,360 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 313 раз(а) ![]() |
Я изменил код. Хе-хе, ты своё сообщение делаешь. В принципе, да, выход. Что-то я туплю...Смотри в коде. ReleaseMutex вызывать не надо, т.к. мьютекс не был захвачен. При завершении процесса мьютекс автоматически закрывается. Я просто сторонник того, что сколько памяти выделил, сколько хэндлов занял - чтобы в конце программы всё освободил... Типа, на ОС полагайся, а сам не плошай. (*улыбается*)Кстати, а зачем в FormClose стоит Sleep(1000)?.. Это просто так или имеет какое-то важное стратегическое значение? Ещё раз спасибо за помощь! |
-=CHE@TER=- |
![]()
Сообщение
#12
|
Walter Sullivan ![]() ![]() ![]() Группа: Root Admin Сообщений: 1,360 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 313 раз(а) ![]() |
Думаю, тут будет полезно приводить некоторые полезные куски кода.
Вот пара из них. Handle - не обязательно какой-то элемент вашей программы - это может быть и хэндл чужой программы. Эмулирование нажатия какой-нибудь клавиши на клавиатуре: CODE SendMessage(Handle, WM_KEYDOWN, VK_SPACE, 0); SendMessage(Handle, WM_CHAR, VK_SPACE, 0); SendMessage(Handle, WM_KEYUP, VK_SPACE, 0); В данном случае посылается код пробела элементу с хэндлом Handle. Обратите внимание, для чтобы нажатая клавиша обработалась корректно, необходимо послать все три сообщения! Т.е. сначала что нажата клавиша пробел, затем, символ клавиши, и потом, что она отжата. Это удобно делать, например, для ListView, если нужно чтобы после удаления элемента автоматом выделился тот, на котором сейчас стоит курсор. Эмулирование нажатия клавиши мыши реализуется по схожей схеме: CODE SendMessage(Handle, WM_LBUTTONDOWN, MK_LBUTTON, MAKELONG(X, Y)); SendMessage(Handle, WM_LBUTTONUP, MK_LBUTTON, MAKELONG(X, Y)); В данном случае, эмулируется нажатие на левую клавишу мышки. X, Y - координаты точки от левого верхнего угла элемента с хэндлом Handle, где "произошло" нажатие. Сразу скажу, что я этот код не тестировал. Хотя, по идее, он должен работать. |
Siberian GRemlin |
![]()
Сообщение
#13
|
![]() Advanced Member ![]() ![]() ![]() Группа: CTPAX-X Сообщений: 537 Регистрация: 4-February 08 Пользователь №: 2 Спасибо сказали: 221 раз(а) ![]() |
Извиняюсь, если не в тему (вроде это WinAPI). Хотелось бы вызывать стандартные диалоги поиска и замены текста, а также использовать их, т.е. брать искомую строку из поля ввода в этих диалогах и т.п. Как это правильно реализовать, если возможно?
|
-=CHE@TER=- |
![]()
Сообщение
#14
|
Walter Sullivan ![]() ![]() ![]() Группа: Root Admin Сообщений: 1,360 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 313 раз(а) ![]() |
Извиняюсь, если не в тему (вроде это WinAP). Хотелось бы вызывать стандартные диалоги поиска и замены текста, а также использовать их, т.е. брать искомую строку из поля ввода в этих диалогах и т.п. Как это правильно реализовать, если возможно? Делаешь: Uses CommDlg; тогда становятся доступны вот эти две функции: function FindText(var FindReplace: TFindReplace): HWND; stdcall; function ReplaceText(var FindReplace: TFindReplace): HWND; stdcall; msdn FindText msdn ReplaceText Если же размер исполняемого .EXE файла не интересует, то используй модуль Dialogs - там уже готовые классы есть, типа FindDialog, ReplaceDialog. |
-=CHE@TER=- |
![]()
Сообщение
#15
|
Walter Sullivan ![]() ![]() ![]() Группа: Root Admin Сообщений: 1,360 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 313 раз(а) ![]() |
А теперь моя очередь задавать вопрос. (*улыбается*)
Кто-нибудь знает, как получить количество переданных/полученых байт подключения? В общем суть задачи - есть некоторое Интернет-соединение, горящее в трее иконкой с двумя перемигивающимися мониторами. Так вот - там отображается значение полученых/переданных байт. Я перепробовал несколько функций из iphlpapi.dll (GetIfTable(), GetIpStatistics(), GetTcpStatistics()) - всегда либо больше, либо меньше того, что там (в трее) отображается. Кто-нибудь знает, как получить точно такое же число? Если что, то у меня есть хэндл этого подключение - брал через RasEnumConnectionsA()/RasGetConnectStatusA(). |
Xplorer |
![]()
Сообщение
#16
|
Advanced Member ![]() ![]() ![]() Группа: CTPAX-X Сообщений: 52 Регистрация: 4-February 08 Пользователь №: 8 Спасибо сказали: 30 раз(а) ![]() |
Для 2000/XP/2003/Vista - RasGetConnectionStatistics
Для 95/98/Me - ключ HKEY_DYN_DATA |
-=CHE@TER=- |
![]()
Сообщение
#17
|
Walter Sullivan ![]() ![]() ![]() Группа: Root Admin Сообщений: 1,360 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 313 раз(а) ![]() |
Xplorer!
RasGetConnectionStatistics - это как раз в точности то, что мне нужно было! Большое, нет просто ГРОМАДНОЕ спасибо! |
-=CHE@TER=- |
![]()
Сообщение
#18
|
Walter Sullivan ![]() ![]() ![]() Группа: Root Admin Сообщений: 1,360 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 313 раз(а) ![]() |
Переименовал тему - теперь тут можете обсуждать что хотите (см. название).
Всё ещё вожусь с Турком. Делать враппер для всех 101-ой функции, которые использует игра, из kernel32.dll очень и очень влом. Киньте в меня, пожалуйста, ссылкой с доками по hook'ам или с примером, скажем, как захукать MessageBoxA() (а то я сколько в сети не нахожу - они все нерабочие; может только под 9х пашут?..)... Вообще - есть примеры, где хук ставится нормально, через стандартные API-функции типа SetWindowsHookEx() / UnhookWindowsHookEx() ? Без записи в чужой процесс и изменения точек входа и без создания отдельной .DLL? По-человечески это вообще реально сделать? Потому что писать в чужой процесс не есть гуд из соображений конфликта с антивирями. Собственно задача: запустить программу, чтобы она работала пока её не закрыли и перехватывала произвольную функцию (все вызовы этой функции), пусть, скажем, это будет MessageBoxA() вызванный любым процессом. |
-=CHE@TER=- |
![]()
Сообщение
#19
|
Walter Sullivan ![]() ![]() ![]() Группа: Root Admin Сообщений: 1,360 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 313 раз(а) ![]() |
Кстати, насчёт ReadKey / KeyPressed - вот, неплохая реализация юнита CRT для Windows:
"CRT32" by FRANK ZIMMER Там, конечно, не все процедуры / функции, но основная часть. Остальное, думаю, кто захочет сделает сам. |
-=CHE@TER=- |
![]()
Сообщение
#20
|
Walter Sullivan ![]() ![]() ![]() Группа: Root Admin Сообщений: 1,360 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 313 раз(а) ![]() |
Вопрос ко всем - возможно ли при помощи класса TFileStream обрубить файл?
Варианты с SetEndOfFile(FS.Handle) и прочее не интересует - т.к. используется модуль Windows, а значит пример не будет мультиплатформенным. |
![]() ![]() |
Упрощённая версия | Сейчас: 26th August 2024 - 04:45 |