@@ -53,7 +53,7 @@ function Invoke-DscCacheRefresh {
53
53
)
54
54
55
55
$refreshCache = $false
56
-
56
+ $namedModules = [ System.Collections.Generic.List [ Object ]]::new()
57
57
$cacheFilePath = Join-Path $env: LocalAppData " dsc\WindowsPSAdapterCache.json"
58
58
59
59
if (Test-Path $cacheFilePath ) {
@@ -73,51 +73,53 @@ function Invoke-DscCacheRefresh {
73
73
" Filtered DscResourceCache cache is empty" | Write-DscTrace
74
74
}
75
75
else {
76
- " Checking cache for stale entries" | Write-DscTrace
76
+ " Checking cache for stale PSModulePath" | Write-DscTrace
77
+
78
+ $m = $env: PSModulePath -split [IO.Path ]::PathSeparator | ForEach-Object { Get-ChildItem - Directory - Path $_ - Depth 1 - ErrorAction Ignore }
79
+
80
+ $hs_cache = [System.Collections.Generic.HashSet [string ]]($cache.PSModulePaths )
81
+ $hs_live = [System.Collections.Generic.HashSet [string ]]($m.FullName )
82
+ $hs_cache.SymmetricExceptWith ($hs_live )
83
+ $diff = $hs_cache
84
+
85
+ " PSModulePath diff '$diff '" | Write-DscTrace
86
+ # TODO: Optimise for named module refresh
87
+ if ($diff.Count -gt 0 ) {
88
+ $refreshCache = $true
89
+ }
77
90
78
- foreach ($cacheEntry in $dscResourceCacheEntries ) {
91
+ if (-not $refreshCache ) {
92
+ " Checking cache for stale entries" | Write-DscTrace
79
93
80
- $cacheEntry.LastWriteTimes.PSObject.Properties | ForEach-Object {
94
+ foreach ( $cacheEntry in $dscResourceCacheEntries ) {
81
95
82
- if (Test-Path $_.Name ) {
83
- $file_LastWriteTime = (Get-Item $_.Name ).LastWriteTimeUtc
84
- # Truncate DateTime to seconds
85
- $file_LastWriteTime = $file_LastWriteTime.AddTicks ( - ($file_LastWriteTime.Ticks % [TimeSpan ]::TicksPerSecond));
96
+ foreach ($_ in $cacheEntry.LastWriteTimes.PSObject.Properties ) {
86
97
87
- $cache_LastWriteTime = [ DateTime ] $_.Value
88
- # Truncate DateTime to seconds
89
- $cache_LastWriteTime = $cache_LastWriteTime .AddTicks ( - ( $cache_LastWriteTime.Ticks % [ TimeSpan ]::TicksPerSecond));
98
+ if ( Test-Path $_.Name ) {
99
+ $file_LastWriteTime = ( Get-Item $_ .Name ).LastWriteTime.ToFileTime()
100
+ $cache_LastWriteTime = [ long ] $_ .Value
90
101
91
- if (-not ($file_LastWriteTime.Equals ($cache_LastWriteTime ))) {
92
- " Detected stale cache entry '$ ( $_.Name ) '" | Write-DscTrace
93
- $refreshCache = $true
102
+ if ($file_LastWriteTime -ne $cache_LastWriteTime ) {
103
+ " Detected stale cache entry '$ ( $_.Name ) '" | Write-DscTrace
104
+ $namedModules.Add ($cacheEntry.DscResourceInfo.ModuleName )
105
+ break
106
+ }
107
+ }
108
+ else {
109
+ " Detected non-existent cache entry '$ ( $_.Name ) '" | Write-DscTrace
110
+ $namedModules.Add ($cacheEntry.DscResourceInfo.ModuleName )
94
111
break
95
112
}
96
113
}
97
- else {
98
- " Detected non-existent cache entry '$ ( $_.Name ) '" | Write-DscTrace
99
- $refreshCache = $true
100
- break
101
- }
102
114
}
103
-
104
- if ($refreshCache ) { break }
105
115
}
106
-
107
- if (-not $refreshCache ) {
108
- " Checking cache for stale PSModulePath" | Write-DscTrace
109
-
110
- $m = $env: PSModulePath -split [IO.Path ]::PathSeparator | % { Get-ChildItem - Directory - Path $_ - Depth 1 - ea SilentlyContinue }
111
-
112
- $hs_cache = [System.Collections.Generic.HashSet [string ]]($cache.PSModulePaths )
113
- $hs_live = [System.Collections.Generic.HashSet [string ]]($m.FullName )
114
- $hs_cache.SymmetricExceptWith ($hs_live )
115
- $diff = $hs_cache
116
-
117
- " PSModulePath diff '$diff '" | Write-DscTrace
118
- if ($diff.Count -gt 0 ) {
119
- $refreshCache = $true
116
+ if ($namedModules.Count -gt 0 ) {
117
+ $refreshCache = $true
118
+ if ($null -ne $Module ) {
119
+ $namedModules.AddRange (@ ($Module ))
120
120
}
121
+ $namedModules = $namedModules | Sort-Object - Unique
122
+ " Module list: $ ( $namedModules -join ' , ' ) " | Write-DscTrace
121
123
}
122
124
}
123
125
}
@@ -131,32 +133,32 @@ function Invoke-DscCacheRefresh {
131
133
' Constructing Get-DscResource cache' | Write-DscTrace
132
134
133
135
# create a list object to store cache of Get-DscResource
134
- [ dscResourceCacheEntry []] $dscResourceCacheEntries = [System.Collections.Generic.List [Object ]]::new()
136
+ $dscResourceCacheEntries = [System.Collections.Generic.List [dscResourceCacheEntry ]]::new()
135
137
136
138
# improve by performance by having the option to only get details for named modules
137
139
# workaround for File and SignatureValidation resources that ship in Windows
138
- if ($null -ne $module -and ' PSDesiredStateConfiguration' -ne $module ) {
139
- if ($module.gettype ().name -eq ' string' ) {
140
- $module = @ ($module )
141
- }
140
+ if ($namedModules.Count -gt 0 ) {
142
141
$DscResources = [System.Collections.Generic.List [Object ]]::new()
143
142
$Modules = [System.Collections.Generic.List [Object ]]::new()
144
143
$filteredResources = @ ()
145
- foreach ($m in $module ) {
146
- $DscResources += Get-DscResource - Module $m
147
- $Modules += Get-Module - Name $m - ListAvailable
148
-
149
- # Grab all DSC resources to filter out of the cache
150
- $filteredResources += $dscResources | Where-Object - Property ModuleName -NE $null | ForEach-Object { [System.String ]::Concat($_.ModuleName , ' /' , $_.Name ) }
144
+ foreach ($m in $namedModules ) {
145
+ $DscResources.AddRange (@ (Get-DscResource - Module $m ))
146
+ $Modules.AddRange (@ (Get-Module - Name $m - ListAvailable))
151
147
}
152
148
149
+ if (' PSDesiredStateConfiguration' -in $namedModules -and $PSVersionTable.PSVersion.Major -le 5 ) {
150
+ # the resources in Windows should only load in Windows PowerShell
151
+ # workaround: the binary modules don't have a module name, so we have to special case File and SignatureValidation resources that ship in Windows
152
+ $DscResources.AddRange (@ (Get-DscResource | Where-Object - Property ParentPath -eq " $env: windir \system32\Configuration\BaseRegistration" ))
153
+ $filteredResources = @ (
154
+ ' PSDesiredStateConfiguration/File'
155
+ ' PSDesiredStateConfiguration/SignatureValidation'
156
+ )
157
+ }
158
+ # Grab all DSC resources to filter out of the cache
159
+ $filteredResources += $dscResources | Where-Object - Property ModuleName -NE $null | ForEach-Object { [System.String ]::Concat($_.ModuleName , ' /' , $_.Name ) }
153
160
# Exclude the one module that was passed in as a parameter
154
- $existingDscResourceCacheEntries = $cache.ResourceCache | Where-Object - Property Type -NotIn $filteredResources
155
- }
156
- elseif (' PSDesiredStateConfiguration' -eq $module -and $PSVersionTable.PSVersion.Major -le 5 ) {
157
- # the resources in Windows should only load in Windows PowerShell
158
- # workaround: the binary modules don't have a module name, so we have to special case File and SignatureValidation resources that ship in Windows
159
- $DscResources = Get-DscResource | Where-Object { $_.modulename -eq ' PSDesiredStateConfiguration' -or ( $_.modulename -eq $null -and $_.parentpath -like " $env: windir \System32\Configuration\*" ) }
161
+ $existingDscResourceCacheEntries = @ ($cache.ResourceCache | Where-Object - Property Type -NotIn $filteredResources )
160
162
}
161
163
else {
162
164
# if no module is specified, get all resources
@@ -232,29 +234,29 @@ function Invoke-DscCacheRefresh {
232
234
# fill in resource files (and their last-write-times) that will be used for up-do-date checks
233
235
$lastWriteTimes = @ {}
234
236
Get-ChildItem - Recurse - File - Path $dscResource.ParentPath - Include " *.ps1" , " *.psd1" , " *.psm1" , " *.mof" - ea Ignore | % {
235
- $lastWriteTimes.Add ($_.FullName , $_.LastWriteTime )
237
+ $lastWriteTimes.Add ($_.FullName , $_.LastWriteTime.ToFileTime () )
236
238
}
237
239
238
- $dscResourceCacheEntries += [dscResourceCacheEntry ]@ {
240
+ $dscResourceCacheEntries.Add ( [dscResourceCacheEntry ]@ {
239
241
Type = " $moduleName /$ ( $dscResource.Name ) "
240
242
DscResourceInfo = $DscResourceInfo
241
243
LastWriteTimes = $lastWriteTimes
244
+ })
245
+ }
246
+
247
+ if ($namedModules.Count -gt 0 ) {
248
+ # Make sure all resource cache entries are returned
249
+ foreach ($entry in $existingDscResourceCacheEntries ) {
250
+ $dscResourceCacheEntries.Add ([dscResourceCacheEntry ]$entry )
242
251
}
243
252
}
244
253
245
254
[dscResourceCache ]$cache = [dscResourceCache ]::new()
246
- $cache.ResourceCache = $dscResourceCacheEntries
255
+ $cache.ResourceCache = $dscResourceCacheEntries.ToArray ()
247
256
$m = $env: PSModulePath -split [IO.Path ]::PathSeparator | % { Get-ChildItem - Directory - Path $_ - Depth 1 - ea SilentlyContinue }
248
257
$cache.PSModulePaths = $m.FullName
249
258
$cache.CacheSchemaVersion = $script :CurrentCacheSchemaVersion
250
259
251
- if ($existingDscResourceCacheEntries ) {
252
- $cache.ResourceCache += $existingDscResourceCacheEntries
253
-
254
- # Make sure all resource cache entries are returned
255
- $dscResourceCacheEntries = $cache.ResourceCache
256
- }
257
-
258
260
# save cache for future use
259
261
# TODO: replace this with a high-performance serializer
260
262
" Saving Get-DscResource cache to '$cacheFilePath '" | Write-DscTrace
0 commit comments