@@ -53,7 +53,7 @@ function Invoke-DscCacheRefresh {
5353 )
5454
5555 $refreshCache = $false
56-
56+ $namedModules = [ System.Collections.Generic.List [ Object ]]::new()
5757 $cacheFilePath = Join-Path $env: LocalAppData " dsc\WindowsPSAdapterCache.json"
5858
5959 if (Test-Path $cacheFilePath ) {
@@ -73,51 +73,53 @@ function Invoke-DscCacheRefresh {
7373 " Filtered DscResourceCache cache is empty" | Write-DscTrace
7474 }
7575 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+ }
7790
78- foreach ($cacheEntry in $dscResourceCacheEntries ) {
91+ if (-not $refreshCache ) {
92+ " Checking cache for stale entries" | Write-DscTrace
7993
80- $cacheEntry.LastWriteTimes.PSObject.Properties | ForEach-Object {
94+ foreach ( $cacheEntry in $dscResourceCacheEntries ) {
8195
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 ) {
8697
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
90101
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 )
94111 break
95112 }
96113 }
97- else {
98- " Detected non-existent cache entry '$ ( $_.Name ) '" | Write-DscTrace
99- $refreshCache = $true
100- break
101- }
102114 }
103-
104- if ($refreshCache ) { break }
105115 }
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 ))
120120 }
121+ $namedModules = $namedModules | Sort-Object - Unique
122+ " Module list: $ ( $namedModules -join ' , ' ) " | Write-DscTrace
121123 }
122124 }
123125 }
@@ -131,32 +133,32 @@ function Invoke-DscCacheRefresh {
131133 ' Constructing Get-DscResource cache' | Write-DscTrace
132134
133135 # 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()
135137
136138 # improve by performance by having the option to only get details for named modules
137139 # 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 ) {
142141 $DscResources = [System.Collections.Generic.List [Object ]]::new()
143142 $Modules = [System.Collections.Generic.List [Object ]]::new()
144143 $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))
151147 }
152148
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 ) }
153160 # 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 )
160162 }
161163 else {
162164 # if no module is specified, get all resources
@@ -232,29 +234,29 @@ function Invoke-DscCacheRefresh {
232234 # fill in resource files (and their last-write-times) that will be used for up-do-date checks
233235 $lastWriteTimes = @ {}
234236 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 () )
236238 }
237239
238- $dscResourceCacheEntries += [dscResourceCacheEntry ]@ {
240+ $dscResourceCacheEntries.Add ( [dscResourceCacheEntry ]@ {
239241 Type = " $moduleName /$ ( $dscResource.Name ) "
240242 DscResourceInfo = $DscResourceInfo
241243 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 )
242251 }
243252 }
244253
245254 [dscResourceCache ]$cache = [dscResourceCache ]::new()
246- $cache.ResourceCache = $dscResourceCacheEntries
255+ $cache.ResourceCache = $dscResourceCacheEntries.ToArray ()
247256 $m = $env: PSModulePath -split [IO.Path ]::PathSeparator | % { Get-ChildItem - Directory - Path $_ - Depth 1 - ea SilentlyContinue }
248257 $cache.PSModulePaths = $m.FullName
249258 $cache.CacheSchemaVersion = $script :CurrentCacheSchemaVersion
250259
251- if ($existingDscResourceCacheEntries ) {
252- $cache.ResourceCache += $existingDscResourceCacheEntries
253-
254- # Make sure all resource cache entries are returned
255- $dscResourceCacheEntries = $cache.ResourceCache
256- }
257-
258260 # save cache for future use
259261 # TODO: replace this with a high-performance serializer
260262 " Saving Get-DscResource cache to '$cacheFilePath '" | Write-DscTrace
0 commit comments