ShellExecute въпрос

12 отговора 512 прегледа
#1

ShellExecute въпрос

Имам проблем със shellexecute. Искам да си пусна определено .exe и след някакъв интервал от време да го спра. Дотук добре, пускането и спирането са лесна работа, само че... Как да разбера кое приложение съм пуснал аз? Тази функция връща нещо странно като число... Не е HWND, а някакъв "instance handle of the application that was run" каквото и да означава това... Може ли да ми помогне някой?
....
h:=shellexecute(0,pchar('open'),pchar(edit1.text),nil,pchar('c:\'),sw_hide);
....
SendMessage(FindWindow(nil, PCHAR(edit1.Text)),wm_close,0,0);
....
в момента го правя така, но ако съм пуснал Notepad, после затварям ... произволен Notepad, вървящ в момента, не задължително "моя"... Мога ли да използвам някак си резултата от ShellExecute (h)?

Отговор
в отговор на Kиkимop #2

Re: ShellExecute въпрос

var
Form1: TForm1;

implementation
uses ShellApi;
var
SEI: TShellExecuteInfo;

{$R *.dfm}

procedure TForm1.Button2Click(Sender: TObject);
begin
FillChar(SEI, SizeOf(SEI), 0);
SEI.cbSize := SizeOf(TShellExecuteInfo);
With SEI do begin
fMask := SEE_MASK_NOCLOSEPROCESS;
Wnd := Application.Handle;
lpFile := 'c:\winnt\notepad.exe';
lpDirectory := 'c:\';
lpVerb:='open';
nShow := SW_NORMAL;
end;
ShellExecuteEx(@SEI)
end;


procedure TForm1.Button1Click(Sender: TObject);
var
uExitCode:ULONG;
begin
GetExitCodeProcess(SEI.hProcess,uExitCode);
TerminateProcess(SEI.hProcess,uExitCode);
end;


Отговор
в отговор на Ивaнчo #3

Re: ShellExecute въпрос

само дето не се поддържа в НТ платформата.

Отговор
в отговор на longy #4

Re: ShellExecute въпрос

Въх мъри майка.....

[линк]
Function Information

Minimum DLL Version shell32.dll version 3.51 or later
Custom Implementation No
Header shellapi.h
Import library shell32.lib
Minimum operating systems Windows NT 4.0, Windows 95
Unicode Implemented as ANSI and Unicode versions.

Сигурно моят Windows 2000 Server си е изтрил NT имплиментация и се е маскирал като Windows 3.1 или е отишъл по-нататък та е станал Windows/286

Отговор
в отговор на Ивaнчo #5

Re: ShellExecute въпрос

Работи чудно и навсякъде :) Мерси много :) Хем си знам, че едно "апи" като не ми върши работа - значи се ползва "апи"ex, ама късно се сетих :)
И пак - мерси :)

Отговор
в отговор на Ивaнчo #6

Re: въх мъри майка

woops.
kojto ne moje da chete helpa kat men mu se vizda che pishe "NOT suppoerted on windows NT" a to e Now


ma taka e kat po malkite chasove poluzaspal reshava da proveri cluba :)

Отговор
в отговор на Ивaнчo #7

Re: Друг ShellExecute въпрос

Ами ако Нотепада го сменим с CMD.EXE например и в CMD - то се стартира досовски резидент от регистрите на CMD

Отговор
в отговор на ferrko #8

Re: Друг ShellExecute въпрос

А 5 лева ще ми дадеш ли, ако решението го имам за NT?

Отговор
в отговор на Ивaнчo #9

Re: Друг ShellExecute въпрос

Абе мислих, мислих и накрая реших и без 5 лева да напиша нещо...

Тествано и работи с Windows 2000 Server
Нямам възможност да го тествам на Windows NT 4, но би трябвало да работи с всичко след Windows NT 4 включително и на него

Приемам, че идеята е да се стартира CMD и след това от него да се стартира някакво приложение. След което при затварянето на това приложение, да се затвори и CMD. И да се използва ShellExecuteEx, а не по-лесния начин за случая CreateProcess.... Дано правилно да съм разбрал идеята.

Стартирането на приложението ще извършим чрез ShellExecuteEx...

implementation
uses ShellApi, PsAPI;
var
SEI: TShellExecuteInfo;

{$R *.dfm}

procedure TForm1.btRUNClick(Sender: TObject);
begin
FillChar(SEI, SizeOf(SEI), 0);
SEI.cbSize := SizeOf(TShellExecuteInfo);
With SEI do begin
fMask := SEE_MASK_NOCLOSEPROCESS;
Wnd := Application.Handle;
lpFile := 'c:\winnt\system32\cmd.exe'; // пътя и самият cmd.exe
lpDirectory := 'c:\';
lpVerb:='open';
lpParameters:='cmd /c c:\winnt\notepad.exe'; { те тука ще зададем и приложението (в случая съм избрал notepad.exe), което би трябвало да се стартира от cmd. параметъра /с означава че искаме cmd-то да се затвори самичко след затваряне на notepad.exe}
nShow := SW_NORMAL;
end;
ShellExecuteEx(@SEI)
end;

До тук добре..

Сега нека да се погрижим и за затварянето на notepad.exe от нашето DELPHI приложение.


procedure TForm1.btKILLClick(Sender: TObject);
var
uExitCode:ULONG;
hProc:THANDLE;
PIDs: array [0..1023] of DWORD;
Needed: DWORD;
_iCount:Integer;
PID:DWORD;

// ПЪРВА ВЪТРЕШНА ФУНКЦИЯ

(*
Връща ProcessID oт ProcessHandle
Работи само при Windows NT 4 и по-висока версия
Ако процеса няма административни права, погрижете се да ги има

*)
function GetPid(hProcess:THANDLE):DWORD;
var
hThread: THandle;
pGetCurrentProcessID: Pointer;
rtid: DWord;
begin
pGetCurrentProcessID := GetProcAddress( GetModuleHandle('kernel32.dll'),
'GetCurrentProcessId');
Win32Check(pGetCurrentProcessID <> nil);
hThread:= CreateRemoteThread ( hProcess,
nil,
0,
pGetCurrentProcessID,
nil,
0,
rtid);
Win32Check(hThread <> 0);
WaitForSingleObject(hThread, INFINITE);
GetExitCodeThread(hThread, Result);
CloseHandle(hThread);
end;

// ВТОРА ВЪТРЕШНА ФУНКЦИЯ

(*
Връща РОДИТЕЛСКИЯ ПРОЦЕС на някой си процес
Структурите и функциите които използвам, НЕ СА описани от Майкрософт в нито една версия на MSDN, така че използвайте на свой риск
Но пък е много гот да хакваш тяхни DLL-ли
*)

const
ProcessBasicInformation = 0;


type
TProcessBasicInformation = packed record
ExitStatus: Integer;
PebBaseAddress: Pointer;
AffinityMask: Integer;
BasePriority: Integer;
UniqueProcessID: Integer;
InheritedFromUniqueProcessID: Integer;
end;

TNtQueryInformationProcess =
function(hProcess: THandle; ProcessInformationClass: Integer;
var ProcessInformation; ProcessInformationLength: Integer;
var ReturnLength: Integer): Integer; stdcall;


function GetParentProcessIDForNT(PID:DWORD): Integer;
var
hNTDLL: Integer;
NtQueryInformationProcess: TNtQueryInformationProcess;
PBI: TProcessBasicInformation;
ReturnLength: Integer;
begin
Result := 0;
hNTDLL := LoadLibrary('NTDLL.DLL');
if hNTDLL <> 0 then
begin
NtQueryInformationProcess := GetProcAddress(hNTDLL,
'NtQueryInformationProcess');
if Assigned(NTQueryInformationProcess) then
begin
NtQueryInformationProcess(PID,
ProcessBasicInformation,
PBI, SizeOf(PBI), ReturnLength);
Result := PBI.InheritedFromUniqueProcessID;
end;
FreeLibrary(hNTDLL);
end;
end;



// Е ТУКА ВЕЧЕ ЗАПОЧВА И САМОТО "КИЛВАНЕ" НА ПРОЦЕСИТЕ

begin
PID:=GetPid(SEI.hProcess);

ZeroMemory(@PIDs, SizeOf(PIDs));

if EnumProcesses(@PIDs, SizeOf(PIDs), Needed) then
for _iCount:=0 to (Needed div sizeof(DWORD)-1) do
begin
hProc := OpenProcess(PROCESS_QUERY_INFORMATION,
FALSE,
PIDs[_iCount]);
if hProc>0 then
if PID=GetParentProcessIDForNT(hProc) then
begin
hProc := OpenProcess(SYNCHRONIZE or
PROCESS_TERMINATE,
FALSE,
PIDs[_iCount]);

GetExitCodeProcess(hProc,uExitCode);
TerminateProcess(hProc,uExitCode);

end;
CloseHandle(hProc);
end;

GetExitCodeProcess(SEI.hProcess,uExitCode);
if uExitCode=STILL_ACTIVE then
TerminateProcess(SEI.hProcess,uExitCode);


end;

Те това е!
Малко сложно, ама работи.. Това ми дойде в ъкъла, това и съм направил.

Отговор
в отговор на Ивaнчo #10

Re: Друг ShellExecute въпрос

Ами ако имам лоадер и той стартира цмд който от своя страна сасхто стартира лоадер, но той се прекратява за разлика от парвия след като стартира несхто трето което отваря документ от приложната система на баба-ми-Гюра? тогава? а? ко прайм? и ако може решението да е за Win CE че XP-то не ми се стартира на XT-то (пак уж имат обща буква....)


------------------------------
I got a COMPILER, and I'm not afraid to use it!
Отговор
в отговор на SDR #11

Re: Друг ShellExecute въпрос

Става...
Ама няма да е за 5 лева

Отговор
в отговор на Ивaнчo #12

Re: Друг ShellExecute въпрос

PROSHTAWAITE NO IMAM WAJEN WAPROS I AKO NYAKOI POMOGNE SHTE MU BUDA MNOO BLAGODAREN:) TA STAWA DUMA ZA DLL - FILES, CHESTO MI ME SPUWAT W RABOTA I WSE RAZLI4NI *.DLL SEGA E PSAPI I OSHTE NYAKAW NE GI ZNAM ZA KWO SA NO I NE ZNAM ZASHTO TAKA SE POLUCHAWA NE SAM NA TI TURBOPAS..I DR PODOBNI I AKO NYAKOI ZNAE KADE MOGA DA DRUPNA RIPNAT SOFTWEAR TO FIX DLL PROBLEMS SHTE MU BUDA MNOO BLAGODAREN INAK NE MOGA SEGA I STRONG SI ZAPISHA:) A NEMAM DISK S WINDOWS, NA TEZI KOITO MOGAT I IMAT JELANIETO DA MI POMOGNAT - PREDWARITELNO BLAGODARYA - BOZAVINO@ABV.BG

Отговор
в отговор на BOSCO #13

Re: Друг ShellExecute въпрос

Този въпрос е за клуб Софтуер или Windows. Довечера ще го изтрия.
И ще помоля следващия път да пишеш на кирилица, с малки букви.

чети и дишай по-леко
Отговор