Skip to content

Graph modules fail to import in new runspace once you are connected #253

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
KirkMunro opened this issue Jun 8, 2020 · 4 comments
Closed
Assignees
Labels
Milestone

Comments

@KirkMunro
Copy link

This is most easily reproducible using PowerShell ISE, but can also be reproduced using the ThreadJob PowerShell module or by creating a secondary and running PowerShell in that runspace using .NET directly.

The scenario is simple: once you have connected to graph using Connect-Graph with certificate-based authentication in a runspace, if you then open a new runspace and either try to import a graph module explicitly by invoking something like ipmo Microsoft.Graph.Users.User or you try importing a module explicity by invoking Get-MgUser, in both cases the module import fails. When you attempt to import it explicitly, and you review the error, you will see these Exception details:

PSMessageDetails      : 
Exception             : System.InvalidOperationException: An instance of GraphSession already exists. Call Initialize(Func<GraphSession>, bool) to overwrite it.
                           at Microsoft.Graph.PowerShell.Authentication.GraphSession.Initialize(Func`1 instanceCreator, Boolean overwrite)
                           at Microsoft.Graph.PowerShell.Authentication.GraphSessionInitializer.InitializeSession()
                           at System.Management.Automation.Runspaces.PSSnapInHelpers.ExecuteModuleInitializer(Assembly assembly, Type[] assemblyTypes, Boolean isModuleLoad)
                           at System.Management.Automation.Runspaces.PSSnapInHelpers.AnalyzePSSnapInAssembly(Assembly assembly, String name, PSSnapInInfo psSnapInInfo, PSModuleInfo moduleInfo, Boolean isModuleLoad, 
                        Dictionary`2& cmdlets, Dictionary`2& aliases, Dictionary`2& providers, String& helpFile)
                           at System.Management.Automation.Runspaces.InitialSessionState.ImportCmdletsFromAssembly(Assembly assembly, PSModuleInfo module)
                           at Microsoft.PowerShell.Commands.ModuleCmdletBase.LoadBinaryModule(PSModuleInfo parentModule, Boolean trySnapInName, String moduleName, String fileName, Assembly assemblyToLoad, String 
                        moduleBase, SessionState ss, ImportModuleOptions options, ManifestProcessingFlags manifestProcessingFlags, String prefix, Boolean loadTypes, Boolean loadFormats, Boolean& found, String 
                        shortModuleName, Boolean disableFormatUpdates)
                           at Microsoft.PowerShell.Commands.ModuleCmdletBase.LoadModule(PSModuleInfo parentModule, String fileName, String moduleBase, String prefix, SessionState ss, Object privateData, 
                        ImportModuleOptions& options, ManifestProcessingFlags manifestProcessingFlags, Boolean& found, Boolean& moduleFileFound)
                           at Microsoft.PowerShell.Commands.ImportModuleCommand.ImportModule_LocallyViaName(ImportModuleOptions importModuleOptions, String name)
                           at Microsoft.PowerShell.Commands.ImportModuleCommand.ProcessRecord()
                           at System.Management.Automation.CommandProcessor.ProcessRecord()
TargetObject          : 
CategoryInfo          : NotSpecified: (:) [Import-Module], InvalidOperationException
FullyQualifiedErrorId : System.InvalidOperationException,Microsoft.PowerShell.Commands.ImportModuleCommand
ErrorDetails          : 
InvocationInfo        : System.Management.Automation.InvocationInfo
ScriptStackTrace      : at <ScriptBlock>, C:\Program Files\WindowsPowerShell\Modules\Microsoft.Graph.Authentication\0.5.1\Microsoft.Graph.Authentication.psm1: line 13
                        at <ScriptBlock>, <No file>: line 1
PipelineIterationInfo : {}

The basic error text you get from PowerShell (the error text that the previous exception information comes from) is displayed as follows:

Import-Module : An instance of GraphSession already exists. Call Initialize(Func<GraphSession>, bool) to overwrite it.
At C:\Program Files\WindowsPowerShell\Modules\Microsoft.Graph.Authentication\0.5.1\Microsoft.Graph.Authentication.psm1:13 char:9
+ $null = Import-Module -Name (Join-Path $PSScriptRoot '.\bin\Microsoft ...
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Import-Module], InvalidOperationException
    + FullyQualifiedErrorId : System.InvalidOperationException,Microsoft.PowerShell.Commands.ImportModuleCommand

It seems that the Graph module isn't properly handling module import when you are working in multiple runspaces because it checks to see if you are already connected on import, and since the connection is cached in the current process, it raises this error. Using graph commands in multiple runspaces is a valid, important scenario which must be supported.

Also note that if you go the route of implicit module import, where in your second runspace you simply invoke Get-MgUser -ErrorAction Ignore, then the module appears to load correctly; however, -ErrorAction Ignore must be reserved for scenarios where you truly want to ignore all errors, and this is not one of those scenarios.

If this could be addressed for your next release, that would be appreciated.

Thanks!

@ghost ghost added the ToTriage label Jun 8, 2020
@ghost ghost removed the ToTriage label Jun 8, 2020
@ddyett
Copy link
Contributor

ddyett commented Jun 8, 2020

maybe if initialized we should avoid throwing so the existing instance is returned which seems to work based on the erroraction comment. I'm not sure though that the instance shouldn't be different which'd be more problematic.

@peombwa
Copy link
Member

peombwa commented Jun 8, 2020

@KirkMunro Thanks for reporting this, we will address this.
@ddyett That's right, we can simply reuse the existing session instance as opposed to throwing an exception. The session instance can be reused by the runspace thread without causing any unexpected behavior.

@peombwa peombwa added the Bug label Jun 8, 2020
@KirkMunro
Copy link
Author

KirkMunro commented Jul 13, 2020

@darrelmiller Like #279, this is the other issue that is just killing Graph automation using this module bundle.

I just hit this again when I switched from using the MicrosoftTeams module to using Microsoft.Graph for enumeration of Teams channels because the 1.1.4 release of MicrosoftTeams broke my script, and my script uses multiple threads via the ThreadJob module so that it can complete in a reasonable timeframe.

It should be an easy fix, as @ddyett and @peombwa indicated above.

If there is anything I can do to convince you to include this update in the 0.7.0 fix that @peombwa was working on, I will happily do so. Performing Teams management without this fix in any organization of a decent size is just terrible, because you're forced to use a single-thread for all calls that spend most of their time waiting for REST APIs to return results.

@peombwa peombwa added this to the 0.9.0 milestone Jul 20, 2020
@ddyett
Copy link
Contributor

ddyett commented Jul 22, 2020

released in 0.7.1

@ddyett ddyett closed this as completed Jul 22, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants