Register an HKCU key with CustomAction in a Visual Setup Project?

1 day ago 3
ARTICLE AD BOX

In my solution.slnx file, I have the following C# code projects:

- A simple VSTO .NET Framework 4.8.1 project. (Currently, it's working well.)

- A simple ExcelDna project that adds some extension utility functions, such as SumByStyle, to Excel. It has built 32-bit and 64-bit package.xll files, and I've ensured these files are moved to the correct path that Excel can read, and they all work correctly (if I add them manually in Excel).

- An Installer-SetupProject project (Microsoft Visual Studio Installer Projects 2022, latest version 3.0.0) to package them.

To dynamically write to the Registry for AutoLoad xll in Excel, without requiring any additional user action after installation (using VSTO and ExcelDna), I added a C# ClassLibrary project. I implemented code inherited from Installer and overridden both Installer and Uninstaller. Then I assigned them to the CustomAction of the Setup Project. Some of the Registry registration code is as follows:

public void RegisterOfficeExcelExtension() { WriteLog("Start RegisterOfficeExcelExtension"); LogCurrentContext(); using (RegistryKey officeRoot = Registry.CurrentUser.OpenSubKey(@"Software\\Microsoft\\Office", writable : true)) { if (officeRoot == null) { WriteLog("Not found Office in HKCU"); return; } foreach (string version in officeRoot.GetSubKeyNames()) { if (!Regex.IsMatch(version, @"^\d+(\.\d+)?$")) continue; using (RegistryKey versionKey = officeRoot.OpenSubKey(version, writable : true)) { if (versionKey == null) continue; using (RegistryKey excelOptions = versionKey.CreateSubKey(@"Excel\\Options")) { if (excelOptions == null) continue; var existingValues ​​ = new HashSet < string > (StringComparer.OrdinalIgnoreCase); foreach (string valueName in excelOptions.GetValueNames()) { existingValues.Add(valueName); } int index = 0; foreach (string file in fullFilePathExt) { bool alreadyRegistered = false; foreach (string valueName in excelOptions.GetValueNames()) { string strValue = excelOptions.GetValue(valueName)?.ToString()?.Trim('"'); if (string.Equals(strValue, file, StringComparison.OrdinalIgnoreCase)) { alreadyRegistered = true; WriteLog($"File: {file} Key: {valueName}"); break; break; } } if (!alreadyRegistered) { string newKeyName; due { newKeyName = index == 0 ? "OPEN" : $"OPEN{index}"; index++; } while (existingValues.Contains(newKeyName)); excelOptions.SetValue(newKeyName, file, RegistryValueKind.String); existingValues.Add(newKeyName); string regPath = $@"HKCU\\Software\\Microsoft\\Office\\{version}\\Excel\\Options"; WriteLog($"KeyCreated: '{newKeyName}' Value: '{file}' At: {regPath}"); } } } } } } } } WriteLog("End RegisterOfficeExcelExtension"); }

That loop is just for illustration; you don't need to go into detail about everything in it.

Specifically, I will write the Registry to HKCU (Computer\HKEY_CURRENT_USER\Software\Microsoft\Office\16.0\Excel\Options). Create a new String key with keyname = OPEN, and the value is the exact absolute path to the package.xll files.

Yes, they work perfectly fine without any errors.

But when I Start -> Run -> regedit -> Enter and check the keys at: Computer\HKEY_CURRENT_USER\Software\Microsoft\Office\16.0\Excel\Options is not being written. I also checked my log file and all keys were successfully written.

So I checked in Computer\HKEY_USERS\S-1-5-18\Software\Microsoft\Office\16.0\Excel\Options and, crazy, all keys were written there. Since the Microsoft MSI installer seems to be running on a different context than HKCU, it can't write to HKCU.

I've struggled, looked up, searched, asked AI, and tried everything advanced available today, but all to no avail. I've also looked at other installation solutions, but they are either outdated (e.g., WiX v3), no longer supported, or require payment. So if you have any experience or a better solution, please enlighten me.

Read Entire Article