2

I am attempting to use the Microsoft.PowerShell.SDK package to execute a PowerShell script that uses the Connect-MgGraph command. This command works in a normal PS window, however running the script via my application leads to the "The term 'Connect-MgGraph' is not recognized as a name of a cmdlet..." error. The PS version on my machine is 7.3.5, and the version used by my application is 7.2.10 (supported by .NET 6). It seems I am only having issues with the Graph service as I have no issues importing other modules I installed, eg. ImportExcel. Running Get-Module -ListAvailable through the application results in the Graph modules showing as available as expected.

public async Task<PSDataCollection<PSObject>?> Invoke(string script, CancellationToken cancellationToken)
{
    try
    {
        InitialSessionState iss = InitialSessionState.CreateDefault();
        iss.ExecutionPolicy = Microsoft.PowerShell.ExecutionPolicy.Bypass;

        using PowerShell shell = PowerShell.Create(iss);
        shell.AddScript(script);

        var outputCollection = new PSDataCollection<PSObject>();

        // Uses Task.Factory to incorporate async/await
        // Moves away from the old IAsyncResult functionality still used by the PowerShell API
        var shellTask = Task.Factory.FromAsync(
            shell.BeginInvoke<PSObject, PSObject>(null, outputCollection),
            shell.EndInvoke);

        PSDataCollection<PSObject> result = await shellTask.WaitAsync(cancellationToken)
            .ConfigureAwait(false);

        return result;
    }
    catch (Exception e)
    {
        return null;
    }
}

What I've tried so far:

  1. Modifying $env:PSModulePath to ensure modules are being pulled from the proper locations.
    • The only difference between the module paths included in a normal PS session vs my application is that the application doesn't include c:\program files\powershell\7\Modules, though appending this to the path made no difference.
  2. Using InitialSessionState.CreateDefault() instead of InitialSessionState.CreateDefault2() to avoid loading only the commands required to host PowerShell as per Microsoft docs
  3. Compiling my program as x64 instead of Any CPU as suggested here enter image description here
  4. Consulting other similar SO questions such as this and this, though it seems they had straightforward solutions
  5. Importing the required modules by explicitly adding Import-Module Microsoft.Graph -Verbose to the script, however this produced Could not load type 'Microsoft.Graph.IAuthenticationProvider' from assembly 'Microsoft.Graph.Core, Version=3.0.9.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'.
Anil
  • 655
  • 1
  • 11
  • 25
  • PSModulePath there is a separate value for the user and the system. The Execution Policy may be making changes : https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?view=powershell-7.3 – jdweng Jul 24 '23 at 12:42
  • I did try removing `iss` from the equation as well, though printing PSModulePath gives the same results as when I modify the Execution Policy. Do these changes happen regardless? – Anil Jul 24 '23 at 18:02
  • Read the Long Description in the Link. – jdweng Jul 24 '23 at 18:39
  • Not sure, are you referring to the part stating that the Execution Policy of the user is separate from the current session? I am lost as to how I can make the application's PS session match a PS session on my system. – Anil Jul 25 '23 at 01:36
  • Another detail I noticed is that `Get-PSRepository` results in `Unable to find module providers (PowerShellGet).`... I have also tried running my application as administrator but this hasn't led to any results either. – Anil Jul 25 '23 at 01:37
  • Also not sure why this only seems to be affecting `Microsoft.Graph` and not anything else, as only this module is unavailable to my application. – Anil Jul 25 '23 at 01:43
  • See : https://learn.microsoft.com/en-us/powershell/microsoftgraph/installation?view=graph-powershell-1.0 – jdweng Jul 25 '23 at 10:53
  • Very odd. I guess my installation of Graph must have been corrupted in some way because after completely uninstalling it then reinstalling it on PS 7, the issue is gone. Thank you for this resource. – Anil Jul 26 '23 at 06:13

2 Answers2

0

Sorry I cant comment yet (dont have 50 rep to comment yet), so posting as an answer.

I have a similar project to this, that is running Graph commands like this, and one of the main differences I can see is your not creating a runspace or setting apartmentstate, and adding the session state to that like:

InitialSessionState iss = InitialSessionState.CreateDefault();
iss.ApartmentState = ApartmentState.STA;
Runspace runspace = RunspaceFactory.CreateRunspace(iss);
runspace.Open();

then when you can add the runspace to the shell variable:

shell.Runspace = runspace;
KG-DROID
  • 268
  • 6
  • Thank you for the suggestions. Good catch with the thread `ApartmentState` as it seems the default value is `Unknown`. Since creating a new runspace did not affect the issue, the default runspace is acceptable in my case. – Anil Jul 30 '23 at 03:08
  • 1
    Looks like I can comment on my own answer :), just to clarify, did the apartment state resolve the issue? Or are you going to try it later. – KG-DROID Jul 31 '23 at 08:20
  • The `ApartmentState` tip was helpful, but not for solving this issue. Apparently all it took to solve the issue was reinstalling the module on PS 7. Doh. – Anil Aug 01 '23 at 01:49
0

The issue was resolved by simply uninstalling and reinstalling the Microsoft.Graph module from PS7 using the following commands (see Uninstalling the SDK):

Uninstall-Module Microsoft.Graph -AllVersions
Get-InstalledModule Microsoft.Graph.* | ? Name -ne "Microsoft.Graph.Authentication" | Uninstall-Module
Uninstall-Module Microsoft.Graph.Authentication
Install-Module Microsoft.Graph

I still find it odd that the module was functioning correctly on my system, however when making calls from C#, any calls to the module were not recognized. This supports the conclusion that the module installation was likely corrupted in some way or another.

Key takeaway: Always check the basic stuff first...

Anil
  • 655
  • 1
  • 11
  • 25