我目前正在使用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以上的任何操作系统上运行,并且必须对用户完全透明。
这些是我已经使用过的资源。我想在msdn上添加jeffrey_wall博客,但作为新用户,我一次只能添加2个超链接。再次感谢。
http://www.codeproject.com/Messages/2901324/Re-the-result-of-DefragAnalysis-method-in-csharp.aspx
答案 0 :(得分:3)
尝试在项目属性的“构建”选项卡上构建针对“任何CPU”的应用程序。我怀疑你正在使用x86的目标。如果我这样做,我在Win7 x64机器上会得到相同的错误代码。
事实上,在x86版本的PowerShell中运行PowerShell代码段也会产生一组空的结果。
如果您运行任何没有完全管理员权限的代码,就会发现同样的错误,因此您也确保您的app.manifest正确无误。 UAC提示是一个方便的提示,它正在生效!
不知道为什么这个WMI查询不喜欢在WoW64下运行,我担心,但希望这会给你一个良好的开端。
答案 1 :(得分:1)
您可以简单地调用帖子中提到的PowerShell命令,因为您说PowerShell代码有效。从C#开始,您需要遵循以下工作流程:
RunSpace
Open
RunSpace Commands
属性以下是如何实现此目的的示例,并处理生成的对象输出。
http://www.codeproject.com/Articles/18229/How-to-run-PowerShell-scripts-from-C
对于Windows XP和Windows Vista,您必须确保在要运行程序的每个系统上都安装了PowerShell。这不是一个糟糕的先决条件,但需要记住作为依赖。
希望这会有所帮助。
答案 2 :(得分:1)
Win32_Volume的32位WMI提供程序似乎无法以任何理由启动defragsvc。通过更改代码以添加其他WMI连接选项,即使在WOW64下运行的32位客户端中也可以强制使用64位WMI提供程序:
ConnectionOptions mgmtConnOptions = new ConnectionOptions {
EnablePrivileges = true,
Context = new ManagementNamedValueCollection() {
{ "__ProviderArchitecture", 64 }
}
};