dwmkerr / sharpshell

SharpShell makes it easy to create Windows Shell Extensions using the .NET Framework.
MIT License
1.51k stars 260 forks source link

The menu does not appear #280

Open gmalagutti opened 5 years ago

gmalagutti commented 5 years ago

Version of SharpShell used: 2.x.y

Related type(s) of SharpShell-Server: Any

... the dll is compiled as .NET 4 any cpu on VS2010, tested using 'Test Server in Test Shell' and it works fine, but in Windows Explorer and Shell Debugger it never appears as a menu entry. Testing on Windows 10 x64. Using latest build downloaded today. manager

dwmkerr commented 5 years ago

Hi @gmalagutti check out the troubleshooting guide here:

https://github.com/dwmkerr/sharpshell/blob/master/docs/troubleshooting.md

In particular this guide:

https://github.com/dwmkerr/sharpshell/blob/master/docs/installing/installing.md

Most likely the server is not installing properly, follow the section on 'getting installation logs' and see if you can attach to the issue, which should help with troubleshooting!

gmalagutti commented 5 years ago

I opened a cmd as admin and executed the commands manually to register activating the log. Apparently it should be registered, but the log file does not get created, it is not there. When i run the execution command I see all the windows refreshing. No entry in the menu

C:\Users\Giorgio\Documents\Visual Studio 2010\Projects\DBWorksLogExtension\DBWorksLogExtension\bin\Debug>serverregistrationmanager config LoggingMode File

======================================== SharpShell - Server Registration Manager

Set LoggingMode to File

C:\Users\Giorgio\Documents\Visual Studio 2010\Projects\DBWorksLogExtension\DBWorksLogExtension\bin\Debug>serverregistrationmanager config LogPath '%temp%\SharpShell.log'

======================================== SharpShell - Server Registration Manager

Set LogPath to 'C:\Users\Giorgio\AppData\Local\Temp\SharpShell.log'

C:\Users\Giorgio\Documents\Visual Studio 2010\Projects\DBWorksLogExtension\DBWorksLogExtension\bin\Debug>serverregistrationmanager install dbworkslogextension.dll

======================================== SharpShell - Server Registration Manager

dbworkslogextension.dll installed and registered.

Microsoft .NET Framework Assembly Registration Utility version 4.7.3056.0 for Microsoft .NET Framework version 4.7.3056.0 Copyright (C) Microsoft Corporation. All rights reserved.

Types registered successfully

gmalagutti commented 5 years ago

My fault, it was not com visible. Thank you for time and care

gmalagutti commented 5 years ago

Sorry, not over yet. It seems tricky: in the Shell Debugger the menu item is there and in Windows Explorer it is not. To keep it simple no class of extension and CanShowMenu returns always true

Countryen commented 5 years ago

Hey @gmalagutti In the picture of you OP it says "Specified Associations: None" - maybe you didn't specify any and that's why it's not showing up? I guess you are building a SharpContextMenu? Then you should specify, when to show it (any file, a special extension (like .txt), folders, background, etc.)

fumiya-e commented 5 years ago

I experienced this issue.

I didn't specify any associations as well, because I wanted the menu to always show up. I fixed my problem using [COMServerAssociation(AssociationType.AllFilesAndFolders)]

Just thought I would share. Thank you @Countryen

Countryen commented 5 years ago

Hey @gmalagutti

do you still need help with this or did you find a solution? Did you try out a different COMServerAssociation or check yours? Feel free to share your soltion and/or close this issue :)

woernsn commented 5 years ago

Hi @Countryen, I have the same problem with my project. I am not sure if I am using a library that cannot be used with COM. The only special thing is System.IO, System.Linq and Windows.Forms.Form (with which I created a Form with simple RichTextBox.

It's working fine with "Test Server in Test Shell" of the Server Manager. Anywhere else it is simply not showing. I'm using not file endings but [COMServerAssociation(AssociationType.Directory)].

Registering within srm works fine without any error. The log shows only output with "Test Server in Test Shell" and nothing if used differently.

Any ideas?

Win10 x64, .NET Framework 4.7.2, SharpShell 2.2.1

Countryen commented 5 years ago

Hey @woernsn Please first make sure to use the most recent version of SharpShell: v2.7.1.

What commands do you use to register/install exactly? Can you try using the Server Manager instead? Does it show the "Specified Associationtype"?

I'd also recommend first to download one of the sample projects and try to get them working and registered correctly. If they also do not show up, maybe it's a deeper problem, if they do, it's probably an issue with your project/server.

Sidenote: COM will only use your DLL, and using your DLL (COM-Server) will create a .NET Instance/Runtime/Scope/Application which loads the other .NET Assemblies - they don't need to be available to COM, just .NET. Otherwise, all other classes would also need to be COMVisible.

[Edit: Minor corrections]

woernsn commented 5 years ago

Hi @Countryen!

Sorry for the typo - I am at 2.7.1. ;)

First I tried to install via the Server Manager - this shows the server as successfully installed and registered. Afther it didn't seem to work I tried the manual deploy methods from https://github.com/dwmkerr/sharpshell/blob/master/docs/installing/installing.md. I tried both - regasm and srm.

Directory is shown correctly in the Server Manager.

I also tried to simply register the CountLines project but I had the same behavior there..

Thanks for the sidenote - very good to know.

Countryen commented 5 years ago

Okay, let's first concentrate on getting the sample project working - CountLinesExtension. I just tested it completely from a fresh start (Win10 x64 VS2019). Maybe you wan't to reproduce my steps and see if it works for you, otherwise, feel free to post pictures what exactly is different (especially inside the registry/SM)

Here's what I do:

  1. Download/Clone the project master
  2. Open the CountLinesExtension.csproj (sharpshell/SharpShell/Samples/ContextMenu/CountLinesExtension)
  3. Remove the SharpShell reference
  4. Close VS and save the new CountLinesExtension.sln
  5. Open the new solution, and add the nuget for SharpShell v2.7.1 to the project
  6. Try to create/build the project in Debug AnyCPU -> Should work
  7. Download and open the ServerManager v2.7.1, add your dll from /bin/Debug. Make sure you have administrative rights for your PC.
  8. Execute Install Server (x64) and Register Server (x64) for your dll
  9. Restart explorer.exe (Explorer > Restart Explorer) and close the ServerManager
  10. Rightclick on any .txt file, it should show the context menu entry Count Lines... somewhere at the top of the menu.

This is how it looks inside my SM: image

This is how it looks inside my registry (regedit.exe): image (because we use ClassOfExtension, it uses the "txtfile" instead of ".txt")

image (our new extension, registered via GUID, can be manually set via [Guid("{...}")]-Attribute for the class)

image (searching for that GUID (should be a different one for you), will lead you to somwhere like this)

woernsn commented 5 years ago

Thanks for the detailed step-by-step how-to. This is what I have tried doing before - I didn't know about the registry handling though. My behavior is the expected one like shown in your screenshot. Everything is in the registry, where it should be.

But: image

Countryen commented 5 years ago

Mhm that's very odd then. Can you share pictures of your registry entries + Server Manager? Maybe there is a small difference. You could also try using shexview to see, if it's listed and what the state is. It's a little tool from nirsoft: https://www.nirsoft.net/utils/shexview.html, helps a lot when trying to figure out problems with shell extensions.

woernsn commented 5 years ago

Registry values: image

image

image

Server Manager: image

ShexView shows a very interesting result. It seems that the path to the dll got messed up somehow. image

Countryen commented 5 years ago

Okay did a lot testing and troubleshooting. I think I've found a solution.

The path is weird, but even weirder, for me ShexView shows that my DLL is in the GAC: image

I searched the GAC

but the DLL is nowhere to be found.

So I did some testing and managed to reproduce the issue - I just don't know why but the extension didn't work anymore (like you described). But I also managed to get it working again, manually.

What works for me is a complete fresh start (deinstall and deregister) and then using regasm /codebase. Important: I had to use the x64 version (C:\Windows\Microsoft.NET\Framework64\v4.0.30319). after executing cmd/powershell: regasm "D:\test\CountLinesExtension.dll" /codebase and restarting explorer, the extension works again.

Previously I thought extensions needed to be installed and registered in Server Manager - but now it works with just "installed 64 bit". I searched and analysed the Server Manager a bit and it's actually really confusing and weird.

Back to your case @woernsn. Try the following:

Afterwards you can again use Server Manager to (de-)register/install your extension.

Sadly with registry/registration and installation issues - issues tend to not always be easily reproducable or consistent, they just "work" sometimes. Also, trying it with a completely fresh GUID helped me in the past.

woernsn commented 5 years ago

Thanks for all your support @Countryen! What I did now:

  1. Check with gacutil -u "CountLinesExtension -> Nothing was found.
  2. Unregister with regasm /u (from the Framework64 directory).
  3. Rebuilding the dll with a new GUID.
  4. Registering with regasm. The result in ShellExView is that the new GUID is shown but the file is still missing. image

Registry: image

Countryen commented 5 years ago

Okay a few other things to try:

  1. Make sure there is no firewall/anti-virus-system blocking anything, they tend to not like Shell-Extensions.

  2. Make sure that the context menu for "*.txt" is actually related to Computer\HKEY_CLASSES_ROOT\txtfile by creating a new entry manually (shell) like in the picture below: image The context menu needs to show the custom entry afterwards: image

  3. Install and register for both x86 and x64 with Server Manager

  4. Look for your extension here in the registry: Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\ Remove it, if you find it and try registering/installing again. It should only be in "Approved", I think I deleted the entry in "Cached", too. (Make sure to restart explorer or if possible your PC after changing entries here)

  5. Search the Fusion AssemblyLoading/-Binding log for information: See: https://docs.microsoft.com/de-de/dotnet/framework/tools/fuslogvw-exe-assembly-binding-log-viewer Start the fuslogvwrin elevated VS Dev prompt. Go to settings, enable the last option "enable all bindings...". Refresh, deregister and deinstall completely and install and register again with Server Manager. Then restart explorer exe and open the context menu for the .txt file. It will try to load your file on the first context menu opening after restarting explorer.exe. Search for your extension path or name and view the protocol. image If there is no issue here, see the other logs/protocols as maybe a referenced assembly is missing.

  6. Try building the project in Release mode for x86 and x64 specifically, and retry with Server Manager, Regasm (with and without gacutil) and see if there is any difference.

  7. Move the whole bin content (your dll + SharpShell lib etc.) to another path like "D:\test" (make sure that path is not protected), register/install again. Also make sure to rename your DLL to ".DLL" instead of ".dll" (you probably have to rename twice for that)

  8. Did you already check the installation logs? Should look something like that:

    2019-07-02 22:51:29.672Z - ServerManager - Preparing to register SharpShell Server CountLinesExtension as OS32Bit
    2019-07-02 22:51:29.678Z - ServerManager - Registration of CountLinesExtension completed
    2019-07-02 22:51:32.032Z - ServerManager - Preparing to register SharpShell Server CountLinesExtension as OS64Bit
    2019-07-02 22:51:32.038Z - ServerManager - Registration of CountLinesExtension completed
  9. There have been some instances, where the "ClassOfExtension" was ignored when used. You can try setting the COMServerAssociation to a specific (custom) file-extension or something like "AllFilesAndFolders".

  10. I've also had more problems like this in the past, but after building the complete solution once (including the NativeBridge, which requires the Windows SDK (Visual C++ project), problems seem to be less of a problem. Maybe because some SDK part or something else.

According to the Troubleshooting:

Important: For most SharpShell servers to work on anything other than a development machine, they MUST be built in Release Mode against the Release Mode SharpShell binary. This binary uses an unmanaged C++ component that has a dependency to MSVCRTD100.dll in debug mode - this will NOT be present on none-development machines.

Maybe that's missing?

I am still unsure, why ShexView doesn't show the right path... can you open the "File Properties" from the right click context menu in ShexView? Note: It always shows "Missing File" for me and I can't open the "File Properties", too (but the extension does work for me)

Let me know if anything worked :)

Countryen commented 5 years ago

Oh actually before that, also try registering with gacutil.

  1. deregister and deinstall completely
  2. install in GAC with: gacutil -i "D:\Path\To\CountLinesExtension.dll"
  3. It should then be listed with gacutil -l or inside the GAC_MSIL folder of C:\Windows\Microsoft.NET
  4. Register with regasm /codebase or with the Server Manager (Install & Register)
  5. Check the registry entry, it should now show the GAC-path at CodeBase
  6. Restart Explorer and try it, also see what ShexView now tells you
woernsn commented 5 years ago

Hi @Countryen ,

sorry for the delayed answer - quite busy at the moment at work. After trying registering with gacutil, I am getting the correct path in ShexView: C:\WINDOWS\system32\C:/WINDOWS/Microsoft.Net/assembly/GAC_MSIL/CountLinesExtension/v4.0_1.0.0.0__3abfeebd1a832fed/CountLinesExtension.dll Note the "C:\WINDOWS\system32\" prefix again.

The explorer does still not show the context menu.

Countryen commented 5 years ago

Hi @woernsn, no problem, It's a tedious problem and as long as you don't demand answer asap I won't complain.

Yes, it still shows "C:\WINDOWS\system32..." which is totally weird to me. I will try to reproduce that, if I can.

Feel free to try out my (other) 10 steps above in the meantime. I tried to list them in order of work needed (easy -> hard).

Also be sure to check out the note with the "MSVCRTD100.dll".

yafacex commented 5 years ago

I experienced similar problems.CountLinesExtension works fine both at Shell Debugger and explorer,but AdvancedContextMenuExtension fails at explorer.Any Ideas?

yafacex commented 5 years ago

I experienced similar problems.CountLinesExtension works fine both at Shell Debugger and explorer,but AdvancedContextMenuExtension fails at explorer.Any Ideas?

I comment ToolStripMenuItem's Image.It works.However,I met another problem.When I uninstall the dll using ServerManager and recompile AdvancedContextMenuExtension again.The .dll file can not be deleted.I have to restart my computer.Althogh I restarted my pc,change some code,install it again,there seems no change in result!It seems not really delete that dll(stored somewhere in cache?) and if I want my change take effect,I have to rename the Server Name.

yafacex commented 5 years ago

I experienced similar problems.CountLinesExtension works fine both at Shell Debugger and explorer,but AdvancedContextMenuExtension fails at explorer.Any Ideas?

I comment ToolStripMenuItem's Image.It works.However,I met another problem.When I uninstall the dll using ServerManager and recompile AdvancedContextMenuExtension again.The .dll file can not be deleted.I have restart my computer.Althogh I restarted my pc,change some code,install it again,the result seems no change!It seems not really delete that dll(stored somewhere in cache?) and if I want my change take effect,I have to rename the Server Name.

I found why it can't take effect.The .dll file stored a copy at file:///E:/MyGits/sharpshell/SharpShell/Samples/ContextMenu/AdvancedContextMenuExtension/bin/Release/AdvancedContextMenuExtension.DLL . After I deleted it and install server again.The change take effect.I think maybe in your uninstall logic, should remove this file and clear the associated register file item(HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\xxxxx)

Countryen commented 5 years ago

Hey @yafacex, thanks for the additional infos and details. I noticed that behaviour, too. Made me go nuts when I first tried to create a SharpShell extension, always needing to change the name or make another project helped. I will see, where to put it in the docs.

Hey @woernsn and @gmalagutti, you haven't come back to this issue in a while. Do you still need help / is this still an issue for you? Feel free to share your solution, if you found any. Please don't just close the issue, as I want to add parts of the solution to the docs if possible.

woernsn commented 5 years ago

Hi @Countryen, I gave more or less up on it. A friend of mine created the context menu entry with the "original" C way to register the handler. Once I get some more free time, I will come back to the problem - so that maybe others can find the solution to this problem..

Countryen commented 4 years ago

Just found something that could explain the issue.

There are special considerations for 64-bit Windows when registering handlers that work in the context of 32-bit applications: when Shell verbs are invoked in the context of a 32-bit application, the WOW64 subsystem redirects file system access to some paths. If your .exe handler is stored in one of those paths, it is not accessible in this context. Therefore, as a work around, either store your .exe in a path that does not get redirected, or store a stub version of your .exe that launches the real version.

Source: https://docs.microsoft.com/de-de/windows/win32/shell/shortcut-menu-using-dynamic-verbs#about-static-and-dynamic-verbs

Maybe that's why the C:\WINDOWS\system32\ prefix is added.

barnacleboy commented 3 years ago

I've experienced the same issue and also thought the "C:\WINDOWS\system32" in ShexView is the key to the problem, but it is just a red herring. But: I have another .NET (non SharpShell) shell extension installed from Microsoft that does not have this prefix in the path and it is furthermore not displayed as missing...

Setting up the "Count lines" sample worked immediately for me, so I tracked down the results from Fusion Log and found out that I had messed up several platform settings. My "Shell" assembly that includes all SharpShell relevant subclasses was already "Any CPU", but another project reference of it was set to x86. So now I have every reference in my SharpShell implementation assembly set to "Any CPU" besides of a C++/CLI library that is still set to Win32.

Countryen commented 3 years ago

I had messed up several platform settings

So you mean that it could be because of 64-bit / 32-bit difference? But why does that matter?

Great input though, maybe this helps others in finding their issue.

barnacleboy commented 3 years ago

In my case my app itself has to be 32 bit because of native Win32 code in the C++/CLI mixed mode assembly, otherwise I'm getting BadFormatException on startup. All other assemblies are set now to "Any CPU", the mixed mode is Win32. Fusion Log pointed me in the right direction and told me which assembly could not be loaded. Error message was the message from BadFormatException.

AddioElectronics commented 3 years ago

After days of trouble shooting I found my issue. If your menu calls any functions, or classes with static initializers that call functions that require elevated permissions, your menu will not show up.

fartwhif commented 1 year ago

has anyone figured this out? does this project even work?

AddioElectronics commented 12 months ago

has anyone figured this out? does this project even work?

I used it a long time ago and it did.

fartwhif commented 11 months ago

I don't think it does.

santocaridi99 commented 8 months ago

Hi everyone, I solved this problem without having to use the server manager, just using the regasm. In my project I had to show the contextual menu when I selected one or more .pdf files. i entered [COMServerAssociation(AssociationType.AllFiles)] above the class and in the override of the CanShowMenu function, I put a check on the paths of the files that were selected and if these were not .pdf it exited the function. Specifying only [COMServerAssociation(AssociationType.FileExtension,".pdf")] visually nothing appeared. So everything seems to be working fine