Thursday, January 20, 2011

.NET Preprocessor Update

NTSTATUS: STATUS_DOTNET_MACRO

Latest versions:

  • DOTNETPP Version 0.1.12.0
  • VSDotNetPP Version 0.1.3.0

As before, they can be downloaded here.

VSDotNetPP now implements DOTNETPP and does not call DOTNETPP.EXE, but it is still included in the install anyway. This update fixes some bugs and makes some processing changes (supposedly for the better). Following are the specific feature updates.

Features Updated In The .NET Preprocessor

The setting for <MacroFilePath> now accepts a directory (path), and parses all .npp files for macro definitions. Or, you can just specify a file path (does not have to have a .npp extension).

A list of the source files processed is kept temporarily to avoid restoring files unecessarily during the cleanup process. It was an annoyance otherwise.

Other than that, some bugs have been fixed.

Features Updated In The Visual Studio Add-In

A new setting has been added: Close and re-open source files with macros during build



I added this setting because I was getting annoyed at the source files getting closed. It’s OK if you have one or two, but it’s not OK if you have more open. Also, I think it should be obvious that the main problem with the closing/opening is that it currently does not return you to the same spot in the file you were in.

I recommend the following settings in the image:

  • NOT restore macros in source
  • NOT close/re-open the source files
  • Cleanup expanded source

By using these settings, it’s pretty much the same as using DOTNETPP in your pre-build and post-build events. But with the way it is currently, it works the best. So to do a build, you’d have to build twice. The first build expands the macros, and you have to say YES when Visual Studio asks if you want to reload the files (source changed the Preprocessor). I just build when I want to expand the macros.

Finally

This is pretty much it for the time being. I’ve been using it and it’s been working well. I also found it was quite useful for SQL scripts as well. It managed to reduce some copy/paste/edit.

Here’s a useful macro for the ternary operator:

#define HASVAL(a) a.HasValue ? a.Value : 0

IntelliSense does not do regions:

#define REGPRV

#region Private

#endregion

Sunday, January 16, 2011

Visual Studio & Expression Blend crashes when opening Silverlight XAML

NTSTATUS: STATUS_FATAL_ERROR

This happened to me recently, and it was a nightmare to repair. I will document my experience as many people faced the same problems, and different solutions worked for different people.

I was using Visual Studio 2010 and Expression Blend 4, developing Silverlight 4.

I will put the important points of this post here instead of at the end to save you, the reader, time.

Determined Root Cause of Damage: Updated Silverlight runtime to the latest version.

Caveat: Do NOT install a newer version of Silverlight unless you have the matching developer runtime (if you are developing Silverlight apps). I would also point out that it was IMPOSSIBLE to find the matching Silverlight developer runtime for the latest version of Silverlight. I am extremely infuriated and disappointed.

1. The Problem As It Happened

Suddenly, whenever I opened a Silverlight XAML file, Visual Studio crashed. It does not happen to WPF XAML files. I don’t think I tried Blend at this point as I was trying to get some work done, and was trying to fix my VS.

Steps taken:

  1. Uninstalled Silverlight 4 Toolkit
  2. Reinstalled Silverlight 4 SDK. Did not do an uninstall as the SDK documentation said it was safe to do (unless I read it wrong)

Results:

  • VS still crashes when opening Silverlight XAML
  • Blend 4 crashes when opening Silverlight XAML. It cannot be confirmed if the steps taken caused this, or it was already damaged

2. Reinstallation

The next desperate step was to reinstall my dev tools. This did NOT fix the problem. But I will detail it for the record.

Steps taken:

  1. Uninstalled Silverlight 4 Toolkit
  2. Uninstalled Silverlight 4 SDK
  3. Uninstalled Silverlight 3 Toolkit
  4. Uninstalled Silverlight 3 SDK
  5. Uninstalled Silverlight Runtime
  6. Uninstalled Visual Studio 2010
  7. Uninstalled Visual Studio 2008
  8. Uninstalled Blend 4
  9. Uninstalled Blend 3
  10. Install Visual Studio 2010
  11. Install Blend 4
  12. Install Silverlight 4 SDK
  13. Install Silverlight 4 Toolkit

Results:

  • VS still crashes when opening Silverlight XAML
  • Blend 4 still crashes when opening Silverlight XAML

At this point, it is safe to say that the system is irreparably damaged. I read that some folks had to reinstall their entire system. So not wanting to waste any more time, I restored my last good system image.

3. System Restore & Update

Having restored my system to the last good image, I attempted to update it. I verified that VS and Blend are working properly with Silverlight 4 XAML files. However, when I ran my Silverlight 4 app, it insisted I install a newer version of the Silverlight runtime and just refused to run. I could not understand this as I had just restored my system to an older state which actually is using an older version of Silverlight (4.0.50524.0). I figure this out later. I had no choice at the time, so…

Update Steps:

  1. Update Silverlight runtime to version 4.0.51204.0 (Current version is 4.0.50524.0)

Results:

  • VS cannot debug Silverlight 4 app because the developer runtime does not match the current Silverlight version

So this is a big problem. To fix this, I tried the following:

  1. Uninstall Silverlight runtime
  2. Download and install the latest Silverlight 4 developer runtime that I could find

Result:

  • VS can now debug Silverlight 4 app again
  • However, VS now crashes when opening Silverlight XAML
  • Blend 4 also now crashes when opening Silverlight XAML

So, it looks like this was how my system got damaged in the first place. I vaguely recall installing the latest version of Silverlight when prompted some weeks or months ago, and I had not worked on a Silverlight app until now.

I restored the system AGAIN, and did NOT install the latest version of Silverlight. However, there was still that nagging problem of my app insisting I install the latest version of Silverlight! I finally figure it out:

Silverlight App Project

  • The param “minRuntimeVersion” of the Silverlight object in the host webpage is what causes the popup to install a newer version of Silverlight if the value is above the current version installed. So just make sure that this is no greater than your current version of Silverlight.

<param name="minRuntimeVersion" value="4.0.50401.0" />

  • I believe that I had created the said Silverlight app project after installing the newer version of the Silverlight runtime, and this is what caused the popup dialog to insist on the newer version of Silverlight even after I restored my system. This would make sense as my project was not affected by the system restore.

Conclusion

Ultimately, I was not able to repair the damage. I could only restore my system back to a point where my development system was all good. The only thing I could really do was to make sure that I do not take any of the steps that would cause that kind of damage. And these steps, are those I laid out which I figured out through trial and error. I could have figured it out faster, but unfortunately, installs, uninstalls and system restores take a very, very long time. In all, it was about 18 hours wasted because nothing new was achieved… It was all just to get back to square one.


Wednesday, January 5, 2011

The .NET Preprocessor Visual Studio Add-In

NTSTATUS: STATUS_DOTNET_MACRO

So this is the obvious next best step: a Visual Studio Add-In for DOTNETPP to integrate it (somewhat) with VS. The biggest problem it would fix is ‘the catch’ mentioned in earlier posts regarding open source files that have macros.

The Add-In VSDotNetPP can be downloaded here. The download includes the latest version of DOTNETPP (Version 0.1.10.0).

Do note that this Add-In was built with Visual Studio 2010 for Visual Studio 2010. I do not believe it will work with an older version. The Setup created isn’t the greatest, it’s as basic as installing the files to a directory, and is uninstall-able. I’ll try to create a more comprehensive setup package later, but for now, there are some manual steps.


Registering the add-in

The default install directory is: “C:\Program Files\DOTNETPP\.NET Preprocessor Visual Studio Add-In”. You need to run the batch file Deploy-AddIn.bat to register the add-in with VS. This batch file copies the add-in file VSDotNetPP-Deploy.AddIn to the directory "%HOMEPATH%\Documents\Visual Studio 2010\Addins" which is one of the paths that VS2010 searches for add-ins. As I am using Windows 7, I am not sure if this path is valid for Windows Vista or XP.


You can find the paths that VS2010 searches for add-ins in your options settings by going to Tools->Options->Environment->Add-in/Macros Security. You may place the add-in file in any of those directories. This is the information from MSDN.

After registering the add-in, start VS2010, and you should see a new item in the ‘Tools’ menu called ‘.NET Preprocessor’.

To remove the add-in from VS, just remove the add-in file from the path you put it in and restart VS.


How the Add-In works

The add-in basically does what was suggested in previous posts: it closes the relevant open source files prior to running DOTNETPP… And, it opens them back after the build completes! So with this, you will not be bugged with the dialog asking if you want to reload the file as it has been modified outside the editor and fail the build. With this, you can choose to retain the macros in your source with much less inconvenience. However, I’d still not recommend that. I know it’s an inconvenience, but I don’t know how to set the view of the open file back to where it was before it was closed yet. When I figure it out, I will add that feature.

The add-in will call DOTNETPP for pre-build and post-build, so you will no longer have to add the calls yourself into the pre-build and post-build events in your project settings.


Settings Dialog

There is a settings dialog when you click on the ‘.NET Preprocessor’ menu item in the ‘Tools’ menu. This is basically for editing the DOTNETPP config file. Enter the full path of the config file into the settings dialog, and it will load all the settings. If the config file path is invalid, or it is blank, then DOTNETPP will not run during the build. This is how you can ‘turn it off’.

The rest of the settings have already been explained in the previous post about it.


Some Notes

OK, writing the add-in was really tricky. It was not straight forward at all, and I think I caught most of the ‘catches’, and I’ve been using it, and it works fine for the most part. However, if it is not behaving right, like changed settings don’t seem to be taking effect, I can only suggesting restarting Visual Studio. I know, it’s dumb, but that’s what I did and it was fine. However, in the latest testing, this problem hasn’t turned up, so it’s possible I fixed it. As I said, building add-ins for VS is not straight forward eventhough it looks like it is.

Before I forget, the add-in creates an XML file called VSDotNetPP.xml in your solution path. It is used to keep track of the DOTNETPP config file path.

Send me email at tim@bugslayersrus.com to comment, report bugs, or chat. Or, you could leave a comment here. Thanks.

Monday, January 3, 2011

The .NET Preprocessor - Part 4

NTSTATUS: STATUS_DOTNET_MACRO

OK, so now let’s see what macros would be useful… But before we actually get to that, I think we should look at the motivations and the sensibilities behind it. For those who are or were not C/C++ programmers, this would be relevant. Also, the article on the C Preprocessor in Wikipedia is a good place to start.

One of the first points, I believe, is that the macros should help you reduce or simplify your work/effort. Apart from general term replacement as in declaring what would be const values and such, is that the macros can help you expand arguments into pieces of code. So the common sense here would be that if it takes more effort to use the macros than actually writing the code, then it’s probably a poor choice in using that macro.

The only real guidelines I can recommend are the following:

  1. If you start to get annoyed about having to write some code because you’ve done it so many times and want some magic shortcut, then it’s a good candidate to be a macro.
  2. If you are writing a piece of code that is repetitive, but a term or two changes just a little bit here and there, then it’s a good candidate to be a macro.
  3. If calling the macro takes more effort than writing the code itself, then it might not be a good idea.
Because IntelliSense is so good now, some code don’t need to be macros as keystrokes have been reduced dramatically for languages like C# and VB.NET. Not so lucky if you’re writing C/C++. IntelliSense still (until today) behaves like a retarded potato that is two bricks short of a load. I just don’t get it. Do they think that Visual C/C++ don’t need IntelliSense to pop-up as soon as you type and make clever suggestions and auto-complete for you? OK, now that I’ve gotten that out of the way, you get the point.

If a macro results in more keystrokes, then it might not be that great an idea. Also, do take note that the macro (keystroke) recorder is a brilliant tool which I love, that is perfect for adjusting text with a pattern or structure. It’s an absolute gem of Visual Studio. However, that isn’t really practical in actually writing code.

Here are some macros that you might useful for C#. I use some of them:




As for the names of the macros (the identifier), those above are basically cryptic. This is because I’m keeping them short, for if not, it’ not be practical as I’d have to type a long name, which might make me punch more keys than if I did not use the macro in the first place. So it’s really up to you how you choose to name it. Refer to guideline no.3 above.

So really, you can do quite a lot with macro expansion, and as cliché’d as it sounds, it’s really up to your imagination. For example, the macro PROPVM(p) above is something that would be useful for implementing MVVM, and you’re not using any magic framework. Even a basic Property like that though simple to write, becomes tedious when you need to do a lot of it. Yes, you can copy/paste and modify, you but it does get tedious, doesn’t it? The macro would have reduced work significantly.

The .NET Preprocessor - Part 3

NTSTATUS: STATUS_DOTNET_MACRO


Now let’s go through the config file that DOTNETPP expects. It’s an XML file, and doesn’t expect any special name, and I called mine dotnetpp.xml. Here are the settings:

<?xml version="1.0" encoding="utf-8" ?>

<Settings>

<Language>C#</Language>

<Extension>.cs</Extension>

<MacroFilePath>.\MyMacros.npp</MacroFilePath>

<SourceBasePath>C:\MyProject</SourceBasePath>

<RecurseSubDirectories>true</RecurseSubDirectories>

<RestoreMacrosInSource>false</RestoreMacrosInSource>

<CleanupOriginalSources>false</CleanupOriginalSources>

<ClenupExpandedSources>false</ClenupExpandedSources>

<Diagnostics>

<stdout>true</stdout>

<debug>true</debug>

</Diagnostics>

</Settings>

Following are the meanings of each setting item:

Language: [C#/VB]

Supports only ‘C#’ and ‘VB’ where it will look for files of their respective extensions.

Extension: source file extensions including the dot (.cs, .vb)

OK, so it doesn’t only specifically support only .NET languages like C#/VB.NET. It will parse files of any extension you specify here. And this setting will override the <Language> setting.

MacroFilePath: Full path to the macro file

No specific file name, but will expect .npp as an extension. Currently, this setting expects the full path to a file, but does not harp on the file name or extension. However, the next feature upgrade will allow you to put a path (directory) in this setting, and it will look for all .npp files to parse for marco definitions.

SourceBasePath: The base path of the source files which require macro expansion

Usually would either be the path of your solution, or project.

RecurseSubDirectories: [true/false]

Recurse the subdirectories of <SourceBasePath> in search of source files

RestoreMacrosInSource: [true/false]

Restore the macros in the source files after expansion. Refer to ‘The Catch’ in Part 2. As mentioned prior, might be a better way to NOT restore macros and have them ‘permanently’ expanded into actual source.

CleanupOriginalSources: [true/false]

Delete all saved copies of source files before the expansion

ClenupExpandedSources: [true/false]

Delete all copies of the expanded source files. They have the extension .nmx. There was some challenge in finding an extension that was not already used and had an associated application.

stdout: [true/false]

Output messages to stdout.

debug: [true/false]

Output messages to the Debugger. Can be viewed with DebugView from Sysinternals.