January 2005 Blog Posts

So earlier I said "This is gonna piss some people off..." about the EntLib, right? Well, straight from the developer's mouth:

The registration process is to help us better connect with you. I hope it doesn't detract you from downloading. I think you will love it.
 
Well, I hope I didn't come across as "I'm not going to download it", cuz I most definitely am. Matter of fact, I'm downloading now. I just thought it would be interesting to see who would say such classics as "The mothership is tracking you!" or some other garbage like that. Why would I not want to register with Microsoft? They're already tracking my behaviors on Windows XP (HAHA! just kidding (or am I?)) :)

With the help of Laurent Kempé, I've traced down a bug in the PostXING FTP library (or rather my handling of it) and ended up changing the underlying FTP library code to the open source edtFTPnet library. This is a more complete library than the sample socket code that I was using before, and since it's LGPL licensed, I can link it into my code without affecting the license that PostXING is released under (which is zlib/libpng).

I also plan to add proxy support soon - the only hold up right now is that I like to at least dry run what I'm releasing before I put it out there, and I have no idea how to test if proxy code is going to work. Is there a such thing as a free proxy server that I can test against? I'm pretty resolved to, er, 'borrowing' the functionality for proxy support from RssBandit simply because the code works and has been a good reference for me before. So, I'm not worried about how to implement it, just on how to test it. Any ideas?

[ Currently Playing : Move On - Jet - Get Born (4:20) ]

Going to download the spankin new Enterprise Library, and before you can download you're presented with this:

Enterprise Library

Your registration information enables us to better provide you with the latest resources relevant to your needs, including pointers to service packs, security notices, training, trial versions of new products, conferences, new books, and more. Note that at any time you can manage all your Microsoft.com communication preferences from our Profile Center. Thank you for your interest in this download.

Registration required for this download

Yes, please take me to the registration page and then start the download.
No, I do not wish to register--which is required for this download--so please return me to the previous page.
 
I'll probably still download it on Monday, but it'll be fun to see what people say about this.

[ Currently Playing : Get What You Need - Jet - Get Born (4:07) ]

I am not an expert in this area. Not even close. Wouldn't even call myself an amateur. But I had to stop reading the letter when he says "It's the most secure OS the world has ever seen..."

A quick hop over to the link provided for solaris shows how proud they are...of thier new logo. Call me crazy, but if you were to make the claim that you are releasing the "most secure OS the world has ever seen", wouldn't that be what was highlighted on the front page of the site you are pointing to?

Right, different audiences, different priorities, different reasons for installing an OS, but if you are claiming that you have the "most secure OS the world has ever seen" (still can't get over that) - say it loud, proud, and in bright red letters on the first page of your site. Heh.

I feel like a kid in one of those old milk commercials - you may try to com...ment $p4|\/| me, on....line pok...er, but my blog is running CS::Blogs, so your stupid comment doesn't get past my inbox. Comment moderation: it does a blog good.

update: This blog is not running the version of CS::Blogs that has moderation. As a matter of fact, this blog is running .Text version 0.94 because of a bug in the Metablog API implementation of v0.95. Sorry to get your hopes up, I was talking about my other blog on weblogs.asp.net.

[ Currently Playing : Floyd The Barber - Nirvana - Bleach (2:18) ]

I've been playing Halo 2 recently, and I got to a part that reminded me why I lost interest in the first one.

Once you get to a certain part of the game (either one), it gets so difficult to advance that it's not fun anymore. Now, granted, I've never been close to being the Wizard, but gimme a break already. I guess it's back to Prince of Persia (again, either one) for me. UbiSoft gets it. Make a game that I'll want to play over and over.

</rant type="As If You Cared">

I've gone ahead and uploaded a new build of PostXING. I extended the plugin architecture a little bit to allow for posting to non-.Text blog engines using IBlogExtension plugins, of which there are a few out there already. Everything else is pretty much the same, but I had to give out some credit for the plugin architecture - I didn't come up with that stuff on my own and I'm all about giving credit where credit is due.

To test this IBlogExtension plugin architecture (really all you have to do is drop the IBlogExtension dll/exe into PostXING's plugins subdirectory) I created a blogger account that I could use the NewsGator blogger plugin to test against. Guess what? It works.

[ Currently Playing : No Excuses - Alice in Chains - Unplugged (4:56) ]

I can now use the great IBlogExtension plugins for NewsGator to post with PostXING. (with my built about 10 minutes ago dogfood version, that is :) Thanks for that idea, Joel.

The only problem with this method is that it's "push only" - I can only publish with these plugins. No history management, and strictly speaking, not manageable on the same level as using the Metablog API. So, I can't set an account for IBlogExtension blogs - no navigating to the site without manually opening a browser, basically no integration with the current UI. Categories seem to be up to the plugin as well. But I can post. That's one step in the right direction, right?

[ Currently Playing : Still Frame - Trapt - Trapt (4:30) ]

I've uploaded a new release of PostXING to ProjectDistributor. This release adds the ability to Load or Save a post as a .htm file, as well as managing your blog (Categories, Post, Post & Publish, Cross-Post, Delete, and plugins) from the Preview page.

How ya like that, Bob? :)

I went ahead and included a couple of bugfixes that slipped into this release, so the latest version of PostXING is now uploaded and reflected on ProjectDistributor. Sorry I let a couple of bugs slip in there. Thanks for the feedback, Bob!

I've uploaded a new release of PostXING to ProjectDistributor. This release adds the ability to Load or Save a post as a .htm file, as well as managing your blog (Categories, Post, Post & Publish, Cross-Post, Delete, and plugins) from the Preview page.

How ya like that, Bob? :)

[ Currently Playing : God (Interlude) - Andre 3000 - Speakerboxxx/The Love Below (2:19) ]

...for PostXING that I should have added a long time ago. It only took roughly 40 lines of code (including gratuitous whitespace). I'll give you a hint on what it is:

There are a couple of other things that I would like to implement before uploading a new release, tho. For example - I don't see a good reason why you shouldn't be able to post/publish/cross post from the preview pane. Also, Joel Ross gave me the spectacular idea of using existing IBlogExtension plugins to make posting to blogs other than .Text or some other Metablog API enabled blog engine not only possible, but extremely easy.

 Couple of feature requests
posted by Bob Yexley on 1/7/2005 12:02:04 PM :
Hey nice work on the latest version. Spell checking works very nicely. There are a couple of things that I've noticed about the application that I thought would make it nicer that I wanted to mention. Fairly simple I'm pretty sure.

First off, especially with all of the different version releases you've had lately, I've wanted to check the "About" box to make sure that the correct new version was running after the new version, and I noticed that the current version isn't displayed on it. It would be great to have the current version displayed on the About box just for reference if nothing else.

I've also noticed that when I switch to the "Preview" tab, that the toolbar with the "Post & Publish" button disappears. Normally when I compose a new entry, I write it up in the editor tab, and then I check spelling (well, I will from now on anyway), and then I switch over to the preview tab to make sure everything looks OK with my stylesheets applied and all. Well, if everything looks good, I'd like to be able to just click "Post & Publish" right then and there, but since that toolbar is gone, I have to switch back to "Design" view to get that toolbar back to publish the entry. It seems to me like that's a fairly common toolbar, and maybe it (or it's buttons) should just be added to the standard toolbar that has the "Setting" button on it. At very least, it would be nice to have that one button displayed when using the "Preview" tab.

Thanks for the great free application though. I love it.

Now, that is some great feedback. I've got seperate use cases than what I always do and clear concise suggestions on how to implement them. These are the types of things that you as a developer don't tend to think of all the time because you are used to a certain useage scenario. I would have never thought of any of these (except maybe the about box thing. whoops :) There are of course some other things that I know the application needs - like for example validation maybe? Heh.

Honestly, tho, I'm just glad that a few people are finding my humble little app useful. But to anybody else who is using PostXING, I am always happy to at least consider making changes suggested on ProjectDistributor or my blog. It just makes it so much easier (and therefore likely to get implemented) with great feedback like Bob gave.

Royo asks:

I'm interested to know whether you found my Extensibility application block useful, or if you had to make many changes to it to make it workable.

The short answer to this question is: yes and that depends on your definition of 'many'.

The EAP was useful to me: without the ideas and articles supporting it, it would have taken me at least twice as long to implement a spell checking plugin for PostXING. That said, there were some hurdles I had to overcome in order to get it working consistently for me.

First, let me say that I wanted to mimic RssBandit's plugin architecture because a) I have the source code handy and b) it works. RssBandit's method of loading plugins (called "ServiceManager")...

/// <summary>
/// ServiceManager implements a similar algorithm described in
/// http://msdn.microsoft.com/asp.net/using/building/components/default.aspx?pull=/library/en-us/dnaspp/html/searchforplugins.asp 
/// to find classes in assemblies that implements Syndication.Extensibility.IBlogExtension.
/// </summary>

Well, guess what? The author of the above article and the EAP are one and the same! Good news for me.

Okay, that said, I was unable to get the DynamicFindPluginProvider to work correctly consistently. The problem was that I was trying to load an assembly from within itself (I think - I'm no reflection guru by any means) and the result was that when the application was launched standalone it would work, when it was launched from the plugin in would b0rk.

I also had to add some properties and methods to the IPlugin interface and the AppContext class in order for IPlugin to be even remotely useful to me. I found out rather quickly that I was going to need some way to configure each IPlugin implementation individually, so I "borrowed" that part of the contract from IBlogExtension. A couple of properties were required in my case in AppContext -

		protected bool _isCallingFromHostApplication = true;
		public virtual bool IsCallingFromHostApplication{
			get{return _isCallingFromHostApplication;}
			set{_isCallingFromHostApplication = value;}
		}

		protected string _currentEditorText = string.Empty;
		public virtual string CurrentEditorText{
			get{ return _currentEditorText;}
			set{ _currentEditorText = value;}
		}

CurrentEditorText shows up in some of Roy's articles, but not the EAP itself. I'm interested in the text, but I can see that CurrentEditorText is not generic enough to be included by default. This kind of makes me think that the EAP is mis-named: it's really a foundation, or building block, whereas the Patterns & Practices Application Blocks come kind of ready-to-go OOB. That doesn't detract from its validity and usefulness - I've just become accustomed to not having to modify an "Application Block" to get it working right away.

Anyways, semantics aside, I needed these properties for dealing with the IPlugin correctly. The override of CurrentEditorText in my app-specific AppContext (called PostXINGAppContext, natch) raises an event saying that it was modified on set, and the consuming event loads the text back into the editor only if the CurrentEditorText was not set by the calling application - I thought that might end up in endless loads of text into the editor which would get rid of the usefulness of a plugin. I could be wrong, but that's what I went with, okay?:)

I found it useful to inherit my IPlugin implementation from the GenericDockablePlugin, even tho there is no UI except for the NetSpell-supplied dialogs. This way, I was able to set an icon thru the designer and have it embedded as a resource instead of including it with the install of the dll. It was just the easiest way to get from idea to implementation for me.

In summary, the EAP is great as a building block for getting plugin functionality into your windows forms app. With some minor modifications, I was able to pull functionality that was originally going to be part of the host application out into a plugin in a few hours.

[ Currently Playing : Tip Your Bartender - Glassjaw - Worship & Tribute (2:59) ]

With the latest release of PostXING, a plugin architecture has been added to allow for external extensions such as the new NetSpellPlugin that adds spell checking to PostXING.

All that is required to install the plugin is to add the .dll file to the plugins subdirectory of PostXING's install directory, for me that's C:\bin\PostXING\plugins. When you start PostXING, you should see a new button in the toolbar:

as well as a couple of entries in the plugins menu under the Tools main menu:

I really wish that was all there was to it, but unfortunately there's more that needs to be done. As I've said before, the spell checker is pretty well useless without a good dictionary file. If you try to use the plugin straightaway you should see this:

So how do you do that? By using the ... - Configure menuitem, of course! :) Before you configure, tho, you should download the correct (for you) .dic dictionary file by either going to LoreSoft's NetSpell page, creating your own, or downloading from http://vaultpub.sourcegear.com if you have SourceGear's Vault Client (at least version 3.0 at this time). Here's how to get the en-US.dic dictionary file from the command line:

Create a .bat file called getdic or whatever and put it either in your PATH or in SourceGear vault's install directory. Navigate to where vault.exe is located (for me it was cd C:\Program Files\SourceGear\Vault Client). Drop something like the following into the .bat file:

mkdir C:\tmp\vaultpub

vault get -host vaultpub.sourcegear.com -user guest -password guest -repository postxing -makewritable -destpath C:\tmp\vaultpub $/ThirdParty/dic/en-US.dic

Vault should tell you if you were successful or not in downloading the file. Note that the vault command above is all on one line. I don't know if the -makewritable is necessary or not, but this is what worked for me. Remember, if you prefer to blog in a different language (or a different, erm, dialect? of English) the ones available in vaultpub and from the NetSpell component itself are:

de-DE.dic
en-AU.dic
en-CA.dic
en-GB.dic
en-US.dic
es-ES.dic
es-MX.dic
fr-FR.dic
it-IT.dic

Now that you've downloaded the correct dictionary file, go to Tools -> Plugins -> ...- Configure and you'll be greeted by this simple dialog:

Above, we said download to C:\tmp\vaultpub(\en-US.dic) so navigate there and hit OK. (side note: this is necessary because depending on where PostXING is launched from, i.e. standalone or from the BlogThisUsingPostXINGPlugin, NetSpell will look in a different path (I think the Application.StartupPath) for the default dictionary based on your cultureInfo. This way, you can blog in English no matter what your cultureInfo is set to.)

You should now be able to spell check any Post from PostXING using either the toolbar button or the menu item.

[ Currently Playing : 99 Problems - Jay-Z - The Black Album (3:54) ]

MVP LogoI just found out that I got the nod for Microsoft MVP again for 2005. I was hoping that would be the case, because I really enjoyed going to the MVP Summit last year, and was looking forward to going again in 2005.

[Via Jonathan Goodyear / angryCoder]

So, er, me too ;) except I hope to make this year's my first MVP summit.
Congrats, John!

Well, I've implemented it. I figured out a way to have a user-defined dictionary location (very simple implementation), but now I'm still facing the dilemma of where do I point to for the dictionaries? Like I said before, the NetSpell component comes with a few dictionaries by default.

OpenOffice has a project called lingucomponent that has a more exhaustive listing of dictionaries, but they are not in the same format that NetSpell uses. (I even tried using the en_US dictionary. Needless to say it was useless as it stopped on every word.) However, there is an article for NetSpell about creating a custom dictionary, although I don't know, looking at the contents of the files together, if that will be of much help at all.

Either way, it looks like it might require a download of the NetSpell software for the included dictionaries and the dictionary build tool. What do you think?

When I was working on the latest release of the BlogThisUsingPostXINGPlugin, I kept running into file access issues.

The whole thing was an excersize in refactoring - well, really, the whole thing WAS a refactor, since the basic functionality already existed, but I was making additions in how things were going to work.

First, I changed the XsltStream to return a FileStream or a ManifestResourceStream, based on the existence of a user-specific file:

  1 		Stream XsltStream
  2 		{
  3 			get
  4 			{
  5 				string filePath = Path.Combine(ConfigurationPath, this.BlogType.ToString() + ".xslt");
  6 				if(File.Exists(filePath)){
  7 					//read from a file stream.
  8 					FileStream fs = new FileStream(filePath, FileMode.Open);
  9 					return (Stream)fs;
 10 				}else{
 11 					string resourceName = "PostXING.Rss.BlogExtensions.Resources." + this.BlogType.ToString() + ".xslt";
 12 					return Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName);
 13 				}
 14 			}
 15 		}

Again, this part was shamelessly lifted  modified from haacked who generously gave out the source code for his BlogThisUsingWbloggarPlugin. (the configurationPath property was changed a bit to enable more than one file to go into that particular path).

Then I added a button next to each option in the config dialog that says simply "Customize...". Pressing this button opens a modal form that loads up the text from the user-defined file if it exists, else from the resource stream.:

  1 		string transformPath;
  2 
  3 		public CustomizeForm()
  4 		{
  5 			//
  6 			// Required for Windows Form Designer support
  7 			//
  8 			InitializeComponent();
  9 
 10 		}
 11 
 12 		public CustomizeForm(string TransformToCustomize) : this(){
 13 			transformPath = Path.Combine(BlogThisUsingPostXINGPlugin.ConfigurationPath, string.Format("{0}.xslt", TransformToCustomize));
 14 
 15 			this.LoadTransform(TransformToCustomize);
 16 		}	
 17 
 18 		private void LoadTransform(string TransformToCustomize){			
 19 			string resourceName = string.Format("PostXING.Rss.BlogExtensions.Resources.{0}.xslt", TransformToCustomize);
 20 			//Stream resourceStream;
 21 			StreamReader sr;
 22 
 23 			if(File.Exists(transformPath)){
 24 				sr = new StreamReader(transformPath);
 25 				this.rtbTransform.Text = sr.ReadToEnd();
 26 				sr.Close();
 27 				
 28 			}else{
 29 				sr = new StreamReader(ResourceStream(resourceName));
 30 				this.rtbTransform.Text = sr.ReadToEnd();
 31 				sr.Close();
 32 				
 33 			}
 34 		}
 35 
 36 		Stream ResourceStream(string resourceName){
 37 			return Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName);
 38 		}

3 buttons were added to the form: Revert to Original, Apply, and Cancel. I didn't really think that I needed DialogResults, since you have to invoke the plugin via its menu every time you want to use it. Revert to Original just deletes the user-defined file. Cancel simply closes the form and does nothing. Apply does this:

  1 		private void btnApply_Click(object sender, System.EventArgs e) {
  2 			if(File.Exists(transformPath)){
  3 				File.Delete(transformPath);
  4 			}
  5 
  6 			StreamWriter sw = new StreamWriter(transformPath, false); //doesn't release file handle?
  7 			sw.Write(this.rtbTransform.Text);
  8 			sw.Flush();
  9 			sw.Close();
 10 
 11 			this.Close();
 12 		}

Notice my little note to myself? It turned out that I tried using the using statement, using File.CreateText(transformPath) (which is why the pre-step File.Delete is in there) and I kept getting "Cannot access file 'blah' because it is in use by another process." When I opened up sysinternal's process explorer and searched for the file, it said that the file handle was opened by RssBandit. grr.

All I ended up having to do was to add one argument to File.Open from the XsltStream property getter:

  1 		Stream XsltStream
  2 		{
  3 			get
  4 			{
  5 				string filePath = Path.Combine(ConfigurationPath, this.BlogType.ToString() + ".xslt");
  6 				if(File.Exists(filePath)){
  7 					//read from a file stream.
  8 					FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
  9 					return (Stream)fs;
 10 				}else{
 11 					string resourceName = "PostXING.Rss.BlogExtensions.Resources." + this.BlogType.ToString() + ".xslt";
 12 					return Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName);
 13 				}
 14 			}
 15 		}

And bam! the problem went away. It looks like the default for a new FileStream (sans FileAccess attribute) is FileAccess.ReadWrite. Anyways, I hope this helps someone else out there from banging their head too much.

[ Currently Playing : Inertiatic ESP - Mars Volta - De-Loused In The Comatorium (4:23) ]

This new version of the BlogThisUsingPostXINGPlugin handles customizing the transform used to output into a new Post in PostXING. For example, say I want to have the title of the post referenced in the post body. I would start off with the LinkOnly.xslt option:

  1 <?xml version="1.0" ?>
  2 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  3 	<xsl:output method="html" /> 
  4 	<xsl:variable name="feed-title" select="/rss/channel/title" />
  5 	
  6 	<xsl:template match="/">
  7 		<xsl:apply-templates select="//item" />
  8 	</xsl:template>
  9 
 10 	<xsl:template match="/rss/channel/item">
 11 		<html>
 12 		<title>RE: <xsl:value-of select="title" /></title>
 13 		<xsl:choose><xsl:when test="link"><a href="{link}"><xsl:value-of select="$feed-title" /></a></xsl:when><xsl:otherwise><xsl:value-of select="$feed-title" /></xsl:otherwise></xsl:choose>
 14 		</html>
 15 	</xsl:template>
 16 </xsl:stylesheet>

Line 13 is the key line. All I did was change the use of xsl:variable to the actual title that is context-specific in this case. So we now have:

  1 <?xml version="1.0" ?>
  2 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  3 	<xsl:output method="html" /> 
  4 	<xsl:variable name="feed-title" select="/rss/channel/title" />
  5 	
  6 	<xsl:template match="/">
  7 		<xsl:apply-templates select="//item" />
  8 	</xsl:template>
  9 
 10 	<xsl:template match="/rss/channel/item">
 11 		<html>
 12 		<title>RE: <xsl:value-of select="title" /></title>
 13 		<xsl:choose><xsl:when test="link"><a href="{link}"><xsl:value-of select="title" /></a></xsl:when><xsl:otherwise><xsl:value-of select="title" /></xsl:otherwise></xsl:choose>
 14 		</html>
 15 	</xsl:template>
 16 </xsl:stylesheet>

Subtle difference, but it changes a post from this:

 Frans Bouma's blog

to this:

 Template Studio for LLBLGen Pro released!

I only left the three default options for formatting in there with the idea that most of the time, I would only want to use one of these anyways. This opens up the door for this plugin to be completely customized, to where the descriptions don't mean anything for the content of the actual transform.

[ Currently Playing : Killer Is Me - Alice in Chains - Unplugged (5:23) ]


www.AcehAid.org

What do they need? MONEY of course to pay for the supplies going into Aceh. Macs, lots of macs and digital cameras and more.

An external hard drive for backing up precious data. More money. Stuff. Sleep. Rest. Peace.



http://www.AcehAid.org
[Via Julia Lerman Blog - Don't Be Iffy...]
 
 
 
blog comments powered by Disqus