PowerShell: Determine The Last Day of a Month (incl. the Day of the Week)

Except for February, it is possible to hard-code the last day of each month since the number of days is fixed. However, you still have to determine the day of the week separately.

Rather than doing this manually, the code snippet below should do the trick:

#determine the last day of the first quarter of the year 2020 including the day of the week (Jan to March)


$date = Get-Date "2020-01-01"
$qtr2 = $date.AddMonths(3)
$qtr2
#Mittwoch, 1. April 2020 00:00:00


$qtr2FirstDay = Get-Date -Month $qtr2.Month -Day 1 -Year $qtr2.year;
$qtr2FirstDay
#Mittwoch, 1. April 2020 23:56:43


$qtr1LastDay = $qtr2FirstDay.AddDays(-1);
$qtr1LastDay
#Dienstag, 31. März 2020 23:56:43

Windows PowerShell 5.1, PowerShell Core 6.x & (slipped Jan 2020 GA) PowerShell 7

Windows PowerShellPowerShell Core 6.x (6.0, 6.1 and 6.2) is Microsoft’s initial attempts to bring the veteran Windows PowerShell outside of its core Windows ecosystem to Linux and macOS based platforms. It is designed to run side-by-side (SxS) when installed on supported Windows operating systems where the feature set is not on par with Windows PowerShell due to its high dependency on Windows specific components and the full .NET Framework stack.

This has not stopped PowerShell enthusiasts from writing scripts that already utilize new PowerShell Core functionality (but often not properly “labelled”). Besides breaking backwards compatibility, such code may pose a real risk if not closely inspected first for suitability of use. This is because many are either delivered with sparse or incomplete documentation and neither follow good software development practices nor have security baked right in i.e. lack of safety nets* due to “fire fighting” nature in the real world, for instance.

Although it now looks like the planned January 2020 GA of PowerShell 7 per the PowerShell team has slipped – with a possible yet unannounced Release Candidate 2 (RC2) – you can start preparing for the transition to the “harmonized” P7 version based on the .NET Core 3.1 LTS by working on the last Release Candidate v7.0.0-rc.1 (2019-12-16) posted on GitHub.

* version check, try/catch blocks, advanced functions, etc.

Next Release: PowerShell 7 / .NET Core 3.0

Windows PowerShellFollowing the March 2019 release of PowerShell Core 6.2, the Microsoft PowerShell team announced that Windows PowerShell 5.1 and the PowerShell 6.x Core version will converge into a single version known as PowerShell 7.

Apart from automation across Linux, macOS and Windows, a very high degree of compatibility with existing Windows PowerShell (5.x) modules can be achieved with the next release of PowerShell 7 by leveraging changes in .NET Core 3.0 (such as the return of Out-GridView in Windows).

Unlike the current PowerShell Core support lifecycle, PowerShell 7 will have both LTS (Long Term Servicing) and non-LTS releases which aligns closely with the .NET Core support lifecycle.

PowerShell 7 in Windows is planned to ship as a side-by-side feature with Windows PowerShell 5.1. No information around the PS7 release date in a future version of Windows 10 or Windows Server is available though as the release timelines of .NET Core and Windows do not align.

According to Microsoft, May (2019?) is the likely first Preview release of PowerShell 7 with the generally available (GA) some time after the GA of .NET Core 3.0.

 

 

#powershell #activedirectory *-AD* Cmdlets

Besides the common -Identity parameter, most cmdlets from the Active Directory Module for PowerShell support the -Filter parameter.

If you encounter the following error even though the syntax is correct,

PS C:\> Get-ADGroup -Identity *
Get-ADGroup : Cannot find an object with identity: * under: ‘DC=swissitpro,DC=com’
At line;1 char:1
+ Get-ADGroup -Identity *
+ CategoryInfo : ObjectNotFound: (*:ADGroup) [Get-ADGroup], ADIdentityNotFoundException

simply replace -Identity with -Filter and try again. Obviously this makes sense (and is the only way) to get a list of all defined active directory security and distribution groups in the organisation.

 

 

#powershell TIP: Local vs Remote Background Jobs

It is common to use Start-Job to run a  background job against a remote machine via the -ScriptBlock parameter:

Start-Job -ScriptBlock { param($computer) Get-EventLog -LogName system -ComputerName $computer } -ArgumentList $computer

However, this always runs as a local BackgroundJob, consumes local resources and can be very slow.

Instead, consider using the -AsJob parameter of Invoke-Command to run the task as a RemoteJob on a remote host via -ComputerName i.e.

Invoke-Command -AsJob -ComputerName $computer -ScriptBlock { Get-EventLog -LogName system }

#powershell #skype4b Trunk Configuration

With New-CsTrunkConfiguration, a trunk can be created at the Global (default), site or pool (service) scope for a PSTN service from a PSTN gateway, IP-Public Branch Exchange (PBX) to a Session Border Controller (SBC) at the service provider.

Correspondingly, it is a simpe matter to run Get-CsTrunkConfiguration to get back a list of available trunk configuration information. However, executing this cmdlet with just the name of the trunk will fail:

PS > Get-CsTrunkConfiguration -Identity trunkName
Get-CsTrunkConfiguration: Cannot get item at this location. Get item at scopes: “Global, Site, Service”
Parameter name: Identity
At line:1 char:1
+ Get-CsTrunkConfiguration -Identity trunkName
+ ~~~
+ CategoryInfo : InvalidArgument: (Tag: trunkName:XdsIdentity)
[Get-CsTrunkConfiguration, ArgumentException
+ FullyQualifiedErrorId :BadLocation, Microsoft. Rtc.Management.Internal.GetCsTrunkConfigurationCmdlet

The solution is to always prefix the name with the trunk’s scope i. e.

Get-CsTrunkConfiguration site:trunkName

#powershell #skype4b PSTN Usage, Voice Policy & Route

Think of PSTN usage records as something which specify a class of call permitted in an organisation such as internal, local or international. Such records are used to associate with voice policies* and routes** to dictate usage of specific (gateway) routes by authorised users. A call can only be successful when a dialed number matches a route in a PSTN Usage.

A list of Public Switched Telephone Network, PSTN Usage records is accessible using the appropriately named Get-CsPstnUsage cmdlet. Because Global is the only identity applicable (to PSTN usages), you can basically retrieve available records via (Get-CsPstnUsage).Usage.

It is not possible to inspect the relationship between PSTN Usage, voice policy or route with a statement like Get-CsPstnUsage CH_Zurich. To resolve this, use Get-CsVoiceRoute or Get-CsVoicePolicy.

* assigned at the site or user scope where each voice policy must be linked to at least one PSTN usage record
** routes are assigned to telephone numbers

REFERENCE
Configure voice policies, PSTN usage records, and voice routes in Skype for Business
PSTN usage records in Lync Server 2013

#powershell #skype4b #msexchange List Mismatched Mail(box) Enabled User Email and SIP Addresses

#requires -version 3.0
###############################################################################
# Copyright (c) 201x-2018 leedesmond.com
# All Rights Reserved. Use at your own risk and responsibility.
# Version 1.00
#
# Get a list of mismatched mail(box) enabled user email and SIP addresses
# without SkypeforBusiness or Exchange Server PowerShell modules
#
###############################################################################
# Continue reading “#powershell #skype4b #msexchange List Mismatched Mail(box) Enabled User Email and SIP Addresses”

#powershell #skype4b Get List of Not Enabled Skype for Business Users (Without #skype4b Cmdlets)

#requires -version 3.0
###############################################################################
# Copyright (c) 201x-2018 leedesmond.com
# All Rights Reserved. Use at your own risk and responsibility.
# Version 1.00
#
# Get a list of not enabled Skype for Business Users (without SkypeForBusiness
# Module Cmdlets)
#
###############################################################################
# Continue reading “#powershell #skype4b Get List of Not Enabled Skype for Business Users (Without #skype4b Cmdlets)”