【问题标题】:How to obtain DefragAnalysis using C#如何使用 C# 获取碎片整理分析
【发布时间】:2012-03-18 10:14:53
【问题描述】:

我目前正在使用 C# (.NET 4.0) 开发一个应用程序,该应用程序应该具有确定特定卷上碎片百分比的能力作为其功能的一部分。所有其他功能都已经过测试并且工作正常,但我在尝试访问这些数据时遇到了障碍。理想情况下,我更喜欢使用 WMI,因为它与我用于其他功能的格式相匹配,但此时我愿意使用任何可以有效集成到应用程序中的东西,即使我必须使用 RegEx 过滤数据。我目前正在 Windows 7 Professional (x64) 机器上进行开发。我已经使用管理员权限测试了以下 Powershell sn-p,它可以完美运行。

$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 以上的任何操作系统上运行,并且必须对用户完全透明。

这些是我已经使用过的资源。我也想在 msdn 上添加 jeffrey_wall 博客,但作为新用户,我一次只能添加 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

【问题讨论】:

    标签: c# powershell wmi wql defragmentation


    【解决方案1】:

    您可以简单地调用您在帖子中提到的 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。拥有一个不错的先决条件,但作为依赖项需要牢记。

    希望这会有所帮助。

    【讨论】:

    • 感谢 Trevor,尽管 Dogmang 的解决方案对我有用,但您的建议似乎是解决我在 ManagementObjectCollection 中遇到的其他问题的好方法。正式注明。
    • 老实说,我通常不会推荐它。对于您在 WMI 中执行的大多数(如果不是全部)操作,请坚持使用 System.Management 命名空间和 C# 代码。在编写 C# 代码时,我已广泛使用 WMI,并且我非常喜欢 .NET 基类库中的 API。另一方面,如果您主要使用 PowerShell 编写代码,请继续使用 PowerShell 结构。 :) 干杯
    【解决方案2】:

    尝试在项目属性的“构建”选项卡上构建以“任何 CPU”为目标的应用程序。我怀疑你使用的是 x86 的目标。如果我这样做,我会在我的 Win7 x64 机器上得到相同的错误代码。

    事实上,在 x86 版本的 PowerShell 中运行 PowerShell sn-p 也会得到一个空的结果集。

    如您所见,如果您在没有完全管理员权限的情况下运行任何一段代码,您会遇到同样的错误,因此还要确保您的 app.manifest 是正确的。 UAC 提示是一个方便的提示,它正在生效!

    不知道为什么这个 WMI 查询不喜欢在 WoW64 下运行,但希望这会给你一个先机。

    【讨论】:

    • 这很有趣——我测试了也得到了相同的结果。好建议。
    • 实际上,我认为将架构设置为“任何 CPU”是 解决方案。干得好。
    • 非常感谢您这么快的回复。这就是问题的确切解决方案。谁曾想到。再次感谢。
    【解决方案3】:

    Win32_Volume 的 32 位 WMI 提供程序似乎无论出于何种原因都无法启动 defragsvc。即使在 WOW64 下运行的 32 位客户端中,您也可以强制使用 64 位 WMI 提供程序,方法是更改​​代码以添加额外的 WMI 连接选项:

    ConnectionOptions mgmtConnOptions = new ConnectionOptions {
        EnablePrivileges = true,
        Context = new ManagementNamedValueCollection() { 
            { "__ProviderArchitecture", 64 }
        }
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-17
      • 1970-01-01
      • 2018-07-12
      • 2011-01-16
      • 2017-12-09
      • 2018-01-03
      • 2010-11-26
      • 2010-11-18
      相关资源
      最近更新 更多