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}
Related
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
I am storing the following query value in a variable:
$unquotedPaths = Get-WmiObject -Class Win32_Service | Select-Object -Property Name,DisplayName,PathName,StartMode | Select-String "auto"
The problem starts when i print that variable becouse the variable takes from the query an object which is formed by hashtables like in this output:
PS C:\Users\pc> Get-WmiObject -Class Win32_Service | Select-Object -Property Name,DisplayName,PathName,StartMode | Select-String "auto"
#{Name=AGMService; DisplayName=Adobe Genuine Monitor Service; PathName="C:\Program Files (x86)\Common Files\Adobe\AdobeGCClient\AGMService.exe"; StartMode=Auto}
#{Name=AGSService; DisplayName=Adobe Genuine Software Integrity Service; PathName="C:\Program Files (x86)\Common Files\Adobe\AdobeGCClient\AGSService.exe"; StartMode=Auto}
#{Name=asComSvc; DisplayName=ASUS Com Service; PathName=C:\Program Files (x86)\ASUS\AXSP\1.01.02\atkexComSvc.exe; StartMode=Auto}
#{Name=AudioEndpointBuilder; DisplayName=Compilador de extremo de audio de Windows; PathName=C:\WINDOWS\System32\svchost.exe -k LocalSystemNetworkRestricted -p; StartMode=Auto}
How i can get and output like this:
Name DisplayName PathName Startmode
---------- ------------- ------------ ------------
ExampleName ExampleDisplayName C:\Example Auto
Select-String is meant to search and match patterns among strings and files, If you need to filter an object you can use Where-Object:
$unquotedPaths = Get-WmiObject -Class Win32_Service |
Where-Object StartMode -EQ Auto |
Select-Object -Property Name,DisplayName,PathName,StartMode
If the filtering required more complex logic you would need to change from Comparison Statement to Script Block, for example:
$unquotedPaths = Get-WmiObject -Class Win32_Service | Where-Object {
$_.StartMode -eq 'Auto' -and $_.State -eq 'Running'
} | Select-Object -Property Name,DisplayName,PathName,StartMode
I have tried get-volume, wmi/cim etc, but every example I've tried lists all volumes. What I need is a list of only the local volumes, not any cluster volumes.
Solved - code below:
$myDisks = Get-CimInstance -ClassName Win32_LogicalDisk | Where-Object –FilterScript {$.DriveType -Eq 3} | Select-Object DeviceID, VolumeName, Size, FreeSpace, #{Name="UsedSpace"; Expression={$.Size - $_.FreeSpace}} | Sort-Object -Property DeviceID
$myServer = (Get-Content env:COMPUTERNAME).ToUpper()
Import-Module FailoverClusters
$myCluster = $(Get-Cluster).Name
$myClusterDisks = Get-CimInstance -Namespace Root\MSCluster -ClassName MSCluster_Resource -ComputerName $myCluster | Where-Object –FilterScript {($.Type -eq 'Physical Disk') -and ($.OwnerNode -eq $myServer)}
$myClusterVolumes = $myClusterDisks | %{Get-CimAssociatedInstance -InputObject $_ -ResultClassName MSCluster_DiskPartition} | Select-Object Path, VolumeLabel, TotalSize, FreeSpace, #{Name="UsedSpace"; Expression={$.TotalSize - $.FreeSpace}} | Sort-Object Path
$myLocalVolumes = $myDisks | Where {$_.DeviceId -notin #($myClusterVolumes.Path)}
In some cases, local disks have a Disk Number, non-local ones do not. Therefore, to get the volumes for only the disks which exist on the local cluster, exclude the disks where the DiskNumber returned by Get-Partitions is null. In other cases, the 'AccessPaths' for the cluster volumes are null, so you can exclude the partitions with a filter on that. Then you can get the volumes matching those partitions.
$parts = Get-Partition | Where-Object -Property 'DiskNumber' -ne $null
$parts | Format-Table -AutoSize -Property 'OperationalStatus', 'Type', 'DiskNumber', 'DriveLetter', 'IsActive', 'IsBoot', 'IsHidden', 'IsOffline', 'IsShadowCopy', 'IsSystem', 'MbrType', 'NoDefaultDriveLetter', 'Offset', 'PartitionNumber', 'Size', 'TransistionState', 'AccessPaths'
$vols = Get-Volume -Path ( $parts.AccessPaths -match '^\\\\\?\\Volume{' )
$vols | Format-Table -AutoSize -Property 'OperationalStatus', 'HealthStatus', 'DriveType', 'FileSystemType', 'FileSystemLabel', 'AllocationUnitSize', 'DriveLetter', 'Size', 'SizeRemaining'
To return only volumes with drive letters, add this to the end of the first line above:
| Where-Object -Property 'DriveLetter' -ne 0x00
So i have a very simple powershell command that is looking for a specific file extension on a remote server. These remote servers have multiple logical drives (c:,e:,d: ect...) and when i run this command it works against the C: drive of the server but any drives afterwards return a single error Get-ChildItem : Cannot find drive. A drive with the name 'D' does not exist.
Command is this, any help is appreciated:
Get-WmiObject -ComputerName chsccm10 win32_logicaldisk -Filter "DriveType = 3" | Select-Object DeviceID | ForEach-Object {Get-ChildItem ($_.DeviceID + "\") -Include *.log -Recurse } | select VersionInfo
Haven't tested, but maybe something like this:
$servers = gc c:\serverlist.txt
$results = $servers | %{
invoke-command -cn $_ -scriptblock {
gwmi win32_logicaldisk -filter "DriveType = 3" |
select-object DeviceID |
Foreach-object {
Get-childitem ($_.DeviceID + "\") -include *.log -recurse } |
select VersionInfo}}
$results | out-gridview
How do I properly use $_ in out-file? Here's my code:
get-content computers.txt |
Where {$_ -AND (Test-Connection $_ -Quiet)} |
foreach { Get-Hotfix -computername $_ } |
Select CSName,Description,HotFixID,InstalledBy,InstalledOn |
convertto-csv | out-file "C:\$_.csv"
I'm trying to execute a get-hotfix for all the computers listed in the text file then I want them to be exported to CSV with the computer name as the filename.
You need one pipeline to process the computers.txt files, and a nested one inside the foreach to process the list of hotfixes for each computer:
get-content .\computers.txt |
Where {$_ -AND (Test-Connection $_ -Quiet)} |
foreach {
Get-Hotfix -computername $_ |
Select CSName,Description,HotFixID,InstalledBy,InstalledOn |
convertto-csv | out-file "C:\$_.csv"
}
Edit: Changed computers.txt to .\computers.txt, as this is required for local paths in powershell
i can see with this:
get-content .\computers.txt | Where {$_ -AND (Test-Connection $_ -Quiet)} | foreach{ Get-Hotfix -id KB4012212 -computername $_ | Select CSName,Description,HotFixID,InstalledBy,InstalledOn | convertto-csv | out-file "C:\$_.csv" }
i can see only in which PC is the fix (KB4012212) installed.
it's possible to see the following
CSNAME Fix(Inst/NotInst)
PC1 FIxInstalled
PC2 FixNotinstalled
PC3 FixnotInstalled
..
..
etc
I monkeyed with this for a while and nothing I found on-line worked until I used this combo.
I used the method is this thread but it was SO slow and I wanted to learn more about using jobs so this is what ended up working for me on Windows 7 PS Ver 4.
All other options were either too slow or did not return data from the remote system.
$VMs = get-content C:\WinVms.txt #Generate your hostnames list however you deem best.
foreach ($vm in $vms)
{
Write-Host "Attempting to get hotfixes on:" $vm
invoke-command -computername $vm -ScriptBlock {start-job -scriptblock {(get-hotfix | sort installedon)[-1]} | wait-job | receive-job} -AsJob
}
start-sleep 60 # give it a minute to complete
get-job | ? { $_.state -eq "Completed"} | receive-job -keep | export-csv c:\temp\win-patch.csv
you can check your failures too like this:
get-job | ? { $_.state -eq "Failed"}