1

I am trying to run the following script

$citrixServers = @('server1', 'server2' , 'server3')
$time = (get-date).AddDays(-16)
foreach ($citrixServer in $citrixServers) {'System' , 'Security' , 'Application'| ForEach-Object {Get-WinEvent -computerName $citrixServer  –FilterHashtable @{logname= $_; starttime=$time}}  | Export-Csv -Path 'd:\scripts\$citrixServer'EventLogs'}

This is creating the first csv file with server1's names and logs but is not moving on to the second servers name. The script does not stop running however it just seems like it stalls out.

Ideally the script will create individual csv files with the event logs for each server. I feel like I am missing something simple here

  • Its like its not moving to the next server its just that you're overwriting your CSV on each loop iteration – Santiago Squarzon Apr 15 '23 at 15:48
  • @SantiagoSquarzon I don't think it's overriding because the data in the CSV is all for server1 no data for any other servers – tryingToLearn10 Apr 15 '23 at 15:53
  • This is missing a closing quote, and you would need double quotes to interpret variables inside. `'d:\scripts\$citrixServer'EventLogs'` – js2010 Apr 15 '23 at 15:54
  • My bad, I didn't see you had `$citrixServer` as part of the CSV path. I would recommend you to form your path like this so the variable can expland: `| Export-Csv -Path "d:\scripts\${citrixServer}EventLogs"` – Santiago Squarzon Apr 15 '23 at 16:42

1 Answers1

0

I don't see anything particularly wrong with your code other than what js2010 mentioned in their comment, there is a syntax error in your path:

'd:\scripts\$citrixServer'EventLogs'

There is a missing closing quote ' and also variables can't expand in literal strings '...', those quotes should be double quotes "..." so $citrixServer can expand.

You could use Invoke-Command to parallelize your query though and the LogName key from -FilterHashtable can be LogName = <String[]> so there is no need for the inner loop:

$citrixServers = @('server1', 'server2' , 'server3')

Invoke-Command -ComputerName $citrixServers {
    Get-WinEvent -FilterHashtable @{
        LogName   = 'System', 'Security', 'Application'
        StartTime = (Get-Date).AddDays(-16)
    } | Select-Object prop1, prop2, ... # <= Can be used here to reduce the amount of memory and CPU usage in local server
} | Group-Object PSComputerName | ForEach-Object {
    $_.Group | Export-Csv -Path ('d:\scripts\{0}EventLogs' -f $_.Name)
}
Santiago Squarzon
  • 41,465
  • 5
  • 14
  • 37
  • So would this run all of the Get-WinEvent for all $citrixServers in parallel? Would this create the CSV files immediately (the original one I wrote creates the file then just writes to it as it goes) or will it not actually create the CSV till it is done grabbing all of the logs? I kicked off the script and haven't seen it start creating the CSV files yet. – tryingToLearn10 Apr 15 '23 at 17:43
  • @tryingToLearn10 yeah this runs in parallel, by default, 32 servers at the same time (if you want to do more than that you can use `-ThrottleLimit XX` and a higher number). As for writing to the CSV, if you weren't doing one CSV per server then it should start writing as soon as there are results but since you want one CSV per server it has to use `Group-Object` and that requires to collect all input before writing unfortunately – Santiago Squarzon Apr 15 '23 at 17:46
  • Any ideas how to be more efficient? The System, Security and Application Logs have a ton of logs in them. My original script above was running for about an hour and had just started going through the 'security' logs at that time. I like running the different servers in parallel to help with this. Can I do -ThrottleLimit 4 to limit the amount of CPU being used because it seems CPU is spiking to about 60-70% for this process trying to do the 16 different servers at once? – tryingToLearn10 Apr 15 '23 at 17:53
  • @tryingToLearn10 yeah for sure you can limit it to 4 servers at a time but note that everything that happens inside the scriptblock of `Invoke-Command` will consume the CPU of the remote servers not the local one, what is consuming CPU in the local server are all the logs coming from the remote servers and then grouping them and then exporting them and I don't think lowering the `-ThrottleLimit` will make that consume less CPU. Perhaps you should instead export all to a single CSV, also you already have a reference of the server each log belongs to with the `PSComputerName` property (column) – Santiago Squarzon Apr 15 '23 at 17:58
  • @tryingToLearn10 another way to have it consume less CPU would be to limit the log properties only to those of interest to you with `Select-Object` for example, select only `Message, Id, TimeCreated` instead of all, try this in your computer `Get-WinEvent -LogName Application -MaxEvents 1 | Select-Object *` and see which properties on that object are of interest to you then you can filter out all those that are irrelevant – Santiago Squarzon Apr 15 '23 at 18:01
  • Would I just use | Select-Object -Property X, X, X? Or would that be grabbing all of the data and THEN just grabbing those properties? Or is there a way when grabbing the data to just grab those properties? – tryingToLearn10 Apr 15 '23 at 18:13
  • @tryingToLearn10 see my update. put it inside the scriptblock of `Invoke-Command` so the remote hosts do that work instead of your local server. Also smaller objects travel faster thru the network ;) – Santiago Squarzon Apr 15 '23 at 18:15
  • 1
    This is awesome. Since I don't have all the extra columns it is running through so much faster now! Thank you! :) – tryingToLearn10 Apr 15 '23 at 18:20
  • @tryingToLearn10 awesome :) if this answer ends up being helpful please consider accepting it – Santiago Squarzon Apr 15 '23 at 18:21