CodeProject has a great Windows shell extension tutorial.
Compile, run Regasm.exe CSShellExtContextMenuHandler.dll /codebase
, and the shell extension is available, it works great.
But asking users to run Regasm
would not be user-friendly, so I wrote the small WiX script below. (just copied the output of heat
, plus a dependency DLL I want to use).
PROBLEM: When I install the resulting MSI, the shell extension does not appear (in Windows Explorer, right-clicking on a file does not show my item, despite it working with Regasm
)
<?xml version='1.0' encoding='windows-1252'?>
<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
<Product Name='HelloWorld Shell Extension' Id='2afd44ab-16d7-40f4-8741-69ad546cb7cf' UpgradeCode='c5139d19-21ba-43c6-a17d-68760331f332'
Language='1033' Codepage='1252' Version='0.4.4' Manufacturer='Me'>
<Package Id='*' Keywords='Installer' Description="HelloWorld Shell Extension Setup" Manufacturer='Me'
InstallerVersion='100' Languages='1033' Compressed='yes' SummaryCodepage='1252' />
<Media Id='1' Cabinet='HelloWorldShellExtension.cab' EmbedCab='yes' DiskPrompt='HelloWorld CAB' />
<Property Id='DiskPrompt' Value="HelloWorldShellExtension Bundle CAB Installation" />
<Directory Id='TARGETDIR' Name='SourceDir'>
<Directory Id='ProgramFilesFolder' Name='PFiles'>
<Directory Id='INSTALLDIR' Name='HelloWorldShellExtension'>
<Component Id="cmpB0970E4FB9610FC20E1C6B6B2D45C606" Guid="7044db96-17d3-4d4f-93b0-135b89b042c8">
<Class Id="{CE43A2AB-B457-49BF-C83F-4306208D438B}" Context="InprocServer32" Description="CSShellExtContextMenuHandler.FileContextMenuExt" ThreadingModel="both" ForeignServer="mscoree.dll">
<ProgId Id="CSShellExtContextMenuHandler.FileContextMenuExt" Description="CSShellExtContextMenuHandler.FileContextMenuExt" />
</Class>
<File Id="fil5B7C752C5541C807852A6781921F95AB" KeyPath="yes" Source="bin\CSShellExtContextMenuHandler.dll" />
<RegistryValue Root="HKCR" Key="*\shellex\ContextMenuHandlers\{ce43a2ab-b457-49bf-c83f-4306208d438b}" Value="CSShellExtContextMenuHandler.FileContextMenuExt Class" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{CE43A2AB-B457-49BF-C83F-4306208D438B}\Implemented Categories\{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}" Value="" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{CE43A2AB-B457-49BF-C83F-4306208D438B}\InprocServer32\1.0.0.0" Name="Class" Value="CSShellExtContextMenuHandler.FileContextMenuExt" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{CE43A2AB-B457-49BF-C83F-4306208D438B}\InprocServer32\1.0.0.0" Name="Assembly" Value="CSShellExtContextMenuHandler, Version=1.0.0.0, Culture=neutral, PublicKeyToken=73df467e0a99a326" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{CE43A2AB-B457-49BF-C83F-4306208D438B}\InprocServer32\1.0.0.0" Name="RuntimeVersion" Value="v4.0.30319" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{CE43A2AB-B457-49BF-C83F-4306208D438B}\InprocServer32\1.0.0.0" Name="CodeBase" Value="file:///[#fil5B7C752C5541C807852A6781921F95AB]" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{CE43A2AB-B457-49BF-C83F-4306208D438B}\InprocServer32" Name="Class" Value="CSShellExtContextMenuHandler.FileContextMenuExt" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{CE43A2AB-B457-49BF-C83F-4306208D438B}\InprocServer32" Name="Assembly" Value="CSShellExtContextMenuHandler, Version=1.0.0.0, Culture=neutral, PublicKeyToken=73df467e0a99a326" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{CE43A2AB-B457-49BF-C83F-4306208D438B}\InprocServer32" Name="RuntimeVersion" Value="v4.0.30319" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{CE43A2AB-B457-49BF-C83F-4306208D438B}\InprocServer32" Name="CodeBase" Value="file:///[#fil5B7C752C5541C807852A6781921F95AB]" Type="string" Action="write" />
</Component>
<Component Id='Libraries' Guid='f982a0bb-824d-4835-921d-e51b47b8598b'>
<File Id='dependency.dll' Name='dependency.dll' Source='bin\dependency.dll' DiskId='1' />
</Component>
</Directory>
</Directory>
</Directory>
<Feature Id='HelloWorldShellExtensionFeature' Title='HelloWorld' Description='HelloWorld' Level='1' AllowAdvertise='no'>
<ComponentRef Id="cmpB0970E4FB9610FC20E1C6B6B2D45C606" />
<ComponentRef Id="Libraries" />
</Feature>
<UI>
<UIRef Id="WixUI_InstallDir" />
</UI>
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLDIR" />
</Product>
</Wix>
I tried to change Root="HKCR" Key="[...]"
to Root="HKLM" Key="SOFTWARE\Classes\[...]"
, to mimic the keys Regasm actually installs, but that does not work either.
First, the CLSID you are using is different than the original example source. Perhaps you edited it to make it your own. Make sure you are using the same value as the attribute on the FileContextMenuExt
class.
WiX's heat.exe doesn't seem to support the codebase element. Perhaps the assumption is that since you are registering the COM assembly machine-wide, you would also put it in the machine-wide assembly location (i.e., the GAC). If you do, codebase won't be required.
heat file ...
will generate everything except the Codebase element but you've entered that by hand, I see. You also have the other required registration entry, *\shellex\ContextMenuHandlers
. It's an application-specific element so it can't be generated. But, you also entered that by hand.
Finally, the installer and explorer.exe have to have the same "bit-ness." Otherwise, the installer might make registry entries for the 32-bit explorer.exe where the 64-bit explorer.exe won't see them. To deploy the product, you'll have to have an x86 and an X64 build of the installer. You can explicitly set the Platform for the package in the Wix/Product/Package
element.
Other than that, your Product.wxs
"works on my machine."
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With