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 “admin@contoso.com” -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 "admin@contoso.com"
    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

    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 "admin@contoso.com" -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 {
          "$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.

    Migrate a Single Mailbox Out of a Exchange Online Migration Batch

    A few posts on this since it’s what I’m working on :)

    It is possible to sync all your mailboxes from Exchange On-Prem to Exchange Online as a single batch, and then complete individual items – but it’s not obvious that this is even possible.

    Normally if you start a migration, you can choose multiple mailboxes or use a CSV file to specify which accounts to start migrating – while specifying the option to manually complete the batch, so the actual migration happens when you want it to:

    The problem is, once you’ve fixed any problems that arise and mailboxes are in a ‘synced’ state, there’s no visible way to complete a single mailbox – just the whole batch. That may not be what you want to do. You could work out a way to create a separate batch for every single mailbox you’re migrating, but there’s also a way to complete one mailbox at a time.

    In PowerShell, once you’ve connected to Exchange Online, you can run the a command to see all the mailboxes syncing, and their status:


    If a mailbox is ready to be finalised, it should have the status of ‘Synced’. This is different to the status of ‘Completed’, which occurs once the mailbox has been fully migrated across.

    To trigger the completion of a single mailbox in a batch, use this PowerShell command:

    Set-MoveRequest -Identity “mailbox name” -CompleteAfter 1

    The mailbox will then do it’s final syncing and complete, without affecting the other jobs in the same batch. The -CompleteAfter parameter is supposed to set the delay before the request is completed in date/time format, but using the value ‘1’ seems to immediately trigger this.

    Now you can do a single batch job, and selectively complete mailboxes as you choose – easy! 

    (Note that there was an old method of doing the above by setting the variable SuspendWhenReadytoComplete to $false which no longer works)