Getting C: drive capcity from multiple servers - powershell

$computers = Get-Content -Path c:\server\computers.txt
$computers | foreach {
$os = Get-WmiObject win32_OperatingSystem -computername $_
Get-WMIObject Win32_Logicaldisk -filter "deviceid='$($os.systemdrive)'" -ComputerName $_
} | Select PSComputername,DeviceID,
#{Name="SizeGB";Expression={$_.Size/1GB -as [int]}},
#{Name="FreeGB";Expression={[math]::Round($_.Freespace/1GB,2)}} |
Sort FreeGB | Format-Table -Autosize >> C:\server\diskreport.txt

Since there really was no question posted or errors given for what you have, here's what I use to get the disk space on a server. You can always get a list and throw it into a foreach loop sending them to this function and throw the output to a file however you would like.
Function Get-DiskInventory
{
[CmdletBinding()]
Param (
[Parameter(ValueFromPipeline,ValueFromPipelineByPropertyName)]
[alias("Name")]
[string[]]$ComputerName="localhost",
[validateset(2,3)]
[int]$DriveType=3,
[Parameter()]
[string]$DriveLetter
)
Begin{
Write-Verbose "Getting disk inventory on $ComputerName"
}
Process {
foreach ($Computer in $ComputerName) {
Write-Verbose "Connecting to $Computer"
Write-Verbose "Looking for drive type $DriveType"
$Result = Get-WmiObject -Class win32_logicaldisk -ComputerName $Computer -Filter "drivetype=$DriveType" |
Select-Object -Property #{label='Computer';expression={$Computer}},
DeviceID,
#{label='Size(GB)';expression={$_.Size / 1GB -as [int]}},
#{label='UsedSpace(GB)';expression={($_.Size - $_.FreeSpace) / 1GB -as [int]}},
#{label='FreeSpace(GB)';expression={$_.FreeSpace / 1GB -as [int]}},
#{label='%Free';expression={$_.FreeSpace / $_.Size * 100 -as [int]}}
if ($DriveLetter) {
Write-Verbose "Filtering drives"
$Result = $Result | where deviceid -EQ "$DriveLetter`:"
}
$Result | Select-Object -Property * -Unique
}
}
End{
Write-Verbose "Finished running command"
}
}

Related

Script to remove user profiles using powershell

I'm trying to build a powershell script that I can use to delete all or some of the user profiles on multiple pc's since they often cause the drives to go full.
I found the current script which I got to work for me, but I'd like to optimize it so I can input or import a list of computers where I want him to remove all the user profiles from.
Can you guys help me to input this feature?
Current Code:
$ExcludedUsers ="admin","test"
$RunOnServers = $false
[int]$MaximumProfileAge = 0 # Profiles older than this will be deleted
$osInfo = Get-CimInstance -ClassName Win32_OperatingSystem
if ($RunOnServers -eq $true -or $osInfo.ProductType -eq 1) {
New-EventLog -LogName Application -Source "Stone Profile Cleanup" -ErrorAction SilentlyContinue
$obj = Get-WMIObject -class Win32_UserProfile | Where {(!$_.Special -and $_.Loaded -eq $false )}
#$output = #()
foreach ($littleobj in $obj) {
if (!($ExcludedUsers -like $littleobj.LocalPath.Replace("C:\Users\",""))) {
$lastwritetime = (Get-ChildItem -Path "$($littleobj.localpath)\AppData\Local\Microsoft\Windows\UsrClass.dat" -Force ).LastWriteTime
if ($lastwritetime -lt (Get-Date).AddDays(-$MaximumProfileAge)) {
$littleobj | Remove-WmiObject
# $output += [PSCustomObject]#{
# 'RemovedSID' = $littleobj.SID
# 'LastUseTime' = $litteobj.LastUseTime
# 'LastWriteTime' = $lastwritetime
# 'LocalPath' = $littleobj.LocalPath
# }
}
}
}
#$output | Sort LocalPath | ft
#$output | Sort LocalPath | ft * -AutoSize | Out-String -Width 4096 | Out-File -filepath "C:\MyOutput.TXT" -append -Encoding Unicode
Write-EventLog –LogName Application –Source "Stone Profile Cleanup" –EntryType Information –EventID 1701 -Category 2 -Message ("Profiles older than $MaximumProfileAge days have been cleaned up")
}$ExcludedUsers ="adminbholemans","testbholemans1"
$RunOnServers = $false
[int]$MaximumProfileAge = 0 # Profiles older than this will be deleted
$osInfo = Get-CimInstance -ClassName Win32_OperatingSystem
if ($RunOnServers -eq $true -or $osInfo.ProductType -eq 1) {
New-EventLog -LogName Application -Source "Stone Profile Cleanup" -ErrorAction SilentlyContinue
$obj = Get-WMIObject -class Win32_UserProfile | Where {(!$_.Special -and $_.Loaded -eq $false )}
#$output = #()
foreach ($littleobj in $obj) {
if (!($ExcludedUsers -like $littleobj.LocalPath.Replace("C:\Users\",""))) {
$lastwritetime = (Get-ChildItem -Path "$($littleobj.localpath)\AppData\Local\Microsoft\Windows\UsrClass.dat" -Force ).LastWriteTime
if ($lastwritetime -lt (Get-Date).AddDays(-$MaximumProfileAge)) {
$littleobj | Remove-WmiObject
# $output += [PSCustomObject]#{
# 'RemovedSID' = $littleobj.SID
# 'LastUseTime' = $litteobj.LastUseTime
# 'LastWriteTime' = $lastwritetime
# 'LocalPath' = $littleobj.LocalPath
# }
}
}
}
#$output | Sort LocalPath | ft
#$output | Sort LocalPath | ft * -AutoSize | Out-String -Width 4096 | Out-File -filepath "C:\MyOutput.TXT" -append -Encoding Unicode
Write-EventLog –LogName Application –Source "Stone Profile Cleanup" –EntryType Information –EventID 1701 -Category 2 -Message ("Profiles older than $MaximumProfileAge days have been cleaned up")
}
I found this piece of code for the computer input but I'm not sure how I can implement it properly.
Get-CimInstance -ComputerName SRV1,SRV2,SRV3 -Class Win32_UserProfile | Where-Object { $_.LocalPath.split('\')[-1] -eq 'UserA' } | Remove-CimInstance
Thanks for the help everyone.
Get-CimInstance -ComputerName SRV1,SRV2,SRV3 -Class Win32_UserProfile | Where-Object { $_.LocalPath.split('')[-1] -eq 'UserA' } | Remove-CimInstance
Do u test it before? Work OK?

having issues recording error in export-csv

I have powershell script to pull down hotfixID, installedon, lastbootuptime and freespace in C drive. (I googled around and changed couple of things I need.) when the Pc is not reachable it will
Write-Warning "$_ cannot be reached, skipping."
I also want to capture the computer name of the failed PC to my CSV. I tried
| Export-Csv C:\test\computerDetails.csv -NoTypeInformation
or append but seems like its not working. can someone please help? below is my whole script.
(Get-Content C:\test\serverlist.txt).Trim() | ForEach {
If (Test-Connection -ComputerName $_ -Count 1 -Quiet)
{
$update = Get-CimInstance Win32_QuickFixEngineering -ComputerName $_ | Sort-Object InstalledOn -Descending | Select-Object -First 1
$os = Get-CimInstance win32_operatingsystem -ComputerName $_
$disk = Get-WmiObject Win32_LogicalDisk -ComputerName $_ -Filter "DeviceID='C:'"
$props = #{
ComputerName = $_
HotFixID = $update.HotFixID
InstalledOn = $update.InstalledOn
lastbootuptime = $os.LastBootUpTime
FreeSpace_GB = $disk.FreeSpace / 1GB
}
New-Object PsObject -Property $props
}
Else {
Write-Warning "$_ cannot be reached, skipping." | Export-Csv C:\test\computerDetails.csv -NoTypeInformation
}
} | Sort ComputerName |
Select ComputerName,HotFixID,InstalledOn,lastbootuptime,FreeSpace_GB |
Export-Csv C:\test\computerDetails.csv -NoTypeInformation
Main problem with adding it to the CSV is that it is a string. If you treat the erroneous machines the same as successful ones, then you can throw them in the same CSV.
I have added an ArrayList there as the storage variable and then for each computer it creates a temp PSObject to store your results in, overwriting the variable each loop but not before dumping the variable into the ArrayList for export at the end.
$Errors = New-Object System.Collections.ArrayList
(Get-Content C:\test\serverlist.txt).Trim() | ForEach {
$Temp = New-Object -TypeName PSObject
If (Test-Connection -ComputerName $_ -Count 1 -Quiet) {
$update = Get-CimInstance Win32_QuickFixEngineering -ComputerName $_ | Sort-Object InstalledOn -Descending | Select-Object -First 1
$os = Get-CimInstance win32_operatingsystem -ComputerName $_
$disk = Get-WmiObject Win32_LogicalDisk -ComputerName $_ -Filter "DeviceID='C:'"
$props = [ordered]#{
ComputerName = $_
HotFixID = $update.HotFixID
InstalledOn = $update.InstalledOn
lastbootuptime = $os.LastBootUpTime
FreeSpace_GB = $disk.FreeSpace / 1GB
Error = "Success"
}
$Temp | Add-Member -NotePropertyMembers $props -TypeName temp
} Else {
$props = [ordered]#{
ComputerName = $_
Error = "Cannot be reached"
}
$Temp | Add-Member -NotePropertyMembers $props -TypeName temp
Write-Warning "$_ cannot be reached, skipping."
}
$Errors.Add($Temp) > $null
}
$Errors | Export-Csv C:\temp\computerDetails.csv -NoTypeInformation -Append

Add column to CSV file with powershell AzureVM

Not sure how to explain this, we're doing an assessment on disk usage on Azure, to reduce costs. We are trying to asses the space on each vm and reduce the disks
I'd like to add a recommendation column in there based on the free space, if the freespace is greater than 90% then add a comment "consider resizing" if less than 15% then "consider disk clean up".
The script I have works fine except it doesn't add the comment in, first I tried this...
$computers = (Get-AdComputer -Filter "name -like 'VM-*'").Name | Sort-Object
foreach ($computer in $Computers)
{
$vol = gwmi Win32_volume -Computer $Computer -Filter 'DriveType = 3'
#$vol
$info = $vol | select PsComputerName, DriveLetter, Label,
#{n='Capacity';e={[int]($_.capacity/1GB)}},
#{n='FreeSpace';e={[int]($_.FreeSpace/1GB)}},
#{n='FreeSpace (%)';e={[int](($_.FreeSpace) / ($_.capacity) * 100.0)}}
if ('FreeSpace (%)' -gt 85)
{
Write-Output "Disk Usage Low, Consider Resizing Options"
}
else
{
Write-Output "Disk Usage High"
}
$info | Export-Csv "c:\temp\tempfiles\question.csv" -Append
}
That didn't work, I then tried adding another section, where I get true or false, which seems to work.. that one is below, however I need to dd recommendations in..
$computers = (Get-AdComputer -Filter "name -like 'VM-*'").Name | Sort-Object
foreach ($computer in $Computers)
{
$vol = gwmi Win32_volume -Computer $Computer -Filter 'DriveType = 3'
#$vol
$info = $vol | select PsComputerName, DriveLetter, Label,
#{n='Capacity';e={[int]($_.capacity/1GB)}},
#{n='FreeSpace';e={[int]($_.FreeSpace/1GB)}},
#{n='FreeSpace (%)';e={[int](($_.FreeSpace) / ($_.capacity) * 100.0)}},
#{n='Recommendation';e={[String] ($_.FreeSpace -gt 90)}}
$info | Export-Csv "c:\temp\tempfiles\question.csv" -Append
}
Hope that makes sense.
Thanks in advance :)
The e stands for Expression. So you should be able to use an expression in there, using the original object properties (i.e. not your custom property names such as FreeSpace (%))
$computers = (Get-AdComputer -Filter "name -like 'VM-*'").Name | Sort-Object
foreach ($computer in $Computers)
{
$vol = gwmi Win32_volume -Computer $Computer -Filter 'DriveType = 3'
#$vol
$info = $vol | select PsComputerName, DriveLetter, Label,
#{n='Capacity';e={[int]($_.capacity/1GB)}},
#{n='FreeSpace';e={[int]($_.FreeSpace/1GB)}},
#{n='FreeSpace (%)';e={[int](($_.FreeSpace) / ($_.capacity) * 100.0)}},
#{n='Recommendation';e={
if((($_.FreeSpace) / ($_.capacity) * 100.0) -gt 90){
"Disk Usage Low, Consider Resizing Options"
}elseif((($_.FreeSpace) / ($_.capacity) * 100.0) -gt 75){
"Something else"
}else{
"Disk Usage High"
}
}
$info | Export-Csv "c:\temp\tempfiles\question.csv" -Append
}

How to extract server information

Objective: How to extract server information?
For each server name listed in servers.txt, I would like to get the following information (in this format):
Server name, IP Address, OS name, Total Physical Memory, Processors, each drive letter and size, System Model
Comma separated and new line for each server.
Below is my PowerShell code. Can your guys give a hint on why this does not work? Also why I get an error with New-Object statement?
foreach ($ComputerName in (Get-Content -Path .\servers.txt)) {
$HashProps = #{
'tHostname' = Get-WmiObject Win32_Computersystem -ComputerName $ComputerName | Select-Object -ExpandProperty Name
'tIP' = [System.Net.Dns]::GetHostAddresses($computername)
'tOS' = Get-WmiObject -ComputerName $ComputerName -Class Win32_OperatingSystem | Select-Object -ExpandProperty Caption
'tMemory' = Get-WmiObject Win32_PhysicalMemory | Measure-Object -Property capacity -Sum | foreach { "$("{0:n2}" -f ( $_.Sum/1GB ) )" }
'tcpu' = Get-WmiObject Win32_processor | Select-Object name, numberofcores
'tDisks' = Get-WmiObject Win32_LogicalDisk | foreach { "$($_.DeviceID) $("{0:n2}" -f ( $_.Size/ 1GB ) )" }
'tsysmodel' = Get-Wmiobject Win32_computersystem | Select-Object model
}
New-Object -TypeName psObject -Property $HashProps |
ConvertTo-Csv -NoTypeInformation | Out-File -Append .\output.csv
}
I am open for a other approach, if this is easier.
Have you verified that each of those lines actually return what you want?
I just threw this into the ISE and it works fine:
$f = gwmi win32_computersystem | select name,model,totalphysicalmemory
$hash = #{
'name' = $f.name
'model' = $f.model
'memory' = $("{0:n2}" -f ( $f.totalphysicalmemory/1GB ) )
}
New-Object -TypeName psobject -Property $hash | ConvertTo-Csv -NoTypeInformation | Out-File -Append .\test.csv
Also, if you want the properties to appear in a specific order in the CSV, it will take some additional magic, otherwise they're put in alphabetically.
A little bit pimped, maybe this will help you:
$Servers = Foreach ($ComputerName in (Get-Content -Path .\Servers.txt)) {
$CS = Get-WmiObject Win32_ComputerSystem -ComputerName $ComputerName
$OS = Get-WmiObject Win32_OperatingSystem -ComputerName $ComputerName
$PM = Get-WmiObject Win32_PhysicalMemory -ComputerName $ComputerName
$PR = Get-WmiObject Win32_processor -ComputerName $ComputerName
$LD = Get-WmiObject Win32_LogicalDisk -ComputerName $ComputerName
$IP = [System.Net.Dns]::GetHostAddresses($ComputerName)
[PSCustomObject]#{
ServerName = $CS | Select-Object -ExpandProperty Name
IPAddress = $IP | Select-Object -ExpandProperty IPAddressToString
OS = $OS | Select-Object -ExpandProperty Caption
Memory = $PM | Measure-Object -Property Capacity -Sum | foreach { "$("{0:n2}" -f ( $_.Sum/1GB ) )" }
CPU = $PR | Select-Object Name, NumberOfCores
Disks = $LD | foreach { "$($_.DeviceID) $("{0:n2}" -f ( $_.Size/ 1GB ) )" }
Model = $CS | Select-Object -ExpandProperty Model
}
}
$File = Join-Path $env:TEMP 'Ouptut.csv'
$Servers | Export-Csv -Path $File -NoTypeInformation -Delimiter ';'
Start-Process $File

Table not showing output in new line

I'm sure there is a simple solution, but I'm stuck. The output in the members column is like this
{domain\Domain Admins, domain\joerod...
How can I show the
$member
value on each line?
Function Get-AdminGroups{
foreach($i in (Get-Content C:\Users\joerod\Desktop\remove_users.txt)){
#test if machine is on the network
if (-not (Test-Connection -computername $i -count 1 -Quiet -ErrorAction SilentlyContinue)) {
Write-Warning "$i is Unavalible"
"`r"
}
else {
(invoke-command {
$members = net localgroup administrators |
? {$_ -AND $_ -notmatch "command completed successfully"} |
select -skip 4
New-Object PSObject -Property #{
Computername = $env:COMPUTERNAME
Users=$members
}
} -computer $i -HideComputerName |
Select * -ExcludeProperty RunspaceID )
}
}
}
Get-AdminGroups |ft
Iterate through $members and make an object for each one. This creates an empty array, loops through the computers in your text file, and in that loop it pulls a list of the local administrators, and for each one it creates a custom object just like you are doing, and it adds it to that array.
$Results = #()
foreach($i in (GC C:\Users\joerod\Desktop\remove_users.txt)){
#test if machine is on the network
if (!(Test-Connection -computername $i -count 1 -Quiet -ErrorAction SilentlyContinue)) {
Write-Warning "$i is Unavalible`r"
Continue
}
invoke-command {
$members = net localgroup administrators |?{$_ -AND $_ -notmatch "command completed successfully"} | select -skip 4
ForEach($member in $members){
$Results += New-Object PSObject -Property #{
Computername = $env:COMPUTERNAME
Users=$member
}
}
} -computer $i -HideComputerName # | Select * -ExcludeProperty RunspaceID
}
$Results | FT