Files
DP44/enriched-qwen3-coder-next/DataPRO/Modules/InstallerCustomActions/RegAddProductCode.md
2026-04-17 14:55:32 -04:00

101 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
source_files:
- DataPRO/Modules/InstallerCustomActions/RegAddProductCode/AddProductCode.cs
generated_at: "2026-04-16T04:43:28.721583+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "c22465a70e9ccf40"
---
# RegAddProductCode
## Documentation: `AddProductCode.cs` — Installer Custom Action for Registry Policy Configuration
---
### 1. Purpose
This module implements a Windows Installer custom action (`AddProductCode`) responsible for configuring Windows Installer security policies in the registry prior to or during DataPRO installation. Specifically, it enforces the `SecureRepairPolicy` setting and adds the DataPRO product code to the `SecureRepairWhitelist`, enabling the installer to perform repair operations on `DataPRO.exe` and its dependencies without being blocked by Windows Installers secure repair restrictions. It also validates architecture compatibility between the installer process (32- or 64-bit) and the operating system, terminating the installation with a user-facing error if a mismatch is detected (e.g., 32-bit installer on 64-bit OS), to prevent downstream failures such as incompatible SQL LocalDB version conflicts.
---
### 2. Public Interface
The class `AddProductCode` exposes only one public entry point:
#### `static int Main(string[] args)`
- **Signature**: `private static int Main(string[] args)`
- **Behavior**:
Entry point for the custom action. Parses `args[0]` as `architectureVersion` (`"x86"` or `"x64"`), logs environment details (process bitness, OS bitness), and performs architecture validation:
- If `architectureVersion == "x86"` and OS is 64-bit → shows error message and returns `1`.
- If `architectureVersion == "x64"` and OS is 32-bit → shows error message and returns `1`.
- Otherwise, calls `AddCodeToRegistry()` and returns `0` (success) or `1` (failure if registry write fails).
- Logging is performed via `EventLog.WriteEntry` under source `"DataPROInstaller"`.
> **Note**: Though declared `private`, this method is the *de facto* public entry point for the custom action as invoked by the Windows Installer (e.g., via `CustomAction` table). It is not called internally.
---
### 3. Invariants
- **Architecture Consistency**:
The installer process bitness must match the target OS bitness *relative to the requested architecture* (`args[0]`). Mismatches cause early termination with exit code `1`.
- **Registry Hive & View**:
All registry modifications target `HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Installer` using `RegistryView.Registry64`, ensuring writes occur in the 64-bit view even on 64-bit systems (i.e., not redirected to `WOW6432Node`).
- **Policy Values**:
The following must be set:
- `SecureRepairPolicy` (DWORD) = `2` (enables secure repair for whitelisted products).
- `SecureRepairWhitelist\{C4889149-0CAF-44C1-B226-8F6E73684DF4}` (DWORD) = `0` (adds product code to whitelist).
- **Exit Codes**:
- `0`: Success (registry updated or already correct).
- `1`: Failure due to architecture mismatch or registry write error.
---
### 4. Dependencies
#### Imports / External Dependencies:
- `System.Diagnostics.EventLog` for installer logging.
- `Microsoft.Win32.RegistryKey`, `RegistryHive`, `RegistryView`, `RegistryValueKind` for registry access.
- `System.Windows.Forms.MessageBox` for user-facing error messages.
- `RegAddProductCode.Properties.Settings.Default` static configuration values:
- `Settings.Default.InstallerKey`: Registry path `"SOFTWARE\\Policies\\Microsoft\\Windows\\Installer"`
- `Settings.Default.SecureRepairPolicy`: Policy value name `"SecureRepairPolicy"`
- `Settings.Default.SecureRepairWhitelistKey`: Subkey path `"SOFTWARE\\Policies\\Microsoft\\Windows\\Installer\\SecureRepairWhitelist"`
- `Settings.Default.ProductCode`: Product code GUID `"{C4889149-0CAF-44C1-B226-8F6E73684DF4}"`
- `Settings.Default.MissingKey`: Format string for error messages (e.g., `"Registry key missing: {0}"`).
#### Usage:
- **Called by**: Windows Installer as a custom action (likely in a WiX or similar MSI project).
- **Depends on**:
- Administrative privileges (required to write to `HKLM\SOFTWARE\Policies\...`).
- `EventLog` source `"DataPROInstaller"` must exist or be creatable by the installer process.
---
### 5. Gotchas
- **Hardcoded Product Code**:
The product code `"{C4889149-0CAF-44C1-B226-8F6E73684DF4}"` is hardcoded in both `Settings.Default.ProductCode` and the whitelist logic. Changing the product code in the installer project requires updating this value manually—no dynamic injection is present.
- **Silent Failure Risk in 32-bit on 64-bit**:
The comment explains that allowing a 32-bit installer on 64-bit OS could cause the SQL LocalDB 2014 prerequisite to fail silently, leading to runtime DB version incompatibility. This is a *preventive guard*, but the fix is architectural (blocking 32-bit installers entirely on 64-bit OS), not a workaround.
- **Registry View Hardcoded to 64-bit**:
`RegistryView.Registry64` is used unconditionally—even on 32-bit OSes. While `OpenBaseKey` with `Registry64` on a 32-bit OS is safe (it falls back to the native view), this may be unintentional or legacy. No explicit fallback to `RegistryView.Registry32` exists.
- **No Rollback Handling**:
If `AddCodeToRegistry()` succeeds but the main installer fails later, the registry changes are *not* rolled back. The policy settings remain in place.
- **Commented-Out UI Error**:
The line `// MessageBox.Show(result);` is commented out in `Main()`, meaning registry errors are *only* logged to Event Log, not shown to the user. This may reduce visibility during silent installs.
- **No Exception Handling Granularity**:
`AddCodeToRegistry()` catches all exceptions generically and returns only the message string. Specific exceptions (e.g., `UnauthorizedAccessException`, `SecurityException`) are not differentiated.
- **Assumes Installer Runs with Admin Rights**:
The code assumes the custom action runs with elevated privileges. If not, registry writes will fail silently (or with generic error), and no fallback is implemented.
---
*End of documentation.*