MSFT_Volume格式化方法,在WinPE中

MSFT_Volume Format Method, in WinPE

我希望可能有一些见解,也许对我的查询有所帮助。

我正在尝试将最后一个模块写入自定义 Windows 恢复环境,基于 Windows 10 的 WinPE。

该解决方案目前利用 DiskPart 创建磁盘分区(符合 Microsoft 的建议 here),更改为不提供 WinRE 分区。

在对 MSDN 上找到的项目进行大量研究和修改后,我设法获得了一个工作项目,该项目将 clear/partition 并使用 WMI 格式化磁盘(MSFT_Disk,MSFT_Partition & MSFT_Volume).这在 15 GiB 大小的虚拟磁盘上 Windows 10 内完全有效。

当我在 WinPE 中尝试它时(因为这将是它将在其上使用的 OS),它在多个元素上失败,即使方法被报告为在那里)。 (MSFT_Disk::清除,MSFT_Volume::Format)。

检查我在 DiskPart 中的工作结果时,我注意到即使 MSFT_Volume::Format 的 return 值为 2 "Unknown Error" 它实际上格式化了数据分区(NTFS,集群大小 4096)。但是,当将 Format 方法应用于 ESP(FAT32,簇大小 512/1024/4096)时,它会完全失败,文件系统仍被报告为 RAW,但会应用 AccessPath。 "ExtendedStatus" 只有 return 错误 2(除非我没有正确访问它)。

有没有其他人遇到过这个问题并设法解决了这个问题?多次 Google 搜索排除了可能存在 WMI 错误的想法,但在 PowerShell 中,而不是在 C#/C++ 中编码。下面是一些代码片段和屏幕截图:

正在创建分区:

try
{
    parameters = disk.GetMethodParameters("CreatePartition");
}
catch (Exception e)
{
    Console.WriteLine("Exception in Line 88: " + e.Message);
}
if (PartitionType != "PRIMARY")
{
    FillInvocationParameters(parameters, new Dictionary<string, object> { { "Size", _partitionSize.ToString() },
                                                                          { "AssignDriveLetter", false },
                                                                          { "GpTType", _partitionType} });
} 
else
{
    FillInvocationParameters(parameters, new Dictionary<string, object> { { "UseMaximumSize", true },
                                                                          { "AssignDriveLetter", false },
                                                                          { "GpTType", _partitionType} });
}
try
{
    res = disk.InvokeMethod("CreatePartition", parameters, null);
    objresult = res["ReturnValue"]; //write error handliong routine for the objResult.
    Int32.TryParse(objresult.ToString(), out intRes);
}
catch (Exception e)
{
    Console.WriteLine("Exception in Line 146: " + e.Message);
    ErrorID = Marshal.GetLastWin32Error();
    return false;
}
if (intRes != 0)
{
    Console.Write("CreatePartition {0} failed with the result: {1} Line 111.", PartitionType, objresult.ToString());
    Console.ReadKey();
    ErrorID = Marshal.GetLastWin32Error();
    return false;
}
//this is the format point for EFI System Disk.. MSFTPARTITIONtoVOLUME MSFT VOLUME::FORMAT

Console.Write($"{PartitionType} Partition has been created\r\n");

string partition   = ((ManagementBaseObject)res["CreatedPartition"])["__PATH"] as string;
var MSFT_Partition = new ManagementObject(@"root\Microsoft\Windows\Storage", partition, null);
var partitionIndex = partition.IndexOf(@"ObjectId=\");

partition      = partition.Substring(partitionIndex);
partitionIndex = partition.IndexOf(@"}\");
partitionIndex = partitionIndex + 1;
partition      = partition.Substring(0, partitionIndex);

var strMSFTPartition = partition;
partition = partition.Replace("root", "ROOT");

var partitionGuid = MSFT_Partition["Guid"] as string;
Console.WriteLine("Line 138: New Partition GUID: " + partitionGuid);

参数声明为:

 ManagementBaseObject parameters = null;

FillInvokationParamters:

private static void FillInvocationParameters(ManagementBaseObject InvocationParameters, IDictionary<string, object> parameters)
{
    foreach (var pair in parameters)
    {
        string stringParamValue;

        var managementObjectParam = pair.Value as ManagementObject;
        var arrayParam = pair.Value as string;

        if (managementObjectParam != null)
        {
            stringParamValue = managementObjectParam.GetText(TextFormat.CimDtd20);
            InvocationParameters[pair.Key] = stringParamValue;
        }
        else if (arrayParam != null)
            InvocationParameters[pair.Key] = arrayParam;
        else if (pair.Value != null)
        {
            stringParamValue = pair.Value.ToString();
            InvocationParameters[pair.Key] = stringParamValue;
        }
    }
}

格式方法调用:

try
{
    Console.Write("Line 174: Attempting to Format with MSFT_Volume::Format FileSystem {0}, Label: {1}, ClusterSize: {2}\r\n", _FileSystem, _VolumeLable, _allocationUnit.ToString());
    parameters = MSFTVolume.GetMethodParameters("Format");

    FillInvocationParameters(parameters, new Dictionary<string, object>{ { "FileSystem", _FileSystem },
                                                                             { "AllocationUnitSize", _allocationUnit },
                                                                             { "FileSystemLabel", _VolumeLable },
                                                                             { "Full", false} });

    res = MSFTVolume.InvokeMethod("Format", parameters, null);
    objresult = res["ReturnValue"];

    Int32.TryParse(objresult.ToString(), out intReslt);
}
catch (Exception e)
{
    Console.WriteLine("Line: 189 The Following error occured while attmpeting to Format the Volume: " + e.Message);
    ErrorID = Marshal.GetLastWin32Error();
    return false;
}

对于 ESP,以下内容适用:

switch(PartitionType)
{
    case "EFI":
    {
        _partitionType  = "{c12a7328-f81f-11d2-ba4b-00a0c93ec93b}";
        _partitionSize  = 260 /*bytes*/ *1024 /*Kilobytes*/ *1024 /*Megabytes*/;
        _FileSystem     = "FAT32";
        _allocationUnit = 1024;
        _VolumeLable    = "System";
        break;
    }
}

我的控制台应用程序和 diskpart 结果的屏幕截图:

Format Disk Console output

DiskPart Results

任何 help/insights 将不胜感激。

此致

里奇

请注意,对于 Windows 10 的较新版本,有多个 ADK 版本...请务必使用最新和最好的版本。我们在 dism.exe 和 diskpart.exe 上遇到了与您类似的问题。有一次,(早期赢得 10 个 adks)我们从一个 8.1 adk 得到了 dism.exe 和 diskpart.exe。虽然很老套,但你必须做你必须做的事:-)

更新:

与支持小组核实...事实证明,我搞混了版本。第一个 win 10 adk 有一个可用的 dism 和 diskpart(adk for windows 10 1503)...我们一直无法在 PE 中使用 newer ...所以我们仍然从新的 ADK 部署一个新的 winpe - 但从 1503 adk 中复制了 diskpart 和 dism。我们从未部署过 8.1 版本——我的错。仍然 - 像所有 git 一样 hacky。

据我们所知,它只在房子的一侧出现问题...要么是 BIOS+MBR,要么是 UEFI+GPT...但我们 none 记得是哪一个。