Improve finding files relative to Core.Native assembly
Should fix unit testing issues when .cub files cannot be found.
Rob Mensching committed
Mar 19, 2021 at 07:47 UTC
062d6387692d074f502176296f361c52026b96d5
3 files changed
+84
-30
src/WixToolset.Core.Native/AssemblyExtensions.cs
new
+70
@@ -0,0 +1,70 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+namespace WixToolset.Core.Native
4
+{
5
+ using System;
6
+ using System.IO;
7
+ using System.Reflection;
8
+ using System.Text;
9
+
10
+ internal static class AssemblyExtensions
11
+ {
12
+ internal static FindAssemblyRelativeFileResult FindFileRelativeToAssembly(this Assembly assembly, string relativePath, bool searchNativeDllDirectories)
13
+ {
14
+ // First try using the Assembly.Location. This works in almost all cases with
15
+ // no side-effects.
16
+ var path = Path.Combine(Path.GetDirectoryName(assembly.Location), relativePath);
17
+ var possiblePaths = new StringBuilder(path);
18
+
19
+ var found = File.Exists(path);
20
+ if (!found)
21
+ {
22
+ // Fallback to the Assembly.CodeBase to handle "shadow copy" scenarios (like unit tests) but
23
+ // only check codebase if it is different from the Assembly.Location path.
24
+ var codebase = Path.Combine(Path.GetDirectoryName(new Uri(assembly.CodeBase).LocalPath), relativePath);
25
+
26
+ if (!codebase.Equals(path, StringComparison.OrdinalIgnoreCase))
27
+ {
28
+ path = codebase;
29
+ possiblePaths.Append(Path.PathSeparator + path);
30
+
31
+ found = File.Exists(path);
32
+ }
33
+
34
+ if (!found && searchNativeDllDirectories && AppContext.GetData("NATIVE_DLL_SEARCH_DIRECTORIES") is string searchDirectoriesString)
35
+ {
36
+ // If instructed to search native DLL search directories, try to find our file there.
37
+ possiblePaths.Append(Path.PathSeparator + searchDirectoriesString);
38
+
39
+ var searchDirectories = searchDirectoriesString?.Split(Path.PathSeparator);
40
+ foreach (var directoryPath in searchDirectories)
41
+ {
42
+ var possiblePath = Path.Combine(directoryPath, relativePath);
43
+ if (File.Exists(possiblePath))
44
+ {
45
+ path = possiblePath;
46
+ found = true;
47
+ break;
48
+ }
49
+ }
50
+ }
51
+ }
52
+
53
+ return new FindAssemblyRelativeFileResult
54
+ {
55
+ Found = found,
56
+ Path = found ? path : null,
57
+ PossiblePaths = possiblePaths.ToString()
58
+ };
59
+ }
60
+
61
+ internal class FindAssemblyRelativeFileResult
62
+ {
63
+ public bool Found { get; set; }
64
+
65
+ public string Path { get; set; }
66
+
67
+ public string PossiblePaths { get; set; }
68
+ }
69
+ }
70
+}
src/WixToolset.Core.Native/WindowsInstallerValidator.cs
+10
-6
@@ -86,9 +86,6 @@ namespace WixToolset.Core.Native
86
var previousHwnd = IntPtr.Zero;
87
InstallUIHandler previousUIHandler = null;
88
89
- var baseCubePath = Path.Combine(Path.GetDirectoryName(typeof(WindowsInstallerValidator).Assembly.Location), CubesFolder);
90
- var cubeFiles = this.CubeFiles.Select(s => Path.Combine(baseCubePath, s)).ToList();
91
-
89
try
90
{
91
using (var database = new Database(this.DatabasePath, OpenDatabase.Direct))
@@ -116,11 +113,18 @@ namespace WixToolset.Core.Native
113
}
114
115
// Merge in the cube databases.
119
- foreach (var cubeFile in cubeFiles)
116
+ foreach (var cubeFile in this.CubeFiles)
117
{
118
+ var findCubeFile = typeof(WindowsInstallerValidator).Assembly.FindFileRelativeToAssembly(Path.Combine(CubesFolder, cubeFile), searchNativeDllDirectories: false);
119
+
120
+ if (!findCubeFile.Found)
121
+ {
122
+ throw new WixException(ErrorMessages.CubeFileNotFound(findCubeFile.Path));
123
+ }
124
+
125
try
126
{
123
- using (var cubeDatabase = new Database(cubeFile, OpenDatabase.ReadOnly))
127
+ using (var cubeDatabase = new Database(findCubeFile.Path, OpenDatabase.ReadOnly))
128
{
129
try
130
{
@@ -136,7 +140,7 @@ namespace WixToolset.Core.Native
140
{
141
if (0x6E == e.NativeErrorCode) // ERROR_OPEN_FAILED
142
{
139
- throw new WixException(ErrorMessages.CubeFileNotFound(cubeFile));
143
+ throw new WixException(ErrorMessages.CubeFileNotFound(findCubeFile.Path));
144
}
145
146
throw;
src/WixToolset.Core.Native/WixNativeExe.cs
+4
-24
@@ -7,7 +7,6 @@ namespace WixToolset.Core.Native
7
using System.ComponentModel;
8
using System.Diagnostics;
9
using System.IO;
10
- using System.Reflection;
10
11
internal class WixNativeExe
12
{
@@ -81,35 +80,16 @@ namespace WixToolset.Core.Native
80
{
81
if (String.IsNullOrEmpty(PathToWixNativeExe))
82
{
84
- var path = Path.Combine(Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath), WixNativeExeFileName);
85
- var possiblePaths = path;
83
+ var result = typeof(WixNativeExe).Assembly.FindFileRelativeToAssembly(WixNativeExeFileName, searchNativeDllDirectories: true);
84
87
- var found = File.Exists(path);
88
- if (!found && AppContext.GetData("NATIVE_DLL_SEARCH_DIRECTORIES") is string searchDirectoriesString)
89
- {
90
- possiblePaths = searchDirectoriesString;
91
- var separatorChar = Path.PathSeparator;
92
- var searchDirectories = searchDirectoriesString?.Split(separatorChar);
93
- foreach (var directoryPath in searchDirectories)
94
- {
95
- var possiblePath = Path.Combine(directoryPath, WixNativeExeFileName);
96
- if (File.Exists(possiblePath))
97
- {
98
- path = possiblePath;
99
- found = true;
100
- break;
101
- }
102
- }
103
- }
104
-
105
- if (!found)
85
+ if (!result.Found)
86
{
87
throw new PlatformNotSupportedException(
88
$"Could not find platform specific '{WixNativeExeFileName}'",
109
- new FileNotFoundException($"Could not find internal piece of WiX Toolset from: {possiblePaths}", WixNativeExeFileName));
89
+ new FileNotFoundException($"Could not find internal piece of WiX Toolset from: {result.PossiblePaths}", WixNativeExeFileName));
90
}
91
112
- PathToWixNativeExe = path;
92
+ PathToWixNativeExe = result.Path;
93
}
94
}
95