@@ -67,26 +67,68 @@ public enum ProcessEnv {
6767 /// Returns a dictionary containing the current environment.
6868 public static var block : ProcessEnvironmentBlock { _vars }
6969
70+ #if os(Windows)
71+ private static var _vars : ProcessEnvironmentBlock = {
72+ guard let lpwchEnvironment = GetEnvironmentStringsW ( ) else { return [ : ] }
73+ defer { FreeEnvironmentStringsW ( lpwchEnvironment) }
74+ var environment : ProcessEnvironmentBlock = [ : ]
75+ var pVariable = UnsafePointer < WCHAR > ( lpwchEnvironment)
76+ while let entry = String . decodeCString ( pVariable, as: UTF16 . self) {
77+ if entry. result. isEmpty { break }
78+ let parts = entry. result. split ( separator: " = " , maxSplits: 1 , omittingEmptySubsequences: false )
79+ if parts. count == 2 {
80+ environment [ CaseInsensitiveString ( String ( parts [ 0 ] ) ) ] = String ( parts [ 1 ] )
81+ }
82+ pVariable = pVariable. advanced ( by: entry. result. utf16. count + 1 )
83+ }
84+ return environment
85+ } ( )
86+ #else
7087 private static var _vars = ProcessEnvironmentBlock (
7188 uniqueKeysWithValues: ProcessInfo . processInfo. environment. map {
7289 ( ProcessEnvironmentBlock . Key ( $0. key) , $0. value)
7390 }
7491 )
92+ #endif
7593
7694 /// Invalidate the cached env.
7795 public static func invalidateEnv( ) {
96+ #if os(Windows)
97+ guard let lpwchEnvironment = GetEnvironmentStringsW ( ) else {
98+ _vars = [ : ]
99+ return
100+ }
101+ defer { FreeEnvironmentStringsW ( lpwchEnvironment) }
102+
103+ var environment : ProcessEnvironmentBlock = [ : ]
104+ var pVariable = UnsafePointer < WCHAR > ( lpwchEnvironment)
105+ while let entry = String . decodeCString ( pVariable, as: UTF16 . self) {
106+ if entry. result. isEmpty { break }
107+ let parts = entry. result. split ( separator: " = " , maxSplits: 1 , omittingEmptySubsequences: false )
108+ if parts. count == 2 {
109+ environment [ CaseInsensitiveString ( String ( parts [ 0 ] ) ) ] = String ( parts [ 1 ] )
110+ }
111+ pVariable = pVariable. advanced ( by: entry. result. utf16. count + 1 )
112+ }
113+ _vars = environment
114+ #else
78115 _vars = ProcessEnvironmentBlock (
79116 uniqueKeysWithValues: ProcessInfo . processInfo. environment. map {
80117 ( CaseInsensitiveString ( $0. key) , $0. value)
81118 }
82119 )
120+ #endif
83121 }
84122
85123 /// Set the given key and value in the process's environment.
86124 public static func setVar( _ key: String , value: String ) throws {
87125 #if os(Windows)
88- guard TSCLibc . _putenv ( " \( key) = \( value) " ) == 0 else {
89- throw SystemError . setenv ( Int32 ( GetLastError ( ) ) , key)
126+ try key. withCString ( encodedAs: UTF16 . self) { pwszKey in
127+ try value. withCString ( encodedAs: UTF16 . self) { pwszValue in
128+ guard SetEnvironmentVariableW ( pwszKey, pwszValue) else {
129+ throw SystemError . setenv ( Int32 ( GetLastError ( ) ) , key)
130+ }
131+ }
90132 }
91133 #else
92134 guard TSCLibc . setenv ( key, value, 1 ) == 0 else {
@@ -99,7 +141,9 @@ public enum ProcessEnv {
99141 /// Unset the give key in the process's environment.
100142 public static func unsetVar( _ key: String ) throws {
101143 #if os(Windows)
102- guard TSCLibc . _putenv ( " \( key) = " ) == 0 else {
144+ guard key. withCString ( encodedAs: UTF16 . self, {
145+ SetEnvironmentVariableW ( $0, nil )
146+ } ) else {
103147 throw SystemError . unsetenv ( Int32 ( GetLastError ( ) ) , key)
104148 }
105149 #else
@@ -124,9 +168,7 @@ public enum ProcessEnv {
124168 public static func chdir( _ path: AbsolutePath ) throws {
125169 let path = path. pathString
126170 #if os(Windows)
127- guard path. withCString ( encodedAs: UTF16 . self, {
128- SetCurrentDirectoryW ( $0)
129- } ) else {
171+ guard path. withCString ( encodedAs: UTF16 . self, SetCurrentDirectoryW) else {
130172 throw SystemError . chdir ( Int32 ( GetLastError ( ) ) , path)
131173 }
132174 #else
0 commit comments