這裏是另一種使用內核的替代方案。 微軟建議它,但它已顯示非常有效的跨越卷,掛載點和其他卷類型信息以幫助關聯磁盤和卷。
$resultVolumeMappingFromKernel = Invoke-Command -ScriptBlock $scriptBlockInvokeCommandKernel32 -ComputerName $hostName -Credential $credential -ArgumentList (,$arrayOfVolumeSerial)
它需要你想用管理員帳戶信息的遠程計算機上運行:
$scriptBlockInvokeCommandKernel32 = {
param([array]$arrayOfVolumeSerial)
$cSharpCodeKernel32GetDisk = @"
using System;
using Microsoft.Win32.SafeHandles;
using System.IO;
using System.Runtime.InteropServices;
public class GetDisk
{
private const uint IoctlVolumeGetVolumeDiskExtents = 0x560000;
private const uint HASMOREDATA = 234;
// 4 rounded to 8 + 8 + 8= 24
[StructLayout(LayoutKind.Sequential)]
public struct DiskExtent
{
public int DiskNumber;
public Int64 StartingOffset;
public Int64 ExtentLength;
}
//size 4 rounded to 8 + number of extends * 24
[StructLayout(LayoutKind.Sequential)]
public struct DiskExtents
{
public int numberOfExtents;
public DiskExtent extents;
}
//4
[StructLayout(LayoutKind.Sequential)]
public struct DiskExtentsBeforeArray
{
public int numberOfExtents;
}
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern SafeFileHandle CreateFile(
string lpFileName,
[MarshalAs(UnmanagedType.U4)] FileAccess dwDesiredAccess,
[MarshalAs(UnmanagedType.U4)] FileShare dwShareMode,
IntPtr lpSecurityAttributes,
[MarshalAs(UnmanagedType.U4)] FileMode dwCreationDisposition,
[MarshalAs(UnmanagedType.U4)] FileAttributes dwFlagsAndAttributes,
IntPtr hTemplateFile
);
[DllImport("Kernel32.dll", SetLastError = false, CharSet = CharSet.Auto)]
private static extern bool DeviceIoControl(
SafeFileHandle hDevice,
uint IoControlCode,
[MarshalAs(UnmanagedType.AsAny)] [In] object InBuffer,
uint nInBufferSize,
ref DiskExtents OutBuffer,
int nOutBufferSize,
ref uint pBytesReturned,
IntPtr Overlapped
);
[DllImport("Kernel32.dll", SetLastError = false, CharSet = CharSet.Auto)]
private static extern bool DeviceIoControl(
SafeFileHandle hDevice,
uint IoControlCode,
[MarshalAs(UnmanagedType.AsAny)] [In] object InBuffer,
uint nInBufferSize,
IntPtr outBuffer,
int nOutBufferSize,
ref uint pBytesReturned,
IntPtr Overlapped
);
[DllImport("Kernel32.dll", SetLastError = false, CharSet = CharSet.Auto)]
private static extern int GetLastError();
public static DiskExtent[] GetPhysicalDriveString(string path)
{
DiskExtent[] diskExtent = null;
path = path.TrimEnd('\\');
if (!path.StartsWith(@"\\.\"))
path = @"\\.\" + path;
SafeFileHandle safeFileHandle = CreateFile(path, FileAccess.Read, FileShare.Read | FileShare.Write, IntPtr.Zero, FileMode.Open, 0,
IntPtr.Zero);
if (safeFileHandle.IsInvalid)
{
Exception e = Marshal.GetExceptionForHR(Marshal.GetLastWin32Error());
}
uint bytesReturned = new uint();
DiskExtents VOLUME_DISK_EXTENTS = new DiskExtents();
bool result = DeviceIoControl(
safeFileHandle,
IoctlVolumeGetVolumeDiskExtents,
IntPtr.Zero,
0,
ref VOLUME_DISK_EXTENTS,
Marshal.SizeOf(VOLUME_DISK_EXTENTS),
ref bytesReturned,
IntPtr.Zero);
if (result)
{
diskExtent = new DiskExtent[1];
diskExtent[0] = VOLUME_DISK_EXTENTS.extents;
}
else
{
int numberOfExtents = VOLUME_DISK_EXTENTS.numberOfExtents;
int lastError = GetLastError();
if (lastError == HASMOREDATA)
{
int size = 8 + 24 * numberOfExtents;
uint bytesReturned2 = new uint();
IntPtr blob = default(IntPtr);
blob = Marshal.AllocHGlobal(size);
bool resultMutipleDiskExtent = DeviceIoControl(
safeFileHandle,
IoctlVolumeGetVolumeDiskExtents,
IntPtr.Zero,
0,
blob,
(int)size,
ref bytesReturned2,
IntPtr.Zero
);
if (resultMutipleDiskExtent)
{
DiskExtentsBeforeArray lie = default(DiskExtentsBeforeArray);
lie = (DiskExtentsBeforeArray)Marshal.PtrToStructure(blob, typeof(DiskExtentsBeforeArray));
diskExtent = new DiskExtent[lie.numberOfExtents];
for (int i = 0; i <= lie.numberOfExtents - 1; i++)
{
IntPtr offset = new IntPtr(blob.ToInt64() + 8 + 24 * i);
diskExtent[i] = (DiskExtent)Marshal.PtrToStructure(offset, typeof(DiskExtent));
}
}
}
else{
throw new System.ComponentModel.Win32Exception();
}
}
safeFileHandle.Close();
return diskExtent;
}
}
"@
$resultOfOperation [email protected]{}
$volumeKernelInfo [email protected]{}
$type = Add-Type -TypeDefinition $cSharpCodeKernel32GetDisk -ErrorAction Continue -ErrorVariable errorAddType -PassThru
if($errorAddType){
$resultOfOperation["error"]= ("error at CsharpBuild" + $errorAddType)
}
foreach($volumeSerial in $arrayOfVolumeSerial){
$volumeString = "Volume{" + $volumeSerial + "}"
$volumeKernelInfo[$volumeSerial] = [GetDisk]::GetPhysicalDriveString($volumeString)
}
$resultOfOperation["volumeKernelInfo"]=$volumeKernelInfo
return $resultOfOperation
}
你可以調用它。
我試圖使用這個,但格式似乎有點關閉。上面的部分(在'function'之上)意味着是另一個腳本/函數的一部分,因爲有'return'語句。 – GregL
你說得對。我編輯了一個我現在使用的代碼的摘要。我不能把它全部放在這裏,因爲它是900行代碼,意味着要在運行各種Windows操作系統的遠程計算機上運行。位轉換器部分非常重要,因爲以前的版本可能無法正確轉換它。 – Alex