@@ -4,11 +4,11 @@ module RProvider.Internal.Configuration
4
4
open System
5
5
open System.IO
6
6
open System.Reflection
7
- open System.Configuration
8
7
open System.Collections .Generic
8
+ open System.Xml
9
9
10
10
/// Returns the Assembly object of RProvider.Runtime.dll (this needs to
11
- /// work when called from RProvider.DesignTime.dll and also RProvider.Server.exe)
11
+ /// work when called from RProvider.DesignTime.dll and also RProvider.Server.exe/dll )
12
12
let getRProviderRuntimeAssembly () =
13
13
AppDomain.CurrentDomain.GetAssemblies()
14
14
|> Seq.find ( fun a -> a.FullName.StartsWith( " RProvider.Runtime," ))
@@ -33,23 +33,51 @@ let getAssemblyLocation (assem:Assembly) =
33
33
( Uri( assem.Location)) .LocalPath
34
34
else assem.Location
35
35
36
+ /// Returns the real config file location even when shadow copying is enabled.
37
+ /// To account for single-file server executables, we use AppContext.BaseDirectory
38
+ /// and navigate up two directories to get to the original RProvider.Runtime.dll
39
+ /// location where the config file is (from server/{platform}/)
40
+ let getConfigFileLocation ( assem : Assembly ) =
41
+ if String.IsNullOrEmpty assem.Location
42
+ then Path.GetFullPath( Path.Combine( AppContext.BaseDirectory,
43
+ @" ../../" , assem.GetName() .Name + " .dll.config" ))
44
+ else getAssemblyLocation assem + " .config"
45
+
46
+ /// Load a .config XML file and obtain the value of the AppSetting
47
+ /// called 'ProbingLocations'.
48
+ let probingLocationsFromXmlConfig file =
49
+ if not <| File.Exists file then Error " Configuration file missing"
50
+ else
51
+ let doc = XmlDocument()
52
+ doc.LoadXml( File.ReadAllText file)
53
+ let appSettings = doc.SelectSingleNode " //appSettings"
54
+ let setting = appSettings.SelectSingleNode " //add[@key='ProbingLocations']"
55
+ if isNull setting then Error " Appsetting not set: ProbingLocations"
56
+ else
57
+ let locations = setting.Attributes.GetNamedItem( " value" )
58
+ if isNull locations then Error " Appsetting not set: ProbingLocations"
59
+ else locations.Value |> Ok
60
+
36
61
/// Reads the 'RProvider.dll.config' file and gets the 'ProbingLocations'
37
62
/// parameter from the configuration file. Resolves the directories and returns
38
63
/// them as a list.
39
- let getProbingLocations () =
64
+ let getProbingLocations () =
40
65
try
41
- let root = getRProviderRuntimeAssembly() |> getAssemblyLocation
42
- let config = ConfigurationManager.OpenExeConfiguration( root)
43
- let pattern = config.AppSettings.Settings.[ " ProbingLocations" ]
44
- if not <| isNull pattern then
45
- [ let pattern = pattern.Value.Split( ';' , ',' ) |> List.ofSeq
46
- for pat in pattern do
47
- let roots = [ Path.GetDirectoryName( root) ]
48
- for dir in roots |> searchDirectories ( List.ofSeq ( pat.Split( '/' , '\\' ))) do
49
- if Directory.Exists( dir) then yield dir ]
50
- else []
51
- with :? ConfigurationErrorsException | :? KeyNotFoundException -> []
52
-
66
+ let configLocation = getRProviderRuntimeAssembly() |> getConfigFileLocation
67
+ Logging.logf " RProvider configuration file is %s " configLocation
68
+ if String.IsNullOrEmpty configLocation then []
69
+ else
70
+ Logging.logf " Attempting to load config file '%s '" configLocation
71
+ let pattern = probingLocationsFromXmlConfig configLocation
72
+ match pattern with
73
+ | Ok pattern ->
74
+ [ let pattern = pattern.Split( ';' , ',' ) |> List.ofSeq
75
+ for pat in pattern do
76
+ let roots = [ Path.GetDirectoryName( configLocation) ]
77
+ for dir in roots |> searchDirectories ( List.ofSeq ( pat.Split( '/' , '\\' ))) do
78
+ if Directory.Exists( dir) then yield dir ]
79
+ | Error _ -> []
80
+ with :? KeyNotFoundException -> []
53
81
54
82
/// Given an assembly name, try to find it in either assemblies
55
83
/// loaded in the current AppDomain, or in one of the specified
0 commit comments