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.
Related
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.
I am trying to create a bulk of distribution lists, as instructed on technet site.
https://gallery.technet.microsoft.com/How-to-Bulk-create-6be6c82f#content
but i am encountering some errors while trying to work with the script they offered there.
This is my CSV
https://imgur.com/CXGoRIv
And this is the script of working with:
# Create Bulk Distribution Groupsmake CSV file
Import-Csv "C:\Users\user\Desktop\PowerShell\CreateDistributionLists.csv" | foreach {
New-DistributionGroup -Name $_.name -DisplayName $_.displayname –Alias $_.alias -PrimarySmtpAddress $_.PrimarySmtpAddress -RequireSenderAuthenticationEnabled ([boolean] $_.RequireSenderAuthenticationEnabled)}
when i launch the script, i get this error:
A positional parameter cannot be found that accepts argument '->RequireSenderAuthenticationEnabled'.
+ CategoryInfo : InvalidArgument: (:) [New-DistributionGroup], >ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,New->DistributionGroup
+ PSComputerName : server.domain.com
Please Assist.
<<<< UPDATE >>
Edited script as suggested by Matias ( thanks buddy ).
Now i face the same error when launching.
A positional parameter cannot be found that accepts argument '->RequireSenderAuthenticationEnabled:'.
+ CategoryInfo : InvalidArgument: (:) [New-DistributionGroup], >ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,New-DistributionGroup
in the csv , im typing "false" or "FALSE" under the "RequireSenderAuthenticationEnabled" column ,same as initially shown in the screenshot i attached.
To be RequireSenderAuthenticationEnabled to always be false...that will do the work for me, if you can help me edit the script to always be false in this, that will be awesome also, aslong as it work.
for reference, here is the script the way i use it now:
# Create Bulk Distribution Groupsmake CSV file
Import-Csv "C:\Users\user\Desktop\PowerShell\CreateDistributionLists.csv" | foreach {
New-DistributionGroup -Name $_.name -DisplayName $_.displayname –Alias $_.alias -PrimarySmtpAddress $_.PrimarySmtpAddress -RequireSenderAuthenticationEnabled:$([bool]::Parse($_.RequireSenderAuthenticationEnabled))}
<<< UPDATE SEP-03-2019 >>>
i have changed the script as suggested here to the following:
# Create Bulk Distribution Groupsmake CSV file
Import-Csv "C:\Users\user\Desktop\PowerShell\CreateDistributionLists.csv" | foreach {
New-DistributionGroup -Name $_.name -DisplayName $_.displayname –Alias $_.alias -RequireSenderAuthenticationEnabled $false}
Still i am getting the following error:
[PS] C:\users\user\Desktop\PowerShell>.\CreateDistributionLists.ps1
A positional parameter cannot be found that accepts argument '->RequireSenderAuthenticationEnabled'.
+ CategoryInfo : InvalidArgument: (:) [New-DistributionGroup], >ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,New-DistributionGroup
+ PSComputerName : server.domain.com
Any suggestion ?
Thanks.
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
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
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.