Windows Side-by-Side
When you want to share your DLL's across applications there are a couple of options:
- put in a directory and add a path variable
- dump in the Windows system directory
- put in the Windows Side-by-Side (WinSxS)
- since Windows 7: using application config files and probing. This is the same as the first option but without a fragile global PATH variable.
Under Windows XP the first two options were not recommended. The third option was then the way to go but the documentation is not updated. Therefore one may question if it is still recommended.
To put something in the WinSxS one need:
- a manifest
- a signed cat file which lists all the installed components
- one or more DLL's to install
The following steps were executed:
- Create a certificate in PowerShell with e.g. 'New-SelfSignedCertificate -Type CodeSigningCert -Subject "CN=SxSTestCert" -CertStoreLocation "Cert:\CurrentUser\My"'. This creates a SxSTestCert in the personnel section of the certification store. One can check this with 'cermgr.msc'.
- extract the public key and store in a *.cer file.
- create a publicKeyToken with SDK tool pktextract.exe from the just created *.cer file. Use calculated value for in the manifest file. This is a crucial step: with an incorrect publicKeyToken one get all kinds of errors.
- create a manifest (see below). The entries in the manifest file described the side by side assembly
- create a cdf file listing all files in the manifest file
- create a cat file from the cdf; e.g. 'makecat.exe Test.cdf'
- sign the cat file with the certificate with signtool. For example use 'signtool.exe sign /s My /n "SxSTestCert" /fd SHA256 /t http://timestamp.digicert.com Test.MyCompany.MyAssembly.cat'
A manifest file may look like:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
type="win32"
name="Test.MyCompany.MyAssembly"
version="1.0.0.0"
processorArchitecture="amd64"
publicKeyToken="91cb7a3ae2229a15"/>
<!-- Add your DLL file here -->
<file name="MyPayload.dll">
</file>
</assembly>
The associated cdf file may look like this:
[CatalogHeader]
Name=Test.MyCompany.MyAssembly.cat
ResultDir=.
PublicVersion=1
CatalogVersion=2
HashAlgorithms=SHA256
[CatalogFiles]
<HASH>Test.MyCompany.MyAssembly.manifest=Test.MyCompany.MyAssembly.manifest
<HASH>MyPayload.dll=MyPayload.dll
Now that you have all files in code you have to invoke 'InstallAssembly'. Note that there is no sxs.lib to link against so the function 'CreateAssemblyCache' must be extracted from 'sxs.dll' through LoadLibrary / GetProcAddress.
#include <winsxs.h>
#include <atlbase.h>
void AssemblyCreate()
{
CComPtr<IAssemblyCache> ptrCache;
HMDULE hModule = ::LoadLibrary(sxs.dll);
using PfCreateAssemblyCache = HRESULT (*) (IAssemblyCache**, DWORD);
PfCreateAssemblyCache pfCreateAssemblyCache = reinterpret_cast<PfCreateAssemblyCache>(::GetProcAddress(hModule, "CreateAssemblyCache"));
HRESULT hr = pfCreateAssemblyCache(&ptrCache, 0);
FUSION_INSTALL_REFERENCE ref = { 0 };
ref.cbSize = sizeof(FUSION_INSTALL_REFERENCE);
ref.dwFlags = 0;
ref.guidScheme = FUSION_REFCOUNT_OPAQUE_STRING_GUID; // Required!
ref.szIdentifier = L"MyTestInstallerApp";
ref.szNonCannonicalData = L"Test Installation";
constexpr wchar_t szManifestFilePath[] = L"Test.MyCompany.MyAssembly.manifest";
hr = ptrCache->InstallAssembly(0, szManifestFilePath, &ref);
if (SUCCEEDED(hr))
{
}
::FreeLibrary(hModule);
}
This creates a side by side package:
- on Windows 10 on C:\Windows\WinSxS and Manifests folders
- on Windows 11 on C:\Windows\WinSxS\Fusion folder
Acknowledgement
AI tooling Gemini guided me through the process of uncovering most of the information presented here. A couple of times I was steered in the wrong direction as well. For example on Windows 11 side-by-side components are installed in the Fusion subdirectory which was thought to be a .NET only location by Gemini. It suggested an alternative route through IAssemblyCacheItem but this yielded the same outcome. Only later I had to correct Gemini that Fusion is probably a Windows 11 thing. Claude first classified it as an outdated technology; later recommended this option based on the requirements until it concluded that installing in SxS would not be possible (based on SxS tracing) and only reserved for Microsoft themselves.