Question

Je développe actuellement une application en C # (.NET 4.0) qui devrait faire partie de sa fonctionnalité la capacité de déterminer le pourcentage de fragmentation sur un volume particulier. Toutes les autres fonctionnalités ont été testées et fonctionnent bien, mais j'ai frappé un SNAG en essayant d'accéder à ces données. Je préfère idéalement utiliser WMI car cela correspond au format que j'utilise pour les autres fonctionnalités, mais à ce stade, je suis prêt à utiliser tout ce qui peut être intégré efficacement dans l'application, même si je dois utiliser Regex pour filtrer le Les données. Je fais actuellement le développement sur une machine Windows 7 Professional (X64). J'ai testé l'extrait de PowerShell suivant en utilisant les droits de l'administrateur et cela fonctionne parfaitement.

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

C'est la méthode que j'utilise dans C # pour accomplir la même chose, mais l'invokemethod continue de retourner 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;
    }

J'ai même ajouté la ligne suivante à l'application.Manifest mais toujours rien.

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

Quelqu'un pourrait-il me dire ce que je néglige? L'échec n'est pas une option pour moi à ce sujet, donc si cela ne peut pas être fait en utilisant C #, cela ne me dérange pas de créer une DLL dans une autre langue (même si je dois l'apprendre), cela me donnera les résultats dont j'ai besoin. Idéalement, l'application doit pouvoir travailler sur n'importe quel système d'exploitation de XP vers le haut et doit être totalement transparent à l'utilisateur.

Ce sont les ressources que j'ai déjà utilisées. Je voulais également ajouter le blog Jeffrey_Wall sur MSDN, mais en tant que nouvel utilisateur, je ne peux ajouter que 2 hyperliens à la fois. Merci encore.

http://www.codeproject.com/mesages/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

Était-ce utile?

La solution

Essayez de construire votre application Cibler «Any CPU» - sur l'onglet Build des propriétés du projet. Je soupçonne que vous utilisez une cible de x86. J'obtiens le même code d'erreur sur ma machine Win7 X64 si je le fais.

En fait, l'exécution de votre extrait PowerShell dans la version x86 de PowerShell donne également un ensemble vide de résultats.

Vous obtenez la même erreur si vous exécutez l'un ou l'autre morceau de code sans privilèges d'administrateur complet, comme vous l'avez trouvé, assurez-vous également que votre app.Manifest est correcte. Une invite UAC est un indice pratique que cela prend effet!

Je ne sais pas pourquoi cette requête WMI n'aime pas courir sous WOW64, je le crains, mais j'espère que cela vous donnera un démarrage.

Autres conseils

Vous pouvez simplement appeler la commande PowerShell que vous avez mentionnée dans votre message, car vous avez dit que le code PowerShell fonctionnait. De C #, vous voudriez suivre ce flux de travail:

  1. Instancier un powershell RunSpace
  2. Open l'espace run
  3. Ajouter un script au Commands propriété
  4. Invoquez la liste de commandes

Voici un exemple de la façon d'y parvenir et de traiter la sortie de l'objet résultant.

http://www.codeproject.com/articles/18229/how-to-run-powershell-scripts-from-c-c

Pour Windows XP et Windows Vista, vous devez vous assurer que PowerShell a été installé sur chacun des systèmes sur lesquels vous souhaitez exécuter votre programme. Pas une mauvaise condition préalable à avoir, mais quelque chose à garder à l'esprit comme dépendance.

J'espère que cela t'aides.

Le fournisseur WMI 32 bits pour Win32_Volume ne semble pas pouvoir démarrer le Defragsvc pour une raison quelconque. Vous pouvez forcer le fournisseur WMI 64 bits même dans un client 32 bits exécuté sous WOW64 en modifiant votre code pour ajouter une option de connexion WMI supplémentaire:

ConnectionOptions mgmtConnOptions = new ConnectionOptions {
    EnablePrivileges = true,
    Context = new ManagementNamedValueCollection() { 
        { "__ProviderArchitecture", 64 }
    }
};
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top