pnp / powershell

PnP PowerShell
https://pnp.github.io/powershell
MIT License
683 stars 348 forks source link

[BUG] Could not load type 'Microsoft.Graph.AssignedLabel' when using New-PnPSite -Type TeamSite within C# #4446

Closed MiiChielHD closed 1 month ago

MiiChielHD commented 1 month ago

Reporting an Issue or Missing Feature

I'm using an App created on Azure. This had the specifics rights for making changes within the SharePoint scope. I can succesfully connect with Connect-PnPOnline through PowerShell ISE and C#. Commands like creating security groups, assigning members all works in PowerShell ISE and C#.

When trying to create a Teamsite with code stated below, it works in PowerShell ISE, yet not in C#.

$teamSiteUrl = New-PnPSite -Type TeamSite -Title "TitleName" -Alias "AliasName" -Description "DescriptionText" -Owner "administrator@domain.com"

[PSCustomObject]@{teamSiteUrl= $teamSiteUrl}

The Exception I receive is: System.Management.Automation.PSInvalidOperationException: Could not load type 'Microsoft.Graph.AssignedLabel' from assembly 'Microsoft.Graph, Version=5.60.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. at PnP.PowerShell.Commands.Base.PnPConnectedCmdlet.ProcessRecord() in c:\build\src\Commands\Base\PnPConnectedCmdlet.cs:line 101 at PnP.PowerShell.Commands.PnPSharePointCmdlet.ProcessRecord() in c:\build\src\Commands\Base\PnPSharePointCmdlet.cs:line 121 at System.Management.Automation.CommandProcessor.ProcessRecord() at <ScriptBlock>, <No file>: line 1

I updated the Microsoft.Graph package to the latest version in the C# Project, yet when I use a dll inspector I can't find any AssignedLabels class in the dll. Has this been removed?

Update 1: When I use dotpeek on both dll's, the one in the module of Pnp.PowerShell and the NugetPackage i see the difference:

afbeelding

Expected behavior

Able to create a Teamsite through the New-PnPSite cmdlet executed through C#.

Actual behavior

It can't find Microsoft.Graph.AssignedLabel thus it throws an exception.

Steps to reproduce behavior

Call the code below in PowerShell through C#.

$teamSiteUrl = New-PnPSite -Type TeamSite -Title "TitleName" -Alias "AliasName" -Description "DescriptionText" -Owner "administrator@domain.com"

What is the version of the Cmdlet module you are running?

Manifest 2.12.0 PnP.PowerShell

Which operating system/environment are you running PnP PowerShell on?

jackpoz commented 1 month ago

Manifest 1.12.0 PnP.PowerShell

The latest version is 2.12.0 and supports only PowerShell 7.x . You might want to try updating to the latest version and see the behavior.

As you are executing commands from C#, including a small C# project might help troubleshoot the issue. I sounds like a very peculiar edge case. Would it make more sense to use https://github.com/pnp/pnpcore or https://github.com/pnp/pnpframework from C# instead ?

MiiChielHD commented 1 month ago

Manifest 1.12.0 PnP.PowerShell

The latest version is 2.12.0 and supports only PowerShell 7.x . You might want to try updating to the latest version and see the behavior.

Yes I edited the post to 2.12.0, somehow it reverted. I installed 2.12.0 but it is still showing the same error. The point is that PnpPowerShell in PowerShell ISE is using its own Microsoft.Graph.dll that has verison 3.33, while in C# it is using Microsoft.Graph.dll on version 5.60.

As you are executing commands from C#, including a small C# project might help troubleshoot the issue. I sounds like a very peculiar edge case. Would it make more sense to use https://github.com/pnp/pnpcore or https://github.com/pnp/pnpframework from C# instead ?

Powershell Initiating `var tempSession = new PowerShellSession(); InitialSessionState iss = InitialSessionState.CreateDefault(); iss.ExecutionPolicy = Microsoft.PowerShell.ExecutionPolicy.RemoteSigned; iss.ThrowOnRunspaceOpenError = true;

Runspace remoteRunspace = RunspaceFactory.CreateRunspace(iss); tempSession.runspace = remoteRunspace;

remoteRunspace.Open(); powerShell.Runspace = remoteRunspace;

PowerShell powerShell = PowerShell.Create(); tempSession.powerShell = powerShell;`

Executing PowerShell Commands Collection<PSObject> tempPSObjectCollection = default; try { tempPSObjectCollection = argSession.powerShell.Invoke(); } catch (Exception ex) { if (argSession.powerShell.HadErrors) throw new Exception($"ExecutingScripts Failed:\n\n{ex}\n\n{FindErrors(argSession.powerShell)}"); } finally { argSession.powerShell.Commands.Clear(); }

Script for connecting with SharePoint root site $"$password = (ConvertTo-SecureString -AsPlainText '{argPassword}' -Force)\r\n" + $"Connect-PnPOnline {argSharePointHostname} -ClientId {argClientId} -Tenant {argTenantId} -CertificatePath \"{argCertPfxPath}\" -CertificatePassword $password";

Script for creating teamsite $"$teamSiteUrl = New-PnPSite -Type TeamSite -Title \"{argTeamTitle}\" -Alias \"{argAlias}\" -Description \"{argDescription ?? argTeamTitle}\" -Owner \"{argAdminUPNOwner}\"\r\n [PSCustomObject]@{{teamSiteUrl= $teamSiteUrl}}";

The PSCustomObject is needed so I receive the teamsiteurl in an object, which is easy to convert in a generic function for converting PSObject objects to instances of classes.

Your idea of using PnP Core I understand. I have looked briefly at the introduction page. The concept we use is that we have a 'player' application, that is generic for many tenants and does all the executing functions through graph, pnp or exo automated. So in our database we store the information we use to connect and when we start our 'player' application by schedule we recal the connection data from our database. From what I have read briefly about pnpcore I'm not really clear on how to do this...

I would really prefer that PnpPowerShell uses the newest Microsoft.Graph.dll. Because sooner or later new classes that are being used by Microsoft that will be decleared in this dll, so I can't imagine PnpPowerShell not upgrading the Microsoft.Graph.dll version in their package.