Как получить DefragAnalysis с помощью C # - PullRequest
5 голосов
/ 29 февраля 2012

В настоящее время я занимаюсь разработкой приложения на C # (.NET 4.0), которое должно иметь в качестве части своей функциональности возможность определять процент фрагментации на конкретном томе. Все остальные функции были протестированы и работают нормально, но я попал в ловушку, пытаясь получить доступ к этим данным. В идеале я бы предпочел использовать WMI, поскольку это соответствует формату, который я использую для других функций, но на данный момент я готов использовать все, что может быть эффективно интегрировано в приложение, даже если мне придется использовать RegEx для фильтрации данные. В настоящее время я занимаюсь разработкой на компьютере под управлением Windows 7 Professional (x64). Я протестировал следующий фрагмент Powershell с правами администратора, и он работает безупречно.

$drive = Get-WmiObject -Class Win32_Volume -Namespace root\CIMV2  -ComputerName . |   Where-Object { $_.DriveLetter -eq 'D:' }
$drive.DefragAnalysis().DefragAnalysis

Это метод, который я использую в C # для достижения той же цели, но InvokeMethod продолжает возвращать 11 (0xB).

public static Fragmentation GetVolumeFragmentationAnalysis(string drive)
{
//Fragmenation object initialization removed for simplicity
        try
        {
            ConnectionOptions mgmtConnOptions = new ConnectionOptions { EnablePrivileges = true };
            ManagementScope scope = new ManagementScope(new ManagementPath(string.Format(@"\\{0}\root\CIMV2", Environment.MachineName)), mgmtConnOptions);
            ObjectQuery query = new ObjectQuery(string.Format(@"SELECT * FROM Win32_Volume WHERE Name = '{0}\\'", drive));
            scope.Connect();
            using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query))
            {
                object[] outputArgs = new object[2];
                foreach (ManagementObject moVolume in searcher.Get())
                {
                    // Execution stops at this line as the result is always 11
                    UInt32 result = (UInt32)moVolume.InvokeMethod("DefragAnalysis", outputArgs);
                    if (result == 0)
                    {
                        Console.WriteLine("Defrag Needed: = {0}\n", outputArgs[0]);
                        ManagementBaseObject mboDefragAnalysis = outputArgs[1] as ManagementBaseObject;
                        if (null != mboDefragAnalysis)
                        {
                            Console.WriteLine(mboDefragAnalysis["TotalPercentFragmentation"].ToString());
                        }
                    }
                    else
                    {
                        Console.WriteLine("Return Code: = {0}", result);
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("Could not acquire fragmentation data.\n" + ex);
        }

        return result;
    }

Я даже добавил следующую строку в app.manifest, но все еще ничего.

<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />

Может кто-нибудь сказать мне, что я пропускаю? Для меня это не вариант, поэтому, если это невозможно сделать с помощью C #, я не возражаю против создания DLL на другом языке (даже если мне придется ее изучать), что даст мне необходимые результаты. В идеале приложение должно работать на любой ОС от XP и выше и должно быть полностью прозрачным для пользователя.

Это ресурсы, которые я уже использовал. Я также хотел добавить блог jeffrey_wall на msdn, но как новый пользователь я могу добавлять только 2 гиперссылки за раз. Еще раз спасибо.

http://www.codeproject.com/Messages/2901324/Re-the-result-of-DefragAnalysis-method-in-csharp.aspx

http://social.technet.microsoft.com/Forums/vi-VN/winserverfiles/thread/9d56bfad-dcf5-4258-90cf-4ba9247200da

Ответы [ 3 ]

3 голосов
/ 29 февраля 2012

Попробуйте создать приложение, ориентированное на «Любой ЦП» - на вкладке «Построение» свойств проекта. Я подозреваю, что вы используете цель x86. Я получаю тот же код ошибки на моем компьютере с Win7 x64, если я это делаю.

Фактически, выполнение фрагмента PowerShell в версии PowerShell для x86 также дает пустой набор результатов.

Вы получаете ту же ошибку, если вы выполняете любой фрагмент кода без полных прав администратора, как вы обнаружили, поэтому также убедитесь, что ваш app.manifest правильный. Подсказка UAC - это удобный намек на то, что она вступает в силу!

Я не знаю, почему этот WMI-запрос не любит работать под WoW64, боюсь, но, надеюсь, это даст вам преимущество.

1 голос
/ 20 октября 2016

32-разрядный поставщик WMI для Win32_Volume, по-видимому, не может запустить defragsvc по какой-либо причине. Вы можете принудительно установить 64-разрядный поставщик WMI даже в 32-разрядном клиенте, работающем под WOW64, изменив свой код, добавив дополнительную опцию подключения WMI:

ConnectionOptions mgmtConnOptions = new ConnectionOptions {
    EnablePrivileges = true,
    Context = new ManagementNamedValueCollection() { 
        { "__ProviderArchitecture", 64 }
    }
};
1 голос
/ 29 февраля 2012

Вы можете просто вызвать команду PowerShell, которую вы упомянули в своем посте, поскольку вы сказали, что код PowerShell работает.Из C # вы хотели бы следовать этому рабочему процессу:

  1. Создание PowerShell RunSpace
  2. Open RunSpace
  3. Добавление сценария в Commandsсвойство
  4. Вызов списка команд

Вот пример того, как этого добиться, и обработать полученный результат объекта.

http://www.codeproject.com/Articles/18229/How-to-run-PowerShell-scripts-from-C

Для Windows XP и Windows Vista вам необходимо убедиться, что PowerShell был установлен на каждой из систем, на которой вы хотите запустить свою программу.Не плохая предпосылка, но что-то, что нужно иметь в виду, как зависимость.

Надеюсь, это поможет.

...