What is Platform Verification Task?
Smart Device development involves writing applications that target a particular device platform. Toolbox filtering, the unsupported control designer and IntelliSense provide design time aid to the developer to add only PMEs (properties/methods/events) supported by the current platform to his application. But in certain scenarios the developer might have written an application for a particular platform and then ported it to another platform. In this scenario it is necessary to identify the PMEs not supported by the new platform at build time. These errors cannot be caught by simply compiling the project against NETCF assemblies (For example, if your project contains a "Button" control, then, building it against the NETCF system assemblies will always succeed, since "System.Windows.Forms.Button" is a supported NETCF control. But "System.Windows.Forms.Button" is not supported by all device platforms (For example, Smartphone does not support it)). Platform Verification Task (PVT) is a post-build validation step to catch the unsupported PMEs before they can result in a runtime exception.
Just another MSBuild target:
So what is this post build step and how does fit into Visual Studio build system? As you might be aware VS2005 uses the MSBuild engine from the IDE to perform all compile time actions. The project file contains the information about the set of target files (which contain the list of MSBuild targets) that need to be imported and executed by the MSBuild engine. The set of targets specific to Smart Device projects are defined in Microsoft.CompactFramework.Common.targets file (installed in the System .NET Framework directory) and are imported inside each Smart device project’s project file.
Platform Verification task is one of the MSBuild targets added to Microsoft.CompactFramework.Common.targets file which is executed after the project has been built. If project build is successful, then PVT is executed with the following parameters:
1) PlatformFamilyName (example, PocketPC)
2) PlatformID (example, ID corresponding to PPC2003)
3) SourceAssembly name
4) ReferencePath, i.e. assembly path
5) TreatWarningsAsErrors , a flag specifying whether PVT should generate Warnings or Errors and
6) PlatformVersion (example NETCF v2)
What is required? A managed code analysis tool to examine the managed assemblies for correctness issues. Every managed code developer already uses it, isn’t it?
As stated above, PVT is not a build time step. What this means is that PVT does not parse the source code to identify unsupported PMEs. It parses the IL to do the same work. This is where FXCop comes into picture. FXCop architecture provides the necessary extensibility to define customized FXCop rules. FXCop rules are generally used to identify violations of design guidelines in the code, but the user can define just about any policy specific to his requirement.
FXCop has three main facets:
1) Targets - the assemblies to be analyzed
2) Rules - the checks to be performed
3) Messages - the output from the rules
PVT internally implements a customized FXCop rule which performs the checks for unsupported PMEs.
So how does it all work?
The basic control flow is as follows:
1) PVT is invoked with the necessary parameters mentioned above.
2) It identifies the list of assemblies referenced by the source assembly and loads the metadata in the platform specific asmmeta assemblies corresponding to each of the referenced assemblies. (Platform specific asmmeta assemblies are assmeta files which contains the information about platform’s supported PMEs. For each platform there is one assmeta file provided by NETCF. The files are located under %Program files%\Microsoft Visual Studio 8\smartdevices\sdk folder)
3) PVT then executes a customized FXCop rule (PlatformVerificationRule) with this metadata and the source assembly.
4) PlatformVerificationRule (PVR) parses the IL; in fact, it is the base FXCop rule that does the parsing. The FXCop analysis engine uses Reflection exposed type system in the assemblies to disassemble IL, build color graphs from assemblies and create control flow graphs from Method. The base FXCop rule lets you ask for higher-level constructs in the MSIL for the code. For identifying whether the application is conformant to the target platform, PVT needs to perform checks only for some constructs (ones which can access platform unsupported PMEs). Hence it overrides the methods which are called when following constructs are identified in the assembly:
b. Expression statement
5) For the above construct types, it performs the following checks in the corresponding overridden methods:
c. Constructor: In this method, PVR gets the assmeta type of the object getting instantiated and checks whether this type has “SupportedAttribute” attribute set to false. If yes, it generates a message for each violation.
d. Expression statement: In this method, PVR checks if the expression statement involves a method call. If so, it gets the assmeta type for the type on which the method is getting called and checks whether this type has “SupportedAttribute” attribute set to false. It also gets the asmmeta type for the method getting called and checks whether it has “SupportedAttribute” attribute set to false. For each violation a Message is generated.
6) The Messages are then output as Warning/Errors.
Disabling PlatformVerificationTask: If it is so useful, why will I disable it at all?
Though Platform Verification Task aids the developer in identifying all the unsupported PMEs getting accessed in code at build time itself, it does add quite a bit to the build time. Ideally the developer might like to run PVT only once in a while and not during every build. Currently there is no support in the VS2005 IDE to customize the execution of PVT during build, though we are looking to add support for it in next release. As a workaround for VS2005, PVT execution can be customized by following the steps below:
1) Open the file %windir%\Microsoft.NET\Framework\v2.0.50727\Microsoft.CompactFramework.Common.Targets for editing.
2) Go to the line which reads:Name="PlatformVerificationTask">and change it to:Name="PlatformVerificationTask" Condition="'$(SkipPlatformVerification)' != 'true'">
3) Add the SkipPlatformVerification environment variable to the system and set it to "true" (To re-enable Platform Verification set the environment variable to "false")
4) Restart Visual Studio for the changes to take effect (If building from the command line using MSBuild, add /p:SkipPlatformVerification=true to your command line to turn off the task. You can specify the variable in the project file also, so that this information is persisted across sessions).