@@ -13,22 +13,46 @@ namespace System.Management.Automation.Internal
13
13
{
14
14
internal static class ModuleUtils
15
15
{
16
+ // These are documented members FILE_ATTRIBUTE, they just have not yet been
17
+ // added to System.IO.FileAttributes yet.
18
+ private const int FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS = 0x400000 ;
19
+
20
+ private const int FILE_ATTRIBUTE_RECALL_ON_OPEN = 0x40000 ;
21
+
16
22
// Default option for local file system enumeration:
17
23
// - Ignore files/directories when access is denied;
18
24
// - Search top directory only.
19
25
private static readonly System . IO . EnumerationOptions s_defaultEnumerationOptions =
20
- new System . IO . EnumerationOptions ( ) { AttributesToSkip = FileAttributes . Hidden } ;
26
+ new System . IO . EnumerationOptions ( ) { AttributesToSkip = FileAttributesToSkip } ;
27
+
28
+ private static readonly FileAttributes FileAttributesToSkip ;
21
29
22
30
// Default option for UNC path enumeration. Same as above plus a large buffer size.
23
31
// For network shares, a large buffer may result in better performance as more results can be batched over the wire.
24
32
// The buffer size 16K is recommended in the comment of the 'BufferSize' property:
25
33
// "A "large" buffer, for example, would be 16K. Typical is 4K."
26
34
private static readonly System . IO . EnumerationOptions s_uncPathEnumerationOptions =
27
- new System . IO . EnumerationOptions ( ) { AttributesToSkip = FileAttributes . Hidden , BufferSize = 16384 } ;
35
+ new System . IO . EnumerationOptions ( ) { AttributesToSkip = FileAttributesToSkip , BufferSize = 16384 } ;
28
36
29
37
private static readonly string EnCulturePath = Path . DirectorySeparatorChar + "en" ;
30
38
private static readonly string EnUsCulturePath = Path . DirectorySeparatorChar + "en-us" ;
31
39
40
+ static ModuleUtils ( )
41
+ {
42
+ if ( ExperimentalFeature . IsEnabled ( ExperimentalFeature . PSModuleAutoLoadSkipOfflineFilesFeatureName ) )
43
+ {
44
+ FileAttributesToSkip = FileAttributes . Hidden
45
+ // Skip OneDrive files/directories that are not fully on disk.
46
+ | FileAttributes . Offline
47
+ | ( FileAttributes ) FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS
48
+ | ( FileAttributes ) FILE_ATTRIBUTE_RECALL_ON_OPEN ;
49
+
50
+ return ;
51
+ }
52
+
53
+ FileAttributesToSkip = FileAttributes . Hidden ;
54
+ }
55
+
32
56
/// <summary>
33
57
/// Check if a directory is likely a localized resources folder.
34
58
/// </summary>
@@ -276,6 +300,11 @@ internal static IEnumerable<string> GetDefaultAvailableModuleFiles(string topDir
276
300
manifestPath += StringLiterals . PowerShellDataFileExtension ;
277
301
if ( File . Exists ( manifestPath ) )
278
302
{
303
+ if ( HasSkippedFileAttribute ( manifestPath ) )
304
+ {
305
+ continue ;
306
+ }
307
+
279
308
isModuleDirectory = true ;
280
309
yield return manifestPath ;
281
310
}
@@ -288,6 +317,11 @@ internal static IEnumerable<string> GetDefaultAvailableModuleFiles(string topDir
288
317
string moduleFile = Path . Combine ( directoryToCheck , proposedModuleName ) + ext ;
289
318
if ( File . Exists ( moduleFile ) )
290
319
{
320
+ if ( HasSkippedFileAttribute ( moduleFile ) )
321
+ {
322
+ continue ;
323
+ }
324
+
291
325
isModuleDirectory = true ;
292
326
yield return moduleFile ;
293
327
@@ -337,6 +371,25 @@ internal static List<Version> GetModuleVersionSubfolders(string moduleBase)
337
371
return versionFolders ;
338
372
}
339
373
374
+ private static bool HasSkippedFileAttribute ( string path )
375
+ {
376
+ try
377
+ {
378
+ FileAttributes attributes = File . GetAttributes ( path ) ;
379
+ if ( ( attributes & FileAttributesToSkip ) is not 0 )
380
+ {
381
+ return true ;
382
+ }
383
+ }
384
+ catch
385
+ {
386
+ // Ignore failures so that we keep the current behavior of failing
387
+ // later in the search.
388
+ }
389
+
390
+ return false ;
391
+ }
392
+
340
393
private static void ProcessPossibleVersionSubdirectories ( IEnumerable < string > subdirectories , List < Version > versionFolders )
341
394
{
342
395
foreach ( string subdir in subdirectories )
0 commit comments