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
Related
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
I get this error when running this script:
Exception calling "Matches" with "1" argument(s): "Value cannot be
null. Parameter name: input" At V:\compiler\shitter2.ps1:3 char:1
+ $tables = $regex.matches((GC v:\compiler\test.txt -raw)).groups.value
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ArgumentNullException
Here is the script code:
$Path = 'V:\compiler\po.htm'
[regex]$regex = "(?s)<TABLE ID=.*?</TABLE>"
$tables = $regex.matches((GC v:\compiler\test.txt -raw)).groups.value
ForEach($String in $tables){
$table = $string.split("`n")
$CurTable = #()
$CurTableName = ([regex]'TABLE ID="
([^"]*)"').matches($table[0]).groups[1].value
$CurTable += ($table[1] -replace "</B></TH><TH><B>",",") -replace "</?
(TR|TH|B)>"
$CurTable += $table[2..($table.count-2)]|ForEach{$_ -replace "</TD>
<TD>","," -replace "</?T(D|R)>"}
$CurTable | convertfrom-csv | export-csv "$CurTableName.csv" -notype
}
You probably forgot the access the entry using [1]:
$tables = $regex.matches((GC v:\compiler\test.txt -raw)).groups[1].value
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.
I have a list of hostnames from which I'd like to extract all AppLocker related eventlogs, especially the ones with level warning and/or error.
I crafted this script:
$ComputersToCheck = Get-Content 'X:\ListWithTheNames.txt'
foreach($OneHost in $ComputersToCheck)
{
try
{
$EventCollection = Get-WinEvent -LogName "Microsoft-Windows-AppLocker/EXE and DLL" -ComputerName $OneHost -Credential $CredentialFromUser
foreach ($SingelEvent in $EventCollection)
{
if($SingelEvent.LevelDisplayName -ne "Information")
{
$pathtosaveto = 'SomeFileName.txt'
$ResultString += $SingelEvent | Select Message,MachineName,UserId | Export-Csv -Path $pathtosaveto -Append
}
}
}
catch
{
//handling exceptions
}
}
This works for a while, but after a certain ammount of time I got an error:
Get-WinEvent : The remote procedure call failed
At X:\FileName.ps1:22 char:28
+ $EventCollection = Get-WinEvent -LogName "Microsoft-Windows-AppLocker/EX ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-WinEvent], EventLogException
+ FullyQualifiedErrorId : The remote procedure call failed,Microsoft.PowerShell.Commands.GetWinEventCommand
And right after the script start giving errors like this:
Get-WinEvent : The handle is invalid
At X:\FileName.ps1:22 char:28
+ $EventCollection = Get-WinEvent -LogName "Microsoft-Windows-AppLocker/EX ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-WinEvent], EventLogException
+ FullyQualifiedErrorId : The handle is invalid,Microsoft.PowerShell.Commands.GetWinEventCommand
My first thought was that it is related to the host the script try to reach, but the next in the list is the same type (Os, even the same model) as the previous.
I ran the script 3 times, and every time the output size was different (probably because not the same hosts were online with the same amount of logs).
The script should run against more than 700 hosts, to which a special account is needed which I prompt by the Get-Credential, store in a variable and pass it the the Get-WinEvent as a parameter.
To be honest I stuck with this issue, not really sure what cause this and why.
If anyone has an idea please share with me :)
Give this a try to attempt catching references to failed hosts and empty objects. You could write the exception received but I didn't include that in this to make the failedhosts file simple to read. Hope I got it right as I winged it and don't have a true case to test against.
$ComputersToCheck = Get-Content 'X:\ListWithTheNames.txt'
foreach($OneHost in $ComputersToCheck) {
try {
$EventCollection = Get-WinEvent -LogName "Microsoft-Windows-AppLocker/EXE and DLL" -ComputerName $OneHost -Credential $CredentialFromUser -ErrorAction Stop
if($EventCollection) {
foreach ($SingelEvent in $EventCollection) {
if($SingelEvent.LevelDisplayName -ne "Information") {
$pathtosaveto = 'SomeFileName.txt'
$ResultString += $SingelEvent | Select Message,MachineName,UserId | Export-Csv -Path $pathtosaveto -Append
}
}
} else {
Out-File -InputObject $($OneHost + " Empty Event Collection") -FilePath "C:\FailedHosts.txt" -Append -Encoding ascii
}
}
catch {
Out-File -InputObject $($OneHost + " Failed Connection") -FilePath "C:\FailedHosts.txt" -Append -Encoding ascii
}
}
I want to execute below code in the either local or remote machine whith current user.
$BackUpSqlAgentAndRemoveOldbackup = {
param([string]$AppServer,[string]$SqlInstance,[string]$BackupShare,[string]$alias)
[Environment]::UserName #I got same user name in all cases.
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.Smo') | Out-Null
$server = New-Object ('Microsoft.SqlServer.Management.Smo.Server') $SqlInstance
$backupName = 'SqlAgentJob_' + $SqlInstance + '_' + (Get-Date –format ‘yyyyMMdd_HHmm’) + '_' + $alias + '.sql'
$backupPath = join-path $BackupShare $backupName
$oldBackups = Get-ChildItem $backupShare | where { ( $_.name -like 'SqlAgentJob_*.sql' ) }
$server.JobServer.Jobs.Script() | Out-File -filepath $backupPath
foreach ( $item in $oldBackups ) { remove-item $item.fullName }
}
the #argList is
#('hafcapp-1', 'hafcsql-1', '\\Host5FileSrv\Backup\test','auto')
I notice that
this one, it works well (no -comupterName and -session)
Invoke-Command -ScriptBlock $BackUpSqlAgentAndRemoveOldbackup -argumentList $argList
this one, it throw execption (I also tried "-session", get same result)
Invoke-Command -computerName localhost -ScriptBlock $BackUpSqlAgentAndRemoveOldbackup -argumentList $argList
the exception is as below, it seems the it can not access the folder.
Cannot find path '\\Host5FileSrv\Backup\test' because it does not exist.
+ CategoryInfo : ObjectNotFound: (\\Host5FileSrv\Backup\test:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
You cannot call a method on a null-valued expression.
+ CategoryInfo : InvalidOperation: (Script:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Cannot bind argument to parameter 'Path' because it is null.
+ CategoryInfo : InvalidData: (:) [Remove-Item], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.RemoveItemCommand
does anyone know how can I do if I want to add computerName or session?
(notes:[Environment]::UserName return identical user)
You have run into the double hop problem. Your credentials can be transferred to the next machine (first hop), but no further (second hop). This means that you can't use the credentials of the machine where you are executing Invoke-Command on, the remote machine (localhost) to connect to a file share (\Host5FileSrv\Backup). Even if you use localhost as computername, it is still remoting. A solution could be CredSSP. See here and here for more information.
This looks like a "second hop" remoting problem, and you'll need to configure WinRM on the computers involved to use CredSSP
http://msdn.microsoft.com/en-us/library/windows/desktop/ee309365(v=vs.85).aspx