Question

I have an Exchange server with lots of mountpoints. Given the path to the database files is there a way to find out what volume they are on? The problem is that they are typically not at the volume mount point, but further down the tree. I'm using Powershell, so I need a solution preferably using WMI but could also use any .NET or COM objects.

Was it helpful?

Solution 2

I'd just discovered the ReparsePoint attribute.

After grabbing the directory I'm in, I can walk up the tree untill I get to Root and check for ReparsePoints along the way.

$dbDir = (get-item (Get-MailboxDatabase $db).edbfilepath).directory
$dbDir
if($dbdir.parent){
  #todo make this recursive
}

#test if it's a reparse point.    
if ($dbdir.attributes -band [System.IO.FileAttributes]::ReparsePoint ){
  #it's a mountpoint.
}

From here there's the "mountvol /L" tool, or better the WMI Association class Win32_MountPoint and Win32_Volume.

A bit involved- but I don't see a simple way to just ask "what volume am I on?" Once I get it all put together, I'll post a full explanation.

edit - more details here: http://slipsec.com/blog/?p=126

OTHER TIPS

PSCX includes a Get-ReparsePoint cmdlet:

C:\temp> Get-ReparsePoint d | ft -auto

Target                                           Path      ReparsePointTag
------                                           ----      ---------------
\??\Volume{a5908e7a-eca5-11dd-be98-005056c00008} C:\temp\d      MountPoint

You can map volume GUIDs to familiar drive names using the registry:

Get-ItemProperty HKLM:\SYSTEM\MountedDevices

[...]
\DosDevices\D:                                   : {22, 35, 171, 65...}
[...]
\??\Volume{a5908e7a-eca5-11dd-be98-005056c00008} : {22, 35, 171, 65...}

Putting things together, we can get the serial # of the physical drive that's mounted at c:\temp\d:

$guid = (Get-ReparsePoint d).target
$serial = (get-itemproperty HKLM:\SYSTEM\MountedDevices).$guid

You can compare that serial against the serial numbers of the other logical volumes such as the ones with DOS letters.

> function ArrayEqual([psobject[]]$arr1, [psobject[]]$arr2) 
      { @(Compare-Object $arr1 $arr2 -sync 0).Length -eq 0 }

> (gi HKLM:\SYSTEM\MountedDevices).property | ?{ $_ -like "\dos*" } | 
      ?{ ArrayEqual$serial (gp HKLM:\SYSTEM\MountedDevices).$_ }

\DosDevices\D:

See Keith Hill's blog for an explanation of the array comparison function.

For completeness, note this does NOT seem to be the same serial reported by COM...

> $comSerial = (new-object -com scripting.filesystemobject).getdrive("d")
> [bitconverter]::GetBytes($comSerial)
18
208
242
202
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top