In DISKPART.EXE, I get the info when multiple mount points are assigned to a volume. In the picture we see that Drive G: can also be accessed using D:\SQL\MSSQL13.MSSQLSERVER\DATA\ or D:\BlaBla:
But I can't find the same info using PowerShell's Get-Volume or Get-WMIObject -Class Win32_Volume. Does anyone knows how to extract this info using a native PowerShell function?
I thought of extracting the info by calling DISKPART.EXE inside PowerShell but I would prefer an native PowerShell function like Get-Volume.
Perhaps surprisingly, you can look up mount points via the Win32_MountPoint class:
Get-WmiObject Win32_MountPoint | Select-Object Directory, Volume
Further details can be obtained by looking up the references:
Get-WmiObject Win32_MountPoint | ForEach-Object {
$dir = [wmi]$_.Directory | Select-Object -Expand Name
$vol = [wmi]$_.Volume
New-Object -Type PSObject -Property #{
Directory = $dir
Label = $vol.Label
DriveLetter = $vol.DriveLetter
FileSystem = $vol.FileSystem
DeviceId = $vol.DeviceId
}
}
Related
Is there a way to get mapped network drives labels?
I know it's possible to get multiple properties through the
Get-Object Win32_MappedLogicalDisk
But none of them are labels (please do not misunderstand, I do not want Name i.e. K:, I want labels i.e. My Network drive)
You could use the Com Shell.Application object for this:
$shell = New-Object -ComObject Shell.Application
(Get-WmiObject -Class Win32_MappedLogicalDisk).DeviceID |
# or (Get-CimInstance -ClassName Win32_MappedLogicalDisk).DeviceID |
# or ([System.IO.DriveInfo]::GetDrives() | Where-Object { $_.DriveType -eq 'Network' }).Name |
Select-Object #{Name = 'Drive'; Expression = {$_}},
#{Name = 'Label'; Expression = {$shell.NameSpace("$_").Self.Name.Split("(")[0].Trim()}}
# when done, clear the com object from memory
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($shell)
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
Output:
Drive Label
----- -----
X: MyCode
Some explanation for the above:
Using the COM object Shell.Application, you can drill down through its properties and methods.
.NameSpace create and return a Folder object for the specified folder
.Self gets a Read-Only duplicate System.Shell.Folder object
.Name from that we take the Name property like 'MyCode (X:)'
.Split this name we split on the opening bracket '(',
[0] take the first part of the splitted name and
.Trim() get rid of any extraneous whitespace characters
Another way is to go into the registry, but remember that after a mapped network folder is unmapped, the old registry value remains.
This is why below code still uses one of two methods to find active network mappings first:
# the registry key to search in
$regKey = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2'
# list the mapped network drives and loop through
# you can also use Get-CimInstance -ClassName Win32_MappedLogicalDisk
Get-WmiObject -Class Win32_MappedLogicalDisk | ForEach-Object {
# create the full registry key by replacing the backslashes in the network path with hash-symbols
$key = Join-Path -Path $regKey -ChildPath ($_.ProviderName -replace '\\', '#')
# return an object with the drive name (like 'X:') and the Label the user gave it
[PsCustomObject]#{
Drive = $_.DeviceID
Label = Get-ItemPropertyValue -Path $key -Name '_LabelFromReg' -ErrorAction SilentlyContinue
}
}
Output here also:
Drive Label
----- -----
X: MyCode
I am not aware of a cmdlet that will give you that info. I believe you can find it by looking at the registry with gci, but you would need to cleanup the output.
get-childitem "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2"
When I execute this powershell command to get a list of running COM objects that match the prefix "Python", I get the following output:
PS C:\Users\{path-to-arbitrary-directory}> Get-ChildItem HKLM:\Software\Classes | Where-Object {
$_.PSChildName -match '^Python[\.a-zA-Z]*$' } | Select-Object
Hive: HKEY_LOCAL_MACHINE\Software\Classes
Name Property
---- --------
Python (default) : Python ActiveX Scripting Engine
Python.Dictionary (default) : Python Dictionary
Python.Interpreter (default) : Python Interpreter
Python.TestServer (default) : Python Test COM Server
What I would like to do is just get a list of the Name and Description.
Currently I am able to get the names with this command:
PS C:\Users\{path-to-arbitrary-directory}> Get-ChildItem HKLM:\Software\Classes | Where-Object {
$_.PSChildName -match '^Python[\.a-zA-Z]*$' } | Select-Object PSChildName,Property
PSChildName Property
----------- --------
Python {(default)}
Python.Dictionary {(default)}
Python.Interpreter {(default)}
Python.TestServer {(default)}
But I can't for the life of me figure out how to show the Descriptions that I see when I execute the 1st command?
This is the output I would want:
Name Description
---- --------
Python Python ActiveX Scripting Engine
Python.Dictionary Python Dictionary
Python.Interpreter Python Interpreter
Python.TestServer Python Test COM Server
(if it helps anyone, I am also able to view the description with this command)
PS C:\Users\{path-to-arbitrary-directory}> Get-ChildItem HKLM:\Software\Classes | Where-Object {
$_.PSChildName -match '^Python[\.a-zA-Z]*$' } | Get-ItemProperty
(default) : Python ActiveX Scripting Engine
PSPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Classes\Python
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Classes
PSChildName : Python
PSProvider : Microsoft.PowerShell.Core\Registry
...
One way to do this is the use of calculated properties. You can use Get-ItemProperty to get the value of the (default) registry key property. Then you can show this value as a calculated property.
Get-ChildItem HKLM:\software\Classes\ |
Where-Object {$_.PSChildName -match 'document'} |
Select-Object PSChildName, #{Name = "Default"; Expression = {($_ | Get-ItemProperty)."(default)"}}
Try this out. Things like this are better in functions.
function Get-COMDescription {
Param(
[parameter(Mandatory=$true)][string]$Search
)
Get-ChildItem HKLM:\Software\Classes | Where-Object {
# Match naming convention for COM Object ensure they key has a CLSID folder.
$_.PSChildName -match "^$Search\.\w+$" -and (Test-Path -Path "$($_.PSPath)\CLSID") } |
Select-Object PSChildName,#{l="Description";e={$_ | Get-ItemProperty | select -ExpandProperty "(default)" }}
}
Usage example:
PS C:\> Get-COMDescription -Search GoogleUpdate
PSChildName Description
----------- -----------
GoogleUpdate.CoCreateAsync CoCreateAsync
GoogleUpdate.CoreClass Google Update Core Class
GoogleUpdate.CoreMachineClass Google Update Core Class
GoogleUpdate.CredentialDialogMachine GoogleUpdate CredentialDialog
GoogleUpdate.OnDemandCOMClassMachine Google Update Broker Class Factory
GoogleUpdate.OnDemandCOMClassMachineFallback Google Update Legacy On Demand
GoogleUpdate.OnDemandCOMClassSvc Google Update Legacy On Demand
GoogleUpdate.PolicyStatus Google Update Policy Status Class
GoogleUpdate.ProcessLauncher Google Update Process Launcher Class
GoogleUpdate.Update3COMClassService Update3COMClass
GoogleUpdate.Update3WebMachine Google Update Broker Class Factory
GoogleUpdate.Update3WebMachineFallback GoogleUpdate Update3Web
GoogleUpdate.Update3WebSvc GoogleUpdate Update3Web
The existing answers are helpful, but let me add some background information:
The reason that the default output shows the target keys' values is that the default output formatting enumerates them, as this command reveals:
(Get-FormatData Microsoft.Win32.RegistryKey -PowerShellVersion $PSVersionTable.PSVersion).FormatViewDefinition.Control.Rows.Columns.DisplayEntry.Value
This shows:
PSChildName # column 1 - below is the script block that defines column 2
$result = (Get-ItemProperty -LiteralPath $_.PSPath |
Select * -Exclude PSPath,PSParentPath,PSChildName,PSDrive,PsProvider |
Format-List | Out-String | Sort).Trim()
$result = $result.Substring(0, [Math]::Min($result.Length, 5000) )
if($result.Length -eq 5000) { $result += "..." }
$result
As you can see, Get-ItemProperty is called behind the scenes to enumerate a key's values.
As an aside: This method of enumerating values as part of the formatting leads to incorrect output when retrieving values from a remote registry - see this answer.
While calling Get-ItemProperty in the script block of a calculated property, as shown in the other answers, definitely works, there is a more efficient alternative: You can call the .GetValue() method of the Microsoft.Win32.RegistryKey instances that Get-Item outputs:
Get-ChildItem HKLM:\Software\Classes |
Where-Object PSChildName -match '^Python[\.a-z]*$' |
Select-Object #{ n='Name'; e='PSChildName' },
#{ n='(default)'; e={ $_.GetValue('') } }
I'm trying to get a list of drive letters in a drop-down menu. I'm currently using the code below and it works just fine in Windows 10, but doesn't work at all in Windows 7.
$Drive_Letters = Get-WmiObject Win32_LogicalDisk
ForEach ($Drives in $Drive_Letters.DeviceID) { $Dest_Drive_Box.Items.Add($Drives) }
In Win 7 I tried adjusting the code to this...
$Drive_Letters = Get-WmiObject Win32_LogicalDisk | Select-Object DeviceID
ForEach ($Drives in $Drive_Letters) { $Dest_Drive_Box.Items.Add($Drives) }
But now it shows "#DeviceID=C:}", "#DeviceID=D:}", etc. in Win 7 and 10 for each drive letter. I need to just show "C:", "D:", etc.
Thanks!
Get-PSDrive
This will return all drives mapped in the current session. The Name property contains the drive letter.
To capture just drive letters:
(Get-PSDrive).Name -match '^[a-z]$'
Tested working in PSv2:
Get-PSDrive | Select-Object -ExpandProperty 'Name' | Select-String -Pattern '^[a-z]$'
$drives = (Get-PSDrive -PSProvider FileSystem).Root
returns an array for drives with the root path:
C:\
D:\
E:\
You can easily trim the ending if you don't want it.
$Drives = Get-WmiObject Win32_Logicaldisk | % {$_.DeviceId}
$Drives | % {$Dest_Drive_Box.Items.Add($_)}
It would appear that each item $drives is a HashTable with one Key-Value Pair DeviceID = driveletter a quick test shows that using $Drives.DeviceID returns just the value of the key-value pair.
ForEach ($Drives in $Drive_Letters) { $Dest_Drive_Box.Items.Add($Drives.DeviceID) }
I am trying to get the location of currently running process on your computer using PowerShell.
Example
C:\Program Files (x86)\Mozilla Firefox
C:\Windows\sysWOW64\WindowsPowerShell\v1.0
C:\Program Files (x86)\Internet Explorer
When I run the command
$path = Get-Process | Select-Object Path
Split-Path $path
I get the following output, which I not what I want. Why does it add #{Path=?
#{Path=C:\Program Files (x86)\Mozilla Firefox
#{Path=C:\Windows\sysWOW64\WindowsPowerShell\v1.0
#{Path=C:\Program Files (x86)\Internet Explorer
When I run Split-Path as follows, it gives me the correct output C:\Windows\sysWOW64\WindowsPowerShell\v1.0.
$pshpath = "C:\Windows\sysWOW64\WindowsPowerShell\v1.0\powershell.exe"
Split-Path $pshpath
$path = Get-Process | Select-Object Path
returns an array of objects. Each object in the array will have the property 'Path' along with an optional value.
The 'path' parameter of split-path takes 'string' arguments so when you run
Split-Path $path
i guess each object is being converted to type string so you get the hashtable format output.
split-path can accept path values from pipeline by property name so you can do:
$path | Split-path
if you just want the path perhaps you could try:
Get-Process | Select-Object -ExpandProperty Path
To get a list of all paths just use:
ps | % {$_.Path}
or full syntax:
Get-Process | ForEach-Object {$_.Path}
when using:
$path = Get-Process | Select-Object Path
lets look at what $path is:
$path | Get-Member
and you get:
TypeName: Selected.System.Diagnostics.Process
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Path NoteProperty System.String Path=C:\windows\system32\atieclxx.exe
so Path is not a String but a NoteProperty, I guess that's why you can't use Split-Path directly.
Another way of getting the path is by doing something like this:
(Get-Process -Name firefox).path
But, since one process can appear multiple times (I'm looking at you, chrome.exe), you'd get the same path repeated as many times as the process appears in the process list. IMO, a better way of getting the path is by process id (1234 as an example):
(Get-Process -Id 1234).path
Or, if you're not sure what your process' id is, you could loop through all the running processes, and then check each of them individually, piping the results to a file, for later analysis. For example:
$processList = Get-Process #let's get all the processes at once
$newline = "`r`n"
$tabChar = "`t"
$separator = "--------"
$file = "C:\Users\Admin\Desktop\proc-loc.txt" # where do we want to pipe out the output
Write-Output "Processes $newLine $separator" > $file # out with the previous contents of the file, let's start anew
# let's loop through the list, and pick out the stuff we need
foreach($item in $processList) {
$itemObject = $item | Select-Object
$itemName = $itemObject.Name
$itemId = $itemObject.Id
$itemPath = (Get-Process -Id $itemId).path
Write-Output "$itemId $tabChar $itemName $tabChar $itemPath" >> $file
}
If you're interested in getting the running services as well, you could expand on the previous bit, with this:
$serviceList = Get-WmiObject win32_service | Where {$_.state -eq "Running"}
Write-Output "$newline $newline Services $newline $separator" >> $file
foreach($item in $serviceList) {
$itemName = $item.Name
$itemId = $item.ProcessId
$itemPath = $item.PathName
Write-Output "$itemId $tabChar $itemName $tabChar $itemPath" >> $file
}
One thing to note, though - this won't give you a path for each and every process currently running on your system. For example, SgrmBroker, smss, System and some instances of svchost won't have a path attached to them in your output file.
Just remove that split-path command and give a object parameter as stated below.
$path = Get-Process | Select-Object Path
$path.path
And output would be as stated below.
C:\Program Files (x86)\Citrix\ICA Client\SelfServicePlugin\SelfServicePlugin.exe
C:\WINDOWS\system32\SettingSyncHost.exe
C:\Windows\SystemApps\ShellExperienceHost_cw5n1h2txyewy\ShellExperienceHost.exe
C:\WINDOWS\system32\sihost.exe
C:\WINDOWS\system32\svchost.exe
C:\WINDOWS\system32\svchost.exe
C:\WINDOWS\system32\svchost.exe
I am generating a report where I need to find which servers has mountpoints configured on it..
can you help how to get that infor using WMI or powershell.
I mean I need to identify the servers, if mountpoints exists in it.. and also their names....
Get a list of all servers from textfile, AD, etc. and run a foreach loop with something like this:
Get-Wmiobject -query “select name,driveletter,freespace from win32_volume where drivetype=3 AND driveletter=NULL” -computer servername
A quick google search for "windows mount point wmi" would return THIS (source).
Then export the results to CSV, HTML or whatever you need. Your question is lacking a lot of details and any sign of effort from your part, so I can't/won't go any further.
UPDATE: Does this help? It lists mount points(folder paths, not driveletters).
$servers = #("server1","server2","server3","server4","server5")
$servers | % {
$mountpoints = #(Get-WmiObject Win32_MountPoint -ComputerName $_ | Select-Object -ExpandProperty Directory | ? { $_ -match 'Win32_Directory.Name="(\w:\\\\.+)"' }) | % { [regex]::Match($_,'Win32_Directory.Name="(\w:\\\\.+)"').Groups[1].Value -replace '\\\\', '\' }
if($mountpoints.Count -gt 0) {
New-Object psobject -Property #{
Server = $_
MountPoints = $mountpoints
}
}
}
Server MountPoints
------ -----------
{server1} {D:\SSD, C:\Test}