我有一个脚本,该脚本在一个文件夹中循环,并将多个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。
答案 0 :(得分:2)
看着您的脚本,您最终用完内存不足为奇,因为您一直在创建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个字符。
我查看了您的项目,尤其是Shares_Complete.psm1
文件。
尽管我当然不愿意重写您的整个项目,但我确实有一些建议可以帮助您:
[System.Net.Dns]::GetHostByName()
已过时。使用GetHostEntry() $ObjForm.Dispose()
从内存中清除它[System.GC]::Collect(); [System.GC]::WaitForPendingFinalizers()
[System.Windows.MessageBox]::Show()
而不是Com对象$a = new-object -comobject wscript.shell
。再次,您将该对象留在内存中徘徊。Join-Path
cmdlet代替$RD = $FSCSV + "*.csv"
或$Cop = $FSCSV + "*.csv"
构造replace '[\\/?*:[\]]', ''
)中删除无效字符Location
,Delete
和File
之类的功能,什么都没有意义Shares
。那时它还不存在,因为函数本身是在第69行中编写的。
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($worksheet) | Out-Null
中添加Excel-Write
$Excel
)中使用变量$Script:Excel = New-Object -ComObject excel.application
,该变量仅在函数的本地使用。