Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Context Menu Count Lines example won't show when trying with image files #385

Open
WaGi-Coding opened this issue Jan 9, 2023 · 5 comments

Comments

@WaGi-Coding
Copy link

WaGi-Coding commented Jan 9, 2023

Hey i just try the count lines examples.

It works fine. But when i want to show the context menu entry on a .png instead of a .txt by changing it to [COMServerAssociation(AssociationType.ClassOfExtension, ".txt", ".png")] does not work.

It simply does not show the menu entry for count lines for png files or any other image files, while it still works fine on .txt

Only using .png also won't work. I somehow have the feeling that i've too many context menu entries or so for image files already?!:
grafik

Any help would be appreciated. Greetings

@WaGi-Coding
Copy link
Author

WaGi-Coding commented Jan 9, 2023

When i use AllFiles it works
[COMServerAssociation(AssociationType.AllFiles)]

now i am even more confused. But unfortunately, i won't show it on all files


When using this
[COMServerAssociation(AssociationType.ClassOfExtension, ".bmp", ".dib", ".rle", ".png", ".jpeg", ".jpg", ".jpe", ".jfif", ".gif", ".tif", ".tiff", ".txt")]

it also only works with .txt files

the deprecated AssociationType.FileExtension does not work at all.

I am on .NET Framework 4.8 on a Windows 10 22H2 machine


Now also tried
[COMServerAssociation(AssociationType.Class, "pngfile")]
which wont work while
[COMServerAssociation(AssociationType.Class, "txtfile")]
works.

I guess there is some major bug with that :/


All that tested with the nuget package & also from main branch compiled .dll

@WaGi-Coding
Copy link
Author

nvm i found the issue in https://github.com/dwmkerr/sharpshell/blob/main/docs/troubleshooting.md#the-file-type-verifier

It seems that sometimes creating the [ComServerAssociation] is not enough. When you add the registry key for the given extension, the context menu may be got from a different part of the registry for the users preference. For example, for 'png', uou can determine this by checking the user choice:

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts.png\UserChoice 

This will give you the progid gives you the keyname to associate with the server. In this case, it might be WindowsLive.PhotoGallery.png.16.4.

I did this manually and hey presto it works.

@WaGi-Coding
Copy link
Author

WaGi-Coding commented Jan 9, 2023

But now i run into another problem.

As it's not always the same ProgId, but the Association needs to be constant, how could i actually detect that and set it, so it does not only work on my machine or on machines where ProgId happens to be the same?

For my system it is AppX43hnxtbyyps62jhe9sqpdzxn1790zetc
[COMServerAssociation(AssociationType.Class, "AppX43hnxtbyyps62jhe9sqpdzxn1790zetc")]
which now works,

but it's not the same on another machine and [COMServerAssociation(AssociationType.ClassOfExtension, ".png")] won't work as mentioned earlier.

So i need to set the correct values from users registry, but idk how one could properly do that.


I guess the problem is that i should actually use ClassOfExtension for that, but there is something in getting the actual class name not properly working. Not sure. I give up :(

@WaGi-Coding WaGi-Coding reopened this Jan 9, 2023
@WaGi-Coding
Copy link
Author

WaGi-Coding commented Jan 9, 2023

Hmm, so i checked ServerRegistrationManager.cs and it seems that it tries to get the default values of the extensions in HKEY_CLASSES_ROOT
grafik

But i actually need the ProcId from HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.png\UserChoice
grafik

I don't really understand that. It basically installs the server for all users and also tries to get the global extension classname, while it would differ from user to user?!

I made this little method now which would pick the one for the current user

private static string GetProgIdForFileType(string fileExtension)
        {
            string progId = null;

            // Read the UserChoice key for the file extension
            using (RegistryKey userChoiceKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey($@"Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts.{fileExtension}\UserChoice"))
            {
                if (userChoiceKey != null)
                {
                    progId = (string)userChoiceKey.GetValue("ProgId");
                }
            }

            return progId;
        }

But well, i guess that would not work when another user wants to use it who does use anoter ProcId, or when the same user changes the default program for the extension via windows?

Sorry for all that confusion, but it's not that easy it seems ._.

@Jdbye
Copy link

Jdbye commented Nov 15, 2023

This was a big issue for me,and the comment about it in the documentation was not exactly helpful in figuring out to solve it.

However, I did figure out an easy solution, that doesn't involve getting the key from UserChoice, it's just a simple copy and paste.
All you do, is add the file association to HKEY_CLASSES_ROOT\SystemFileAssociations\.ext instead of directly in HKEY_CLASSES_ROOT\.ext. And it just works.
I simply exported the .reg file from the existing entries that SharpShell had added to HKEY_CLASSES_ROOT.ext\ShellEx, modified the paths, and imported it back in, and it immediately worked. That's the quickest way to do it right now, but obviously adding things into the registry manually is not really ideal for the end user. In any case, the .reg file made is universal across PCs (since it doesn't contain any unique data, like that UserChoice key), but it will be specific to your app since it contains the GUID. So you could just ask your users to import the reg file, if you don't feel like doing it in code.

I'd like to suggest to the devs that this be officially implemented, since it's a much easier solution than the workaround that's barely mentioned in the docs. Not sure if I should make a new issue for it or not.

In the end I asked ChatGPT to convert the reg file to C# code for me (lazy heh and I so rarely deal with the registry that I don't remember exactly how to do it) so I could add it to my installer/uninstaller code, for a quick fix. Works perfectly.

If anybody by chance is curious about my installer/uninstaller code - I just looked at the Server Manager source code and copied the bits needed for installing/registering/uninstalling/unregistering. That was the easy part, figuring this one issue out was the hardest part by far, especially as that comment in the docs is hidden away and it took me hours to discover it, all the while I thought I was doing something wrong and my shell extension was broken because of it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants