Skip to content

Commit c8e797c

Browse files
committed
Improve DLL search path fixer.
- Use a class to keep track of state. - Use the Unity Application data dir property instead of current directory + "Assets" - Handle looking in x86 vs x86_64 - does not fully fix the 64-bit support but it's one step.
1 parent 62319a6 commit c8e797c

1 file changed

Lines changed: 143 additions & 62 deletions

File tree

Lines changed: 143 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,143 @@
1-
/// OSVR-Unity Connection
2-
///
3-
/// <copyright>
4-
/// Copyright 2014 Sensics, Inc.
5-
///
6-
/// Licensed under the Apache License, Version 2.0 (the "License");
7-
/// you may not use this file except in compliance with the License.
8-
/// You may obtain a copy of the License at
9-
///
10-
/// http://www.apache.org/licenses/LICENSE-2.0
11-
///
12-
/// Unless required by applicable law or agreed to in writing, software
13-
/// distributed under the License is distributed on an "AS IS" BASIS,
14-
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15-
/// See the License for the specific language governing permissions and
16-
/// limitations under the License.
17-
/// </copyright>
18-
19-
using System;
20-
using System.IO;
21-
using System.Text;
22-
23-
namespace OSVR
24-
{
25-
namespace Unity
26-
{
27-
public class DLLSearchPathFixer
28-
{
29-
/// <summary>
30-
/// Call in a static constructor of an object depending on native code.
31-
///
32-
/// It is required if that native DLL being accessed depends on other native DLLs alongside it.
33-
/// </summary>
34-
public static void fix()
35-
{
36-
string[] dllPaths = {
37-
"Assets" + Path.DirectorySeparatorChar + "Plugins",
38-
"Assets"+ Path.DirectorySeparatorChar + "Plugins"+ Path.DirectorySeparatorChar + "x86", // todo don't hardcode this
39-
"StreamingAssets"+ Path.DirectorySeparatorChar + "Plugins",
40-
"StreamingAssets"+ Path.DirectorySeparatorChar + "Plugins"+ Path.DirectorySeparatorChar + "x86" // todo don't hardcode this
41-
};
42-
// Amend DLL search path - see http://forum.unity3d.com/threads/dllnotfoundexception-when-depend-on-another-dll.31083/#post-1042180
43-
// for original inspiration for this code.
44-
string currentPath = Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Process);
45-
string[] currentPaths = currentPath.Split(Path.PathSeparator);
46-
StringBuilder paths = new StringBuilder();
47-
foreach (string dllPath in dllPaths)
48-
{
49-
String fullDllPath = Environment.CurrentDirectory + Path.DirectorySeparatorChar + dllPath;
50-
if (Array.IndexOf(currentPaths, fullDllPath) < 0)
51-
{
52-
paths.AppendFormat("{1}{0}", Path.PathSeparator, fullDllPath);
53-
}
54-
}
55-
// Keeps our new paths in front.
56-
paths.Append(currentPath);
57-
Environment.SetEnvironmentVariable("PATH", paths.ToString(), EnvironmentVariableTarget.Process);
58-
}
59-
60-
}
61-
}
62-
}
1+
/// OSVR-Unity Connection
2+
///
3+
/// <copyright>
4+
/// Copyright 2014 Sensics, Inc.
5+
///
6+
/// Licensed under the Apache License, Version 2.0 (the "License");
7+
/// you may not use this file except in compliance with the License.
8+
/// You may obtain a copy of the License at
9+
///
10+
/// http://www.apache.org/licenses/LICENSE-2.0
11+
///
12+
/// Unless required by applicable law or agreed to in writing, software
13+
/// distributed under the License is distributed on an "AS IS" BASIS,
14+
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
/// See the License for the specific language governing permissions and
16+
/// limitations under the License.
17+
/// </copyright>
18+
19+
using System;
20+
using System.Collections.Generic;
21+
using System.IO;
22+
using UnityEngine;
23+
24+
namespace OSVR
25+
{
26+
namespace Unity
27+
{
28+
public class DLLSearchPathFixer
29+
{
30+
/// <summary>
31+
/// Call in a static constructor of an object depending on native code.
32+
///
33+
/// It is required if that native DLL being accessed depends on other native DLLs alongside it.
34+
/// </summary>
35+
public static void fix()
36+
{
37+
// Amend DLL search path - see http://forum.unity3d.com/threads/dllnotfoundexception-when-depend-on-another-dll.31083/#post-1042180
38+
// for original inspiration for this code.
39+
40+
var fixer = new DLLSearchPathFixer();
41+
fixer.ConditionallyAddRelativeDir("Plugins");
42+
fixer.ConditionallyAddRelativeDir(new List<String>() { "Plugins", IntPtr.Size == 4 ? "x86" : "x86_64" });
43+
fixer.ApplyChanges();
44+
}
45+
46+
/// <summary>
47+
/// Constructor for private use as a helper within the static fix() method.
48+
/// </summary>
49+
private DLLSearchPathFixer()
50+
{
51+
var currentPath = Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Process);
52+
Debug.Log(String.Format("Old PATH: {0}", currentPath));
53+
OrigDirs = new List<string>(currentPath.Split(Path.PathSeparator));
54+
UnityDataDir = Application.dataPath;
55+
UnityDataDirBackslashed = Application.dataPath.Replace("/", "\\");
56+
}
57+
58+
/// <summary>
59+
/// Update the process environment PATH variable to contain the full list (entries new and old) of directories.
60+
/// </summary>
61+
private void ApplyChanges()
62+
{
63+
// Combine new and old dirs
64+
var allDirs = new List<String>(NewDirs);
65+
allDirs.AddRange(OrigDirs);
66+
67+
var newPathString = String.Join(Path.PathSeparator.ToString(), allDirs.ToArray());
68+
Debug.Log(String.Format("New PATH: {0}", newPathString));
69+
Environment.SetEnvironmentVariable("PATH", newPathString, EnvironmentVariableTarget.Process);
70+
}
71+
72+
/// <summary>
73+
/// If a directory specified relative to the Unity data dir is not yet in the PATH, add it.
74+
/// </summary>
75+
/// <param name="dirComponents">Components of a directory name relative to the Unity data dir.</param>
76+
private void ConditionallyAddRelativeDir(List<string> dirComponents)
77+
{
78+
ConditionallyAddRelativeDir(PathTools.Combine(dirComponents));
79+
}
80+
81+
/// <summary>
82+
/// If a directory specified relative to the Unity data dir is not yet in the PATH, add it.
83+
/// </summary>
84+
/// <param name="dirComponents">A directory name relative to the Unity data dir.</param>
85+
private void ConditionallyAddRelativeDir(string relativePortion)
86+
{
87+
if (IsRelativeDirIncludedInPath(relativePortion))
88+
{
89+
// early out.
90+
return;
91+
}
92+
NewDirs.Add(PathTools.Combine(UnityDataDir, relativePortion));
93+
}
94+
95+
/// <summary>
96+
/// Checks to see if a directory specified relative to the Unity data dir is included in the path so far.
97+
/// It checks using both forward-slashed and backslashed versions of the Unity data dir.
98+
/// </summary>
99+
/// <param name="relativePortion">Directory relative to the Unity data dir</param>
100+
/// <returns>true if the given directory is included in the path so far</returns>
101+
private bool IsRelativeDirIncludedInPath(string relativePortion)
102+
{
103+
return IsIncludedInPath(PathTools.Combine(UnityDataDir, relativePortion)) || IsIncludedInPath(PathTools.Combine(UnityDataDirBackslashed, relativePortion));
104+
}
105+
106+
/// <summary>
107+
/// Checks to see if a directory is included in the path so far (both new and old directories).
108+
/// </summary>
109+
/// <param name="dir">Directory name</param>
110+
/// <returns>true if the given directory name is found in either the new or old directory lists.</returns>
111+
private bool IsIncludedInPath(string dir)
112+
{
113+
return NewDirs.Contains(dir) || OrigDirs.Contains(dir);
114+
}
115+
116+
private string UnityDataDir;
117+
private string UnityDataDirBackslashed;
118+
private List<string> NewDirs = new List<string>();
119+
private List<string> OrigDirs;
120+
121+
/// <summary>
122+
/// Utilities for combining path components with a wider variety of input data types than System.IO.Path.Combine
123+
/// </summary>
124+
private class PathTools
125+
{
126+
internal static string Combine(string a, string b)
127+
{
128+
return Path.Combine(a, b);
129+
}
130+
131+
internal static string Combine(string[] components)
132+
{
133+
return String.Join(Path.DirectorySeparatorChar.ToString(), components);
134+
}
135+
136+
internal static string Combine(List<String> components)
137+
{
138+
return PathTools.Combine(components.ToArray());
139+
}
140+
}
141+
}
142+
}
143+
}

0 commit comments

Comments
 (0)