Powershell

Microsoft Teams PowerShell Phone Number Assigning Cmdlet Change

Microsoft has sent out an announcement on PowerShell changes for setting and removing phone numbers in Microsoft Teams:

Changes coming to phone number assignment using Teams PowerShell Module cmdlets
MC316139 · Published 19 Jan 2022

In summary, these commands are being deprecated “The retirement is planned to begin in early April and be complete by mid-April.” :

Set-CsOnlineVoiceUser
Set-CsOnlineApplicationInstance
Set-CsOnlineVoiceApplicationInstance

and Set-CSUser can’t be used to allocate phone numbers either. I’d been allocating numbers with the Set-CsOnlineVoiceUser command. The replacement for this is:

Set-CsPhoneNumberAssignment and Remove-CsPhoneNumberAssignment

They run under the MicrosoftTeams module for PowerShell, but you also need to make sure you have the latest version. If you don’t have a version that supports this new command, you’ll get the error:

Set-CsPhoneNumberAssignment : The term 'Set-CsPhoneNumberAssignment' is not recognized as the name of a cmdlet,
function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the
path is correct and try again.
At line:1 char:1

To update, run the command:

Update-module MicrosoftTeams 

Then try the above cmdlet again. If you’re feeling really brave, you can update all your modules with:

Update-module *

Disconnect or restart PowerShell or you’ll get problems running the new cmdlet if you had it connected while updating.

The new cmdlet Set-CsPhoneNumberAssignment doesn’t work exactly the same way as the old cmdlets. Read the documentation for more details

Set-CsPhoneNumberAssignment -Identity [email protected] -PhoneNumber +61987654321 -PhoneNumberType CallingPlan

The options for -PhoneNumberType (required) are DirectRouting, CallingPlan and OperatorConnect.

I’d suggest testing and migrating soon, before you miss the April deadline of the command being dropped.

PowerShell Slow to Load and AutoFill

I had this problem on a server for a while – when first launching PowerShell, it would take ~20 seconds or so to accept input. Also, when pressing tab to auto-complete a command, it would again take ~20 seconds to start, like it was freezing. These were one time problems when launching PowerShell, after that it would work fine until a new session was launched.

A lot of searching didn’t help me work it out, so I logged a Microsoft case. After a few task manager executable dumps, they worked out the delay was on a path I had in an environment variable. Somehow in my account’s user variable, I had a github desktop path that was mapping to a network share, using a PC name that was decommissioned (e.g. ;\\pcname\c$\Users\AdamFowler\AppData\Local\GitHubDesktop\bin.

I expect that this name was timing out, and PowerShell was waiting a while before giving up. In case you have the same symptoms as me, check the environment variables – user variables paths if it’s only your account affected, or the system variables if it’s all users. Click on the path value, then click edit, and remove anything that shoudn’t be there (take a backup of the text if you aren’t sure, it’s easy to put back in if you keep a copy).

To get to Environment Variables, depending on the OS version, get to System Properties, the Advanced tab, and then the Environment Variables button:

Hope that helps someone else with the same problem!

Microsoft Lists Date/Time Settings Incorrect

Microsoft Lists is available for a lot of people already, and should be globally available by the end of October 2020. Users can start using it as soon as it’s released for your tenant, which is great; but you might get caught out by the same date and time regional problem I did.

Creating a List is easy (right now I have the option available in Teams, but the app in Office 365 hasn’t turned up yet), and there’s many use cases for wanting a date or time field.

However, the suggestion on what day it is was wrong:

Today is actually Wednesday, October 14th 2020. It’s being caused because the timezone is wrong for the list. How do we fix that?

A Microsoft List can be created two ways – in the single user context, or in a Microsoft 365 Group context. If you’re doing in in Teams then the later only applies. Individually, it’s saved in the same area as your OneDrive for Business (which is backeneded by SharePoint), but for a Group it’s saved straight into the Site for the Group.

Lists in OneDrive for Business

For the individual point of view, there’s already a Microsoft Answer on how to fix this – change your Time Zone and Region Locale. The link for this is indivualised for your tenant and account, but you can access it by:

  • Browse to office.com and sign in
  • Click the OneDrive app from the left hand menu
  • Click the cog in the top right corner and choose ‘OneDrive Settings’
  • Click ‘More Settings’ in the left hand list
  • Under ‘Region and Language’ choose ‘Regional Settings’
  • Choose the correct Time Zone and Locale for your account

Changing this for all users is a bit more of a problem. There’s a PowerShell script here to update all existing ones, and new users there appears to be no way to do it based on this outstanding UserVoice – if you find anything different, please share and I’ll update this post.

Lists in SharePoint Online

A Microsoft List tied to a Microsoft 365 Group will read the Time Zone and Region settings from the Group’s site, which is accessed a bit differently:

  1. Browse to office.com and sign in
  2. If you have the Lists app in the left hand menu, choose that and skip to step 5
  3. If there is no Lists app, click the SharePoint app from the left hand menu
  4. Choose the Microsoft 365 Group that contains the Microsoft List (if you’re unsure, you can try finding the List in Teams, clicking the elipsis and choosing ‘Open in SharePoint’.
  5. Click the cog in the top right corner and choose ‘Site Contents’ then choose ‘Site Settings’
  6. Click ‘Regional Settings’ under ‘Site Administration’
  7. Choose the correct Time Zone and Locale for your Group and press ‘OK’ in the bottom right corner.

This works for a single site, but what about a company wide default?

In the SharePoint admin center, under Settings then Site creation, you can set the default time zone for new sites. This won’t help any existing Microsoft 365 Group already created (as a site is created at the time the group gets created), but will help with future sites.

If you want to update existing sites in PowerShell, you’ll need to start with this command:

Set-SPoSitesRegionalSettings -Url site.url.goes.here -TimeZoneID 19

That will change just the specified site.

The list of TimeZoneIDs is available from Microsoft here and there’s also a Gallery Script called Update the time zones in all sites in SharePoint Online which you could use to update all sites if you can’t work out how to do it.

A lot of details there just to change the date detection in Lists, but hopefully this gives you enough information to understand the scenarios and how to resolve them.

Connecting to Skype for Business Online via PowerShell in a Hybrid Environment

How to connect to Skype for Business Online via Powershell

To connect to Skype for Business Online:

  • Download and install the module from Microsoft

  • Run the following commands in PowerShell:

    Import-Module SkypeOnlineConnector

    $sfboSession = New-CsOnlineSession -UserName “[email protected]” -OverrideAdminDomain “yourtennant.onmicrosoft.com”

    Import-PSSession $sfboSession

    Applies To : Windows 10, Windows Server


    I’ve been caught out by this twice and it’s taken me a while to find the rather simple answer.

    Most instructions give you a pretty simple way to connect to Skype for Business Online (or they’ll just call it Skype for Business). You install the module via executable, downloaded from Microsoft, and then try to run the following PowerShell commands (or some similar variation):

    Import-Module SkypeOnlineConnector
    $sfboSession = New-CsOnlineSession -UserName "[email protected]"
    Import-PSSession $sfboSession

    If you don’t have Skype for Business On-Premises, it should just work. If you DO have it and set up hybrid, you’ll probably get this error:

    Unable to discover PowerShell endpoint URI.
    At C:\Program Files\Common Files\Skype for Business
    Online\Modules\SkypeOnlineConnector\SkypeOnlineConnectorStartup.psm1:155 char:9
    +         throw $resources.DiscoveringEndpointFail
    +         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : OperationStopped: (Unable to disco...l endpoint URI.:String) [], RuntimeException
        + FullyQualifiedErrorId : Unable to discover PowerShell endpoint URI.

    Or, you might get this error if you managed to get the interactive logon to pop up first and then entered your credentials there:

    Get-CsOnlinePowerShellAccessToken : One or more errors occurred.
    At C:\Program Files\Common Files\Skype for Business
    Online\Modules\SkypeOnlineConnector\SkypeOnlineConnectorStartup.psm1:214 char:28
    +             $accessToken = Get-CsOnlinePowerShellAccessToken @params
    +                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [Get-CsOnlinePowerShellAccessToken], AggregateException
        + FullyQualifiedErrorId : System.AggregateException,Microsoft.Rtc.Management.OnlineConnector.GetPowerShellAccessTo
       ken

    There’s a huge amount of potential fixes offered, but for me it was one simple switch, which I found thanks to enterinit.com – use the -OverrideAdminDomain switch.

    Import-Module SkypeOnlineConnector
    $sfboSession = New-CsOnlineSession -UserName "[email protected]" -OverrideAdminDomain “yourtennant.onmicrosoft.com”
    Import-PSSession $sfboSession

    Really easy fix, but the errors really don’t make it sound like this could be your problem. Now the next time I try to connect, I’ll re-read my own blog post to remind me of this switch :)

    Note: I had to connect to this to make a Microsoft Teams change!

    How To Check What Files Are In Use On A Remote Windows Computer

    This one had me stumped for a while, and I even asked on Twitter with a large amount of replies (thanks everyone who did!) but none that I could get to work, or that weren’t overly complicated requiring the compiling of code.

    It’s easy locally to find out what files are open, and here’s a great article covering several free ways: https://www.winhelponline.com/blog/find-process-locked-file-openfiles-utility/

    None of those worked remotely for me in a Windows 10 environment – but I thought Handle from the SysInternals Suite would be the best bet. Running locally, it did exactly what I wanted – a giant list of every file open, and say what process had it open (like WinWord.exe).

    Using PSExec with Handle however, causes it to forever wait for something. On the remote PC, it definitely launches handle.exe and handle64.exe, but they have no activity. I thought it might be the EULA prompt getting stuck somewhere, but there’s a registry setting that will autoaccept that prompt, and putting that in place didn’t help (but I did check locally and it was skipping the EULA agree prompt. Thanks to this blog post explaining the reg key required https://peter.hahndorf.eu/blog/post/2010/03/07/WorkAroundSysinternalsLicensePopups which was:

    reg.exe ADD HKCU\Software\Sysinternals /v EulaAccepted /t REG_DWORD /d 1 /f

    I added this to the remote machine under both the user logged on to the remote device, and the user I was connecting as, with no luck.

    After a bunch of Googling and trying solutions, I ended up finding this thread on stackoverflow. One of the answers with 0 votes (which can be easily overlooked) was a PowerShell script, invoking the command remotely, from a user called A.D – thank you A.D!

    I’ve barely modified it for my purposes, but if this helps you please go vote his post up on stackoverflow (I did but don’t have enough rep for it to show):

    $computerName = 'computername'
     $stringtoCheck = 'test' # String you want to search for, can be blank by removing text between '' quotes
     $pathtoHandle = 'c:\temp\handle.exe' #location of handle.exe on the remote server.
     Invoke-command -ComputerName $computerName -Scriptblock {
         param(
         [string]$handles,
         [string]$stringToCheck
         )
          "$handles /accepteula $stringToCheck" | Invoke-Expression 
         } -ArgumentList $pathtoHandle,$stringtoCheck

    The script requires handle.exe to be on the remote computer under C:\Temp, and that of course you have admin rights to the remote PC with the account this script is being run. Beyond that, it’ll show back all open files that match the variable set in $stringtocheck across any of the results – it could be the path, the process that has the file open etc.

    Why would you want to do this remotely at all? You might be troubleshooting something to do with open files and not want to interrupt the user. You might have a reason to see what files the user has open, or maybe it’s a locked PC and the user left.

    Hope this helps others as it was a much harder task to accomplish than I assumed.