Monday, April 27, 2009

CR_HelloWorld – Your first DXCore plugin

So for your first DXCore Plugin, we’ll show you the traditional “Hello World” program…plugin style.

We’ll show you how you can execute any managed code from a plugin – Fun stuff

First up you’ll need to Create a Vanilla plugin. From here you’ll be able to add all the relevant pieces to create CR_HelloWorld.

 

Ok first Step… ensure you’re looking at the designer view of your plugin. If you’ve not renamed it this will be the “Plugin1” (cs or vb) file.

DXCoreDesignSurfaceSmall

Next locate the ‘Action’ component in your toolbox and place one on the designer surface.

DXCoreControls

The set an appropriate name and a few properties:

actSayHelloWorld

Finally handle the “Execute” Action and do something within it.

This seems appropriate:

-------------------------------------------------------------
Private Sub actSayHelloWorld_Execute(ByVal ea As ExecuteEventArgs) Handles actSayHelloWorld.Execute
    MessageBox.Show("Hello World")
End Sub
-------------------------------------------------------------

Ok well that’s the majority of the work done.

However you’re going to need some way to activate this action…

So hit F5 to run up a new instance of studio to debug your new plugin.

Once this new copy of studio is running, be sure to ensure your plugin is actually running in memory.

Next we will attach your new action to a shortcut….

Open up the DXCore options screen (DevExpress\Options) Note – You may need to use the previously mentioned 'registry hack' to get the DevExpress menu to show up, if you’re running one of the Free DXCore based products.

Next select the IDE\Shortcuts page from the left hand side and you should see something like the following.

DXCoreOptionsShortcuts

In the shot you can see (Click to view full image) I have created a new ‘keyboard shortcut’ ( which I did via a context menu within the shortcut tree) and then I have filled out the Key1 and command options.

Now you can have your copy of Studio say “Hello World” whenever you choose :)

Obviously this is a something of a contrived example but, as you can see, it would be easy to have studio execute any managed code you care to dream up in a similar way.


How do I test my DXCore Plugin?

A simple enough question but it deserves a bit of thought.

You’ll recall from my previous post on creating a plugin, I suggested indicating that your plugin was a “Community plugin”

The reason for this was to prevent multiple copies of studio from loading and thus locking the plugin dll that you were working on.

So this leads you to a small problem… How to get the DXCore to load your plugin if you have explicitly asked it not to?

Well here’s how…

Simply open up the plugin manager from the DevExpress\Tool Windows\Plug-in Manager.

 

Side note: If you are using one of the free DXCore products, then you may not have such a menu. In order to acquire access to this most useful of facilities you’ll need to do a bit of registry hackery.
The following solution was provided in the AlexS (Another very helpful DevExpress employee)  in the DevExpress IDE Tools Forums
-------------------------------------------------------------
Please invoke the Registry editor, add the "HideMenu" DWORD value to the following Registry key, and set its Value to 0:

HKEY_LOCAL_MACHINE\SOFTWARE\Developer Express\CodeRush for VS\9.1
This should make the "DevExpress" menu visible.
-------------------------------------------------------------

DevExpressPluginManagerMenuOption

…to reveal this…

PluginManagerHelloWorld

Simply double click the entry you would like to load and, after confirmation your action, the DXCore will load your plugin.

All should now be good and you can commence testing your plugin..


What is a DXCore Action?

An action is one of the components you can drop on your plug-in design surface.

When you do so it looks like this ....

DXCoreAction

It can be triggered via either a mouse or keyboard shortcut (found in the IDE shortcuts page of the options screen) or placed on a menu (for example the context menu of the Code Editor)

It is a derivative of ‘system.component’ adding a few properties…

 DXCoreActionProperties

…and events…

DXCoreActionEvents

Some of these are worth drawing special attention to.

Properties
ActionName: The name of the action as displayed to UI like the commands dropdown in the IDE\Shortcuts options page.
ButtonText: What text would you like to represent this action when it is placed on a menu?
CommonMenu: A list of some of the more common menus found around VS.
ParentMenu: An alternative to CommonMenu. Use the name of any menu you know of, to place the action on that rather than one of the ‘common’ ones.

Note: The placing of Actions on menus is entirely optional and CommonMenu and ParentMenu are mutually exclusive options.

Events
Execute: The main event (so to speak :)). Fired whenever the assigned shortcut is triggered or the representative menu item is chosen. This is how the Action does it’s stuff.

In my next post I will walk you through your first actual plugin … Yes we will be starting slow, but we’ll ramp up fairly quickly as the posts flow… so you’ll be knocking out your own custom refactorings and the like pretty soon.


Wednesday, April 15, 2009

CodeRush 9.1.3 Community plugin support.

In the latest drop of the IDE Tools, the community folder experience has been enhanced.

Previous versions of the installer placed the community folder within the DevExpress folder structure (beneath Program Files).

This new location has several benefits:

1.> Creating a new plugin should (untested) no longer require you to launch VS with Admin rights. since your plugin ins not being rebuilt under program files :)

2.> Uninstall will not remove community plugins. (Shouldn’t have anyway but this really seals it.)

3.> Community folder will be immune to path changes as the version numbers of the IDE Tools increase.

As of 9.1.3, the Default folder for community plugins is now “{My Docs}\DevExpress\IDE Tools\Community\Plugins”


Monday, April 13, 2009

Creating a new DXCore Plugin

[Updated: This post has been updated to account for some small changes in the 9.1.3 release]

There are certain steps you must follow in order to create a DXCore plugin of any kind. This blog post will outline and explain those steps.

So the first step is to create the right sort of project.

If all is installed correctly you should be able to find the 2 available projects (‘Standard Plug-in’ and ‘Tool Window Plug-in’) in the DXCore section under either the Visual Basic or Visual C# sections in the New Project dialog.

Initially I’ll suggest that you pick ’Standard Plug-in’ as you can always add the Tool window later if you need to.

FileNewDXCorePlugin

Once you’ve given your plugin a Name, and hit Ok, you’ll be presented with the Plug-in Project settings dialog.

 InitialPluginSettings913_thumb5

Plug-in Type: System Plug-in: will cause your plugin to be deemed a ‘System plugin’ Duh! But what does this mean? Simply put, system plugins are loaded ahead of non system plugins. 90% of all plugins have no need to do this… I have yet to use this facility in any plugin I have written.

Plug-in Type: Plugin: Will cause your plugin to be built to “IDETools\System\DXCore\Bin\PlugIns\”. I’m guessing that this is something that DevExpress do themselves. Although I see no reason not to use the Community option.

Plug-in Type: Community Plug-in: is a new option with version 9.1.3. This is due, from what I can see, to the new Community Plugin Path option. This option sets the compile path of your new plugin, to your current community folder (Setup when you first loaded CodeRush or RefactorPro or DXCore after installing 9.1.3.) This means that, if you accepted the default, your plugin will exist under your ‘My Docs’ folder and as such will not require you to Launch Visual Studio with Admin rights in order to compile your plugin. – You should pretty much always pick this option.

Checking ‘Load manually’ will cause an entry to be added to the ‘plugin manager’ (another plugin), which in turn will prevent the DXCore from automatically loading your plugin.

Why would you do this?

Well, suppose that whilst developing your plugin, you are suddenly required to do something else. (Heaven forbid that anything should come ahead of this most important work). What you do is you go and immediately fire up another copy of VS and you load what ever you need into that session and off you go.

The trouble is that (assuming that you’ve compiled your plugin at least once) DXCore has now loaded a copy of your unfinished/unpolished plugin into memory. This might not be a problem but there are 2 ways I can think of that might mean it is…

1.> You’re writing the most killer refactoring known to man, and you’ve just completed the ‘DeleteAllThisUselessCrap’ routine but haven’t quite gotten around to writing the ‘InsertGloriouslyShineyCode’ and if activated, without taking suitable precautions then you could be up the swanny.

2.> You might want to tab back to to some more development on your plugin whilst you’re waiting for the results of your latest check-in on your ‘Important project’, but unfortunately the copy of VS hosting your ‘Important Project’ is maintaining a lock on your plugin’s dll and as such you’ll be unable to compile it, much less test it.

So in order to avoid these scenarios, I always tick the ‘Load Manually’ tick box which then ensures that the DXCore never *automatically* loads my plugin. Then when I launch a copy of VS for testing it, I locate it in the plugin manager and double click it in there. At this point DXCore wakes up, notices the plugin and loads it. In doing this you have only loaded your plugin into the address space of a single instance of VS, which exists entirely for the purpose of testing your plugin. This also means that when you shut down this single copy of VS, you’ll be able once again to resume development of your plugin. Great huh?

Note: This setting is local to your development installation only and will not affect any users of your plugin.

Default Load Type

I asked AlexZ (one of the great brains behind the DevExpress IDE Tools) about the ‘Default load type’ setting (and most everything else as well :) – Alex is a great source of info) and he had this to say:

On Demand - plugin is loaded when some event happens for which plugin should work. e.g. if you plugin contains some action - then it will be loaded only when action is being executed. Or it may define context or string provider or any other provider - and plugin will be loaded when provider is really accessed.
On Idle - Plugin will be loaded on editor idle, IOW when VS editor is being idle.
At start-up - Plugin will be loaded on start-up - however it will add time to overall loading time.

So which one should you select.. well the answer is it depends.. Personally I typically leave the default of ‘On demand’ in place as this means your plugin should not affect the start-up time of VS. This might mean that you have a minor slow down as you activate your plugin for the first time, but it will not contribute to slowing down the start up time of VS.

So to summarize… I recommend that you tick the ‘Load manually’ option and leave everything else (except perhaps the name) exactly as default … then hit Ok

At this point VS churns away and provides you with a nice clean plugin project ready for you to create the greatest plugin known to man… after all .. that’s what you were going to do right :)

I am now contractually obligated to make you wait until the next instalment before I reveal anything else :)


DXCore Plugin Types

A single DXCore plugin dll can perform a single simple task or many different functions. These functions are added to a plugin by adding various components to it’s design surface. These components will need various properties set and events handled, but the process is typically quite simple.

These components include:

  • Action – A simple object which represents any arbitrary piece of Code you like. Placable on many of the VS menus and assignable to a keyboard or mouse shortcut (optionally in combination with a context) using the DXCore IDE\Shortcuts option page.
  • RefactoringProvider – Used to add items to the ‘Refactor’ Menu in RefactorPro
  • CodeProvider – Used to add items to the ‘Code’ menu in CodeRush. It differs from the RefactoringProvider in that by convention items placed on this menu are allowed to alter the functionality of the code they affect
  • IssueProvider – Used to add ‘Code smells’, ‘Warnings’ and the like to the CodeRush ‘Code Issues’ feature.
  • CodeMetricProvider – Used to provide additional metrics for both inline metrics and the Metrics tool window.
  • ContextProvider – Used to add items to the Context Tree. This in turn is used to indicate suitability of Templates, Shortcuts and other Coderush facilities.
  • NavigationProvider – Used to add extra Items to the Navigate SmartMenu
  • SmartTagProvider – Used to add a new section to the DXCore SmartTag menu. Items like the existing ‘Refactor’ and ‘Code’ menu sections
    StringProvider and TextCommand – used to enhance existing features like templates, selection embeddings, Selection Inversions and others. Both perform some function, but the StringProvider returns a value to it’s calling mechanism where the TextCommand does not.

Depending on the type of functionality you are after, you may not need to place any additional component on your plugin. The plugin object itself has several properties and events that, when properly used, can provide some very useful effects.

Over the course of the next few blog posts I am hoping to provide some insight into the general process of creating a plugin, as well as the facilities provided by each of these components.


Thursday, April 02, 2009

Community Plugins for CodeRush 9.1

DXCore 9.1 introduces a different directory structure for the IDE Tools (CodeRush, RefactorPro) based on it.

Similarly you will need to move any 3rd party plugin assemblies you rely on to “C:\Program Files (x86)\DevExpress 2009.1\IDETools\Community\PlugIns”

Please adjust this path according to the setup of your own machine (System/install drive, x86 Vs x64)

All community plugins I have tried so far appear to work fine. If you know better please feel free to contact me via the comments.