- Using the FxCop GUI
- Repairing the Errors
- Ignoring the Rules
- Employing FxCop During a Build
- Creating New Rules
- Bottom Line
Repairing the Errors
Let's look at a few of the issues that FxCop found. The sample application uses frmMain for the name of the form. FxCop marked this usage as an error because standard convention is to use Pascal case for class names. In addition, frm isn't a word, so FxCop suggests correcting the spelling of the word. Simply changing the name of the class to FormMain (initial capital letter and recognizable name) clears up this problem. More importantly, this change makes the class name easier to read and understand. However, the code executes much as it did beforenothing has really changed.
The next error concerns Common Language Specification (CLS) compliance. The application doesn't indicate whether it's compliant with CLS. A CLS-compliant application only uses features that are available as part of CLS. For example, if your C# application uses a UInt32 variable, it's not CLS compliant because the UInt32 type is a language-specific feature. The purpose in marking an application as CLS compliant is to indicate that it can run in any environment that completely emulates CLS. Using a UInt32 datatype would mean that you could run the application only on a Windows system that allows access to unsigned integers. Here's how you would indicate that an entire assembly is CLS compliant:
// Define the assembly as CLS compliant. [assembly:CLSCompliant(true)] namespace SimpleApp { ... Other Code ... }
You can mark sections of an application as noncompliant using the same attribute. For example, if the whole application is CLS compliant except for one method that uses a UInt32, you could mark the method like this:
[CLSCompliant(false)] private void btnTest_Click(object sender, System.EventArgs e) { UInt32 NonCLSVariable; // UInt32 is not CLS compliant. // Initialize the variable. NonCLSVariable = 3; // Display a message. MessageBox.Show("The value is: " + NonCLSVariable.ToString()); }
Marking an assembly might not seem like a very big deal, but consider the changes that are happening with computing as a whole. The application you build today on a 32-bit machine might have to execute on a 64-bit machine tomorrow. Considering CLS issues today means you'll have less work to do to update the application tomorrow.
The next issue is the first security consideration. I don't know of any application authors who mark their assembly's security needs todayand that's a problem. FxCop marks out minimal essential security requirements. The first is to tell the Common Language Runtime (CLR) what resources your application actually needs. In this case, the application only needs to display a message, and should be marked as such. More importantly, the application should contain information about resources that it doesn't need. For example, this application doesn't need to access the hard drive, so you can deny hard drive access. Adding this information prevents a virus from gaining access to those resources even if it infiltrates the application. Here are some typical assembly-level security descriptions:
// Define the security needs for the assembly. [assembly:EnvironmentPermissionAttribute(SecurityAction.RequestRefuse)] [assembly:FileIOPermission(SecurityAction.RequestRefuse)] [assembly:RegistryPermission(SecurityAction.RequestRefuse)]
These three assembly-level permissions tell CLR that it shouldn't allow the application to do anything with environmental variables, access the disk drive, or change the registry. If a virus infects this application, it won't be able to do many of the things that viruses commonly do, such as infecting disk files with virus information. The virus can't move data around, or make itself permanent, for that matter. The .NET Framework provides a wealth of permissions that you can use to control your application. Here are some of the common permissions you should consider:
EnvironmentPermissionAttribute
FileDialogPermissionAttribute
FileIOPermissionAttribute
IsolatedStoragePermissionAttribute
PermissionSetAttribute
PrincipalPermissionAttribute
PublisherIdentityPermissionAttribute
ReflectionPermissionAttribute
RegistryPermissionAttribute
SecurityPermissionAttribute
SiteIdentityPermissionAttribute
StrongNameIdentityPermissionAttribute
UIPermissionAttribute
UrlIdentityPermissionAttribute
ZoneIdentityPermissionAttribute
A second security error is that this assembly isn't signed. An assembly with a strong name is harder to tamper with and therefore harder to corrupt. The strong name doesn't protect the assembly from prying eyesyou need a product such as Dotfuscator to modify the code in such a way that others can't really understand what you're doing. To add a strong name to your assembly, use the SN (strong name) utility to create a key pair like this:
sn -k MyKey
It's important to protect this key because someone else could use it to modify your code.
In addition, you should sign all of your code using the same key or designate a specific key for each purpose. Once you generate a key, you add it to your code using a special attribute, like this:
[assembly: AssemblyKeyFile("MyKey")]