I am trying to run cmdlets from powershell module MicrosoftTeams (version 2.0.0) in a C# web application. I am using Authorization code flow and code from the answer provided in this post to acquire token: Acquire AAD token using ASP.Net web forms. Note: I had changed resource in the code to graph.windows.net to acquire AAD token. Token is acquired by using AuthenticationContext.AcquireTokenByAuthorizationCodeAsync Method.
Once the token is acquired, I run the following lines to create a powershell instance in C# and to import MicrosoftTeams Module.
PowerShell pshell
InitialSessionState iss;
iss = InitialSessionState.CreateDefault2();
iss.ImportPSModule(new[] { "MicrosoftTeams" });
pshell = PowerShell.Create(iss);
Then to connect with MicrosoftTeams, I run the following code:
var connectCmd = new Command("Connect-MicrosoftTeams");
connectCmd.Parameters.Add("AadAccessToken", AccessToken);
connectCmd.Parameters.Add("AccountId", "xxxxxxx#xxxxxx.onmicrosoft.com");
pshell.Commands.AddCommand(connectCmd);
var result1 = pshell.Invoke();
Code works fine till here.
After this I clear the shell commands and invoke the Get-CsTeamsCallingPolicy cmdlet:
pshell.Commands.Clear();
pshell.Streams.Error.Clear();
pshell.AddScript("Get-CsTeamsCallingPolicy");
var result2 = pshell.Invoke();
After Invoke, I get an exception and this dialog pops up:
Pressing 'Continue' brings back the same dialogue a couple of times.
Exception details from this screen are:
System.Collections.Generic.KeyNotFoundException was unhandled by user code
HResult=-2146232969
Message=The given key was not present in the dictionary.
Source=mscorlib
StackTrace:
at System.Collections.Concurrent.ConcurrentDictionary`2.get_Item(TKey key)
at Microsoft.TeamsCmdlets.Powershell.Connect.Models.AzureSessionProvider.GetAccessToken(String resource, IEnumerable`1 scopes) in D:\a\1\s\src\Microsoft.TeamsCmdlets.PowerShell.Connect\Models\AzureSession.cs:line 80
at Microsoft.TeamsCmdlets.Powershell.Connect.TeamsPowerShellSession.GetAccessToken(String resource, IEnumerable`1 scopes) in D:\a\1\s\src\Microsoft.TeamsCmdlets.PowerShell.Connect\TeamsPowerShellSession.cs:line 82
at Microsoft.TeamsCmdlets.PowerShell.Connect.GetCsInternalAccessToken.ProcessRecord() in D:\a\1\s\src\Microsoft.TeamsCmdlets.PowerShell.Connect\GetCsInternalAccessToken.cs:line 61
at System.Management.Automation.CommandProcessor.ProcessRecord()
After pressing continue for the 3rd time, control goes back to C# code, and I receive the following runtime exception:
Exception calling "GetSteppablePipeline" with "1" argument(s):
"Exception calling "GetRemoteNewCsOnlineSession" with "1" argument(s):
"Run either Connect-MicrosoftTeams or new-csonlinesession before running cmdlets.""
Trying to run this logic from the powershell editor shows similar behavior:
Running the following two lines:
$AccessToken = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
Connect-MicrosoftTeams -AadAccessToken $AccessToken -AccountId 'xxxxxxx#xxxxxx.onmicrosoft.com'
gives this result:
Account Environment Tenant TenantId
------- ----------- ------ --------
xxxxxxx#xxxxxx.onmicrosoft.com AzureCloud xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
I then run Get-Team cmdlet:
Get-Team -User xxxxxxx#xxxxxxx.onmicrosoft.com
which results in this message:
Get-Team : The given key was not present in the dictionary.
At line:1 char:1
+ Get-Team -User xxxxxxx#xxxxxxx.onmicrosoft.com
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-Team], KeyNotFoundException
+ FullyQualifiedErrorId : System.Collections.Generic.KeyNotFoundException,Microsoft.TeamsCmdlets.PowerShell.Custom.GetTeam
Running cmdlet Get-CsTeamsCallingPolicy yields this
Exception calling "GetSteppablePipeline" with "1" argument(s):
"Exception calling "GetRemoteNewCsOnlineSession" with "1" argument(s):
"Run either Connect-MicrosoftTeams or new-csonlinesession before running cmdlets.""
At C:\Program Files\WindowsPowerShell\Modules\MicrosoftTeams\2.0.0\net472\SfBORemotePowershellModule.psm1:11369 char:13
+ $steppablePipeline = $scriptCmd.GetSteppablePipeline($myI ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : CmdletInvocationException
If I run Connect-MicrosoftTeams directly without providing access token and accountid, I get the login screens and after login everything works fine but not happening with AadAccessToken.
Same code works fine if connecting to AzureAD module via Connect-AzureAD cmdlet like this both in web application and powershell editor:
Connect-AzureAD -AadAccessToken $AccessToken -AccountId 'xxxxxxx#xxxxxxx.onmicrosoft.com'
If someone has faced and successfully resolved this issue or have some tips on how to resolve this, please help.
I have already tried a lot of things including searching for the specific exception messages and any possible solutions but found nothing that could help in this particular scenario, installed the latest version of MSTeams module, the previous version was old and did not have all the cmdlets that I am looking to work with. I actually installed the preview version of MSTeams module also to see if this issue is fixed in the upcoming release. Uninstalled the deprecated SkypeForBuisnessOnline Connector module, updated windows and so on. If you look at Example 4 in the Microsoft documentation for Connect-MicrosoftTeams, this is what I am following.
There are several problems in your implementation, I will explain them one by one below.
The answer in this post generates an Microsoft Graph access token rather than an AAD Graph access token. But you put it as the -AadAccessToken. You should put it as -MsAccessToken here because Get-Team is calling Microsoft Graph. But we cannot simply use Connect-MicrosoftTeams -MsAccessToken $AadAccessToken-AccountId 'xxxxxxx#xxxxxx.onmicrosoft.com' because the -AadAccessToken is necessary. So for testing purpose, we could set it as the same as -MsAccessToken.
So you can use this cmd to connect to Microsoft Teams:
Connect-MicrosoftTeams -AadAccessToken $AadAccessToken -MsAccessToken $AadAccessToken -AccountId 'xxxxxxx#xxxxxx.onmicrosoft.com'
Then you can run Get-Team -User xxxxxxx#xxxxxxx.onmicrosoft.com successfully.
But there will be another issue here. Get-CsTeamsCallingPolicy is a cmd under Skype For Business Powershell module. We have to run either Connect-MicrosoftTeams (in Teams module) or new-csonlinesession (in SFB module) before running cmdlets.
It means that Get-CsTeamsCallingPolicy is NOT calling Microsoft Graph or AAD Graph.
So the connection method using -AadAccessToken and -MsAccessToken is NOT enough for you to run this command from the SFB module.
I know you don't want to perform login interactively again here for running Powershell cmd. However, since your account has already enabled MFA, static login will no longer apply.
So next I tried to connect with a service principal by following Example 3 here.
Connect-MicrosoftTeams -TenantId c3eac90d-eb4b-48ef-ac86-7acac472d3cd -CertificateThumbprint 9b6ac64bfb8b48dbb53cca75fb33ce2d -applicationid daaaf729-aaff-45ba-8055-a39dd618fe24
Then the error Run either Connect-MicrosoftTeams or new-csonlinesession before running cmdlets. is bypassed BUT I got a new error when I run `Get-CsTeamsCallingPolicy:
Exception calling "GetRemoteNewCsOnlineSession" with "1" argument(s): "Tenant Domain is empty"
But I clearly specified the tenant id when I logged in with the service principal.
So I think that the Microsoft Teams module is not well integrated with SFB module currently.
Your design cannot be implemented in this way.
Hope all my findings are helpful.
Related
Am new to powershell and using this procedure to set application policy with microsoft team
The above is necessary when creating online meetings as per this procedure
but whenever i run
Grant-CsApplicationAccessPolicy -PolicyName Test-policy -Identity "appid"
Am getting an error
Exception calling "GetSteppablePipeline" with "1" argument(s):
"Exception calling "GetRemoteNewCsOnlineSession" with
"1" argument(s): "Run either Connect-MicrosoftTeams or new-csonlinesession before running cmdlets."
I have already Connected using admin credentials by using
Import-Module MicrosoftTeams
Connect-MicrosoftTeams
I have powershell 5.1 on my device.
What am i missing or how do i resolve the error above.
Please check which module your using GA or public preview module,if you have installed both,please do uninstall GA and try to set the policy
Update teams module , close and reopen the powershell and try to assign the policy
Reference link
Please do let me know if above steps works for you
As part of a clean up task, I'm looking for a way to programmatically purge deleted AAD accounts from the User Profile Manager in Sharepoint Online.
I was using the Sharepoint Powershell module (Microsoft.Online.SharePoint.PowerShell) to manually do it, using the Remove-SPOUserProfile commandlet, which worked perfectly if I was using it in an interactive session. But as soon as I tried implementing my script into Azure Automation I found that particular module falls back to Basic Authentication when using a PSCredential object in the Connect-SPOService statement. And Basic Auth is blocked at my Organisation (I can't see them allowing it just for me!)
I found the PnP Module (PnP.PowerShell), which does allow authentication via stored credentials. But it doesn't have an equivalent User Profile Remove cmdlet.
Finally, I tried resorting to pure REST API, and while I can get an existing user profile, I can't get a profile for an account that has been deleted (marked as 'Profiles Missing from Import' in the SPO ProfMngr.aspx page). This is because the SP.UserProfiles.PeopleManager/GetPropertiesFor(accountName=#v) API needs to have an exact match (eg i:0#.f|membership|vardhaman#siteurl.onmicrosoft.com), and when an AAD account is deleted the profile username gets DELETED-<GUID> appended to it.
So my questions are:
Am I right or wrong about the sharepoint module and stored creds? (IE, so the module can be used from Azure Automation with a service principal or service account)
Am I right or wrong about the PnP module and it is missing the similar Remove-SPOUserProfile?
With the REST API, how do you search for profiles, especially profiles "missing from import"?
Is there some way to predict what the DELETED-<GUID> will be for a given user? Because I was able to get a user profile if I looked up the full deleted name and supply that to my REST call.
The official documentation on this is light - the old traditional sharepoint APIs aren't being developed any more, in favour of MS Graph, but the Graph Documentation doesn't seem to cover my particular use case.
Any pointers appreciated
Update 1
Thanks #Michael Han_MSFT.
I was using a pre-release/nightly build (0.3.32) but looking at Release documentation so didn't realise remove profile was in there.
I'm still getting problems though:
Connect-PnPOnline `
-url "https://<tenantname>.sharepoint.com" `
-ClientId $ClientId `
-ClientSecret $ClientSecret
# $guest1 = Guest account's email address
$azureEmail = ($guest1 -replace "#", "_") + "#ext##<tenantname>.onmicrosoft.com"
Remove-PnPUserProfile `
-LoginName $azureEmail
Remove-PnPUserProfile : The remote server returned an error: (401) Unauthorized.
At line:11 char:1
+ Remove-PnPUserProfile `
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Remove-PnPUserProfile], WebException
+ FullyQualifiedErrorId : System.Net.WebException,PnP.PowerShell.Commands.UserProfiles.RemoveUserProf
ile
So I tweaked the URL:
Connect-PnPOnline `
-url "https://<tenantname>-admin.sharepoint.com" `
-ClientId $ClientId `
-ClientSecret $ClientSecret
$azureEmail = ($guest1 -replace "#", "_") + "#ext##azurediagovt.onmicrosoft.com"
Remove-PnPUserProfile `
-LoginName $azureEmail
Remove-PnPUserProfile :
At line:11 char:1
+ Remove-PnPUserProfile `
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (:) [Remove-PnPUserProfile], HttpRequestException
+ FullyQualifiedErrorId : EXCEPTION,PnP.PowerShell.Commands.UserProfiles.RemoveUserProfile
So you can see if I go to <tenantname> I get a 401, but if I go to <tenantname>-name the response is simply blank.
I was certain I had given my App the right permissions (Is there some way to review what permissions have been assigned?)
In AppInv.aspx I think had this permissions code (I was following a couple of blogs):
<AppPermissionRequests AllowAppOnlyPolicy="true">
<AppPermissionRequest Scope="http://sharepoint/content/Tenant" Right="FullControl"/>
<AppPermissionRequest Scope="http://sharepoint/social/Tenant" Right="FullControl"/>
</AppPermissionRequests>
As a further test, I tried the PnP version of what I was doing in REST (Get-PnpUserProfileProperty) and got
Get-PnPUserProfileProperty : Current user is not a tenant administrator.
At line:1 char:1
+ Get-PnPUserProfileProperty -Connection $pnpctx -Account "scottdu#data ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (:) [Get-PnPUserProfileProperty], ServerException
+ FullyQualifiedErrorId : EXCEPTION,PnP.PowerShell.Commands.UserProfiles.GetUserProfileProperty
Which is strange, because REST would give me a results.d response.
At this stage, I could look at making the App Id a Sharepoint Service Admin (I already have approval to allow Azure Automation to have whatever rights it needs to solve this).
(Update 1a: Made no difference, unless there is a delay between assigning the role and the permissions taking affect).
AAD registered app can be used to connect PnpOnline and delete user profile. Please see my below steps:
(Main refer article: https://learn.microsoft.com/en-us/sharepoint/dev/solution-guidance/security-apponly-azuread)
Step1:Registering an Azure AD application in the Azure Active Directory tenant that is linked to your Office 365 tenant and grant permission
Use admin account to access https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps. Click “New registration” and create a name of your app.
Go to “API permissions” and click on the "Add a permission" button and grant SharePoint API permission.
Select needed permissions.
Admin need to consent for those permissions, after that in status column will show green.
Step2: Create a self signed certificate and connect with app
Go to this link(https://learn.microsoft.com/en-us/sharepoint/dev/solution-guidance/security-apponly-azuread#setting-up-an-azure-ad-app-for-app-only-access), copy the scripts and save as “Create-SelfSignedCertificate.ps1”.
Run below command with PowerShell. You will be asked to give a password to encrypt your private key, and both the .PFX file and .CER file will be exported to the current folder.
.\Create-SelfSignedCertificate.ps1 -CommonName "YourCompanyName"
-StartDate 2020-1-09 -EndDate 2022-10-01
Go to AAD app, click on "Certificates & secrets" in the left menu bar. Click on the "Upload certificate" button, select the .CER file you generated and upload it.
Step3: Connect pnp online and perform delete profile
$ Connect-PnPOnline -ClientId <$application client id as copied over
from the AAD app registration above> -CertificatePath '<$path to the
PFX file generated by the PowerShell script above>'
-CertificatePassword (ConvertTo-SecureString -AsPlainText "<$password assigned to the generated certificate pair above>" -Force) -Url
https://<$yourtenant>.sharepoint.com -Tenant
"<$tenantname>.onmicrosoft.com"
$Remove-PnPUserProfile -LoginName $UPN
For REST api way, I found this article noted REST for delete user profile is not implemented.
(https://learn.microsoft.com/en-us/sharepoint/dev/general-development/work-with-user-profiles-in-sharepoint)
You could try the command : Remove-PnPUserProfile
https://pnp.github.io/powershell/cmdlets/Remove-PnPUserProfile.html
You should install the prerelease version of PnP.PowerShell:
https://www.powershellgallery.com/packages/PnP.PowerShell/0.3.8-nightly
Update:
You could try to use tenant administrator account to connect the sharepoint admin site, then run the command Remove-PnPUserProfile. This works for me:
Short story: I get the following error when trying to create a namespace on Azure Service Bus using Azure Powershell (Run as Administrator):
PS C:> New-AzureSBNamespace -Name mynewnamespace2 -Location "East US"
-CreateACSNamespace $true -Namespac New-AzureSBNamespace : Object reference not set to an instance of an object. At line:1 char:1
+ New-AzureSBNamespace -Name mynewnamespace2 -Location "East US" -CreateACSNamespace $ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [New-AzureSBNamespace], NullReferenceException
+ FullyQualifiedErrorId : Microsoft.WindowsAzure.Commands.ServiceBus.NewAzureSBNamespaceCommand
Long story: I created a first namespace in Azure Service Bus to use Relay in buffered mode (namespace=mynewnamespace). It works great except when you want to transfer a larger set of data. For this there is the streamed mode and I found this handy example (https://code.msdn.microsoft.com/How-to-send-a-large-c36ab70e), changed appropriate settings for namespace and credentials and ran the server part from the project and I get the error
{"The remote name could not be resolved:
'mynewnamespace-sb.accesscontrol.windows.net'"}
because, of course, this ACS namespace does not exist. So I found out that I need to create the namespace the old fashioned way using PS, installed Azure CLI and run the commands below with the following result:
For a list of all Azure cmdlets type 'get-help azure'.
For a list of Windows Azure Pack cmdlets type 'Get-Command wapack'.
PS C:> azure login
info: Executing command login
|info: To sign in, use a web
browser to open the page https://aka.ms/devicelogin. Enter the code EE226448L to
authenticate. If you're signing in as an Azure AD application, use the
--username and --password parameters.
/info: Added subscription Visual Studio Enterprise with MSDN info: Setting subscription
"Visual Studio Enterprise with MSDN" as default
info: login command OK
PS C:> New-AzureSBNamespace -Name mynewnamespace2 -Location "East US" -CreateACSNamespace $true -NamespaceType Messaging
WARNING: Microsoft Azure PowerShell collects data about how users use
PowerShell cmdlets and some pro encounter. Microsoft uses this
information to improve our PowerShell cmdlets. Participation is volu
choose to participate your device automatically sends information to
Microsoft about how you use Azure Powershell.
If you choose to participate, you can stop at any time by using Azure
PowerShell as follows:
1. Use the Disable-AzureDataCollection cmdlet to turn the feature Off. The cmdlet can be found in the AzureResourceManager module To disable
data collection: PS > Disable-AzureDataCollection
If you choose to not participate, you can enable at any time by using
Azure PowerShell as follows:
1. Use the Enable-AzureDataCollection cmdlet to turn the feature On. The cmdlet can be found in the AzureResourceManager module To enable
data collection: PS > Enable-AzureDataCollection
Select Y to enable data collection [Y/N]: WARNING: You choose not to
participate in Microsoft Azure PowerShell data collection. WARNING:
The setting profile has been saved to the following path
'C:\Users\PDube\AppData\Roaming\Windows Azure Powershell\AzureDataCollectionProfile.json'.
New-AzureSBNamespace :
Object reference not set to an instance of an object. At line:1 char:1
+ New-AzureSBNamespace -Name mynewnamespace2 -Location "East US" -CreateACSNamespace $ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [New-AzureSBNamespace], NullReferenceException
+ FullyQualifiedErrorId : Microsoft.WindowsAzure.Commands.ServiceBus.NewAzureSBNamespaceCommand
I tried to create the new namespace using Azure CLI on 2 different computers, thinking the first install was corrupted, but I get the exact same error.
How can I fix this error?
I'm trying to manage some of my Azure Services via Powershell, using http://windowsazurewebsitescheatsheet.info/#powershell as a starting point. I was able to download and import my subscription settings just fine (Import-AzurePublishSettingsFile and Select-AzureSubscription)
After choosing my subscription, I'm attempting to run the Get-AzureWebsite command to view all of my websites, and continue onward from there. When I run that command, however, I get the following:
Import-AzurePublishSettingsFile "C:\AzureCredentials.publishsettings"
Select-AzureSubscription "My Azure Subscription"
Get-AzureWebsite
Get-AzureWebsite : String was not recognized as a valid Boolean.
At line:1 char:1
+ Get-AzureWebsite
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [Get-AzureWebsite], FormatException
+ FullyQualifiedErrorId : Microsoft.WindowsAzure.Commands.Websites.GetAzureWebsiteCommand
Anyone have similar issues? I get this error if I run the command as stated above, or if I specify the name of my website. TIA for any help!
This might be related to a known issue enumerating a sites with SSL bindings
There was new release of Windows Azure Powershell released on 02/12. Please try with the new version.
Please run the command again with -Debug turned on, this will display request and response messages and make it easier to pinpoint the issue.
Whenever I try the following line in a powershell script :
Disable-CrmOrganization -Name MyOrganization
I get the following error :
Disable-CrmOrganization : The Deployment Service cannot process the request because one or more validation checks failed.
+ Disable-CrmOrganization <<<< -Name MyOrganization
+ CategoryInfo : NotSpecified: (:) [Disable-CrmOrganization], FaultException`1
+ FullyQualifiedErrorId : System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.Deployment.DeploymentServiceFaul
t, Microsoft.Crm.PowerShell, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]],Microsoft.Crm.Pow
erShell.DisableCrmOrganizationCmdlet
However, if I manually disable the organization, I am able to execute the following line with no problem :
Remove-CrmOrganization -Name MyOrganization
Any idea why I cannot disable the organization with powershell?
You might have run across this page: Use PowerShell to Call the Deployment Web Service for the CRM PowerShell references.
Running this command gives additional error details: $error[0].Exception.Detail.ErrorDetails
Additionally the Windows Application Event Log was showing an error (in my case anyway):
Web service request FindItems to Report Server http://myserver/reportserver/ReportService2005.asmx failed with SoapException. Error: The permissions granted to user 'NT AUTHORITY\NETWORK SERVICE' are insufficient for performing this operation.
Which lead me to this post:
http://social.microsoft.com/Forums/en/crm/thread/0dd4a41b-eeba-405c-9b56-c32bfedb9e7a
The solution was to run the CrmDeploymentServiceAppPool under an account with elevated priviledges. Logon as a service and sysadmin in SQL Server according to the post.
How to enable tracing in Microsoft Dynamics CRM
when I execute 2 times it works so try with:
try {
Disable-CrmOrganization -Name "oragnization_name"
}catch {
Disable-CrmOrganization -Name "oragnization_name"
}