[英]Powershell - Export CSV file correctly
I hope someone can help me with this.我希望有人能帮我解决这个问题。 We want to see which computers have a HDD and SDD.我们想看看哪些计算机有 HDD 和 SDD。 I have an excel.csv of the computers.我有一个 excel.csv 的计算机。 I import the computers.我进口电脑。 But when I export them I never see the csv or its incomplete.但是当我导出它们时,我从未看到 csv 或其不完整的。 Can you tell what part of my script is incorrect.你能告诉我脚本的哪一部分是不正确的。 Thank you谢谢
$computers = Import-csv -path "C:\Temp\MediaType\Computers.csv"
foreach ($computer in $computers) {
Write-Host "`nPulling Physical Drive(s) for $computer"
if((Test-Connection -BufferSize 32 -Count 1 -ComputerName $computer -Quiet)){
Invoke-Command -ComputerName $computer -ScriptBlock {
Get-WmiObject -Class MSFT_PhysicalDisk -Namespace root\Microsoft\Windows\Storage | Select-Object sort -Property PSComputerName, Model, SerialNumber, MediaType
Export-Csv C:\Temp\devices.csv
}
}
}
Continuing from my comment.继续我的评论。 . . . . as is, you would be exporting the results to the remote machine.照原样,您会将结果导出到远程机器。 That's if it was piped properly.那是如果它被正确地管道。 You're currently missing a pipe ( |
) before Export-Csv
.您当前在Export-Csv
之前缺少管道 ( |
)。
Also, there's no need to invoke the command, as Get-WMIObject
has a parameter for remote computers: -ComputerName
.此外,无需调用该命令,因为Get-WMIObject
具有用于远程计算机的参数: -ComputerName
。 It's also a deprecated cmdlet that has been replaced by Get-CimInstance .它也是一个已弃用的 cmdlet,已被Get-CimInstance取代。
$ExportTo = "C:\Temp\devices.csv"
$computers = Import-csv -path "C:\Temp\MediaType\Computers.csv"
foreach ($computer in $computers)
{
Write-Host "`nPulling Physical Drive(s) for $computer"
if (Test-Connection -BufferSize 32 -Count 1 -ComputerName $computer -Quiet) {
Get-CimInstance -ClassName MSFT_PhysicalDisk -Namespace root\Microsoft\Windows\Storage -ComputerName $computer |
Select-Object -Property PSComputerName, Model, SerialNumber, MediaType |
Export-Csv -Path $ExportTo -Append -NoTypeInformation
}
}
Side Note : Get-CimInstance
accepts an array of strings, meaning you can pass the entirety of $Computers
to it.旁注: Get-CimInstance
接受字符串数组,这意味着你可以整体通过$Computers
给它。 This should allow it to perform the the query in parallel , vs serial ( one at a time ):这应该允许它并行执行查询,而不是串行(一次一个):
$ExportTo = "C:\Temp\devices.csv"
$computers = Import-csv -path "C:\Temp\MediaType\Computers.csv"
Get-CimInstance -ClassName MSFT_PhysicalDisk -Namespace root\Microsoft\Windows\Storage -ComputerName $computers -ErrorAction SilentlyContinue |
Select-Object -Property PSComputerName, Model, SerialNumber, MediaType |
Export-Csv -Path $ExportTo -Append -NoTypeInformation
Performing queries one at a time doesn't necessarily mean it's bad.一次执行一个查询并不一定意味着它很糟糕。 You can actually have more control over the control of flow for your script.实际上,您可以更好地控制脚本的流程。
To specifically answer the question:具体回答这个问题:
Export-Csv
)?如何正确导出 CSV 文件(使用Export-Csv
)? You might want to read about PowerShell pipelines and PowerShell cmdlets .您可能想阅读有关PowerShell 管道和PowerShell cmdlet 的信息。
Basically, a cmdlet is a single command that participates in the pipeline semantics of PowerShell.基本上,cmdlet 是参与 PowerShell 管道语义的单个命令。 A well written cmdlet is implemented for the Middle of a Pipeline which means that it processes (" streams ") each individual item received from the previous cmdlet and passes it immediately to the next cmdlet (similar to how items are processed in an assembly line where you can compare each assembly station as a cmdlet). 为流水线中间实现了一个写得很好的 cmdlet ,这意味着它处理(“流”)从前一个 cmdlet 接收到的每个单独的项目,并立即将其传递给下一个 cmdlet(类似于在装配线上处理项目的方式)您可以将每个装配站作为一个 cmdlet 进行比较)。
To better show this, I have created an easier minimal, complete and verifiable example (MVCE) and replaced your remote command ( Invoke-Command ...
) which just an fake [pscustomobject]@{ ... }
object.为了更好地展示这一点,我创建了一个更简单、完整且可验证的示例 (MVCE),并替换了您的远程命令 ( Invoke-Command ...
),它只是一个假的[pscustomobject]@{ ... }
对象。
With that;接着就,随即;
Get-Content
rater then Import-Csv
as your example suggest that Computers.csv
is actually a text file which list of computers and not a Csv
file which would require a (eg Name
) header and a using this property accordingly (like Computer.Name
).我使用Get-Content
ratingr 然后Import-Csv
作为您的示例表明Computers.csv
实际上是一个文本文件,其中包含计算机列表,而不是一个需要(例如Name
)标头和相应使用此属性的Csv
文件(例如Computer.Name
.名称)。ForEach-Object
cmdlet rather than the the foreach
statement which is [ usually faster] consider faster but which is probably not the case here as for the foreach
statement requires to load all $Computers
into memory where a well written pipeline will immediately starts ( remotely ) processing the first computer.为了加强管道优势/理解,我还使用了ForEach-Object
cmdlet而不是foreach
语句,后者 [通常更快] 考虑更快,但这里可能不是这种情况,因为foreach
语句需要加载所有$Computers
到内存中,编写良好的管道将立即开始(远程)处理第一台计算机。Now, coming back on the question " How do I correctly export a CSV file " which a better understanding of the pipeline, you might place it here:现在,回到问题“我如何正确导出 CSV 文件”,可以更好地理解管道,您可以将它放在这里:
Get-Content .\Computers.txt |ForEach-Object {
[pscustomobject]@{
PSComputerName = $_
Model = "Model"
SerialNumber = '{0:000000}' -f (Get-Random 999999)
MediaType = "MydiaType"
} |Export-Csv .\Devices.csv -Append
}
As commented by @lit , this would require the -Append
switch which might not be desired as every time you rerun your script this would append the results to the .\\Devices.csv
file.正如@lit所评论的那样,这将需要-Append
开关,这可能是不需要的,因为每次重新运行脚本时,这会将结果附加到.\\Devices.csv
文件。
Instead you might actually want do this:相反,您可能实际上想要这样做:
Get-Content .\Computers.txt |ForEach-Object {
[pscustomobject]@{
PSComputerName = $_
Model = "Model"
SerialNumber = '{0:000000}' -f (Get-Random 999999)
MediaType = "MydiaType"
}
} |Export-Csv .\Devices.csv
Note the differences: the Export-Csv
is placed outside the loop and the -Append
switch is removed.请注意不同之处: Export-Csv
被放置在循环之外并且-Append
开关被移除。
Explanation解释
As with eg the ForEach-Object
cmdlet, the Export-Csv
cmdlet has internally Begin
, Process
and End
blocks .与例如ForEach-Object
cmdlet 一样, Export-Csv
cmdlet 在内部具有Begin
、 Process
和End
块。 In the Begin
block , the Export-Csv
cmdlet prepares the csv
file with header etc. and overwrites any existing file.在Begin
块中, Export-Csv
cmdlet 准备带有标题等的csv
文件并覆盖任何现有文件。 In the Process
block (which runs for each item received from the pipeline) it adds each line (data record) to the file.在Process
块(为从管道接收的每个项目运行)中,它将每一行(数据记录)添加到文件中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.