5

私は現在、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 以降の任意の OS で動作し、ユーザーに対して完全に透過的でなければなりません。

これらは、私がすでに使用したリソースです。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

4

3 に答える 3

3

プロジェクト プロパティの [ビルド] タブで、「任意の CPU」をターゲットとするアプリケーションをビルドしてみてください。x86 のターゲットを使用していると思われます。これを行うと、Win7 x64 マシンでも同じエラー コードが表示されます。

実際、PowerShell の x86 バージョンで PowerShell スニペットを実行すると、空の結果セットも得られます。

発見したように、完全な管理者権限なしでいずれかのコードを実行すると同じエラーが発生するため、 app.manifest が正しいことも確認してください。UAC プロンプトは、有効になっていることを示す便利なヒントです。

この WMI クエリが WoW64 での実行を好まない理由はわかりませんが、これで有利なスタートが切れることを願っています。

于 2012-02-28T22:34:50.800 に答える
1

PowerShellコードが機能すると述べたので、投稿で言及したPowerShellコマンドを呼び出すだけです。C# から、次のワークフローに従うことをお勧めします。

  1. PowerShell をインスタンス化するRunSpace
  2. Openランスペース
  3. Commandsプロパティにスクリプトを追加する
  4. コマンドリストを呼び出す

これを実現し、結果のオブジェクト出力を処理する方法の例を次に示します。

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

Windows XP および Windows Vista の場合、プログラムを実行する各システムに PowerShell がインストールされていることを確認する必要があります。悪い前提条件ではありませんが、依存関係として覚えておくべきことがあります。

お役に立てれば。

于 2012-02-28T22:34:47.000 に答える