0

I've done a lot of searching, but have not found any examples using the Windows IApplicationActivationManager in Delphi. The interface does not appear to be defined in my Delphi 10.4.2 Community Edition. I need to load Windows AppStore application and wait for them to terminate.

Has anybody used this interface in Delphi, and can provide an example of how to define and use it?

I've found the following on this site using C#, but have been unsuccessful in coming up with a working Delphi equivalent:

IApplicationActivationManager::ActivateApplication in C#?

I have tried using CreateProcess, ShellExecute, explorer.exe, etc invocations with Windows AppStore application (packaged apps with AUMID), but nothing works as needed. Traditional apps work fine. Invoking a process via CreateProcess, ShellExecute, explorer.exe etc all terminate and return to my application before the invoked application itself terminates. I need my application to wait until the invoked application itself terminates.

In my application, I need to:

  1. perform some configurable action (eg: extract a file from a Zip file, decrypt a file, etc).
  2. run a configurable application appropriate to the resulting file in step 1 (eg: edit the file).
  3. perform a mirror/undo action to the action in step 1 (eg: add updated file back into the Zip file, re-encrypt the file, etc).

The IApplicationActivationManager interface appears to do what I need for my application, as it returns a ProcessID, presumably for the application that it started. I can then monitor that ProcessID and wait for the application to terminate.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
dknw78
  • 3
  • 2

1 Answers1

1

Has anybody used this interface in Delphi, and can provide an example of how to define and use it?

Try something like this:

uses
  ..., System.Win.ComObj, Winapi.ShlObj;

type
  ActivateOptions = (
    None = 0,
    DesignMode = 1,
    NoErrorUI = 2,
    NoSplashScreen = 4
  );

  IApplicationActivationManager = interface(IInterface)
    ['{2e941141-7f97-4756-ba1d-9decde894a3d}']
    function ActivateApplication(appUserModelId: PWideChar; arguments: PWideChar; options: ActivateOptions; out processId: DWORD): HResult; stdcall;
    function ActivateForFile(appUserModelId: PWideChar; itemArray: IShellItemArray; verb: PWideChar; out processId: DWORD): HResult; stdcall;
    function ActivateForProtocol(appUserModelId: PWideChar; itemArray: IShellItemArray; out processId: DWORD): HResult; stdcall;
  end;

const
  CLSID_ApplicationActivationManager: TGUID = '{45BA127D-10A8-46EA-8AB7-56EA9078943C}';

...

var
  appMgr: IApplicationActivationManager;
  pid: DWORD;
begin
  appMgr := CreateComObject(CLSID_ApplicationActivationManager) as IApplicationActivationManager;
  // alternatively:
  // OleCheck(CoCreateInstance(CLSID_ApplicationActivationManager, nil, CLSCTX_LOCAL_SERVER, IApplicationActivationManager, appMgr));

  OleCheck(appMgr.ActivateApplication('AppIdHere', nil, ActivateOptions.None, pid)); 

  // use pid to wait on process as needed...
end;

Traditional apps work fine. Invoking a process via CreateProcess, ShellExecute, explorer.exe etc all terminate and return to my application before the invoked application itself terminates. I need my application to wait until the invoked application itself terminates.

CreateProcess() returns a process HANDLE which you can wait on, such as with WaitForSingleObject() or equivalent. ShellExecuteEx() can return a similar HANDLE if you specify the SEE_MASK_NOCLOSEPROCESS flag.

The IApplicationActivationManager interface appears to do what I need for my application, as it returns a ProcessID, presumably for the application that it started. I can then monitor that ProcessID and wait for the application to terminate.

You can pass the returned ProcessID to OpenProcess() to get a HANDLE that you can then wait on.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Remy, Thanks for your excellent and quick response. Your post solved my main problem. I've spent the morning implementing an ActivateForFile version instead of the ActivateApplication version. Everything is now implemented as I've envisioned for my app in this area. Again, Thank you. – dknw78 Mar 07 '23 at 19:22