DJH
DJH

Reputation: 2459

Packaged shell extension killing application

I have a WPF application. To give it an identity to consume UWP APIs, I've added sparse package support. This installs / uninstalls / updates (we're not using MSIX) with my WPF application fine, and my app is running with an identity. It shows in task manager with a Package Name listed on my process.

Now I'm attempting to add context menu support following Microsoft's docs.

I've created a shell extension which will show when opening the context menu for any file and folder, which is pretty much a copy of their sample with different GetIcon(), GetTitle() and Invoke() implementations for IExplorerCommand.

I'm specifying this in the AppxManifest.xml (values anonymised):

<desktop4:Extension Category="windows.fileExplorerContextMenus">
  <desktop4:FileExplorerContextMenus>
    <desktop5:ItemType Type="*">
      <desktop5:Verb Id="MyFileCommand" Clsid="file-guid"/>
    </desktop5:ItemType>
    <desktop5:ItemType Type="Directory">
      <desktop5:Verb Id="MyFolderCommand" Clsid="folder-guid"/>
    </desktop5:ItemType>
  </desktop4:FileExplorerContextMenus>
</desktop4:Extension>

<com:Extension Category="windows.comServer">
  <com:ComServer>
    <com:SurrogateServer DisplayName="SSVerbHandler">
      <com:Class Id="file-guid" Path="my-shell-extension.dll" ThreadingModel="STA"/>
    </com:SurrogateServer>
    <com:SurrogateServer DisplayName="SSVerbHandler">
      <com:Class Id="folder-guid" Path="my-shell-extension.dll" ThreadingModel="STA"/>
    </com:SurrogateServer>
  </com:ComServer>
</com:Extension>

This works, my context menu entry is listed and performs the action as expected. But here's the issue: each time the context menu is opened for the first time, it kills the already running instance of my WPF application. By first time, I mean restarting explorer.exe and right clicking on a file or folder.

My gut feeling is this is related to UWP side of things. This is because originally it would always kill my application when right clicking to open a context menu. But with a little trial and error I solved this by configuring multi-instance support in my AppxManifest.xml:

<Package
  ...
  xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
  xmlns:iot2="http://schemas.microsoft.com/appx/manifest/iot/windows10/2"  
  IgnorableNamespaces="uap mp desktop4 iot2">
  ...
  <Applications>
    <Application Id="App"
      ...
      desktop4:SupportsMultipleInstances="true"
      iot2:SupportsMultipleInstances="true">
      ...
    </Application>
  </Applications>
   ...
</Package>

I'm hoping someone can suggest any troubleshooting ideas as I'm now struggling.

I've sprinkled some ol' trusty MessageBox functions within the shell extension in DllMain, DllCanUnloadNow and DllGetClassObject. But for that first load attempt, no message boxes are shown, no context menu item listed and my application is still killed.

I've poked around in the event viewer hoping to see any errors or warnings listed recently, plus in Applications and Service Logs\Microsoft\Windows\Appx* and Applications and Service Logs\Microsoft\Windows\AppModel-Runtime. Nothing has jumped out at me.

According to this SO anwser, if there's an error with the shell extension itself, it may not show. That does fit, but I'm sceptical as it always works on subsequent attempts, and the previously solved UWP killing issue.

In the scenario where my application stops, using these powershell commands I get:

$process = Start-Process .\MyApp.exe -PassThru -Wait
$process.ExitCode
1

I do have crash logging in my app, but nothing gets logged. This is the only place Environment.Exit(1) is called within the WPF application.

I did try the silent monitoring detection in GFlags on the WPF application, but couldn't seem to trigger it. Only when I manually closed the application. (Ignore Self Exits unchecked for testing). I'm not sure if that's because the exit code is 1.

When the error occurs with process monitor running, I can see lots of ThreadExit before a final ProcessExit with the exit code 1. That would imply it's exiting cleanly with my application itself returning 1?

It's also worth mentioning I've lived in managed / .NET land for the last decade or so, I don't have much experience with C++ (or unmanaged languages in general) or UWP, and the first time I've attempted to write a shell extension.

Upvotes: 0

Views: 191

Answers (0)

Related Questions