InvalidArgument when Invoking Expression containing get-date - powershell

Whenever i try to invoke the following String
$log = "Get-EventLog -LogName " + $name + " -EntryType Error -After " + $datum + " | Format-List -Property TimeWritten,Message"
i get an error
+ ... gName Application -EntryType Error -After 03/08/2021 11:51:37 | Forma ...
+ ~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Get-EventLog], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.GetEventLogCommand
The $datum variable is filled like this
$datum = $((get-date).AddDays(-10))

As the error indicates, $datum expands to a string with a space in between the date and time parts - you need to add quotes around it.
Instead of showing you how to quote it, I'm gonna show you a better way:
Use splatting instead of Invoke-Expression:
$logParams = #{
LogName = $name
EntryType = 'Error'
After = $datum
}
Get-EventLog #logParams |Format-List -Property TimeWritten,Message
Now we don't need to worry about quoting or qualifying parameter argument values, PowerShell binds them correctly for us.

Related

Powershell runbook errors after update to OMS New Query Language

It turned out that after migration to New Query Language in OMS also WebhookData structure for alert has changed.
I was trying to change my powershell script (which is called at OMS alert via Automation Account runbook) and it works locally for the Input I've copied for some previous (updated) alerts but I cannot get it to work in Automation Account.
Can anyone tell why this don't work in Runbook but works locally?
Here is my runbook input: https://jsonblob.com/adf5e1c2-c948-11e7-af9e-2d30dd548850
I took it from here:
Script:
$WebhookData = '{"WebhookName":"OMS Alert Remediation b64051e5-b9c5-44db-b74f-51d7cf5a9df2","RequestBody":"{\"WorkspaceId\":\"8547d992-7979-46d0-912b-8fffeabe1c8b\",\"AlertRuleName\":\"SRVR slow response - TEST\",\"SearchQuery\":\"ApplicationInsights | where TelemetryType == \\\"Request\\\" and Computer startswith_cs \\\"SRVR\\\" and Computer != \\\"SRVR-DEVEL\\\" | summarize AggregatedValue = avg(RequestDuration) by bin_at(TimeGenerated, 4m, datetime(2017-11-12T10:32:00.0000000)), Computer | sort by TimeGenerated desc\",\"SearchResult\":{\"tables\":[{\"name\":\"PrimaryResult\",\"columns\":[{\"name\":\"TimeGenerated\",\"type\":\"datetime\"},{\"name\":\"Computer\",\"type\":\"string\"},{\"name\":\"AggregatedValue\",\"type\":\"real\"}],\"rows\":[[\"2017-11-12T10:28:00Z\",\"SRVR-06\",1535.2852333333333],[\"2017-11-12T10:24:00Z\",\"SRVR-06\",718.91287857142856]]}]},\"SearchIntervalStartTimeUtc\":\"2017-11-12T10:27:00Z\",\"SearchIntervalEndtimeUtc\":\"2017-11-12T10:32:00Z\",\"AlertThresholdOperator\":\"Greater Than\",\"AlertThresholdValue\":700,\"ResultCount\":2,\"SearchIntervalInSeconds\":300,\"LinkToSearchResults\":\"https://8547d992-7979-46d0-912b-8fffeabe1c8b.portal.mms.microsoft.com/#Workspace/search/index?_timeInterval.intervalEnd=2017-11-12T10%3a32%3a00.0000000Z&_timeInterval.intervalDuration=300&q=ApplicationInsights%20%20%7C%20where%20TelemetryType%20%3D%3D%20%5C%22Request%5C%22%20and%20Computer%20startswith_cs%20%5C%22SRVR%5C%22%20and%20Computer%20!%3D%20%5C%22SRVR-DEVEL%5C%22%20%20%7C%20summarize%20AggregatedValue%20%3D%20avg(RequestDuration)%20by%20bin_at(TimeGenerated%2C%204m%2C%20datetime(2017-11-12T10%3A32%3A00.0000000))%2C%20Computer%20%20%7C%20sort%20by%20TimeGenerated%20desc\",\"Description\":\"W runbook-u testujemy powershell workflow, zamiast powershel script \",\"Severity\":\"Critical\"}","RequestHeader":{"Connection":"Keep-Alive","Accept":"application/json","Host":"s2events.azure-automation.net","User-Agent":"OMS-Remediation","x-ms-request-id":"9be297e0-c196-45c0-ad23-3b513e165648"}}'
$Input = ConvertFrom-Json $WebhookData
$RequestBody = ConvertFrom-Json -InputObject $Input.RequestBody
$Computers = New-Object -TypeName System.Collections.ArrayList
foreach($row in $RequestBody.SearchResult.tables[0].rows)
{
$Computers.Add($row[1]) > $null
}
foreach ($Computer in $Computers | Get-Unique)
{
'Computer: ' + $Computer
Invoke-Command -Credential $c -ComputerName $Computer -ScriptBlock {
$date = Get-Date | Out-File -Append 'C:\tmp\test_log.txt'
}
}
And those are errors in Azure Portal:
1.
ConvertFrom-Json : Invalid JSON primitive: .
At line:9 char:10
+ $Input = ConvertFrom-Json $WebhookData
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [ConvertFrom-Json], ArgumentException
+ FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.ConvertFromJsonCommand
2.
ConvertFrom-Json : Cannot bind argument to parameter 'InputObject' because it is null.
At line:10 char:46
+ $RequestBody = ConvertFrom-Json -InputObject $Input.RequestBody
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [ConvertFrom-Json], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ConvertFromJs
onCommand
3.
Cannot index into a null array.
At line:14 char:17
+ foreach($row in $RequestBody.SearchResult.tables[0].rows)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArray
As you noticed the query language has changed. We have published a new sample here on how to parse results from the new language.
Look here:
https://learn.microsoft.com/en-us/azure/log-analytics/log-analytics-alerts-actions#webhook-actions
Have a look at the new sample and see if you can use that to parse the records.
Thanks,
Anirudh

Starting/Stopping AWS EC2 Instances using AWS Powershell Tools

I am attempting to write two separate scripts. One script determines which EC2 instances are stopped, it starts them and documents what it starts to a text file.
The second script will read the text file and stop those instances. For debugging/simplicty sake I am starting out by combining the two scripts into a single script.
Here's my script:
$Instances = (Get-EC2Instance).instances
$start_instances = #()
$Instances | foreach {
$state = Get-EC2InstanceStatus -InstanceId $_.InstanceId -IncludeAllInstance $true
$state = $state.InstanceState.Name
if ($state -eq "stopped"){
$start_instances += $_.InstanceId
}
}
[System.IO.File]::WriteAllText("C:\users\myusername\desktop\so.csv", $($start_instances -join ','))
$shutdown_instances = [System.IO.File]::ReadAllText("C:\users\myusername\desktop\so.csv")
Write-Host "Press any key to continue ..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
Stop-EC2Instance -Instance $shutdown_instances
Starting and documenting what instances are running works fine. Its the stopping instances which is failing.
I'm getting the following error:
Stop-EC2Instance : Invalid id: "i-99edd755,i-8d647f58"
At C:\users\myusername\Desktop\aws-test.ps1:28 char:1
+ Stop-EC2Instance -Instance $shutdown_instances
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Stop-EC2Instance], AmazonEC2Exception
+ FullyQualifiedErrorId : Amazon.EC2.AmazonEC2Exception,Amazon.PowerShell.Cmdlets.EC2.StopEC2InstanceCmdl
Those instance IDs are indeed valid so I can't figure out why the heck its complaining. I was writing the instance IDs to a file via out-file and getting it via get-content but that seemed to have caused a different error.
I'm assuming the issue has something to do with the format of the data once i'm pulling it out of the text file.
Edit
So I've changed my script to:
$start_instances = $start_instances | Select-Object #{Name='Name';Expression={$_}}
$start_instances | Export-Csv -Delimiter ',' -NoTypeInformation -path C:\temp\instances.csv
$stop_instances = #(Import-Csv -path C:\temp\instances.csv)
$stop_instances | Stop-EC2Instance
But still get an error:
Stop-EC2Instance : No instances specified
At C:\temp\aws-test.ps1:22 char:19
+ $stop_instances | Stop-EC2Instance
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Stop-EC2Instance], AmazonEC2Exception
+ FullyQualifiedErrorId : Amazon.EC2.AmazonEC2Exception,Amazon.PowerShell.Cmdlets.EC2.StopEC2InstanceCmdlet
I've also tried:
Stop-EC2Instance -InstanceID $stop_instances
But that also dies:
Stop-EC2Instance : No instances specified
At C:\temp\aws-test.ps1:22 char:1
+ Stop-EC2Instance -InstanceId $stop_instances
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Stop-EC2Instance], AmazonEC2Exception
+ FullyQualifiedErrorId : Amazon.EC2.AmazonEC2Exception,Amazon.PowerShell.Cmdlets.EC2.StopEC2InstanceCmdlet
InstanceId parameter needs array.
You can declare an empty array first
$EC2Instance =#()
Then use Import-CSV and pipe it to append the empty array with each value from csv
Import-CSV C:\Temp\Instance.csv | Foreach-Object {$EC2Instance += $_.InstanceId}
echo $EC2Instance
$EC2instance will now have the required instance id's in an array
Then you can use it in the command
Stop-EC2instance -InstanceId $EC2instance
This worked for me.

Unexpected token error when I have the variable already defined

Simple script but can't figure out why I am getting the error : It should just write the machines that were successful to one text file and the failed to another.
Here is the error I am getting :
Unexpected token '$ip' in expression or statement.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : UnexpectedToken
$computers = Get-Content C:\temp\machines_no_rdp.txt
foreach($computer in $computers)
{
if((New-Object System.Net.NetworkInformation.Ping).Send("$computer",[int]1000).Address.IPAddressToString)
{
$computer
$ip = [System.Net.Dns]::GetHostByName($computer).AddressList.IPAddressToString
$computer + ";" $ip | Out-File C:\temp\Success.txt -Append
}
else{$computer + ";" + "Dead" | Out-File C:\temp\failure.txt -Append}
}
The error is trying to tell you it does know what to do with $ip. It does not care at this point whether it is a variable or not. It's a parsing error.
$computer + ";" $ip
should instead be the following ( in keeping with your coding practice.)
$computer + ";" + $ip

Argument errors with office 365 cmdlet

I'm having issues feeding variables into the New-MsolUser cmdlet. I'm getting the following error.
New-MsolUser : A positional parameter cannot be found that accepts argument 'â?UserPrincipalName ausertest#test.ie â?UsageLocation'.
At C:\users\test\Documents\test.ps1:148 char:1
+ New-MsolUser -DisplayName $TargetFullname â?"UserPrincipalName $TargetEmail â?" ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [New-MsolUser], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.Online.Administration.Automation.NewUser
The code I am using is:
$Source = "AnotherADUser"
$TargetFname = "New"
$TargetLname = "User"
$Target = "ausertest"
$TargetFullname = [string]::Concat($TargetFname ," ", $TargetLname)
$SourceEmail = (Get-ADUser $source -Property EmailAddress).EmailAddress
$SourceDomain = $SourceEmail.split("#")[1]
$TargetEmail = ([string]::Concat($Target , "#" , $SourceDomain))
New-MsolUser -DisplayName $TargetFullname –UserPrincipalName $TargetEmail –UsageLocation "IE" | Set-MsolUserLicense -AddLicenses "TESTINSTALL:EXCHANGESTANDARD"
This command works when I hardcode the details..
–UserPrincipalName and –UsageLocation use not the minus character but the
character with code 8211. Maybe it's fine but try to use the standard minus
instead, just to be sure.

New-Object cannot contain a dash (-) but "needs to"

I am creating a new object for export values to CSV:
New-Object -TypeName PSObject -Property #{
host_name = ($server.name).ToLower()
address = $IPAddress
host_is_collector = "no"
host-preset = "windows-server"
} | Select-Object host_name,address,host-preset | Export-Csv -Path $nConf_import_host_file
The problem is that one of the lines contains a dash (host-preset). I would ofcourse simply change it to an underscore, but my CSV needs this value to be a dash. I could also do a -replace on the entire csv after it has been created but that seems dirty.
Is there a way I can use dash here?
My error msg is:
Missing '=' operator after key in hash literal.
At Z:\Scripts\Testscripts\ScanServers_and_check_nagiosV7.ps1:336 char:16
+ host-preset <<<< = "windows-server"
+ CategoryInfo : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : MissingEqualsInHashLiteral
You simply need to treat the host-preset property name as a string by enclosing it in quotes:
New-Object -TypeName PSObject -Property #{ "host-preset" = "windows-server" }