aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core.Native/AssemblyExtensions.cs
blob: 590a68877cfa18047728aed40bc7261b12ec9450 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// 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.

namespace WixToolset.Core.Native
{
    using System;
    using System.IO;
    using System.Reflection;
    using System.Text;

    internal static class AssemblyExtensions
    {
        internal static FindAssemblyRelativeFileResult FindFileRelativeToAssembly(this Assembly assembly, string relativePath, bool searchNativeDllDirectories)
        {
            // First try using the Assembly.Location. This works in almost all cases with
            // no side-effects.
            var path = Path.Combine(Path.GetDirectoryName(assembly.Location), relativePath);
            var possiblePaths = new StringBuilder(path);

            var found = File.Exists(path);
            if (!found)
            {
                // Fallback to the Assembly.CodeBase to handle "shadow copy" scenarios (like unit tests) but
                // only check codebase if it is different from the Assembly.Location path.
                var codebase = Path.Combine(Path.GetDirectoryName(new Uri(assembly.CodeBase).LocalPath), relativePath);

                if (!codebase.Equals(path, StringComparison.OrdinalIgnoreCase))
                {
                    path = codebase;
                    possiblePaths.Append(Path.PathSeparator + path);

                    found = File.Exists(path);
                }

                if (!found && searchNativeDllDirectories && AppContext.GetData("NATIVE_DLL_SEARCH_DIRECTORIES") is string searchDirectoriesString)
                {
                    // If instructed to search native DLL search directories, try to find our file there.
                    possiblePaths.Append(Path.PathSeparator + searchDirectoriesString);

                    var searchDirectories = searchDirectoriesString?.Split(Path.PathSeparator);
                    foreach (var directoryPath in searchDirectories)
                    {
                        var possiblePath = Path.Combine(directoryPath, relativePath);
                        if (File.Exists(possiblePath))
                        {
                            path = possiblePath;
                            found = true;
                            break;
                        }
                    }
                }
            }

            return new FindAssemblyRelativeFileResult
            {
                Found = found,
                Path = found ? path : null,
                PossiblePaths = possiblePaths.ToString()
            };
        }

        internal class FindAssemblyRelativeFileResult
        {
            public bool Found { get; set; }

            public string Path { get; set; }

            public string PossiblePaths { get; set; }
        }
    }
}