-
Notifications
You must be signed in to change notification settings - Fork 586
/
EnvironmentHelper.fs
213 lines (177 loc) · 9.02 KB
/
EnvironmentHelper.fs
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
[<AutoOpen>]
/// This module contains functions which allow to read and write environment variables and build parameters
module Fake.EnvironmentHelper
open System
open System.IO
open System.Configuration
open System.Diagnostics
open System.Collections.Generic
open System.Text
open System.Text.RegularExpressions
open Microsoft.Win32
/// Type alias for System.EnvironmentVariableTarget
type EnvironTarget = EnvironmentVariableTarget
/// Retrieves the environment variable with the given name
let environVar name = Environment.GetEnvironmentVariable name
/// Combines two path strings using Path.Combine
let inline combinePaths path1 (path2 : string) = Path.Combine(path1, path2.TrimStart [| '\\'; '/' |])
let inline combinePathsNoTrim path1 path2 = Path.Combine(path1, path2)
/// Combines two path strings using Path.Combine
let inline (@@) path1 path2 = combinePaths path1 path2
let inline (</>) path1 path2 = combinePathsNoTrim path1 path2
/// Retrieves all environment variables from the given target
let environVars target =
[ for e in Environment.GetEnvironmentVariables target ->
let e1 = e :?> Collections.DictionaryEntry
e1.Key, e1.Value ]
/// Sets the environment variable with the given name
let setEnvironVar name value = Environment.SetEnvironmentVariable(name, value)
/// Sets the environment variable with the given name for the current process.
let setProcessEnvironVar name value = Environment.SetEnvironmentVariable(name, value, EnvironmentVariableTarget.Process)
/// Clears the environment variable with the given name for the current process.
let clearProcessEnvironVar name = Environment.SetEnvironmentVariable(name, null, EnvironmentVariableTarget.Process)
/// Retrieves the environment variable with the given name or returns the default if no value was set
let environVarOrDefault name defaultValue =
let var = environVar name
if String.IsNullOrEmpty var then defaultValue
else var
/// Retrieves the environment variable or None
let environVarOrNone name =
let var = environVar name
if String.IsNullOrEmpty var then None
else Some var
/// Retrieves the application settings variable with the given name
let appSetting (name : string) = ConfigurationManager.AppSettings.[name]
/// Returns if the build parameter with the given name was set
let inline hasBuildParam name = environVar name <> null
/// Returns the value of the build parameter with the given name was set if it was set and otherwise the given default value
let inline getBuildParamOrDefault name defaultParam =
if hasBuildParam name then environVar name
else defaultParam
/// Returns the value of the build parameter with the given name if it was set and otherwise an empty string
let inline getBuildParam name = getBuildParamOrDefault name String.Empty
/// The path of the "Program Files" folder - might be x64 on x64 machine
let ProgramFiles = Environment.GetFolderPath Environment.SpecialFolder.ProgramFiles
/// The path of Program Files (x86)
/// It seems this covers all cases where PROCESSOR\_ARCHITECTURE may misreport and the case where the other variable
/// PROCESSOR\_ARCHITEW6432 can be null
let ProgramFilesX86 =
let wow64 = environVar "PROCESSOR_ARCHITEW6432"
let globalArch = environVar "PROCESSOR_ARCHITECTURE"
match wow64, globalArch with
| "AMD64", "AMD64"
| null, "AMD64"
| "x86", "AMD64" -> environVar "ProgramFiles(x86)"
| _ -> environVar "ProgramFiles"
|> fun detected -> if detected = null then @"C:\Program Files (x86)\" else detected
/// The system root environment variable. Typically "C:\Windows"
let SystemRoot = Environment.SystemDirectory
/// Determines if the current system is an Unix system
let isUnix = Environment.OSVersion.Platform = PlatformID.Unix
/// Determines if the current system is a MacOs system
let isMacOS = Environment.OSVersion.Platform = PlatformID.MacOSX
/// Determines if the current system is a Linux system
let isLinux = int System.Environment.OSVersion.Platform |> fun p -> (p = 4) || (p = 6) || (p = 128)
/// Determines if the current system is a mono system
/// Todo: Detect mono on windows
let isMono = isLinux || isUnix || isMacOS
/// Arguments on the Mono executable
let mutable monoArguments = ""
/// Modifies the ProcessStartInfo according to the platform semantics
let platformInfoAction (psi : ProcessStartInfo) =
if isMono && psi.FileName.EndsWith ".exe" then
psi.Arguments <- monoArguments + " " + psi.FileName + " " + psi.Arguments
psi.FileName <- "mono"
/// The path of the current target platform
let mutable TargetPlatformPrefix =
let (<|>) a b =
match a with
| None -> b
| _ -> a
environVarOrNone "FrameworkDir32" <|> if (String.IsNullOrEmpty SystemRoot) then None
else Some(SystemRoot @@ @"Microsoft.NET\Framework")
<|> if (isUnix) then Some "/usr/lib/mono"
else Some @"C:\Windows\Microsoft.NET\Framework"
|> Option.get
/// Base path for getting tools from windows SDKs
let sdkBasePath = ProgramFilesX86 @@ "Microsoft SDKs\Windows"
/// Helper function to help find framework or sdk tools from the
/// newest toolkit available
let getNewestTool possibleToolPaths =
possibleToolPaths
|> Seq.sortBy (fun p -> p)
|> Array.ofSeq
|> Array.rev
|> Seq.ofArray
|> Seq.head
/// Gets the local directory for the given target platform
let getTargetPlatformDir platformVersion =
if Directory.Exists(TargetPlatformPrefix + "64") then (TargetPlatformPrefix + "64") @@ platformVersion
else TargetPlatformPrefix @@ platformVersion
/// The path to the personal documents
let documentsFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
/// The directory separator string. On most systems / or \
let directorySeparator = Path.DirectorySeparatorChar.ToString()
/// Convert the given windows path to a path in the current system
let convertWindowsToCurrentPath (windowsPath : string) =
if (windowsPath.Length > 2 && windowsPath.[1] = ':' && windowsPath.[2] = '\\') then windowsPath
else windowsPath.Replace(@"\", directorySeparator)
/// Contains the IO encoding which is given via build parameter "encoding" or the default encoding if no encoding was specified.
let encoding =
match getBuildParamOrDefault "encoding" "default" with
| "default" -> Text.Encoding.Default
| enc -> Text.Encoding.GetEncoding(enc)
/// Returns a sequence with all installed .NET framework versions
let getInstalledDotNetFrameworks() =
let frameworks = new ResizeArray<_>()
try
let matches =
Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP").GetSubKeyNames()
|> Seq.filter (fun keyname -> Regex.IsMatch(keyname, @"^v\d"))
for item in matches do
match item with
| "v4.0" -> ()
| "v4" ->
let key = @"SOFTWARE\Microsoft\NET Framework Setup\NDP\" + item
Registry.LocalMachine.OpenSubKey(key).GetSubKeyNames()
|> Seq.iter (fun subkey ->
let key = @"SOFTWARE\Microsoft\NET Framework Setup\NDP\" + item + @"\" + subkey
let version = Registry.LocalMachine.OpenSubKey(key).GetValue("Version").ToString()
frameworks.Add(String.Format("{0} ({1})", version, subkey)))
| "v1.1.4322" -> frameworks.Add item
| _ ->
let key = @"SOFTWARE\Microsoft\NET Framework Setup\NDP\" + item
frameworks.Add(Registry.LocalMachine.OpenSubKey(key).GetValue("Version").ToString())
frameworks :> seq<_>
with e -> frameworks :> seq<_> //Probably a new unrecognisable version
/// A record which allows to display lots of machine specific information like machine name, processor count etc.
type MachineDetails =
{ ProcessorCount : int
Is64bit : bool
OperatingSystem : string
MachineName : string
NETFrameworks : seq<string>
UserDomainName : string
AgentVersion : string
DriveInfo : seq<string> }
/// Retrieves information about the hard drives
let getDrivesInfo() =
Environment.GetLogicalDrives()
|> Seq.map (fun d -> IO.DriveInfo(d))
|> Seq.filter (fun d -> d.IsReady)
|> Seq.map
(fun d ->
sprintf "%s has %0.1fGB free of %0.1fGB" (d.Name.Replace(":\\", ""))
(Convert.ToDouble(d.TotalFreeSpace) / (1024. * 1024. * 1024.))
(Convert.ToDouble(d.TotalSize) / (1024. * 1024. * 1024.)))
/// Retrieves lots of machine specific information like machine name, processor count etc.
let getMachineEnvironment() =
{ ProcessorCount = Environment.ProcessorCount
Is64bit = Environment.Is64BitOperatingSystem
OperatingSystem = Environment.OSVersion.ToString()
MachineName = Environment.MachineName
NETFrameworks = getInstalledDotNetFrameworks()
UserDomainName = Environment.UserDomainName
AgentVersion =
sprintf "%A" ((System.Reflection.Assembly.GetAssembly(typedefof<MachineDetails>)).GetName().Version)
DriveInfo = getDrivesInfo() }