Недостаточно памяти для продолжения выполнения программы.Создание Xlxs из CSV - PullRequest
0 голосов
/ 05 февраля 2019

У меня есть сценарий, который циклически просматривает папку и объединяет несколько CSV в один файл xlsx с именами CSV в виде рабочих листов.Однако, когда сценарий выполняется как часть более крупного сценария, он завершается ошибкой при обновлении запроса.

$Query.Refresh()

Сам по себе сценарий работает нормально, но при добавлении к большему сценарию происходит сбой.Кто-нибудь может посоветовать, почему это так?

Ниже приведена ошибка, которую я получаю:

Insufficient memory to continue the execution of the program.
At C:\Temp\Scripts\Shares_Complete.psm1:254 char:13
+             $Query.Refresh()
+             ~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (:) [], OutOfMemoryException
    + FullyQualifiedErrorId : System.OutOfMemoryException

Я пробовал один CSV с тем же кодом и тем же результатом.

$script:SP = "C:\Temp\Servers\"

$script:TP = "C:\Temp\Servers\Pc.txt"
$script:FSCSV = "C:\Temp\Server_Shares\Server Lists\"
$script:Message1 = "Unknown Hosts"
$script:Message2 = "Unable to connect"
$script:Message3 = "Unknown Errors Occurred"
$script:Txt = ".txt"
$script:OT = ".csv"
$script:FSERROR1 = $FSCSV+$Message1+$OT
$script:FSERROR2 = $FSCSV+$Message2+$OT
$script:FSERROR3 = $FSCSV+$Message2+$OT

$script:ERL3 = $E4 + "Shares_Errors_$Date.txt"
$script:ECL1 = $E4 + "Shares_Exceptions1_$Date.txt"
$script:ERL1 = $E4 + "Shares_Errors1_$Date.txt"
$script:ECL3 = $E4 + "Shares_Exceptions_$Date.txt"

function Excel-Write {
    if ($V -eq "1") {
        return
    }

    [System.GC]::Collect()
    $RD = $FSCSV + "*.csv" 
    $CsvDir = $RD 
    $Ma4 = $FSCSV + "All Server Shares for Domain $CH4"
    $csvs = dir -path $CsvDir # Collects all the .csv's from the driectory 
    $FSh = $csvs | Select-Object -First 1
    $FSh = ($FSh -Split "\\")[4]
    $FSh = $FSh -replace ".{5}$"
    $FSh
    $outputxls = "$Ma4.xlsx"
    $script:Excel = New-Object -ComObject Excel.Application
    $Excel.DisplayAlerts = $false
    $workbook = $excel.Workbooks.Add()
    # Loops through each CVS, pulling all the data from each one
    foreach ($iCsv in $csvs) {
        $script:iCsv
        $WN = ($iCsv -Split "\\")[-1]
        $WN = $WN -replace ".{4}$"
        if ($WN.Length -gt 30) {
            $WN = $WN.Substring(0, [Math]::Min($WN.Length, 20))
        }
        $Excel = New-Object -ComObject Excel.Application
        $Excel.DisplayAlerts = $false
        $Worksheet = $workbook.Worksheets.Add()
        $Worksheet.Name = $WN

        $TxtConnector = ("TEXT;" + $iCsv)
        $Connector = $worksheet.Querytables.Add($txtconnector,$worksheet.Range("A1"))
        $query = $Worksheet.QueryTables.Item($Connector.Name)

        $query.TextfileOtherDelimiter = $Excel.Application.International(5)

        $Query.TextfileParseType = 1
        $Query.TextFileColumnDataTypes = ,2 * $worksheet.Cells.Column.Count
        $query.AdjustColumnWidth = 1

        $Query.Refresh()
        $Query.Delete()
        $Worksheet.Cells.EntireColumn.AutoFit()
        $Worksheet.Rows.Item(1).Font.Bold = $true
        $Worksheet.Rows.Item(1).HorizontalAlignment = -4108
        $Worksheet.Rows.Item(1).Font.Underline = $true
        $Workbook.Save()
    }
    $Empty = $workbook.Worksheets.Item("Sheet1")
    $Empty.Delete()
    $Workbook.SaveAs($outputxls,51)
    $Workbook.Close()
    $Excel.Quit()
    $ObjForm.Close()
    Delete
}

Следует продолжить сценарий и создать xlsx.

1 Ответ

0 голосов
/ 05 февраля 2019

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

Всякий раз, когда вы создали объекты Com и покончили сиспользуйте эти строки для освобождения памяти:

$Excel.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($workbook) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($Excel) | Out-Null
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()

Кроме того, внимательно посмотрите на код.
Вы создаете объект $Script:Excel = New-Object -ComObject excel.application перед циклом foreach, но не делаетеНе используйте это.Вместо этого вы снова и снова создаете новые объекты Excel и книги внутри цикла, где для этого нет абсолютно никаких оснований, поскольку вы можете повторно использовать тот, который вы создали до цикла.

В качестве отступления:Следующие символы не допускаются в именах листов Excel

\/?*[]:

Ограничение длины составляет 31 символ.


РЕДАКТИРОВАТЬ

IЯ посмотрел на ваш проект и особенно файл Shares_Complete.psm1.
Хотя я, конечно, не хочу переписывать весь ваш проект, у меня есть несколько замечаний, которые могут вам помочь:

  1. [System.Net.Dns]::GetHostByName() устарел.Используйте GetHostEntry ()
  2. при работе с формой Windows, используйте $ObjForm.Dispose(), чтобы очистить ее из памяти
  3. вы делаете много [System.GC]::Collect(); [System.GC]::WaitForPendingFinalizers() без причины
  4. Почему бы не использовать [System.Windows.MessageBox]::Show() вместо использования объекта Com $a = new-object -comobject wscript.shell.Опять вы оставляете этот объект в памяти ..
  5. используйте Join-Path командлет вместо $RD = $FSCSV + "*.csv" или $Cop = $FSCSV + "*.csv" конструкций
  6. удаляйте недопустимые символы из имен листов Excel (replace '[\\/?*:[\]]', '')
  7. используйте имя глагола для своих функций, чтобы стало понятно, что они делают.Теперь у вас есть такие функции, как Location, Delete и File, которые ничего не значат
  8. вы вызываете функции до того, как они определены, как в строке 65, где вы вызываете функцию Shares.На данный момент она еще не существует, поскольку сама функция записана в строке 69
  9. add [System.Runtime.Interopservices.Marshal]::ReleaseComObject($worksheet) | Out-Null в функции Excel-Write
  10. , нет необходимости использовать переменную $Excel вобласть действия скрипта ($Script:Excel = New-Object -ComObject excel.application), где он используется только локально для функции.
  11. вам может понадобиться посмотреть спецификации и ограничения Excel
  12. исправить ваши отступы кодапоэтому ясно, когда цикл или если начинается и заканчивается
  13. Я бы рекомендовал использовать имена переменных с большим значением.Для постороннего или даже для вас самого через пару месяцев двухбуквенные имена переменных приводят в замешательство
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...