Just a quick note to say we’ve fixed the PostSharp Toolkits so that you can build them from source code. Previously, some artifacts were hardcoded to our development environment.
Note that the objective of the toolkits is to provide you with ready-made implementations, so we encourage you downloading the NuGet packages instead of building from source code.
In order to build the toolkits, follow these steps:
1. Download the source code from GitHub
Clone the repository
git://github.com/sharpcrafters/PostSharp-Toolkits.git or download the source code from
https://github.com/sharpcrafters/PostSharp-Toolkits.
2. Install PostSharp
You need PostSharp to build the toolkits, but we don’t use NuGet to retrieve it from the network. This is because the build script needs to be compatible with our development environment. The minimal version number of PostSharp you need is specified in the
dependencies section of the file $\Build\NuGet\Logging\PostSharpDiagnosticsToolkit.nuspec.
If you’ve installed PostSharp with the setup program, you can go to the next step. Otherwise, you need to create a file named $\Dependencies\PostSharp\PostSharpDir.Custom.targets, which specifies where PostSharp is installed. Note that this file should not be checked into the source control.
Here is the content of this file for our development environment:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PostSharpDir>c:\src\PostSharp-2.1\Build\bin</PostSharpDir>
</PropertyGroup>
</Project>
3. Build from Visual Studio or MSBuild
At this point, you will probably want to open the solution PostSharp.Toolkits.sln and build it.
4. Build the NuGet packages
When all binaries are built, you can create the NuGet packages by calling
msbuild Build\NuGet\NuGet.proj
The usual disclaimer
Of course, this blog post has to come with the usual disclaimer that PostSharp Diagnostic Toolkit uses PostSharp SDK, which is officially undocumented and unsupported. That is, we are happy to show you how things work, but we won’t answer questions related to its implementation. The source code of the toolkits itself is largely undocumented and is provided AS IS, and we won’t accept this kind of criticisms.
Happy PostSharping!
-gael
It’s not often that a bug fixes deserves a blog post, but today it happened :-(
64-bit programs (*.exe) processed by PostSharp 2.1.0.0-2.1.6.9 are unable to allocate more than 2GB of memory because of a invalid flag in the NT Header (IMAGE_FILE_32BIT_MACHINE instead of IMAGE_FILE_LARGE_ADDRESS_AWARE). Yes, just one bit.
This issue is especially nasty because generally invisible during testing. It’s only in production that a process attempts to use more memory. The program would them have terminated with an OutOfMemoryException.
Big thanks to Augustunbear Zhang for diagnosing this issue.
The issue is fixed at revision 2.1.6.10.
We recommend customers who have PostSharp-enhanced 64-bit programs (*.exe) in production to rebuild their project and redeploy them.
We sincerely apologize for the inconvenience this issue is causing. For any question or assistance, do not hesitate to contact me personally.
Happy PostSharping!
-gael
With all the good reasons mentioned by Ayende, we decided to officially switch PostSharp 2.1 to a continuous deployment process. We are abandoning the distinction between “milestone releases” and “hotfixes”. Since today, you will know always download the latest revision from the principal download page, as well as on NuGet.
Ayende’s article came at a time when we were frustrated with our release cycle. Although we released dozens of hotfixes, the front-page download was still the initial 2.1 RTM release because we constantly deferred the SP1. Clearly, the majority of people were not downloading the best-quality release, and were therefore hitting bugs that have already been solved for a long time. Not the best user experience!
Technically, the difference is quite small. PostSharp’s build and test processes have always been automated. It takes about 50 minutes to build and test all components. Uploading to our download manager is very easy too – copy the build output to a network share and execute a script that synchronizes with Amazon S3. Therefore, the time-to-market of a bug fix has always been very short – a couple of hours, typically. The fact that deployment is now integrated with the build script does not really change this fact.
Thus, the most significant difference is that we will actually publish hotfixes as front-page downloads.
Unlike “hotfixes”, “milestone releases” got additional manual testing on virtual machines, where the later got only automated testing. Installation tests are still not automated, so there’s a slight chance to get a regression in a front-page release. We bet that these defects will be infrequent and quickly detected by the community.
Bottom line: we bet that the overall quality will be higher by switching to continuous development.
Happy PostSharping, now with a fresh version!
-gael
I’m happy we finally refreshed our front-page download and released PostSharp 2.1 SP 1, featuring 48 bug fixes and user stories.
All fixes were already available under the “download” section, so it’s not that anyone had to wait so long to get a solution.
This service packs solves virtually all defects that have been reported to us, most notably:
- compatibility with Code Analysis (FxCop) – the infamous file locking issue
- compatibility with Code Contracts (issues with debugging symbols)
- compatibility with Silverlight 5
- issues in PostSharp HQ when upgrading PostSharp
This makes this release a very stable one. For a list of all fixes, see the release notes.
The SP 1 contains the following new enhancements:
- View source code enhanced by PostSharp from Visual Studio using your favorite decompiler.
- Example code migrated to Visual Studio 2010 and cleaned up, licensing under BSD 2.0.
- Refresh (actually, revival) of the XML project system:
- Unification of plug-in configuration (psplugin) and project configuration (psproj).
- Support for services that do not refer to PostSharp.Sdk.dll.
- Support for data islands inside XML project files.
- Adding aspects (actually, MulticastAttribute) to an XML project file – so without changing anything to source code.
The last few enhancements can appear a little cryptic to you, but they open the way to a new line of features we’ll blob about from next weeks: PostSharp Toolkits. They will make it easier to use the power of PostSharp without the difficulty of learning aspect-oriented programming.
Happy PostSharping!
-gael
Wow! What a turnout for my first webinar! Thank you all for attending, I had a great time presenting it, and will continue to do more webinars in the future. The webinar was recorded, and the video is now online for your viewing:
As promised, here are the answers to the great questions you asked, which I didn’t have the chance to answer during the live webinar. As always, you can always ask your questions on our Support Forums.
Q: Any reason the [aspect] class must be Serializable?
A: At (post) compilation, the aspect is serialized using binary serialization, and added as a resource to the target process. Then at runtime, the aspect is deserialized. PostSharp will emit a compilation error if you forget to mark your aspect as Serializable.
Q: What is the typical use case for creating interfaces using PostSharp?
A: One typical scenario for implementing interfaces with PostSharp is implementing INotifyPropertyChanged in WPF to support Data Binding.
Q: Are the OnExit and OnEnter aspects thread safe? How would one make it thread safe if it is not?
A: While the aspects themselves are thread-safe, shared state (i.e. custom fields) within the aspects is not. To safely pass data around between OnEnter and OnExit events, you can use the MethodExecutionArgs.MethodExecutionTag property.
Q: What about signed DLLs and PostSharp?
A: PostSharp has no problems with signed DLLs – they will be re-signed after the post-compilation process.
Q: What about Silverlight DLL's, is it also available?
A: Of course, PostSharp comes with the Silverlight assemblies included, you need to add a reference to the PostSharp.SL.dll instead of PostSharp.dll. For more information, please refer to the online documentation.
Q: Can you provide a good definition of aspect oriented programming?
A: Aspect Oriented Programming complements traditional OOP by allowing us to encapsulate infrastructure code (such as logging, security, validation, etc.) into small modules called aspects, and then apply those aspects throughout the entire system in such way that the business logic is completely separated from those concerns.
So go ahead, download the free starter edition now!
Happy PostSharping!
-Igal
I’m thrilled to announce that our partner IdeaBlade has just released a new version of DevForce. This application framework already provided pretty much all of the wiring you need to develop rich line-of-business applications (Silverlight and WPF backed by WCF, Entity Framework, OData). The last release now supports domain models written for Entity Framework in Code First style… and that still respect the spirit of Code First: nice, clean code, free from infrastructure boilerplate.
Guess who is writing that boilerplate for you? Right: PostSharp. What’s nice with DevForce is that you can start coding immediately and don’t have to understand anything about AOP and PostSharp since DevForce provides all the aspects you need. Even better: you don’t need to download PostSharp and you don’t have to check-out any license: all is included in the IdeaBlade package.
See! I managed to avoid the c*c*c word.
I’d like to thank Albert and his team for their efforts and feedback during the RC stage of PostSharp 2.1. I’m sure DevForce and PostSharp will benefit from each other and will make it even easier to develop strong LOB applications.
Happy PostSharping – now even to those who never heard of PostSharp.
-gael
I’m pleased to announce the second release candidate of PostSharp 2.1, available for download today on our web site and on NuGet. The first RC proved to be very stable, so this new version contains only relatively minor bug fixes. This RC also contains all bug fixes from the 2.0 branch.
Here’s the list of bugs that have been fixed in this release:
- CopyCustomAttributes causes exception when several types are passed to the constructor
- Fields are not visible by the debugger when a class has been moved to a binding class
- ImageWriter sets the section virtual size to an invalid value, causing failure in Windows Phone
- Invalid code generation when introducing a property or event of an open generic type
- Invalid code generation when introducing a property with a private property setter
- MainForm.CloseNotificationIcon throws InvalidOperationException after hibernation
- MSBuild failure when building a project on a FAT system (hard links not supported)
- PostSharp HQ throws exception when saving a license key for all users
- Setup program displays maintenance dialog when in silent mode
- Setup program prompts to uninstall previous version of the VS extension even in silent mode
- The license registration wizard should not be displayed after a silent installation.
- Exception in MulticastAtributeTask when a parameter-level MulticastAttribute is applied to a property
- Unused AssemblyRefs are included in the final assembly
- MulticastAttribute.TargetMemberAttributes is not respected for properties and events
PostSharp 2.1 is the fastest and most stable version of PostSharp and the upgrade is recommended for any one. To convert your projects, either use NuGet, either open PostSharp HQ and click on convert projects.
We’re now planning for PostSharp 3 and a new, truly disruptive, product that will change the landscape of instrumentation and diagnostic of in-production applications. We are hiring; drop us an email if you’re interested in joining the team.
Happy PostSharping!
-gael
This is one of these unpopular but necessary decisions that every software publisher has to do now and then. It’s generally accepted that pulling off expensive but little-used features is a healthy decision because it frees resources that can be spent on more popular features. This is what we are doing with documentation and support of PostSharp SDK.
What is PostSharp SDK?
PostSharp is made of two principal components: PostSharp.dll and PostSharp.Sdk.dll.
PostSharp.dll is the high-level public API. It mostly contains interface definitions, abstract classes and custom attributes from which developers can derive their own aspects. This library is designed to be used by developers of business applications. It offers transformation primitives (such as: intercepting a method, wrapping a method, introducing an interface) that developers can add to their code. PostSharp.dll leverages real aspect-oriented programming, a disciplined extension of object-oriented programming. Just as a normal compiler, the high-level API enforces syntactic rules, and you will get a reasonable error message if you violate them.
PostSharp.Sdk.dll is the opposite of PostSharp.dll. Its public API allows you to modify .NET assemblies at a very low level. You can do everything. The API does not enforce any programming discipline or syntactic rules. You can create invalid assemblies without even getting a warning. It requires you to learn the MSIL specification and to understand most of the 565 pages of the ECMA-335 specification. PostSharp.Sdk.dll is made of several components. The most low-level ones (code model, image reader, image writer) are also found in Mono Cecil and Microsoft CCI, although PostSharp SDK has its own implementation. PostSharp SDK also includes several middle-level components such as the project loader, the aspect infrastructure (which could allow you to use PostSharp SDK to develop an aspect weaver that has different syntax than PostSharp.dll), the aspect weaver (the implementation of the PostSharp.dll), the custom attribute multitasking components, and much more.
PostSharp SDK is more complex than you think
Contrarily to PostSharp itself, PostSharp SDK has a very steep, but misleading, learning curve. You get quite quickly the illusion that you “got” it, but the devil is in details. The 80-20 rules does not apply to PostSharp SDK: what applies is 95-5: 95% of time is spent in addressing 5% of cases. Think of MSIL programming as hiking in high mountains without a map. You always have the illusion that the top is near, but whenever you climb on what appeared to be top, you discover another, higher top. If you want to have an idea of the effort you’ll need to reach the goal, you need a map; ECMA-335 and the PostSharp SDK class reference will give you a fair overview of the complexity of your task.
So why do we have PostSharp SDK? First, for our own needs. From our own point of view, PostSharp SDK is the most important component of PostSharp. Secondly, because this API is useful to a tiny minority of ISVs with very specific needs (for instance: high focus on speed). They can afford to maintain MSIL skills because the effort is leveraged to thousands of customers. Third, because PostSharp SDK can be used to overcome missing features of PostSharp.dll. But this is where things can go wrong.
PostSharp SDK is undocumented and unsupported
There has been some criticism that PostSharp SDK is undocumented. This is not accurate: the class reference is quite complete and contains more than what’s obvious from the method signature. Many actually claim that PostSharp SDK has the best documentation of all MSIL rewriting tools.
What is true is there is no conceptual documentation. Let me be clear: the lack of conceptual of documentation is a feature, not a defect. The SDK will not be better documented. As any company, we have to allocate limited resources to a potentially unlimited number of features. It does not economically make sense to spend time in documenting a very complex API that is used by a dozen of customers.
The same holds for support. We cannot provide support on a highly complex and incompletely documented API. We cannot guide you through baby steps. PostSharp SDK is not supported. You use it at your own risks.
Nostra Culpa
On the support forum, you could often read answers that sounded like “this is not possible to do with PostSharp.dll but can be done with PostSharp.Sdk.dll”, followed by a disclaimer that PostSharp SDK is hard and you should maybe not try. This had led some customers to ask for more information for these specific cases, which I published on the blog. Mistake! These blog posts have been interpreted as an advertisement of and an invitation to use PostSharp SDK. I apologize for that. I will not advertise PostSharp SDK again. It will remain unsupported and undocumented. The harmful blog posts have been withdrawn.
PostSharp SDK still available
That said, PostSharp SDK is still available for use in the Professional Edition. We are only making it clearer that this feature is not officially supported, and must be used at own risk. I believe that it’s not a good idea to code directly MSIL instructions unless you can leverage the effort to thousands of customers (as we do), but you’re free to try. It’s just that you’re on your own.
I’m aware this decision will be unpopular, but I’m convinced it’s a necessary one to continue provide good support to the community.
Happy PostSharping !
-gael
I’m excited to announce the first release candidate of PostSharp 2.1, available for download from our website and from the NuGet official repository.
PostSharp 2.1 is a minor upgrade of PostSharp 2.0; the upgrade is free for everybody. The objective of this version is to fix several gray spots in the previous release.
This release candidate is ought to be of very high quality and free of known bugs, but needs to be tested by the community before it can be labeled stable. As required by the RC quality label, the online documentation has been updated to reflect the latest API.
PostSharp 2.1 has full backward binary compatibility with PostSharp 2.0.
What’s new in RC 1?
This release candidates contains the following additions to the previous CTP:
- The design of architecture validation (PostSharp.Constraints) has been finalized.
- Warnings can be disabled locally (for a specific element of code) using the IgnoreWarning custom attribute. See online documentation for details.
- The PostSharp project property page in Visual Studio now allows you to specify which warnings should be globally ignored or escalated into errors.
- Compatibility with Code Contracts 4.0
- As an experimental feature, warnings and errors now come with file/line information. The feature must be enabled manually from Visual Studio options. We’re eager to hear feedback about this feature from customers with larger projects.
- 17 bug fixes
What’s new in PostSharp 2.1?
If you missed the previous announcements, here’s a list of new features in PostSharp 2.1 compared to version 2.0:
- Improved build-time performance: up to 5x faster. Read more.
- Architecture validation: build-time validation of design rules. Read more.
- Extended reflection API: programmatically navigate code references. Read more and more.
- NuGet packaging and improved no-setup deployment experience. Read more.
- Support for obfuscators: we now support Dotfuscator. Read more.
- Support for Silverlight 5.
- Compatibility with Code Contracts 4.
- Improved messaging API.
- Tab page in Visual Studio project properties.
- Streamlined licensing experience.
- License server.
- Streamlined “getting started” experience.
Upgrade your Projects
To upgrade your projects from PostSharp 2.0 to PostSharp 2.1 easily you can use the conversion utility included in the PostSharp HQ application. Just open the app and click on “convert”, then select the folder containing your projects. References to libraries and MSBuild imports will be automatically fixed.
PostSharp 2.1 Roadmap
A release candidate means that we are confident in the code quality and is that all mandatory quality work, including documentation, has been done. PostSharp 2.1 is now the default version on our download page. We’ll wait a couple of weeks to allow the community to give this version a try, then publish the RTM or another RC, according to the feedback.
Note that the license agreement allows for production use.
It’s now time to download PostSharp 2.1 and upgrade your projects!
Happy PostSharping!
-gael
With prior versions of PostSharp, you had to be very careful to make your software compatible with any obfuscator. You could not obfuscate aspect classes, you could not store reflection objects, and you could not add use a reflection object in RuntimeInitialize with obfuscated generic methods. Indeed, all these features caused PostSharp to store the name of the metadata objects at build time, and to deserialize it at run time. But since the obfuscator renamed metadata objects after build time, the deserialization failed. Briefly said, previous versions of PostSharp were incompatible with all obfuscators.
PostSharp 2,1 provides a mechanism through which assemblies can be “repaired” after they have been obfuscated. Assemblies are still fully obfuscated, but PostSharp provides a utility to repair the name-object table. The build process is the following:
1. The compiler produces an assembly.
2. PostSharp post-processes the assembly and embeds an name table in the output assembly.
3. The obfuscator renames metadata objects, therefore breaks the PostSharp name table.
4. The post-obfuscation step (implemented by PostSharp) repairs the name table based on the obfuscation map produced by the obfuscator, and mapping the old name to the new name.
Since the post-obfuscation utility works with the obfuscation map, we need one implementation of this utility for every obfuscation map format, therefore for every obfuscation tool. PostSharp 2.1 includes support for Dotfuscator, the leading obfuscator .NET.
Calling the post-obfuscator
Let’s see how it works practically. You can download the example and try yourself.
To call the post-obfuscation step, you have to create an MSBuild project file and import the targets AddIns\PostSharp.AddIn.PostObfuscation.targets.
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<ItemGroup>
<!-- Required: Path of dependencies of obfuscated assemblies. -->
<ObfuscatedSearchPath Include="Dotfuscated" />
<!-- Required: Path of dependencies of unobfuscated assemblies. -->
<UnobfuscatedSearchPath Include="Unobfuscated"/>
<!-- Required: Obfuscation map file produced by Dotfuscator. -->
<MapFile Include="Dotfuscated\Map.xml"/>
<!-- Required: Obfuscated files -->
<ObfuscatedAssembly Include="Dotfuscated\*.dll"/>
<ObfuscatedAssembly Include="Dotfuscated\*.exe"/>
<!-- Optional -->
<ContentFiles Include="Unobfuscated\*.config"/>
</ItemGroup>
<PropertyGroup>
<!-- Required: output directory -->
<OutputPath>$(MSBuildProjectDirectory)\Remapped</OutputPath>
<!-- Required: selection of the remapping strategy -->
<Obfuscator>Dotfuscator</Obfuscator>
</PropertyGroup>
<Target Name="Build" DependsOnTargets="PostObfuscationRemap">
<!-- Optional: copy other files to the output directory-->
<Copy SourceFiles="@(ContentFiles)" DestinationFolder="$(OutputPath)"/>
</Target>
<Target Name="Rebuild" DependsOnTargets="Clean;Build">
</Target>
<Import Project="..\..\Build\bin\AddIns\PostSharp.AddIn.PostObfuscation.targets" />
</Project>
As you can see, this file defines some locations (required items and properties), and calls the PostObfuscationRemap target defined in PostSharp.AddIn.PostObfuscation.targets.
Safe code references
The post-obfuscator ensures the following references to code are repaired after obfuscation:
- References you are not aware of (used by PostSharp to provide the runtime features).
- Reflection objects (for instance MethodInfo, Type) serialized inside objects using the default serializer (BinaryFormatter). This feature is implemented thanks to serialization surrogates for reflection objects.
There is no magic. Other strings referencing to a metadata element, and stored somewhere else than in a reflection object serialized by the default serializer, will not be fixed. If you wrote your custom aspect serializer and want to take advantage of metadata reference serialization, you have to play with IMetadataEmitter/IMetadataDispenser.
In other words, if you want to write obfuscation-safe aspects, the only serialized metadata references should be reflection objects in an aspect field (or somewhere under an aspect field).
Stripping of events and properties
Dotfuscator allows users to remove events and properties from code. The reason is simple: they are useless at runtime for the CLR. They are pure compiler syntactic sugar… or rather were, before XAML. So what if your aspect stores a PropertyInfo or EventInfo?
PostSharp will be smart enough to provide you with a PropertyInfo or EventInfo. The only visible difference is that the Name property will return null. Other properties and methods will work as usually. Under the hood, PostSharp will give you an object of type ObfuscatedPropertyInfo or ObfuscatedEventInfo instead of RuntimePropertyInfo or RuntimeEventInfo, but your code should not see the difference.
Support for other obfuscators
As a first step, we provide support for Dotfuscator. If other vendors are interested to support PostSharp, we’ll gladly provide them with the specification of the binary format. If you want to contribute a post-obfuscation filter, then be pleased that the Dotfuscator-specific code is only 56 lines long (parsing of their XML obfuscation map). The post-obfuscation add-in is not obfuscated so feel free to use a decompiler :).
Summary
That’s it for obfuscation. A small, unexciting feature, but people who need to obfuscate their applications don’t have any excuse not to use PostSharp!
Happy PostSharping!