La réponse est simple jamais utilice Marshal.FinalReleaseComObject
sauf en cas de nécessité absolue. Et si vous le faites, vous devez respecter certaines règles supplémentaires.
Lorsqu'un objet COM est utilisé dans .NET, le moteur d'exécution crée ce que l'on appelle un "RCW" ou "runtime callable wrapper" pour cet objet. Ce RCW est un objet normal qui contient une référence COM sur l'objet. Lorsque cet objet est ramassé, il appelle IUnknown::Release() sur l'objet COM, comme on peut s'y attendre. Cela signifie qu'à moins que votre objet COM exige que le dernier Release() est effectué à un moment bien précis, il suffit de laisser le garbage collector s'en charger. De nombreux objets COM tombent dans ce cas, il faut donc absolument vérifier que vous doit gérer avec soin l'appel à Release().
Ainsi, lorsque vous appelez FinalReleaseComObject, il s'agit essentiellement de décrémenter la référence que le TCR a sur l'objet COM jusqu'à ce qu'elle atteigne zéro et que le TCR libère l'objet COM. À ce stade, ce RCW est maintenant zombifié, et toute utilisation de celui-ci produira l'exception que vous avez vue. Le CLR (par défaut) ne crée qu'un seul RCW pour tout objet COM sous-jacent, ce qui signifie que si l'API COM que vous utilisez a renvoyé le même objet deux fois, il n'aura qu'un seul RCW. L'appel à FinalReleaseComObject signifierait que soudainement tous Les utilisations de ce RCW sont grillées.
La seule façon de garantir que vous avez un Marshal.GetUniqueObjectForIUnknown unique, ce qui empêche tout partage de RCW. Mais comme je l'ai dit plus haut, dans la plupart des API COM, il n'est pas nécessaire de le faire en premier lieu, alors ne le faites pas.
Paul Harrington a rédigé un bon article de blog sur [Final]ReleaseComObject et ses méfaits. C'est une arme dangereuse qui, si elle n'est pas utilisée, ne fera que vous blesser. Puisque vous posez cette question, je soupçonne que vous n'avez pas besoin de l'appeler du tout :-)