WinApi - GetLastError contre le Maréchal.GetLastWin32Error

J'ai testé beaucoup de choses. Mais je n'ai pas trouvé les inconvénients de ces 2!

Mais voir la accepté de répondre.


J'ai lu ici que l'appel GetLastError en code managé est dangereux, parce que le Cadre pourrait interne "écraser" la dernière erreur. Je n'ai jamais eu de problèmes notables avec GetLastError et il me semble que le .NET Framework est assez intelligent pour ne pas l'écraser. Donc j'ai quelques questions sur ce sujet:

  • dans [DllImport("kernel32.dll", SetLastError = true)] ne le SetLastError attribut de rendre le Cadre de stocker le code d'erreur pour l'utilisation de Marshal.GetLastWin32Error() ?
  • est là un exemple où la plaine GetLastError ne donne pas le résultat correct ?
  • dois-je vraiment à utiliser Marshal.GetLastWin32Error() ?
  • est ce "problème" Framework version liés ?

public class ForceFailure
{
    [DllImport("kernel32.dll")]
    static extern uint GetLastError();
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool SetVolumeLabel(string lpRootPathName, string lpVolumeName);

    public static void Main()
    {
        if (SetVolumeLabel("XYZ:\\", "My Imaginary Drive "))
            System.Console.WriteLine("It worked???");
        else
        {
            //the first last error check is fine here:
            System.Console.WriteLine(GetLastError());
            System.Console.WriteLine(Marshal.GetLastWin32Error());
        }
    }
}


Produire des erreurs:

if (SetVolumeLabel("XYZ:\\", "My Imaginary Drive "))
    Console.WriteLine("It worked???");
else
{
    //bad programming but ok GetlLastError is overwritten:
    Console.WriteLine(Marshal.GetLastWin32Error());
    try
    {
        using (new FileStream("sdsdafsdfsdfs sdsd ", FileMode.Open)) { }
    }
    catch { }
    Console.WriteLine(GetLastError());
}

if (SetVolumeLabel("XYZ:\\", "My Imaginary Drive "))
    Console.WriteLine("It worked???");
else
{
    //bad programming and Marshal.GetLastWin32Error() is overwritten as well:
    Console.WriteLine(GetLastError());
    try
    {
        using (new FileStream("sdsdafsdfsdfs sdsd ", FileMode.Open)) { }
    }
    catch { }
    Console.WriteLine(Marshal.GetLastWin32Error());
}

//turn off concurrent GC
GC.Collect(); //doesn't effect any of the candidates

Console.WriteLine(" -> " + GetLastError());
Console.WriteLine(" -> " + GetLastError());
Console.WriteLine(Marshal.GetLastWin32Error());
Console.WriteLine(Marshal.GetLastWin32Error());
//when you exchange them -> same behaviour just turned around

Je ne vois pas la différence! Les deux se comportent de la même sauf Marshal.GetLastWin32Error stocke les résultats à partir de l'App->CLR->WinApi appelle ainsi et GetLastError stocke uniquement les résultats à partir de l'App->WinApi appels.


La Collecte des ordures ne semble pas appeler n'importe quel WinApi fonctions d'écraser le dernier code d'erreur

  • GetLastError est thread-safe. SetLastError stocke un code d'erreur pour chaque thread appelant.
  • depuis quand serait-GC exécuter dans mes filets ?
  • GetLastError œuvres, il est possible que cela fonctionne dans tous les existants .NET Framework versions et des mises en œuvre. Ainsi, votre code fonctionne, mais ce n'est pas de prouver quoi que ce soit. .NET Framework, les développeurs sont libres de changer .NET mise en œuvre par la voie, que GetLastError va s'arrêter une journée de travail.
  • .NET développeurs seule garantie, que GetLastWin32Error fonctionne correctement. Vous souhaitez utiliser GetlastError hack, peut-être qu'il le sera toujours, mais c'est toujours un hack. Donc, la question est un peu philosophique: peut-on utiliser des hacks, si il n'est pas prouvé, qu'il est incorrect.
  • Ce serait un mauvais .NET Framework version. J'imagine que beaucoup de logiciel est en cours d'exécution avec la simple GetLastError parce que le programmeur n'ai pas entendu parler de Maréchal.GetLastWin32Error ou quoi que ce soit. Faire la mise à jour que vous avez mentionné serait briser tous ces logiciels.
  • Peut-être que ce n'est pas convaincante exemple... de toute façon. Appel de l'API Win32 avec SetLastError=true. Les appels de l'API avec SetLastError=false. Appel GetLastWin32Error - il garde la dernière erreur de la part du premier appel d'API, par définition.
  • Sur la bonne ou mauvaise .NET Framework version - encore une fois, c'est la philosophie. Vous n'avez pas à me convaincre (et personne d'autre, je l'espère) à utiliser GetLastError. Mais tout le monde n'a pas à vous convaincre d'utiliser GetLastWin32Error.
  • Voir this. Je voulais savoir exactement si je dois ou ne pas avoir à les jeter tous mes utilisations de GetLastError dans le code existant. Actuellement, il n'est tout simplement pas de prouver qu'il est dangereux.

InformationsquelleAutor Bitterblue | 2013-07-29