Метод формата MSFT_Volume в WinPE

Я надеюсь, что может быть некоторое понимание и, возможно, помощь в отношении моего запроса.

Я пытаюсь записать последний модуль в настраиваемую среду восстановления Windows на основе WinPE для Windows 10.

В настоящее время решение использует DiskPart для создания разделов диска (согласно рекомендациям Microsoft здесь), с изменением отсутствия раздела WinRE.

После изрядного количества исследований и работы с проектом, найденным в MSDN, мне удалось получить работающий проект, который очищал/разбивал и форматировал диск с помощью WMI (MSFT_Disk, MSFT_Partition и MSFT_Volume). Это полностью работает в Windows 10 на виртуальном диске размером 15 ГБ.

Когда я попробовал это в WinPE (поскольку это будет ОС, на которой он будет использоваться), он не удался на нескольких элементах, хотя методы были указаны там). (MSFT_Disk::Clear, MSFT_Volume::Format).

Изучив результат своей работы в DiskPart, я заметил, что хотя MSFT_Volume::Format возвращало значение 2 «Неизвестная ошибка», на самом деле он отформатировал раздел данных (NTFS, ClusterSize 4096). Однако, когда метод форматирования применяется к ESP (FAT32, размер кластера 512/1024/4096), происходит полный сбой, при этом файловая система по-прежнему отображается как RAW, но применяется AccessPath. «ExtendedStatus» возвращает только ошибку 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;

Параметры FillInvokation:

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:

Форматировать вывод Disk Console

Результаты DiskPart

Любая помощь / идеи будут с благодарностью оценены.

С уважением

Ричи


person R.McInnes-Piper    schedule 13.07.2018    source источник
comment
Не могли бы вы посоветовать, как лучше отформатировать код, пожалуйста. Это не моя повседневная работа, а проект, возникший из-за того, что мне пришлось купить новую версию Windows и жесткий диск, так как он провалился, пока я долгое время находился за пределами Великобритании. Я не только заново изучаю кодирование, но и совершенно новый язык.   -  person R.McInnes-Piper    schedule 19.07.2018
comment
Я бы подумал, что здравый смысл заключается в том, что все, что имеет отступ в 30 вкладок, затрудняет чтение и выглядит ужасно. Когда вы копируете из текстового редактора в Stack Overflow, вкладки также копируются, поэтому все имеет отступ. Вы можете использовать sharplab.io и использовать Shift-Tab, чтобы переместить его, чтобы он имел правильный отступ.   -  person AustinWBryan    schedule 21.07.2018
comment
Спасибо, AustinWBryan - я буду иметь это в виду, хорошая конструктивная критика (с решением), это то, что мне нужно, чтобы помочь опубликовать в StackOverflow в будущем. Тот, кто написал о том, что код ужасно отформатирован и не предлагает решения / не указывает на возможное решение, не очень помог.   -  person R.McInnes-Piper    schedule 22.07.2018
comment
Добро пожаловать. Я отредактировал сообщение, чтобы улучшить форматирование. Вот так это должно выглядеть в следующий раз. Кроме того, примечание: return не является функцией, поэтому вам не нужно выполнять return (false), достаточно return false. И вместо if (!(x == 3)) просто сделайте if (x != 3).   -  person AustinWBryan    schedule 23.07.2018


Ответы (1)


Обратите внимание, что существует несколько сборок ADK для более новых сборок Windows 10... обязательно используйте самую последнюю и самую лучшую. У нас были проблемы, подобные вашей, как с dism.exe, так и с diskpart.exe. В какой-то момент (на ранней версии win 10 adk) мы получили dism.exe и diskpart.exe из adk 8.1. Хак как черт, но вы должны делать то, что должны делать :-)

Обновление:

Проверил в группе поддержки... оказывается, перепутал версии. У самого первого adk для win 10 были работающие dism и diskpart (adk для windows 10 1503)... и мы не могли использовать новые из PE с тех пор... и поэтому мы' re по-прежнему развертывает новый winpe из нового ADK, но копирование в diskpart и dism сохранено из ADK 1503. Мы никогда не развертывали версии 8.1 — это плохо. Еще - халтурно, как все говно.

Насколько мы можем вспомнить, это представляло проблему только в одной части дома... либо в BIOS+MBR, либо в UEFI+GPT... но никто из нас не помнит, в какой именно.

person Clay    schedule 19.07.2018
comment
Я пытался использовать последнюю версию ADK, она сломала сборку. Я еще не пытался использовать его повторно, так как, по сути, программное обеспечение работает с DiskPart. У меня есть ощущение, что это вполне может быть проблема с тестовой средой, поэтому в настоящее время я удаленно загружаю старый ноутбук, чтобы увидеть, проявляется ли проблема снова. Если это так, то я знаю, что это проблема с Virtual Box. - person R.McInnes-Piper; 19.07.2018
comment
Изучив вывод моей консоли, и виртуальная машина, и живая удаленно загруженная система сообщают о разделе EFI как о USB-хранилище (либо это, либо USB-диск по какой-то причине имеет один и тот же GUID!). Когда я повторяю/перечисляю WMI MSFT_Volume и действительно связываю строку сравнения, она работает, находит том, но возвращает код ошибки 2 Unspecified Error. - person R.McInnes-Piper; 19.07.2018
comment
Похоже, это была сборка WinPE. Мне удалось создать работающую WinPE (версия 1803) — без каких-либо настроек, приложение тестового стенда работало, но сначала требуется установить максимальную мощность в системе. Теперь нужно спроектировать и реализовать подпрограмму обратного вызова для интеграции результатов в графический интерфейс без изменения базового кода. Спасибо Клэй. - person R.McInnes-Piper; 20.07.2018
comment
Отлично - 1803 у нас тоже работает чисто. Ваш вопрос побудил нас попробовать удалить хакерскую вставку dism/diskpart... и здесь тоже все работает нормально... так что спасибо, yerseff! - person Clay; 20.07.2018
comment
Я пытаюсь отойти от Diskpart, уже отошел от DISM - мне удалось реализовать wimgapi на C # (ну, небольшое количество функций, позволяющих делать то, что я хочу). Я еще не на полную мощность для пакета - так что не все реализовано. Следующим этапом после интеграции WMI Disk Management является создание более надежной записи для удаленной загрузки и доступа к исходным образам. - person R.McInnes-Piper; 20.07.2018
comment
Я считаю, что базовая реализация diskpart одинакова, независимо от того, приходите ли вы к ней через wmi или через сценарии diskpart... и в основном поэтому я предсказал, что вы добьетесь успеха с фиксированным winpe :-) Достаточно забавно, мы используем только dism, чтобы поместить постоянный winpe в отдельный раздел в начале цикла создания образа. У нас есть собственная дедуплицированная база данных образов, которая разделяет осколки со всеми корпоративными образами. Постепенно стало очень круто. Мы посмотрели на wimgapi, но все стало на 100% странным... часть того, как мы отличаемся друг от друга. Мир! - person Clay; 20.07.2018
comment
Так начался этот проект, отказавший жесткий диск (без предупреждений). Я начал с ImageX (возвращаясь немного назад — пытался портировать его на Pascal — но сдался, когда заявил, что нужно определить слишком много), затем DISM по сценарию. Начал играть с wimgapi чуть меньше года назад. Спасибо за ваши советы, рад, что мой вопрос побудил вас по-новому взглянуть на ваш дистрибутив WinPE. - person R.McInnes-Piper; 20.07.2018