tags:

views:

181

answers:

5

I wrote this utility (exe) which can be called from within this host application. And I'd prefer it that the utility can only be called from the host application. Running it from the outside or a different host should terminate the utility immediately.

Is there a way to find out which process launched my utility?

Thanks for the replies.

+1  A: 

If this application is only being run from inside the host, why not just include the forms for the application inside the main application, and activate it as you would another form?

Tim
We didn't write this host application. There is just this ability to execute another app. I just happened to know how they're executing it.Thanks Tim !
Roderick
+2  A: 

I would add an extra parameter that you only know about ( it can be a guid ) if that guid is not part of the parameters passed to your utility .. Terminate the application right away.

GX
I've been to that path. The problem is is that the parameters passed to utilities can be seen thru the host app's setup or settings screen. And I can not instruct the host app to look for some magic key elsewhere too.Thanks Gs !
Roderick
+1  A: 

The quick answer to your question is "Well, no, you can't prevent an application from being executed". If it is an executable, then it can be executed. No way to stop that.

And, if you can't control the application (as your comments seem to indicate) then Gs's excellent suggestion won't work, right? You don't have any way of controlling what the app does and you can't control it's reaction to your special command line.

So this does present an interesting situation.

The only way I see around this is to prevent access to the EXE altogether, or at least make it hard to find it.

You could do this:

  1. Embed the EXE into your host EXE as a resource
  2. When the time comes to run the EXE, then extract it using TResourceStream
  3. Write it out from the TResourceStream using TFileStream
  4. Execute it
  5. Delete it when you are done.

Not pretty, but it is the only way I can think of to keep the EXE from being run on your terms and your terms only.

Nick Hodges
It looks like what he's asking is if it's possible to verify the identity of the process that launched the app, and then immediately terminate if it's the wrong one. That should be possible.
Mason Wheeler
+4  A: 

You can use the CreateToolhelp32Snapshot funtion to enumerate the running process list and then the Process32First function to get the th32ParentProcessID wich is the identifier of the process that created this process (its parent process).

See this example .

uses
  Psapi,
  Windows,
  tlhelp32,
  SysUtils;

function GetTheParentProcessFileName(): String;
const
  BufferSize = 4096;
var
  HandleSnapShot  : THandle;
  EntryParentProc : TProcessEntry32;
  CurrentProcessId: THandle;
  HandleParentProc: THandle;
  ParentProcessId : THandle;
  ParentProcessFound  : Boolean;
  ParentProcPath      : String;

begin
  ParentProcessFound := False;
  HandleSnapShot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);   //enumerate the process
  if HandleSnapShot <> INVALID_HANDLE_VALUE then
  begin
    EntryParentProc.dwSize := SizeOf(EntryParentProc);
    if Process32First(HandleSnapShot, EntryParentProc) then    //find the first process
    begin
      CurrentProcessId := GetCurrentProcessId(); //get the id of the current process
      repeat
        if EntryParentProc.th32ProcessID = CurrentProcessId then
        begin
          ParentProcessId := EntryParentProc.th32ParentProcessID; //get the id of the parent process
          HandleParentProc := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, ParentProcessId);
          if HandleParentProc <> 0 then
          begin
              ParentProcessFound := True;
              SetLength(ParentProcPath, BufferSize);
              GetModuleFileNameEx(HandleParentProc, 0, PChar(ParentProcPath),BufferSize);
              ParentProcPath := PChar(ParentProcPath);
              CloseHandle(HandleParentProc);
          end;
          break;
        end;
      until not Process32Next(HandleSnapShot, EntryParentProc);
    end;
    CloseHandle(HandleSnapShot);
  end;

  if ParentProcessFound then
    Result := ParentProcPath
  else
    Result := '';
end;
RRUZ
Thanks RRUZ !!! Exactly what I've been looking for. :)
Roderick
A: 

We use a fairly simple technique that just takes a few lines of code. The parent app and the utility app use some common GUIID strings (in code) and call RegisterWindowMessage to create a sort of "Hello" handshake protocol. When the utility app first fires up, it posts that message. If the parent app is running, and did start the utility, it posts the response message, which the utility sees and all is well. If not, the utility times out and exits.

Brian D. Coryell
The parent app will have to be modified/rewritten to implement it that way. Is that correct ?
Roderick
Yes. I didn't see that a 3rd party app was the one running the utility until I had written that. My bad.
Brian D. Coryell