Powershell - Strange result when exporting disk space result to CSV - powershell

I have the following code that finds the free space on a drive on a server called 'Automate' and outputs the result to a .csv file:
$AutomateD = #()
Clear-Host
$AutomateD += Get-WmiObject Win32_logicaldisk -ComputerName Automate ` | Where-Object {$_.VolumeName -ne 'Logs' -and $_.DeviceID -eq 'D:'}| Format-Table DeviceID, MediaType, `
#{Name="Size(GB)";Expression={[decimal]("{0:N0}" -f($_.size/1gb))}}, `
#{Name="Free Space(GB)";Expression={[decimal]("{0:N0}" -f($_.freespace/1gb))}}, `
#{Name="Free (%)";Expression={"{0,6:P0}" -f(($_.freespace/1gb) / ($_.size/1gb))}} `
-AutoSize
$AutomateD | Export-Csv -path "C:\Powershell\Automate\AutomateD.csv" -NoTypeInformation -Encoding Unicode
$ImportAutoD = Import-CSV C:\Powershell\Automate\AutomateD.csv | ConvertTo-Html
The issue is that I get some strange results when I open the csv -
"ClassId2e4f51ef21dd47e99d3c952918aff9cd","pageHeaderEntry","pageFooterEntry","autosizeInfo","shapeInfo","groupingEntry"
"033ecb2bc07a4d43b5ef94ed5a35d280",,,"Microsoft.PowerShell.Commands.Internal.Format.AutosizeInfo","Microsoft.PowerShell.Commands.Internal.Format.TableHeaderInfo",
"9e210fe47d09416682b841769c78b8a3",,,,,
"27c87ef9bbda4f709f6b4002fa4af63c",,,,,
"4ec4f0187cb04f4cb6973460dfe252df",,,,,
"cf522b78d86c486691226b40aa69e95c",,,,,
However, if I just output the $AutomateD variable on the screen, I get a nice table like so:
PS C:\Powershell\SCRIPT> $AutomateD
DeviceID MediaType Size(GB) Free Space(GB) Free (%)
-------- --------- -------- -------------- --------
D: 12 1225 183 15%
Any ideas as to what is going on? There seems to be an problem in the export process, although I don't have any errors to go on what I'm doing wrong.

You need to remove the format-table and replace it with a select-object. You'll also need to drop the -autosize from the end of your pipeline. In addition it is not required but I would recommend dropping the kind odd array creation and then adding a single value to the array, the script can actually get done in a single pipeline with the exception of the import-csv (which I'm not really sure you need but I'll leave it in assuming it's required elsewhere in the script)
Clear-Host
Get-WmiObject Win32_logicaldisk ` | Where-Object {$_.VolumeName -ne 'Logs' -and $_.DeviceID -eq 'D:'}| Select-Object DeviceID, MediaType, `
#{Name="Size(GB)";Expression={[decimal]("{0:N0}" -f($_.size/1gb))}}, `
#{Name="Free Space(GB)";Expression={[decimal]("{0:N0}" -f($_.freespace/1gb))}}, `
#{Name="Free (%)";Expression={"{0,6:P0}" -f(($_.freespace/1gb) / ($_.size/1gb))}} |
Export-Csv -path d:\scripts\test.csv -NoTypeInformation -Encoding Unicode -Force
$ImportAutoD = Import-CSV d:\scripts\test.csv | ConvertTo-Html
Also note that I did make some path changes to make it work on my machine without building out a new folder structure.

when exporting the csv use -NoTypeInformation

Related

Out-gridview does not sorting results

I have a script that I am trying to collect drive letters from a list of servers (as well as used space and free space) and then gridview the results out.
$servers = Get-Content "path.txt"
foreach ($server in $servers) {
Invoke-Command -ComputerName $server {Get-PSDrive | Where {$_.Free -gt 0}}
Select-Object -InputObject usedspace,freespace,root,pscomputername |
Sort-Object root -Descending | Out-Gridview
}
I can get it to display the drive information for each server on the list but gridview does not work. I have tried moving the brackets around (before and after gridview) as well as piping elements but have had no luck.
Can anyone advise me as to what I am doing wrong? I feel like it is something simple but all of the examples I am finding online do not use the foreach command which I think has to do with throwing it off.
Your Select-Object is missing pipeline input - pipe the Invoke-Command call's output to it.
Instead of -InputObject, use -Property:
Note: -InputObject is the parameter that facilitates pipeline input, and is usually not meant to be used directly.
As with Sort-Object, -Property is the first positional parameter, so you may omit -Property in the call below.
foreach ($server in Get-Content "path.txt") {
Invoke-Command -ComputerName $server { Get-PSDrive | Where { $_.Free -gt 0 } } |
Select-Object -Property usedspace, freespace, root, pscomputername |
Sort-Object root -Descending |
Out-Gridview
}
Also note that -ComputerName can accept an array of computer names, which are then queried in parallel, so if you want to query all computers and then call Out-GridView only once, for the results from all targeted computers:
Invoke-Command -ComputerName (Get-Content "path.txt") {
Get-PSDrive | Where Free -gt 0
} |
Select-Object -Property usedspace, freespace, root, pscomputername |
Sort-Object root -Descending |
Out-Gridview
To group the results by target computer, use
Sort-Object pscomputername, root -Descending
If you'd rather stick with your sequential, target-one-server-at-a-time approach, change from a foreach statement - which cannot be used directly as pipeline input - to a ForEach-Object call, which allows you to pipe to a single Out-GridView call:
Get-Content "path.txt" |
ForEach-Object {
Invoke-Command -ComputerName $_ { Get-PSDrive | Where Free -gt 0 }
} |
Select-Object -Property usedspace, freespace, root, pscomputername |
Sort-Object root -Descending |
Out-Gridview

Extract some information using a WMI query and send it to file

I'm collecting information using a WMI query. I want to send this information to a CSV file including the machine name. I can send the information but I'm not able to include machine name with it.
$PasswordState = Get-WmiObject -Class Lenovo_BiosPasswordSettings -Namespace root\wmi |
Select -Expand PasswordState |
Select-Object -Last 1 |
Out-File -FilePath '\\server\share\Bios_Password_Status.csv' -Append -Encoding Unicode
I need this to create a CSV file with two items:
Data returned from WMI query
Machine name
Does this give you what you want, it will store the result in an array called $Output. You can then use $Output | Out-File -Append to add it to a file or something.
$Result = Get-WmiObject -Class Lenovo_BiosPasswordSettings -Namespace root\wmi | Select -Property PSComputerName,PasswordState
$Output += $Result | Format-Table -HideTableHeaders

Work with ADComputer output in foreach loop

I want to output all hostnames within a network first with a foreach loop, in order (for example) to be able to ping them.
However with the following code I do not get any output in the console. The CSV file will be saved, but what is written in the loop will not be executed.
Does anyone know what the reason for this is and how I can solve it?
Import-Module activedirectory
Get-ADComputer -Filter * -Property * | Select Name | Export-CSV -Path $env:TEMP\ZZZEXPORTE.csv -NoTypeInformation -Encoding UTF8 | ForEach {
$computerName = $_.Name
Write-Host $computerName
Write-Host "----"
}
This occurs because Export-CSV does not output an object. Sometimes cmdlets like this have a -PassThru parameter which you can use to have an object passed along, but thats not the case with Export-CSV, they simply expect it to always be the last cmdlet in the pipeline.
You should instead do this:
$Computers = Get-ADComputer -Filter * -Property * | Select Name
$Computers | Export-CSV -Path $env:TEMP\ZZZEXPORTE.csv -NoTypeInformation -Encoding UTF8
$Computers | ForEach {
$computerName = $_.Name
Write-Host $computerName
Write-Host "----"
}
You could also do this:
Get-ADComputer -Filter * -Property * | Select Name | ForEach {
$computerName = $_.Name
Write-Host $computerName
Write-Host "----"
$_
} | Export-CSV -Path $env:TEMP\ZZZEXPORTE.csv -NoTypeInformation -Encoding UTF8
Noting that we have to add $_ to our ForEach-Object loop so that it outputs the current item to the pipeline, but that our Write-Host statements don't effect the pipeline because they are writing to the console only. To be honest though, this is a bit harder to follow for anyone else reading your code.

Only shows one computer name instead of many systems in servers.txt

I am trying to run this simple script to get the services and the accounts that are running them. My problem is that the data looks correct in the report but the server name does not change in the report. Here is the code.
$servers = get-content C:\temp\servers.txt
foreach ($server in $servers)
{
Get-WmiObject win32_service | Select-Object -Property SystemName, DisplayName, startname | format-list -GroupBy startname | Out-File c:\temp\results.txt
}
This will work.
$servers = get-content C:\temp\servers.txt
foreach ($server in $servers)
{
Get-WmiObject win32_service -Computername $server | Select-Object -Property SystemName, DisplayName, startname | format-list -GroupBy startname | Out-File -append c:\temp\results.txt
}
You can also use the following but note SystemName is not a property of Win32_Service. To troubleshoot this, try using Get-Service | Select -first 1 | Get-Member will display the available attributes (sorry if this is the wrong term) with the important one being MachineName thus replace SystemName for MachineName and you'll get the desired results. Look up Hey Scripting Guy articles for further information. For example, this page
gc .\Servers.txt | foreach {get-service -ComputerName $_ | `
Select-Object -Property MachineName, DisplayName, startname | `
format-list -GroupBy startname | Out-File -append c:\temp\results.txt}
Note, I'm using the backtick ` to make the command readable, paste into the Powershell ISE to save/run the script or just paste the lines into the console and press enter twice to run the multi-line script.

Only get the partition label

I'm coding a little script with Powershell.
The script is getting the drive letters and exports them with some additional code to the temp directory in a batch file.
Here's an example:
$TempFolderSavePath = $env:temp + "\SDelete.cmd"
Get-PSDrive -PSProvider 'FileSystem' | Select-Object Name | foreach { $_.Name } | ForEach-Object {"SDelete -z "+ $_} | Out-File $TempFolderSavePath
The problem is, that the script is also including mapped network drives.
How I can only use the local drives?
Here's a version of the script without generating a new file and just outputting it to the console.
Get-PSDrive -PSProvider 'FileSystem' | Select-Object Name | foreach { $_.Name } | ForEach-Object {"SDelete -z "+ $_} | Write-Host
As far as I know, Get-PSDrive doesn't know the difference betwee network and local drive. You can use Get-WMIObject Win32_LogicalDisk, which supports filtering drives by type.
Filtering example:
Get-WmiObject Win32_LogicalDisk | select-object DeviceID, DriveType, #{Name="Type";Expression={[IO.DriveType]$_.DriveType}} | ? {$_.Type -eq 'Fixed'}
or
Get-WmiObject Win32_LogicalDisk | ? {$_.DriveType -eq 3}