Skip to content

Commit 8879000

Browse files
committed
Enable local registry registration for debug builds using the same Rube-Goldsberg machine to avoid "Works on my computer" symptoms.
1 parent 851624d commit 8879000

File tree

8 files changed

+153
-5
lines changed

8 files changed

+153
-5
lines changed

Rubberduck.Deployment/BuildRegistryScript.ps1

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
# Possible syntax for Post Build event of the project to invoke this:
88
# C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
99
# -command "$(ProjectDir)BuildRegistryScript.ps1
10+
# -config '$(ConfigurationName)'
1011
# -builderAssemblyPath '$(TargetPath)'
1112
# -netToolsDir '$(FrameworkSDKDir)bin\NETFX 4.6.1 Tools\'
1213
# -wixToolsDir '$(SolutionDir)packages\WiX.Toolset.3.9.1208.0\tools\wix\'
@@ -15,6 +16,7 @@
1516
# -includeDir '$(ProjectDir)InnoSetup\Includes\'
1617
# -filesToExtract 'Rubberduck.dll'"
1718
param (
19+
[Parameter(Mandatory=$true)][string]$config,
1820
[Parameter(Mandatory=$true)][string]$builderAssemblyPath,
1921
[Parameter(Mandatory=$true)][string]$netToolsDir,
2022
[Parameter(Mandatory=$true)][string]$wixToolsDir,
@@ -24,6 +26,12 @@ param (
2426
[Parameter(Mandatory=$true)][string]$filesToExtract
2527
)
2628

29+
function Get-ScriptDirectory
30+
{
31+
$Invocation = (Get-Variable MyInvocation -Scope 1).Value
32+
Split-Path $Invocation.MyCommand.Path
33+
}
34+
2735
Set-StrictMode -Version latest
2836
$ErrorActionPreference = "Stop";
2937

@@ -65,20 +73,50 @@ try
6573

6674
# For debugging
6775
# $entries | Format-Table | Out-String |% {Write-Host $_};
68-
76+
6977
$writer = New-Object Rubberduck.Deployment.Writers.InnoSetupRegistryWriter
7078
$content = $writer.Write($entries);
7179

7280
$regFile = ($includeDir + ($file -replace ".dll", ".reg.iss"))
73-
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
74-
[System.IO.File]::WriteAllLines($regFile, $content, $Utf8NoBomEncoding)
81+
$encoding = New-Object System.Text.UTF8Encoding $False
82+
[System.IO.File]::WriteAllLines($regFile, $content, $encoding)
83+
84+
# Register the debug build on the local machine
85+
if($config -eq "Debug")
86+
{
87+
$writer = New-Object Rubberduck.Deployment.Writers.LocalDebugRegistryWriter
88+
$content = $writer.Write($entries);
89+
90+
$dir = ((Get-ScriptDirectory) + "\LocalRegistryEntries");
91+
$regFile = $dir + "\DebugRegistryEntries.reg";
92+
93+
if (Test-Path -Path $dir -PathType Container)
94+
{
95+
if (Test-Path -Path $regFile -PathType Leaf)
96+
{
97+
$datetime = Get-Date;
98+
& reg.exe import $regFile;
99+
& reg.exe import ($dir + "\RubberduckAddinRegistry.reg");
100+
Move-Item -Path $regFile -Destination ($regFile + ".imported_" + $datetime.ToUniversalTime().ToString("yyyyMMddhhmmss") + ".txt" )
101+
}
102+
}
103+
else
104+
{
105+
New-Item $dir -ItemType Directory
106+
}
107+
$encoding = New-Object System.Text.ASCIIEncoding;
108+
[System.IO.File]::WriteAllLines($regFile, $content, $encoding);
109+
}
75110
}
76111
}
77112
catch
78113
{
79114
Write-Host -Foreground Red -Background Black ($_);
115+
# Cause the build to fail
116+
throw;
80117
}
81118

82119
# for debugging locally
83120
# Write-Host "Press any key to continue...";
84121
# Read-Host -Prompt "Press Enter to continue";
122+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# ignore any auto-generated files
2+
/Rubberduck.reg.iss
3+
/license.rtf
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/DebugRegistryEntries.reg
2+
/*.txt
Binary file not shown.

Rubberduck.Deployment/Rubberduck.Deployment.csproj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@
5050
<Compile Include="Writers\InnoSetupRegistryWriter.cs" />
5151
<Compile Include="Properties\AssemblyInfo.cs" />
5252
<Compile Include="Builders\RegistryEntryBuilder.cs" />
53+
<Compile Include="Writers\IRegistryWriter.cs" />
54+
<Compile Include="Writers\LocalDebugRegistryWriter.cs" />
5355
</ItemGroup>
5456
<ItemGroup>
5557
<Content Include="Examples\Delete HKCU Rubberduck Registry Entries.reg.txt" />
@@ -105,7 +107,7 @@
105107
</ItemGroup>
106108
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
107109
<PropertyGroup>
108-
<PostBuildEvent>C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -command "$(ProjectDir)BuildRegistryScript.ps1 -builderAssemblyPath '$(TargetPath)' -netToolsDir '$(FrameworkSDKDir)bin\NETFX 4.6.1 Tools\' -wixToolsDir '$(SolutionDir)packages\WiX.Toolset.3.9.1208.0\tools\wix\' -sourceDir '$(TargetDir)' -targetDir '$(TargetDir)' -includeDir '$(ProjectDir)InnoSetup\Includes\' -filesToExtract 'Rubberduck.dll'"</PostBuildEvent>
110+
<PostBuildEvent>C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -command "$(ProjectDir)BuildRegistryScript.ps1 -config '$(ConfigurationName)' -builderAssemblyPath '$(TargetPath)' -netToolsDir '$(FrameworkSDKDir)bin\NETFX 4.6.1 Tools\' -wixToolsDir '$(SolutionDir)packages\WiX.Toolset.3.9.1208.0\tools\wix\' -sourceDir '$(TargetDir)' -targetDir '$(TargetDir)' -includeDir '$(ProjectDir)InnoSetup\Includes\' -filesToExtract 'Rubberduck.dll'"</PostBuildEvent>
109111
</PropertyGroup>
110112
<PropertyGroup>
111113
<PreBuildEvent>C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -command "$(ProjectDir)PreInnoSetupConfiguration.ps1 -WorkingDir $(ProjectDir)</PreBuildEvent>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using System.Linq;
2+
using Rubberduck.Deployment.Structs;
3+
4+
namespace Rubberduck.Deployment.Writers
5+
{
6+
public interface IRegistryWriter
7+
{
8+
string Write(IOrderedEnumerable<RegistryEntry> entries);
9+
}
10+
}

Rubberduck.Deployment/Writers/InnoSetupRegistryWriter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
namespace Rubberduck.Deployment.Writers
99
{
10-
public class InnoSetupRegistryWriter
10+
public class InnoSetupRegistryWriter : IRegistryWriter
1111
{
1212
private readonly List<string> registryEntries = new List<string>();
1313

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
5+
using System.Reflection;
6+
using System.Text;
7+
using Microsoft.Win32;
8+
using Rubberduck.Deployment.Structs;
9+
10+
namespace Rubberduck.Deployment.Writers
11+
{
12+
public class LocalDebugRegistryWriter : IRegistryWriter
13+
{
14+
public string Write(IOrderedEnumerable<RegistryEntry> entries)
15+
{
16+
var sb = new StringBuilder("Windows Registry Editor Version 5.00" + Environment.NewLine + Environment.NewLine);
17+
var distinctKeys = new List<string>();
18+
19+
foreach (var entry in entries)
20+
{
21+
//Guard clause to prevent registry write to wrong places
22+
if (!entry.Key.StartsWith("Software\\Classes") &&
23+
!entry.Key.StartsWith("Software\\Classes\\CLSID\\") &&
24+
!entry.Key.StartsWith("Software\\Classes\\Interface\\") &&
25+
!entry.Key.StartsWith("Software\\Classes\\TypeLib\\") &&
26+
!entry.Key.StartsWith("Software\\Classes\\Record\\") &&
27+
!entry.Key.StartsWith("Software\\Classes\\Rubberduck.")
28+
)
29+
{
30+
throw new InvalidOperationException("Unexpected registry entry: " + entry.Key);
31+
}
32+
33+
var value = ReplacePlaceholder(entry.Value, entry.Bitness);
34+
35+
var key = Registry.CurrentUser.CreateSubKey(entry.Key);
36+
if (string.IsNullOrWhiteSpace(entry.Name) && string.IsNullOrWhiteSpace(value))
37+
{
38+
key.CreateSubKey(entry.Key);
39+
}
40+
else
41+
{
42+
key.SetValue(entry.Name, value);
43+
}
44+
45+
if (!distinctKeys.Contains(entry.Key))
46+
{
47+
distinctKeys.Add(entry.Key);
48+
}
49+
}
50+
51+
foreach (var key in distinctKeys)
52+
{
53+
//we need a break each entry, so 2 newline is wanted (AppendLine adds one, and we add another)
54+
sb.AppendLine("[-" + key + "]" + Environment.NewLine);
55+
}
56+
57+
return sb.ToString();
58+
}
59+
60+
//Cache the string so we call the AssemblyDirectory only once
61+
private string _currentPath;
62+
private string ReplacePlaceholder(string value, Bitness bitness)
63+
{
64+
if (_currentPath == null)
65+
{
66+
_currentPath = AssemblyDirectory;
67+
}
68+
69+
switch (value)
70+
{
71+
case PlaceHolders.InstallPath:
72+
return _currentPath;
73+
case PlaceHolders.DllPath:
74+
return Path.Combine( _currentPath, "Rubberduck.dll");
75+
case PlaceHolders.TlbPath:
76+
return Path.Combine(_currentPath, bitness == Bitness.Is64Bit ? "Rubberduck.x64.tlb" : "Rubberduck.x32.tlb");
77+
default:
78+
return value;
79+
}
80+
}
81+
82+
public static string AssemblyDirectory
83+
{
84+
get
85+
{
86+
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
87+
UriBuilder uri = new UriBuilder(codeBase);
88+
string path = Uri.UnescapeDataString(uri.Path);
89+
return Path.GetDirectoryName(path);
90+
}
91+
}
92+
}
93+
}

0 commit comments

Comments
 (0)