PDA

View Full Version : قرار نگرفتن برنامه در زیر برنامه دیگر



Mask
چهارشنبه 15 اردیبهشت 1389, 16:02 عصر
با سلام
توسط برنامه خودم ، برنامه دیگر را باز میکنم.
که وقتی با استفاده از تسک منیجر و قسمت end process tree برنامه خودم رو میبندم ، اون برنامه هم چون زیر مجموعه برنامه منه بسته میشه.
برای اینکه برنامه دوم به عنوان یک پروسه مجزا اجرا بشه باید چیکار کرد؟
ممنون.

vcldeveloper
چهارشنبه 15 اردیبهشت 1389, 18:46 عصر
برای اینکه برنامه دوم به عنوان یک پروسه مجزا اجرا بشه باید چیکار کرد؟
برنامه دوم خودش یک Process مجزا هست. هر Process میتونه یک Parent هم داشته باشه. لزومی نداره که وقتی Parent یک Process بسته میشه، خودِ آن Process هم بسته بشه.

ولی شما دارید صراحتا به Task Manager میگید که یک Process رو به همراه Processهایی که توسط آن ایجاد شدند، ببنده. خب، Task Manager هم داره همون درخواست شما رو انجام میده. اگر نمی خواید اینطوری بشه، فقط Process ایی که Parent هست را End Task کنید، نه کل Tree رو.

Mask
چهارشنبه 15 اردیبهشت 1389, 20:50 عصر
فقط Process ایی که Parent هست را End Task کنید، نه کل Tree
خیلی ممنون.
اما بنده این کار رو نمیکنم.
کاربر این کار رو میکنه.
بنا به نیاز در برنامه مجبورم که با برنامه اصلی یه برنامه دومی رو باز کنه.
اما کاربر گاهی اشتباهی از تسک منیجر end process tree رو میزنه که دوتا برنامه بسته میشه.
میشه بگید چطوری باید کاری کرد که اگه end process tree رو زد فقط همون پروسه بسته بشه؟

lord_viper
چهارشنبه 15 اردیبهشت 1389, 22:46 عصر
این یه یونیت برای تغییر parent پروسه به Explorer.exe



unit executeintereativeprocess;

interface

uses
Windows, SysUtils, Controls, Forms,
Dialogs, Registry, Psapi, StdCtrls, Classes;

const
WTS_CURRENT_SERVER_HANDLE = THandle(0);

type
TWtsConnectStateClass = (
WTSActive, // User logged on to WinStation
WTSConnected, // WinStation connected to client
WTSConnectQuery, // In the process of connecting to client
WTSShadow, // Shadowing another WinStation
WTSDisconnected, // WinStation logged on without client
WTSIdle, // Waiting for client to connect
WTSListen, // WinStation is listening for connection
WTSReset, // WinStation is being reset
WTSDown, // WinStation is down due to error
WTSInit); // WinStation in initialization

PWtsSessionInfoA = ^TWtsSessionInfoA;
TWtsSessionInfoA = record
SessionId: DWORD; // session id
pWinStationName: LPSTR; // name of WinStation this session is connected to
State: TWtsConnectStateClass; // connection state (see enum)
end;

const
f_WTSQueryUserToken : function(SessionId: Cardinal; var hToken: THandle): Boolean; stdcall = nil;
f_WTSEnumerateSessions : function(hServer: THandle; Reserved: DWord; Version: DWord; var pSessionInfo: PWtsSessionInfoA; var Count: DWord): Boolean; stdcall = nil;
f_WTSFreeMemory : procedure(pMemory: Pointer); stdcall = nil;
f_WTSSendMessage : function(hServer: THandle; SessionId: DWord; Title: PChar; TitleLength: DWord; Message: PChar; MessageLength: DWord; Style: DWord; Timeout: DWord; var Response: DWord; Wait: Boolean): Boolean; stdcall = nil;

type
TForm8 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }

end;

var
Form8: TForm8;

implementation

{$R *.dfm}

Procedure LogMessage(str: String);
Begin
Showmessage(str) ;
End;

function GetPidFromProcName(const ProcName: String; IncludePath: Boolean): THandle;
var
ProcIDs, P : PDWORD;
Buf : array[0..MAX_PATH] of Char;
cbNeeded, cb, hProc, hModule, PID : DWORD;
S : String;
I : Integer;
begin
Result := 0;
cb := 1024;
GetMem(ProcIDs, cb);
try
while True do
begin
if not EnumProcesses(ProcIDs, cb, cbNeeded) then
RaiseLastOSError;
if cbNeeded < cb then
Break;
Inc(cb, 1024);
FreeMem(ProcIDs);
GetMem(ProcIDs, cb);
end;
P := ProcIDs;
for I := 1 to cbNeeded div SizeOf(DWord) do
begin
PID := P^;
Inc(P);
hProc := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ,
FALSE, PID);
if hProc = 0 then
Continue;
try
if not EnumProcessModules(hProc, @hModule, SizeOf(hModule),
cbNeeded) then
Continue;
GetModuleFileNameEx(hProc, hModule, Buf, MAX_PATH);
S := Buf;
if not IncludePath then
S := ExtractFilename(S);
if CompareText(S, ProcName) = 0 then
begin
Result := PID;
Break;
end;
finally
CloseHandle(hProc);
end;
end;
finally
FreeMem(ProcIDs);
end;
end;

function GetShellProcName: String;
var
Reg : TRegistry;
begin
Reg := TRegistry.Create(KEY_READ);
try
Reg.RootKey := HKEY_LOCAL_MACHINE;
Reg.OpenKeyReadOnly('Software\Microsoft\Windows NT\CurrentVersion\WinLogon');
Result := Reg.ReadString('Shell');
finally
Reg.Free;
end;
end;

function GetShellHandle: THandle;
var
Pid : THandle;
ShellProcName : String;
begin
Result := 0;
ShellProcName := GetShellProcName;
if Length(ShellProcName) > 0 then
begin
Pid := GetPidFromProcName(ShellProcName, False);
if Pid <> 0 then
Result := OpenProcess(PROCESS_ALL_ACCESS, False, Pid);
end;
end;


function GetActiveWtsSession: Integer;
var
PSessionInfo : PWtsSessionInfoA;
Count : DWord;
P : PChar;
I : Integer;
begin
Result := -1;
if f_WtsEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, PSessionInfo, Count) then
try
P := Pointer(PSessionInfo);
for I := 0 to Count -1 do
begin
if PWtsSessionInfoA(P)^.State = WTSActive then
begin
Result := PWtsSessionInfoA(P)^.SessionId;
Break;
end;
Inc(P, SizeOf(TWtsSessionInfoA));
end;
finally
f_WtsFreeMemory(PSessionInfo);
end;
end;


function IsWtsAvailable : Boolean;
begin
Result := Assigned(f_WTSQueryUserToken) and
Assigned(f_WTSEnumerateSessions) and
Assigned(f_WTSFreeMemory) and
Assigned(f_WTSSendMessage);
end;

Procedure ExecuteInteractiveProcess(ProcessPath : string);
var
SI : TStartupInfo;
PI : TProcessInformation;
CmdLine : String;
ProcCreated : Boolean;
hUserToken : THandle;
ActiveSessionID : Integer;
MsgResult : DWord;
hShell : THandle;
begin

Sleep(1000); // Give service manager a chance to finish, it's slow

if IsWtsAvailable then // usually XP and Vista.
begin
ActiveSessionID := GetActiveWtsSession;
if ActiveSessionID < 0 then
begin
LogMessage('GetActiveWtsSession returned -1, no user logged on');
Exit;
end;
{ Get the user token from WtsApi }
if not f_WTSQueryUserToken(ActiveSessionID, hUserToken) then
begin
LogMessage('WTSQueryUserToken error ' + SysErrorMessage(GetLastError));
Exit;
end;
end
else begin // usually NT and W2K.
if (Win32Platform = VER_PLATFORM_WIN32_NT) and
(Win32MajorVersion >= 6) then
begin
{ Will most likely never happen }
LogMessage('Can''t display a message box in Vista if Wts isn''t ' +
'available');
Exit;
end;
{ Requires PSAPI.DLL which isn't available in all NT4-Versions, }
{ however it's a distributable! }
hShell := GetShellHandle;
if hShell = 0 then
begin
LogMessage('No shell handle, no user logged on or PsApi not available');
Exit;
end;
try
{ Get the user token from the shell process }
if not OpenProcessToken(hShell, TOKEN_ALL_ACCESS, hUserToken) then
begin
LogMessage('OpenProcessToken error ' + SysErrorMessage(GetLastError));
Exit;
end;
finally
CloseHandle(hShell);
end;
end;
try
CmdLine := '"' + ProcessPath + '"';
FillChar(SI, SizeOf(SI), #0);
FillChar(PI, SizeOf(PI), #0);
SI.cb := SizeOf(SI);
SI.lpDesktop := PChar('WinSta0\Default');
SI.dwFlags := STARTF_USESHOWWINDOW;
SI.wShowWindow := SW_SHOWDEFAULT;
ProcCreated := CreateProcessAsUser(
hUserToken,
nil,
PChar(CmdLine), // pointer to command line string
nil, // pointer to process security attributes
nil, // pointer to thread security attributes
True, // handle inheritance
0, // creation flags
nil, // pointer to new environment block
nil, // pointer to current directory name
SI, // STARTUPINFO
PI); // PROCESS_INFORMATION

if ProcCreated then
begin
CloseHandle(PI.hProcess);
CloseHandle(PI.hThread);
end
else
LogMessage('CreateProcessAsUser error ' + SysErrorMessage(GetLastError));
finally
CloseHandle(hUserToken);
end;
end;

procedure TForm8.Button1Click(Sender: TObject);
begin
ExecuteInteractiveProcess('notepad.exe');
end;

end.

Modernidea
چهارشنبه 15 اردیبهشت 1389, 23:53 عصر
آقا من چیکار کنم بفهمم این یونیت رو باید چجوری استفاده کنم ؟ :خجالت:

Mask
چهارشنبه 22 اردیبهشت 1389, 13:37 عصر
با تشکر از دوست خوبم cayberfox (http://barnamenevis.org/forum/member.php?u=9257) .
کد شما رو قرار دادم. اما باز مشکل حل نشد.

شبیر کریمی
چهارشنبه 22 اردیبهشت 1389, 16:12 عصر
سلام
برنامه ی دوم رو توسط برنامه خودتون اجرا نکنید بلکه از یه برنامه دیگه استفاده کنید که اونو اجرا کنه و سپس خودش بسته بشه.یعنی برنامه A بیاد برنامه B رو اجراکنه سپس برنامه B برنامه C رو اجرا میکنه و خودش بسته میشه اینطوری هیچ کدوم از برنامه ها مالک دیگری نمیشه.