Experiences with FxCop and wrapping the native debug API
I'm writing some managed wrappers for the native-debugging API (I expect they'll eventually become part of the MDbg sample). I'm trying to make them FxCop compliant. Here are some random thoughts about my experiences.
- FxCop has a lot of great rules. Merely running FxCop to see what it says and giving it the benefit of the doubt is valuable. For example, the rules about Disposable were great. They call out mistakes and point you to examples about how to write it properly. ValidateArgumentsOfPublicMethods was also useful.
- There's a great FxCop forum. You can got a lot more feedback about the rules (and this feedback gets rolled into future docs).
- FxCop really encourages full VB-friendly wrappers that hide all the ugly details of native code. Many of the normal interop techniques are not fxcop friendly (eg, passing value-types by-ref, using IntPtr, using uint). Depending on your goals, it can be nice to import the raw native structures, add some helper methods to smooth things over (eg, stuff to help the marshallers, common utility functionality, etc), but leave the raw native fields available for advanced usage.
a) FxCop and C# don't like IntPtr, which is pretty necessary for low-level API usage.
b) FxCop doesn't like exposing native structures.
c) FxCop does not like exposing instance fields, even for large value-types. - I hit some confused mappings with UseManagedEquivalentsOfWin32Api, particularly confusing the native debugging APIs with the managed ones in the Debugger class. That inspired the comparison here.
- Naming issues. Win32sdk naming (eg, STATUS_SINGLESTEP) is not fxcop compliant. So the wrappers need to decide whether to keep affinity to the native APIs, or change to pick up managed conventions that may confuse the native-API users.
I think the big picture is that FxCop is really intended for friendly class libraries; and so using it directly on native wrappers is somewhat of an abuse. Thus the end wrappers will violate a few rules (though violate them many times). I still found it very useful overall. In the worst case, you can ignore a rule. It's batting average was high enough that I found it certainly added value. If you're not running FxCop on your managed code, try it out.
Comments
- Anonymous
July 12, 2006
I would recommend that you at least conflate things like those "STATUS_SINGLESTEP" (which I've never heard of, I must confess - can't find it on google or in the PSDK either) to something like ThreadStatus.SingleStep - when those things aren't enumerations they just aren't typesafe or discoverable enough.
There's only two things worth doing, IMO: (1) a raw P/Invoke set of method declarations and structures, or (2) a managed api which exposes no SafeHandle or any other underlying mechanism. A mix between the two is just a convenience for Win32 throwbacks. That's just my opinion, though. - Anonymous
July 13, 2006
The comment has been removed - Anonymous
July 14, 2006
Nichol - I think that's a great response and it makes a lot of sense. The key tension I'm sensing is about when to not apply FxCop.
I detect one camp of folks that basically champion that everything should be FxCop compliant (which is what this FxCop blog entry alludes to http://blogs.msdn.com/fxcop/archive/2006/04/11/WeWantYourFeedback.aspx). - Anonymous
July 14, 2006
Barkel - Stuff like "STATUS_SINGLESTEP" can still be in an enum (eg, enum NativeExceptionCodes) so that it's discoverable.
I'm a big fan of NicholG's case #3 - the hybrid. Providing a full managed wrapper for somethings can be bad. I'll write up my thoughts on this in another blog post.