Running O365 modules like Connect-MSOLService

Hello,

I am hoping to use some modules like Connect-Exhangeonline or Connect-MSOLService from a PU dashboard.

The machine hosting Powershell Universal has these installed and I can connect successfully through a PowerShell window. I have a service account with highest permission level for testing (global administrator) however I am seeing errors such as in the attached images.

If I connect to MSOL or Exchange using the deprecated methods this works OK (please ignore plaintext passwords, this is purely for testing purposes) but the below code example throws errors

Function MSOLTest() {
    Import-Module msonline
    # Test connect to AzureAD
    $Username = "test@email.com"
    $Password = "testpassword" 
    $Password = ConvertTo-SecureString $Password -AsPlainText -Force
    $credential = New-Object System.Management.Automation.PsCredential($username, $password)

    # Connect to msol
    Connect-MSOLService -credential $credential

    # Get a list of users or something
    #$Data = Get-MSOLUser -userprincipalname Test@email.com | Select *

    # Display that inside of a text box or similar
    return $Data
}

Connect-MSOLService:

Is there anything obviously wrong with my approach? I’ve tried to connect by directly running these commands in the PU code editor and also by loading a module and running a function to do this.

I can see this is possible for other users such as in this thread:

If you are running these in the integrated powershell env, or in a user installed 7.X powershell env try running these in Powershell 5.1 instead. I use Connect-MSOLService and Connect-ExchangeOnline in a few of my automations and they work in 5.1, but not in 7.x

works fine for us, just do something like this

New-UDEndpoint -Endpoint {
write-debug “ENDPOINT: getting o365 users”
try
{
$cred=$xso365service #cred stored in cred store
Connect-MsolService -Credential $cred
$tmp=get-msoluser -all -Synchronized
$Cache:o365Users=$tmp
write-debug “ENDPOINT: Finished getting o365 users”
}
catch
{
$Cache:Error = “Failed to get o365 users. $_”
}
finally
{
$Cache:Loading = $false
}

}-Schedule (New-UDEndpointSchedule -Every 300 -Second)

We are able to connect to Exchange in our APIs with PSU. Nothing special we had to do. Could be a configuration issue. Take a look at this to help you debug your PowerShell process running your Dashboard

Thanks for your responses everyone.

I’m still trying to get my head around Powershell Universal - I found the below errors in the logs of the dashboard:

Oct 15, 2021 1:18 PM An error occurred: Could not load type 'System.IdentityModel.Tokens.JwtSecurityToken' from assembly 'System.IdentityModel.Tokens.Jwt, Version=6.7.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'.
Endpoint: e29edd93-fbe1-48be-b106-167b4f23a878
Session: ae954ecf-c6d2-4205-bc05-b5e3690823d1
File: C:\ProgramData\UniversalAutomation\Repository\dashboards\MFA Reset Tool\MFA Reset Tool.ps1
Endpoint Start Line: 8
Endpoint End Line: 25
Stack Trace: at <ScriptBlock>, <No file>: line 12

I’ve tried running in the default powershell env, the integrated powershell env and via 5.1 or 7.x with the same issues. It’s not clear to me why this works fine everywhere else on the server but not when the code is run through Powershell Ultimate dashboard.
This seems to be the same issue as in this thread, and it doesn’t seem like a clear solution was found:

It’s a bit of a wild goose chase right now - is there a clear way I can specify which dependencies PU is going to use explicitly when running it such as .NET version and Powershell version?

Can you create a new environment which uses Persistent Runspaces and assign that environment to your Dashboard?

I’m running into the same issue on 2.4.0, but in this instance it is when trying to connect to PNP.PowerShell. I get the same could not load tokens.jwt error message. I’ve tried it using the default, v5.1 and integrated environment with difference in outcome. I do explicitly load the PNP.Powershell module (and see it listed as available in the modules list - that is really cool in 2.4!).

I’m not sure what a persistent runspace would do in this instance as I can’t even make the initial PNP connection?

Any ideas of other things to test?

If I change to a persistent runspace, the error changes to this:

This has to do with the Universal cmdlets. They reference the tokes.JWT assembly version 5.5.0. I’m going to drop the dependency to try and work around this issue because this PNP module is been a pain in the butt to load in PSU. It seems like every time it has been fixed, we encounter a new error with it.

The Universal module will only reference a few dependent assemblies to try to avoid this issue. In tonight’s 2.5 nightly build, it will remove the dependency on this assembly so I’m hoping this will solve the error once and for all.

Well, I have upgraded to the nightly build (10/21) and am now getting a different error trying to connect to PNP.PowerShell:

Not sure what is causing this one when I try to connect to PNP. I guess if it isn’t one thing, it is another.

It does this in all environments? From what I can tell the server is the only thing that uses AppInsights so I would only expect this in the integrated environment.

Man, this module is drivin me nuts :crazy_face:

I actually was under PowerShell 5. I changed to integrated and see it there, as well.

I was thinking, in the meantime, perhaps I will just upload the file to a published folder. With V2.5, I know that it has been simplified (although I’m not seeing the file name come across in the body). What would it look like to copy a file to the published folder?

The event data object should have properties like $EventData.FileName and $EventData.Name.

You can use those to copy from the temp dir to the published folder.

Copy-Item $EventData.FileName (Join-Path "C:\publishedFolder" $EventData.Name)

I don’t seem to get the filename in the body. Here is what I see returned:


With the first parts being other fields I am filling in, but you’ll see that there is no file name. I tried what you had above and get an error
image
because of the missing file name, I would guess.

Can you share the script you are using to create this?

Sure Thing

New-UDForm -Id “UploadFile$InvoicesPKID” -Content {
$PMArray = $PMSQL | Sort-Object PMName
$PMArray += [pscustomobject]@{
PMName = “None”
ProjectManagementPKID = “9999999999”
}
New-UDSelect -Id “DocType” -Label “Document Type” -Option {
foreach ($type in $DLTypeSQL) {
New-UDSelectOption -Name $type.DLType -Value $type.DLType
}
}
New-UDUpload -ID “File” -Text “File”
New-UDTextBox -Id “Description” -Label “File Description”
New-UDSelect -Id “ProjectManagement” -Label “Associated Project” -Option {
foreach ($pm in $PMArray) {
New-UDSelectOption -Name $pm.PMName -Value $pm.ProjectManagementPKID
}
} -DefaultValue “9999999999”
} -OnSubmit {
$DocType = $EventData.DocType
$File = $EventData.File
$Description = $EventData.Description
$ProjectManagement = $EventData.ProjectManagement
If ($ProjectManagement -eq “9999999999”) {
$ProjectManagement = $null
}

$Data = $Body | ConvertFrom-Json 
Show-UDToast -Message $Data -Duration 15000
$FileName = $EventData.File
Show-UDToast -Message "Filename: $FileName" -Duration 15000
Copy-Item $EventData.File (Join-Path "C:\ProgramData\UniversalAutomation\Repository\WebFolder" $Description)

There’s a bug here but here’s a work around. Set the upload into a session variable and then use that within your OnSubmit.

New-UDDashboard -Title "Hello, World!" -Content {
    New-UDForm -Id "UploadFile$InvoicesPKID" -Content {
        New-UDUpload -Id “File” -Text “File” -OnUpload {
            $Session:MyUpload = $Body
        }
    } -OnSubmit {
        $MyUpload = $Session:MyUpload | ConvertFrom-Json
        $bytes = [Convert]::FromBase64String($MyUpload.Data)
        Show-UDToast -Message $MyUpload.Name  -Duration 15000
        Show-UDToast -Message $bytes.Length  -Duration 15000
    }
}
1 Like

Hello there,

Just getting started and I am encouraged and amazed by what people have built.
We are trying to build a very basic Exchange Jr. Admin Portal where techs can grant Proxy Access, Set Email Forwarding, etc. We have all of the scripts working for years and would like to port them to Powershell Universal.

I have this code working fine:
Connect-ExchangeOnline -Credential $secret:pscreds

The problem is when I run the page that calls the script, it reconnects every time.

I would like to connect to exchange once and then be able to run multiple commands as needed under a single session. I am sure that there is a simple way to do this that I am simply overlooking.

Thoughts?

Cris