PowerShell - Office365 Calendar REST API v1.0: Search by Subject - rest

I am trying to use PowerShell to query a group calendar and return only a subset of the events based on a specific string in the Subject field.
Currently, I can use the following and get a listing of all of the events:
$events = Invoke-RestMethod -Uri "https://outlook.office365.com/api/v1.0/users/$calendar/calendarview?startDateTime=$(Get-Date)&endDateTime=$((Get-Date).AddDays(1))" -Credential $cred | foreach-object{$_.Value}
$events | Select-Object -Property Subject,Start,End | fl
This is where I get stuck. I am trying to filter these results to where I only return results where Subject -like '*string*'
However, I just cannot seem to get that to work on the Invoke-RestMethod line...
Any help would be GREATLY appreaciated.
Bonus appreciation to anyone who can take the results of the Start and Stop times from this:
2016-04-25T13:00:00Z
to this:
4/25/2016
For reference, I have already tried this:
Get-Date $events.Start -Format 'MM/dd/yyyy'
Which gives this error:
Get-Date : Cannot convert 'System.Object[]' to the type
'System.DateTime' required by parameter 'Date'. Specified method is
not supported.

Because your using a CalendarView (which is a filter of sorts) you can't apply another filter at the REST level so just filter the results eg
$events | Where-Object {$_.Subject -match 'string'} | Select-Object -Property Subject,Start,End | fl
or if you want to use wildcards
$events | Where-Object {$_.Subject -Like '*string*'} | Select-Object -Property Subject,Start,End | fl
With the Start Stop time just CAST them eg
$events | % {([DateTime]$_.Start).ToString("MM/dd/yyyy")}
Cheers
Glen

Related

Syntax to let PowerShell read an object name based on current month name

I am trying to let PowerShell filter a number of objects from a cmdlet and pick an object that has a specific name format.
The name format is always going to be same like below:
current Month Name + Year + Workstations
For example the format for current month looks like below:
August 2021 Workstations
I tried the below but didn't succeed getting the desired output.
$currentMonth =
(Get-UICulture).DateTimeFormat.GetMonthName((Get-Date).Month.ToString())
$LatestSUG =
Get-CMSoftwareUpdateGroup |
Select-Object LocalizedDisplayName |
Where-Object -Property LocalizedDisplayName -EQ '$currentMonth'
The cmdlet is Get-CMSoftwareUpdateGroup
The object name I am trying to filter is LocalizedDisplayName
Thanks very much for any help on this.
Try removing the single quote around $currentMonth and see if that works better for you.
$currentMonth = (Get-UICulture).DateTimeFormat.GetMonthName((Get-Date).Month.ToString())
$LatestSUG = Get-CMSoftwareUpdateGroup | Select-Object LocalizedDisplayName | Where-Object -Property LocalizedDisplayName -match $currentMonth
Instead for equality you should check if the LocalizedDisplayName matches the $CurrentMonth ... like this maybe:
$currentMonth =
(Get-UICulture).DateTimeFormat.GetMonthName((Get-Date).Month.ToString())
$LatestSUG =
Get-CMSoftwareUpdateGroup |
Where-Object -Property LocalizedDisplayName -Match $currentMonth

PowerShell referencing object in a pipeline

I'm struggling with passing objects in a pipeline.
I have been going round the problem converting them to strings, but that cannot be the most efficient way of doing things.
$mapi = (Get-CASMailbox -Identity $user | fl mapiEnabled | Out-String ).Split(':')[-1]
if ($mapi -match "True") {
Set-CASMailbox -Identity $User -MAPIEnabled $false
}
I really want to directly access the bool returned instead of converting it to string
Similarly, I have been using below to do a for loop:
$groups = (Get-DistributionGroup | fl name | Out-String -Stream ).Replace("Name : ", "")
foreach ($group in $groups) {
echo $group
}
Both examples are from Exchange Online, below one more universal:
if (((Get-NetIPInterface -InterfaceAlias $adapters -AddressFamily Ipv4 | fl dhcp | Out-String -Stream ).Trim() -ne "").Replace("Dhcp : ","") -match "Disabled") {
echo disabled
}
I just wanted to take a second to see if I can help you understand what is happening in the pipeline and why #mathiasR.Jessen and #AdminOfThings comments will help you.
$mapi = (Get-CASMailbox -Identity $user | fl mapiEnabled | Out-String ).Split(':')[-1]
Breaking down that this line of code does:
Get-CASMailbox is going to return an object with multiple properties. Format-List (fl) is still going to return an object, but now it has been formatted so it's less malleable. Out-String is going to transform that formatted list into a single string. Putting those commands in parentheses runs them and allows you to execute a method on the resulting string object.
Using the same concept, we can use the parenthesis to execute the Get-CASMailbox command and get the singular property you are looking for:
$mapi = (Get-CASMailbox -Identity $user).mapiEnabled
Now we have set $mapi to the value of the mapiEnabled property returned by the command.
Hope this helps!

Extracting part of a host name with select-object

I have a simple powershell function where I provide the log type and event and it scans all of our SQL servers. it works except the host name is returned as hostname.domain.local. I want it to return just the host name. I've tried machinename.split('.') and substring and it won't work. I've tried putting the select-object into a separate variable and was going to join it with the rest of the columns, but it takes too long to run.
Here is my sample scrap code i'm testing with before I change my function along with the commented out parts that didn't work. Looked around and found lots of resources about the commands, but they don't work when I try to use them in my script.
The error I keep getting is A positional parameter cannot be found that accepts argument '. '.
$servers = Get-Content -literalpath "C:\temp\sql_servers3.txt"
#$server
#$result =
ForEach($box in $servers) {Get-Eventlog -ComputerName $box -LogName
application -After 1-4-2018 -Entrytype Error | Where {$_.source -notin
'Perfnet','Perflib', 'ntfs', 'vss'}| select-object -property MachineName}
#$result_Host_name = select-object -inputobject $result -property
'MachineName'
#'TimeGenerated', 'MachineName'.Split('.')[1], 'EventID','message'}
#| Where {$_.source -notin 'Perfnet','Perflib', 'ntfs', 'vss'} 0
#return $result_Host_name
What you are looking for is a "Calculated Property" when using Select-Object.
| Select-Object #{n='HostName';e={($_.MachineName -split '\.')[0]}}

Powershell search by single and multiple keyword

I have some commands below that do not give any output when looking for specific keywords in Windows Logs using PowerShell.
Get-WinEvent -FilterHashtable #{LogName="Application"} | Select-String "Information"
However, if I only run Get-WinEvent -FilterHashtable #{LogName="Application"}, there are many entries with Information keyword. Select-String -pattern "Information" also does not work.
Ideally I'd like to search for multiple keywords in the above scenario.
You need to do:
Get-WinEvent -FilterHashtable #{LogName="Application"} | ? { $_.leveldisplayname -eq 'Information' }
The Information you're looking for is a property of the object. The Get-WinEvent cmdlet returns a collection of objects, so you need to add the Where-Object or ? to filter on the LevelDisplayName object property.
To answer your new questions:
The leveldisplayname is going to be Information, Error or Warning. You can add either of these or use logic to combine them. In order to search for keywords in a message, using a regex is probably the best approach:
Get-WinEvent -FilterHashtable #{LogName="Application"} | ? message -imatch "keyword1"
To search multiple keywords, you can modify the regex using the OR | operator:
Get-WinEvent -FilterHashtable #{LogName="Application"} | ? message -imatch "keyword1|keyword2|foo|bar"
If you wanted to search for all Error messages containing "foo" or "bar" you could do;
Get-WinEvent -FilterHashtable #{LogName="Application"} | ? { ($_.message -imatch "foo|bar") -and ($_.leveldisplayname -eq 'Error') }

Powershell pipeline - Retrieve outputs from first cmdlet?

I am trying a few things in Powershell and what I don't manage to achieve is the following (in Exchange):
Get-User | Get-MailboxStatistics
But in the output I would like some fields/outputs from the "Get-User" cmdlet and some fields/outputs from the "Get-MailboxStatistics" cmdlet.
If anyone has an answer, I have searched the web but with no success as I've had difficulties explaining it in a few words.
Thanks in advance for your help.
Start with the execution of one cmdlet, pipe the results to Foreach-Object and then save a reference to the current object ($user), now execute the second command and save it in a variable as well. Create new object with properties from both objects.
You also need to filter users that have mailboxes, use the RecipientTypeDetails parameter.
$users = Get-User -RecipientTypeDetails UserMailox
$users | Foreach-Object{
$user = $_
$stats = Get-MailboxStatistics $user
New-Object -TypeName PSObject -Property #{
FirstName = $user.FirstName
LastName = $user.LastName
MailboxSize = $stats.TotalItemSize
ItemCount = $stats.ItemCount
}
}
I don't know if it is the best or optimal solution, but you certainly do it by saving actual user to variable in foreach:
$users = Get-User
$users | % { $user = $_; Get-MailboxStatistics $_ | %
{
"User name:{0} - some mailbox statistics: {1}" -f $user.SomePropertyOfUser, $_.SomePropertyOfMailbox
}
}
The first step (saving users into separate variable) is required only when working with Exchange cmdlets - as mentioned here, you cannot nest Exchange cmdlets in foreach...
This error is caused when executing the Exchange cmdlets through PowerShell remoting, which do not support more than one pipeline running at the same time. You may see this error when you pipe the output from a cmdlet to foreach-object, which then runs another cmdlet within its scriptblock.
$users = Get-User -RecipientTypeDetails UserMailbox
$users | Foreach-Object{ $user = $_; $stats = Get-MailboxStatistics $user.DistinguishedName; New-Object -TypeName PSObject -Property #{FirstName = $user.FirstName; LastName = $user.LastName;MailboxSize = $stats.TotalItemSize;ItemCount = $stats.ItemCount }}
I've had to add a specific field in input of Get-MailboxStatistics because remotely, I was having:
The following Error happen when opening the remote Runspace: System.Management.Automation.RemoteException: Cannot process argument transformation on parameter 'Identity'. Cannot convert the "gsx-ms.com/Users/userName1" value of type "Deserialized.Microsoft.Exchange.Data.Directory.Management.User" to type "Microsoft.Exchange.Configuration.Tasks.GeneralMailboxOrMailUserIdParameter".
Anyway, thank you both #Jumbo and #Shay-levy
Get-ADUser -identity ADACCOUNT | Select-object #{Name="Identity";Expression={$_.SamAccountName}} | Get-MailboxStatistics
For some reason the Identity parameter doesn't take pipelne input by value, only by property name. So in order to get it to work you can change the name of piped in data to match the parameter name of Identity. Then Get-MailboxStatistics finally knows how to treat the data your feeding it via the pipeline.