Jump to content
FPiette

How to register a shell property sheet for a single file type?

Recommended Posts

20 minutes ago, FPiette said:

Wonderful. From the screen dump I cannot determine that the property sheet handler is registered for all extensions (That work here also) or for a single one (Don't work here). If REG_FILENAME symbol is defined, my code will register for a single file extension (.arw in my original code), that is what you need to try.

It's registered for a single extension. I'm not using your IShellExtInit implementation at all. I'm using the shell integration classes from the Drag and Drop Component Suite, so here's the full extent of changes I needed to make in order to register the property sheet handler:

type
  TPropertySheetHandlerFactory = class(TDropContextMenuFactory)
  protected
    function HandlerRegSubKey: string; override;
  end;

function TPropertySheetHandlerFactory.HandlerRegSubKey: string;
begin
  Result := 'PropertySheetHandlers';
end;

const
  // CLSID for this shell extension.
  // Modify this for your own shell extensions (press [Ctrl]+[Shift]+G in
  // the IDE editor to gererate a new CLSID).
  CLSID_PropertySheetHandler: TGUID = '{1067C264-8B1F-4B22-919F-DB5191C359CB}';
  sFileClass = 'FoobarFile';
  sFileType = 'File of foo';
  sFileExtension = '.foobar';
  sClassName = 'DelphiPropSheetShellExt';

resourcestring
  // Description of our shell extension.
  sDescription = 'Property Sheet example';
  
initialization
  TPropertySheetHandlerFactory.Create(ComServer, TDataModulePropertySheetHandler,
    CLSID_PropertySheetHandler, sClassName, sDescription, sFileClass,
    sFileExtension, ciMultiInstance);
end.

and here's the code to extract the file names (ShellExtInit.Initialize):

function TDataModulePropertySheetHandler.ShellExtInit_Initialize(pidlfolder: PItemIDList; lpdobj: IDataObject; Hkeyprogid: HKEY): HResult;
begin
  Result := NOERROR;

  FFiles.Clear;
  SetFolder(pidlFolder);

  // Save a reference to the source data object.
  FDataObject := lpdobj;
  try

    // Extract source file names and store them in a string list.
    // Note that not all shell objects provide us with a IDataObject (e.g. the
    // Directory\Background object).
    if (DataObject <> nil) then
      with TFileDataFormat.Create(dfdConsumer) do
        try
          if GetData(DataObject) then
            FFiles.Assign(Files);
        finally
          Free;
        end;

  finally
    FDataObject := nil;
  end;
end;

FWIW, I believe the thing that you were missing was registering the class ID in HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved. The 4-space indent and capitalized keywords probably also had a negative influence 🙂

 

Source attached.

PropertySheetHandler.zip

Edited by Anders Melander

Share this post


Link to post
1 hour ago, Remy Lebeau said:

Your PropertySheelHandler should not have its own ProgID assigned to it.  You can assign your PropertySheetHandler to other ProgIDs as needed, but it should not have its own ProgID.  So, get rid of the "HKLM\SOFTWARE\Classes\CLSID\{AF6B...}\ProgID" subkey.

I did not create the "HKLM\SOFTWARE\Classes\CLSID\{AF6B...}\ProgID" subkey. It is created by the code in ComObj to register the COM object.

This is in TComObjectFactory.UpdateRegistry line 985 in Delphi 11.3 System.Win.ComObj.pas. I assume this is normal way of doing the registration.

Removing that subkey doesn't change anything.

 

Share this post


Link to post
13 minutes ago, Anders Melander said:

I'm using the shell integration classes from the Drag and Drop Component Suite

Thank you so much for the hint. I have to study that code to understand which keys it register.

14 minutes ago, Anders Melander said:

I believe the thing that you were missing was registering the class ID in HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved.

I added it manually, it doesn't make it works.

15 minutes ago, Anders Melander said:

The 4-space indent and capitalized keywords probably also had a negative influence 🙂

I don't understand what you are talking about. Do you mean my source code layout?

Share this post


Link to post
50 minutes ago, FPiette said:

This is in TComObjectFactory.UpdateRegistry line 985 in Delphi 11.3 System.Win.ComObj.pas. I assume this is normal way of doing the registration.

My factory overrides GetProgID to return an empty string and TComObjectFactory.UpdateRegistry has this code:

    if ProgID <> '' then
    begin
      CreateRegKey(RegPrefix + ProgID, '', Description, RootKey);
      CreateRegKey(RegPrefix + ProgID + '\Clsid', '', ClassID, RootKey);
      CreateRegKey(RegPrefix + 'CLSID\' + ClassID + '\ProgID', '', ProgID, RootKey);
    end;

 

38 minutes ago, FPiette said:

Do you mean my source code layout?

Yes.

Share this post


Link to post

I dont know if help but I found this page with sample to "Control Panel" + new propsheet with "source code" in "C"  (.... shellex\PropertySheetHandlers)

Quote

As with a normal property sheet extension, a Control Panel extension implements two interfaces: IShellExtInit and IShellPropSheetExt.

IShellExtInit::Initialize()

IShellPropSheetExt::ReplacePage()

IShellPropSheetExt::AddPages()

by Michel Dunn  https://www.codeproject.com/Articles/802/Adding-Custom-Pages-to-Control-Panel-Applets

 

ControlPanelExt3.gif

 

Added:  in the book "Delphi 5 Developer's Guide - Xavier Pacheco and Steve Teixeira (Dec-1999)" exists a topic "Extending the Windows Shell", Chapter 24, pg 1251, about TContextMenu customization

Edited by programmerdelphi2k

Share this post


Link to post
13 hours ago, Anders Melander said:

I'll clean up the code and post it later...

There are much more changes in my code than the excerpts you published.

Would you publish or send to me the full source code as you modified?

 

Share this post


Link to post
4 hours ago, Anders Melander said:

Source attached.

PropertySheetHandler.zip

You code works correctly for the non existent .foobar file extension.

But if I change the file extension to the existing .arw, it doesn't work anymore! Tested on Win10 and Win11 with same result.

 

To change the file extension, I modified 3 code lines in your source:

//  sFileClass     = 'FoobarFile';
//  sFileType      = 'File of foo';
//  sFileExtension = '.foobar';
  sFileClass     = 'ArwFile';
  sFileType      = 'File of arw';
  sFileExtension = '.arw';

 

Is it possible for you to test? Before testing, verify that .arw extension exists on your system and you can open a file with that extension.

If you have no .arw file, you can download a photo in .ARW format: http://wiki.overbyte.be/arch/FPI09894.ARW

If you run Win10, you need to install Microsoft RAW extension from Microsoft store (https://apps.microsoft.com/store/detail/extension-dimage-raw/9NCTDW2W1BH8) It is needed for Win10 but already included by default with Win11.

"RAW Extension" cover a bunch of file extension which are a file format used by camera makers. The extension varies with each camera maker. Arw files are from Sony. Canon, Nikon, Panasonic and all other have a specific extension, sometimes several different!

Share this post


Link to post
26 minutes ago, FPiette said:

Can you open an .arw file?

Yes, but the property page crashes explorer (endless "invalid window handle" error messages) with an actual .arw file. An empty text file renamed to xxx.arw works fine.

I believe this is a problem with the content functionality of the property page, not with the registration and display of the property page (i.e. it's not related to this thread).

 

26 minutes ago, FPiette said:

You should probably upgrade your Win7 to Win11.

Sure. I also shouldn't smoke and eat bacon 🙂

I have Windows 11 on my laptop for when I need a reminder of why I still use Windows 7 on my desktop.

Share this post


Link to post
21 hours ago, Anders Melander said:

FWIW, I believe the thing that you were missing was registering the class ID in HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved.

That is a very good point, I completely forgot about that!  It has been a long time since I last worked with Shell Extension handlers.

Edited by Remy Lebeau

Share this post


Link to post
2 hours ago, Anders Melander said:

Yes, but the property page crashes explorer (endless "invalid window handle" error messages) with an actual .arw file. An empty text file renamed to xxx.arw works fine.

I believe this is a problem with the content functionality of the property page, not with the registration and display of the property page (i.e. it's not related to this thread).

You have the source: the property page itself contains just a TMemo and no processing is done. Selected files in explorer are displayed (Explorer actually passes paths). I also occasionally saw that message. I couldn't reproduce the condition in which this arrive although I suspect this is when a second instance of the property sheet is opened.

Share this post


Link to post
2 hours ago, Anders Melander said:
3 hours ago, FPiette said:

Can you open an .arw file?

Yes, but the property page crashes explorer

Just to be sure, you opened a real .arw file (My sample?) by double clicking on his filename in Explorer window and Windows Photo Viewer displayed it correctly. Right?

Share this post


Link to post
9 minutes ago, FPiette said:

Just to be sure, you opened a real .arw file (My sample?) by double clicking on his filename in Explorer window and Windows Photo Viewer displayed it correctly. Right?

I have another application registered to open it by default (PhotoStage), but yes, double-clicking your file in Explorer opens it correctly.

 

Selecting "Properties" in Explorer bombed on the real file. The reason might be that there's another shell extension registered on the file type and that it's this extension that is causing the crash.

 

All this is on Windows 7. On Windows 10 and later the property page is not displayed (and the arw-file is opened in Photo Viewer).

Edited by Anders Melander

Share this post


Link to post

I just tried (on Windows 10) to:

  • Remove/rename all the non property sheet related registry key/values from the .arw and arwfile registry keys.
  • Copy all the .arw and arwfile registry key/values from HKLM to HKCU.

None of this made any difference.

I then renamed the HKCU .arw to .xxx and arwfile to xxxfile and was then able to display the property page on a test.xxx file.

 

So my experience now matches yours 😞

Share this post


Link to post

Just a thought - have you tried using SysInternals Process Monitor yet to see all of the Registry activity that Explorer invokes on Windows7 vs Windows 10/11 while registering the property handler and while loading the .arw file?

Share this post


Link to post
11 minutes ago, Remy Lebeau said:

have you tried using SysInternals Process Monitor yet to see all of the Registry activity that Explorer invokes on Windows7 vs Windows 10/11 while registering the property handler and while loading the .arw file?

It's about 40,000 log entries on both systems, so it's not a small task.

It's worth a try though. One might get lucky.

Share this post


Link to post
7 hours ago, Remy Lebeau said:

have you tried using SysInternals Process Monitor yet to see all of the Registry activity that Explorer invokes

Yes, I used ProcessMonitor. It is even among the first things I have done. But there is an incredibly high registry activity from explorer.

 

Share this post


Link to post

I've now compared the log from Windows 7 and Windows 10.somethingsomething. I searched for "arw" in both logs.

 

What stands out is that on Windows 7 the Explorer primarily uses the registry keys we're expecting; The documented ones.
For example, it looks for (and finds) the property sheet handler in HKCU\Software\Classes\arwfile\shellex\PropertySheetHandlers and HKCR\arwfile\shellex\PropertySheetHandlers.

 

On Windows 10 however, things are a bit different. Notably, it never looks for *arwfile\shellex\*

 

Both Windows 7 and Windows 10 look for (and don't find) HKCU\Software\Classes\SystemFileAssociations\.arw\shellex\PropertySheetHandlers and HKCR\SystemFileAssociations\.arw\shellex\PropertySheetHandlers.
They also read the more general keys HKCU\Software\Classes\*\shellex\PropertySheetHandlers, and HKCR\*\shellex\PropertySheetHandlers and Windows 10 additionally looks for HKCU\Software\Classes\Kind.Picture\shellex\PropertySheetHandlers and HKCR\Kind.Picture\shellex\PropertySheetHandlers.

 

Apparently, the SystemFileAssociations keys are related to something called Association Arrays.

  • Like 3

Share this post


Link to post
1 hour ago, Anders Melander said:

Both Windows 7 and Windows 10 look for (and don't find) HKCU\Software\Classes\SystemFileAssociations\.arw\shellex\PropertySheetHandlers and HKCR\SystemFileAssociations\.arw\shellex\PropertySheetHandlers.

On my system, the key HKCR\SystemFileAssociations\.arw exist. I updated my property sheet registration code to write a new key HKCR\SystemFileAssociations\.arw\shellex\PropertySheetHandlers\MyDelphiPropSheetHandler having as default value the CLSID of my property sheet. And Bingo! it works.

 

@Anders Melander you are a master! Congratulations!

 

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×