11
2- # Load the module dll
2+ function Get-GraphAuthenticationLoadContextName {
3+ param (
4+ [Parameter (Mandatory = $true )]
5+ [string ] $ModulePath
6+ )
7+
8+ $sha256 = [System.Security.Cryptography.SHA256 ]::Create()
9+ try {
10+ $pathBytes = [System.Text.Encoding ]::UTF8.GetBytes($ModulePath )
11+ $hash = [System.BitConverter ]::ToString($sha256.ComputeHash ($pathBytes )).Replace(' -' , ' ' ).Substring(0 , 16 )
12+ " Microsoft.Graph.Authentication.$hash "
13+ }
14+ finally {
15+ $sha256.Dispose ()
16+ }
17+ }
18+
19+ function Initialize-GraphAuthenticationAssemblyResolver {
20+ if (' Microsoft.Graph.PowerShell.Authentication.Loader.GraphAuthenticationAssemblyResolver' -as [type ]) {
21+ return
22+ }
23+
24+ Add-Type - TypeDefinition @'
25+ using System;
26+ using System.Collections.Concurrent;
27+ using System.IO;
28+ using System.Reflection;
29+ using System.Runtime.Loader;
30+
31+ namespace Microsoft.Graph.PowerShell.Authentication.Loader
32+ {
33+ public static class GraphAuthenticationAssemblyResolver
34+ {
35+ private static readonly ConcurrentDictionary<string, string[]> DependencyFolders = new ConcurrentDictionary<string, string[]>(StringComparer.Ordinal);
36+ private static readonly ConcurrentDictionary<string, bool> RegisteredContexts = new ConcurrentDictionary<string, bool>(StringComparer.Ordinal);
37+
38+ public static void Register(AssemblyLoadContext context, string[] dependencyFolders)
39+ {
40+ if (context == null)
41+ {
42+ throw new ArgumentNullException(nameof(context));
43+ }
44+
45+ string contextName = context.Name ?? string.Empty;
46+ DependencyFolders[contextName] = dependencyFolders ?? Array.Empty<string>();
47+
48+ if (RegisteredContexts.TryAdd(contextName, true))
49+ {
50+ context.Resolving += Resolve;
51+ }
52+ }
53+
54+ private static Assembly Resolve(AssemblyLoadContext context, AssemblyName assemblyName)
55+ {
56+ if (context == null || assemblyName == null)
57+ {
58+ return null;
59+ }
60+
61+ if (!DependencyFolders.TryGetValue(context.Name ?? string.Empty, out string[] dependencyFolders))
62+ {
63+ return null;
64+ }
65+
66+ foreach (string dependencyFolder in dependencyFolders)
67+ {
68+ if (string.IsNullOrWhiteSpace(dependencyFolder) || !Directory.Exists(dependencyFolder))
69+ {
70+ continue;
71+ }
72+
73+ string dependencyPath = Path.Combine(dependencyFolder, assemblyName.Name + ".dll");
74+ if (File.Exists(dependencyPath))
75+ {
76+ return context.LoadFromAssemblyPath(Path.GetFullPath(dependencyPath));
77+ }
78+ }
79+
80+ return null;
81+ }
82+ }
83+ }
84+ '@
85+ }
86+
87+ function Import-GraphAuthenticationAssembly {
88+ param (
89+ [Parameter (Mandatory = $true )]
90+ [string ] $ModulePath
91+ )
92+
93+ if ($PSEdition -ne ' Core' -or -not (' System.Runtime.Loader.AssemblyLoadContext' -as [type ])) {
94+ return Import-Module - Name $ModulePath - PassThru
95+ }
96+
97+ $loadContextName = Get-GraphAuthenticationLoadContextName - ModulePath $ModulePath
98+ $loadContext = [System.Runtime.Loader.AssemblyLoadContext ]::All |
99+ Where-Object { $_.Name -eq $loadContextName } |
100+ Select-Object - First 1
101+
102+ if ($null -eq $loadContext ) {
103+ $loadContext = [System.Runtime.Loader.AssemblyLoadContext ]::new($loadContextName , $false )
104+ }
105+
106+ $moduleRoot = $PSScriptRoot
107+ $dependencyFolders = @ (
108+ (Join-Path $moduleRoot ' Dependencies\Core' ),
109+ (Join-Path $moduleRoot ' Dependencies' ),
110+ $moduleRoot
111+ )
112+
113+ Initialize-GraphAuthenticationAssemblyResolver
114+ [Microsoft.Graph.PowerShell.Authentication.Loader.GraphAuthenticationAssemblyResolver ]::Register($loadContext , [string []] $dependencyFolders )
115+
116+ $moduleAssembly = $loadContext.Assemblies |
117+ Where-Object { $_.GetName ().Name -eq ' Microsoft.Graph.Authentication' } |
118+ Select-Object - First 1
119+
120+ if ($null -eq $moduleAssembly ) {
121+ $moduleAssembly = $loadContext.LoadFromAssemblyPath ((Resolve-Path - LiteralPath $ModulePath ).Path)
122+ }
123+
124+ Import-Module - Assembly $moduleAssembly - PassThru
125+ }
126+
127+ function Test-GraphAuthenticationDoNotExport {
128+ param (
129+ [Parameter (Mandatory = $true )]
130+ [System.Management.Automation.CommandInfo ] $Command
131+ )
132+
133+ $implementingType = $Command.ImplementingType
134+ $null -ne $implementingType -and ($implementingType.GetCustomAttributes ($false ) |
135+ Where-Object { $_.GetType ().FullName -eq ' Microsoft.Graph.PowerShell.Authentication.Utilities.Runtime.DoNotExportAttribute' })
136+ }
137+
138+ function New-GraphAuthenticationCmdletAlias {
139+ param (
140+ [Parameter (Mandatory = $true )]
141+ [System.Management.Automation.CmdletInfo ] $Command
142+ )
143+
144+ $aliasNames = $Command.ImplementingType.GetCustomAttributes ($false ) |
145+ Where-Object { $_.GetType ().FullName -eq ' System.Management.Automation.AliasAttribute' } |
146+ ForEach-Object { $_.AliasNames } |
147+ Where-Object { -not [string ]::IsNullOrWhiteSpace($_ ) } |
148+ Select-Object - Unique
149+
150+ foreach ($aliasName in $aliasNames ) {
151+ New-Alias - Name $aliasName - Value $Command.Name - Force - Scope Script
152+ $aliasName
153+ }
154+ }
155+
156+ # Load the module DLL before exporting cmdlets. On PowerShell Core, loading the
157+ # binary through a custom AssemblyLoadContext keeps its dependencies isolated
158+ # from other Microsoft 365 modules that may already be loaded in the process.
3159$ModulePath = (Join-Path $PSScriptRoot ' Microsoft.Graph.Authentication.dll' )
4- $null = Import-Module - Name $ModulePath
160+ $ModuleInfo = Import-GraphAuthenticationAssembly - ModulePath $ModulePath
5161
6162# Export nothing to clear implicit exports.
7163Export-ModuleMember
@@ -14,4 +170,11 @@ if (Test-Path -Path "$PSScriptRoot\StartupScripts" -ErrorAction Ignore)
14170}
15171
16172# Export binary module cmdlets.
17- Export-ModuleMember - Cmdlet (Get-ModuleCmdlet - ModulePath $ModulePath ) - Alias (Get-ModuleCmdlet - ModulePath $ModulePath - AsAlias)
173+ $CmdletsToExport = $ModuleInfo.ExportedCommands.Values |
174+ Where-Object { $_.CommandType -eq ' Cmdlet' -and -not (Test-GraphAuthenticationDoNotExport - Command $_ ) }
175+
176+ $AliasesToExport = $CmdletsToExport |
177+ ForEach-Object { New-GraphAuthenticationCmdletAlias - Command $_ } |
178+ Select-Object - Unique
179+
180+ Export-ModuleMember - Cmdlet ($CmdletsToExport | Select-Object - ExpandProperty Name - Unique) - Alias $AliasesToExport
0 commit comments