2016-09-12 2 views
0

Я написал несколько сценариев PowerShell для сбора статистики с Windows-машины. Первый из них касался сбора CPU, использования памяти и т. Д. Через определенные промежутки времени. Что хорошо работает. Я написал еще одно, что в основном проверяет LastAccessTime для файлов и создает CSV, код ниже:Ищете лучший способ писать CSVs

$dest="C:\users\Administrator\Documents\filelist.csv" 
[email protected]() 
$source="x:\" 
$count=0 

Get-ChildItem -Recurse $source | foreach{ 

$csvdata += New-Object PSObject -Property @{FileName=$_.FullName;DateAccessed=($_.LastAccessTime).ToShortDateString()} 

$csvdata|Export-Csv $dest -notype 

$count+=1 
$count 

} 

Хорошо так, если я продолжать добавлять вещи $csvdata и только файл экспорта, когда цикл заканчивается, то есть возможность, я мог бы потерять данные, если сценарий заканчивается из-за некоторой ошибки или чего-то еще. Поэтому вместо этого я экспортирую его в цикле, как показано в коде. Но это также означает, что $csvdata будет продолжать увеличиваться в размерах, и это означает, что у него будет объем памяти, который может вырасти до мегабайта или даже больше.

Есть ли способ сбросить эти данные в CSV, пустой $csvdata переменная, не влияя на результаты? Надеюсь, это имеет смысл.

+0

'сценарий заканчивается из-за некоторой ошибки или чего-то еще - что именно происходит? Я думал, что PowerShell продолжает сценарий по умолчанию после обнаружения ошибки. – wOxxOm

+0

На самом деле это не ошибка. Я имею в виду, что я сохраняю CSV-файл в цикле каждый раз, так что если программа неожиданно завершается, у меня все еще есть данные в файле csv. Если я экспортирую csv после цикла, тогда, возможно, я потеряю данные в таком поведении. – Junaid

ответ

3

Примечания: код у вас есть в вашем текущем вопросе нечетно, поскольку он будет переписывать файл на каждом проходе со всеми данными, которые уже были там. С небольшим набором данных вы, возможно, не заметили, но тем не менее это плохо. Читайте дальше, чтобы увидеть, что вы могли бы сделать.

Но это также означает, что $ csvdata будет продолжать увеличиваться в размерах, а это значит, что у него будет область памяти, которая может вырасти до мегабайта или даже больше.

Здесь есть пара вопросов. Во-первых, как вы строите $csvdata. Использование += уничтожит массив и переделает его на один элемент больше. Это дорогостоящая операция и создает проблему с производительностью. Вы должны быть в состоянии использовать трубопровод для достижения того, что вам нужно (на основании того, что мало мы видим здесь.)

Get-ChildItem -Recurse $source | foreach{ 

    New-Object PSObject -Property @{FileName=$_.FullName;DateAccessed=($_.LastAccessTime).ToShortDateString()} | 
     $csvdata | Export-Csv $dest -NoTypeInformation -Append 

    $count+=1 
    $count 
} 

У вас нет причин для хранения $csvdata так что не беспокойтесь это делать. Перейдем к вашему другому источнику горе.

Если вы хотите сохранить его, и вы ожидаете, что большие массивы данных рассмотрят вместо этого использование типа .Net arraylist. Действительно базовый пример использования

$csvData = New-Object System.Collections.ArrayList 

0..9 | ForEach-Object{ 
    [void]($csvData.Add([pscustomobject]@{Number=$_;Even=!($_%2)})) 
} 

$csvData | ExportTo-Csv -NoTypeInformation 

есть возможность, я могу потерять данные, если сценарий заканчивается из-за какой-то ошибки или что-то.

Это основная причина, по которой вы задали свой вопрос. Вы обеспокоены потерей данных во время процесса. Мне нужно будет смутно работать с вашим примером, но вы пытаетесь исправить неправильную проблему, я думаю. Вместо того чтобы пытаться найти более устойчивый процесс экспорта, вы должны беспокоиться об обработке ошибок.

Если существует вероятность отказа кода, вы должны рассмотреть возможность использования блоков try{}catch{}, а также общий параметр командлетов для -ErrorAction. Оба имеют свое место в зависимости от того, имеете ли вы дело с завершающими или не заканчивающимися ошибками.

Использование тех, кто находится в зонах сбоя, не позволит вашему процессу полностью находиться в неполном или сомнительном состоянии.

+0

Спасибо. Мой вопрос был больше о том, как я экспортирую данные. Я знал, что мой метод $ csvdata + = был не лучшим, но это был единственный способ, которым я знал, что он будет работать. Вы дали идеальное решение для него с ключевым словом -Append. Большое спасибо. – Junaid

+0

Чтобы дать вам пример того, насколько сильно изменилось это небольшое изменение, когда я запустил его перед обновлением, потребовалось более 3 часов, чтобы получить до 25 000 файлов. После смены он перевалил за 25 000 за 1 минуту. – Junaid

0

Я не думаю, что есть частичный экспорт CSV, но вы могли бы просто написать запятую значения в виде строки и добавляете их в файл внутри цикла:

$dest="C:\users\Administrator\Documents\filelist.csv" 
[email protected]() 
$source="x:\" 
$count=0 

"FileName,DateAccessed" | Set-Content $dest 

Get-ChildItem -Recurse $source | foreach{ 

    "$($_.FullName),$($_.LastAccessTime.ToShortDateString())" | Add-Content $dest 

$count+=1 
$count 
}