« January 2004 | Main | March 2004 »

February 24, 2004

Anti-spam algorithms & MIT conference papers.

CRM114 - the Controllable Regex Mutilator is a spam filter that claims 99.9% accuracy.

DSPAM is another scalable, open-source statistical-algorithmic hybrid anti-spam filter.

Source code is available for both. Both are meant to integrate with unix flavor mail servers. One wonders whether the spam / anti-spam war isn’t much like the virus / immune system: Spam will adapt to each new filtering algorithm; all victories will be temporary.

The end result, of course, will be spam that passes the Turing test and anti-spam filters that can measure intelligence. Which is harder?

 

February 23, 2004

Good COM Interop Article Series

Beyond (COM) Add Reference: Has Anyone Seen the Bridge? and the follow up article Using the .NET Framework SDK Interoperability Tools by Sam Gentile.

Useful stuff when you have to use a .NET un-friendly COM component.

 

February 22, 2004

Acquiring images from USB connected cameras

The new API for doing this is WIA, Windows Image Acquisition. Older devices may not have WIA drivers (my cheap web cam doesn’t). The WIA scripting library can be used from .NET but it is not strongly typed and has manual wrapper and dispose requirements.

TWAIN is the older API. It may require a windows message pump. My web cam has a TWAIN compatible driver.

WIA provides TWAIN compatibility so a TWAIN application will see WIA devices. An application that speaks both TWAIN and WIA will see the WIA devices twice.

An example using each API is found on CodeProject: http://www.codeproject.com/dotnet/wiascriptingdotnet.asp

WIA scripting can capture an image from simple still cameras but not directly from video cameras (like my Sony DTRV20). Instead, use the support for video to create an object with access to the video stream coming from the device and use a method of that interface to snap individual pictures.

 

 

‘Unable to start debugging’ ASP.NET application

I typically run into the “Unable to start debugging” error message after when trying to continue development of a source controlled an ASP.NET application for the first time on a newly configured system with tight file access security.

Giving “everyone” read access does the trick. What’s the minimum it needs?

 

February 21, 2004

Releasing version 1.0.1512 of TonesNotes

What’s New:

·        You can now update posted notes by reposting the archived copy of a post. The archived file now maintains a posting history to remind you of when you posted the note to which blogs.

·        The Confirmation Dialog now comes up only once if a note is posted to at least one blog that requires confirmation. The dialog has been reworked to let you change any part of the note (title, date, categories, body) and shows you an updated preview of any edits made to the html.

·        Improved error checking. Undoubtedly more to go.

TonesNotes version 1.0.1512 source code zip.

TonesNotes installer.

TonesNotes GDN Workspace.

 

 

Job-Board Journalism, A critique of online job boards

Here’s a good update on the game played by the online job boards. No real news but confirmation that the system is broken and whose system it is.

 

February 17, 2004

Adding posting history and updating to archived notes

Just finished the first round of implementation and testing on closing the loop to allow updating blog posts when an archived note is updated.

Archived notes now will contain a brief history of where and when they might have been posted. If the archived note is posted again, after making some changes for example, the existing blog posts will be updated with the new content and the archived note will be updated in place.

 

Also reorganized the confirmation dialog to confirm only once for all posts and before archiving. The dialog’s preview tab now updates correctly if you edit the HTML.

 

February 16, 2004

TonesNotes release with a fix for people having trouble with archiving enabled.

Under some circumstances Microsoft Word wasn’t making a style defined by the add-in in the main document available to temporary documents created for archiving.

The resulting exception caused an early termination of all posting actions.

 

Download the latest Tones Notes release

 

February 14, 2004

Microphone Boost

The Recording Control dialog has an “Advanced Controls” checkbox on the Options dialog that is disabled by default.

It gives you access, among other things to the Microphone Boost checkbox which enables a +20dB amplification of weak microphone signals.

 

This still isn’t giving me the volume from my microphone on Windows 2003 Server that I was getting on Windows XP Pro.

 

‘What U Hear’ input channel on Creative Audigy sound cards

Creative Audigy sound cards have a generally unknown feature called ‘What U Hear’. It’s an input channel that lets you record what you’re playing; the contemporary equivalent of putting a microphone in front of your speakers.

 

To enable the channel, bring up the Recording Control dialog and  select Properties on the Options menu.

 

February 12, 2004

Release 1.0.1503 of TonesNotes is available.

What’s New:

  • Passwords in configuration files are encrypted.
  • Automatically defines an initial heading style for Word. No longer uses “Heading 1” by default.
  • New Confirmation Dialog lets you view and tweak each post before it gets sent.
  • Images in posts are automatically sent to your blog server and added to an image gallery.
    Post body is modified to reference gallery images either with or without thumbnails.
  • Dialogs do input verification where appropriate.

 

Download the latest release of TonesNotes from here.

 

 

ThreeDegrees.com beyond instant messaging

threedegrees beta lets a small group interact across desktops. Group members simultaneously listen to shared music, share pictures, share “winks” (dynamic emoticons, library & user created), chat (the intercom feature caught my attention). A bit too wanna-be trendy. Mostly about the music.

 

Windows 2003 Server used as a workstation vs. Windows XP Professional

Windows Explorer doesn’t have a Tasks/Other Places/Details panel.

My Computer doesn’t show cameras.

Slideshow screen saver is missing.

SQL databases need access by NT AUTHORITY\NETWORK SERVICE, instead of machine\ASP.NET

 

Generally followed tips on adjusting the configuration found here.

How to convert your Windows Server 2003...

 

Ran into a problem with “mrtRate” service not starting at boot due to a file not found error. Tried reinstalling Quicken 2004 and pressing alt-shift-4 in the “Customize Online Updates” dialog. Didn’t help. Finally resorted to regedit and removed in two places under services. So far so good.

 

Still looking for a replacement to the XP picture viewer and screensaver slideshow.

 

February 11, 2004

.NET COM Add-In installs but doesn’t run from the IDE

Managed Add-Ins built with Visual Studio .NET use the DLL mscoree.dll to load.

 

Microsoft is aware of a problem affecting some developers where the add-in works fine when built and installed by an add-in setup project, but fails to load when recompiled by the IDE. What drives this behavior is a registry key value that is written with a full path by the installer but without a path by the IDE’s build process.

 

Every add-in class has to have a GUID registered under HKCR\CLSID in the registry. The registration includes an “InprocServer32” key which points to the mscoree.dll.

 

If the value includes a full path, the add-in always loads (all other issues aside). If the value is just “mscoree.dll”, the add-in only works for some people. It is not known at this time by Microsoft what configuration differences cause this behavior.

 

When you get tired of the build, install, run manually, attach debugger cycle, which does work reliably, and wish you could just press F5 and hit your breakpoint, do the following:

 

-         Add a new text file to your solution with the name “FixMscoree.vbs”.

-         Edit the following into the file, replacing the guid with the one your add-in uses:

' Run with project build event: cscript $(SolutionDir)FixMscoree.vbs

Dim wshShell,wshEnv,sPath

 

Set wshShell = CreateObject("Wscript.Shell")

set wshEnv = wshShell.Environment("process")

sPath = wshEnv("SYSTEMROOT")

sPath = sPath & "\System32\mscoree.dll"

 

'guid is of the form {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}

wshShell.RegWrite "HKCR\CLSID\{77C3AFCA-8AF6-4b7f-8D7C-657CDB17856E}\InprocServer32\", sPath, "REG_SZ"

 

Set wshEnv = Nothing

Set wshShell = Nothing

-         Set ProjectàPropertiesàBuild EventsàPost-build Event Command Line to “cscript $(SolutionDir)FixMscoree.vbs

 

To the best of my knowledge there are no relevant knowledgebase articles on this problem yet. If you know of one, please post or send the reference.

 

February 09, 2004

Is it just me or should the ErrorProvider provide and indexer or a HasErrors property.

This thread from the managed MS discussion forum captured on .NET247 indicates I’m not alone (and that MS isn’t jumping up and down over the idea!), but it would be very helpful for the ErrorProvider to expose its internal collection of error strings assigned to controls in some way.

A simple “bool HasErrors” property would be great.

 

February 06, 2004

New release of TonesNotes for Dottext supports posting images from Word

 

The latest release of TonesNotes is available here http://workspaces.gotdotnet.com/tonesnotes. It lets you post to a .Text blog from any open Word document and now supports posting images in the body of the note.

The README.htm file installed with the release contains a code change for the Dottext blog server to support posting images.

 

Changes to .Text for Image Posting using TonesNotes

The latest version of TonesNotes lets you post blog entries from Word that contain images:

Here is the change required of 0.95 vintage Dottext codebase.

Add the following method to the SimpleBlogService.asmx.cs file:

/// <summary>

/// Add an image to a specified gallery and return the url by which it will be accessible.

/// </summary>

/// <param name="username"></param>

/// <param name="password"></param>

/// <param name="gallery">Title of the target gallery, gallery will be created if it doesn't exist.</param>

/// <param name="postdate">Date to associate with the image. Not currently supported by the data model.</param>

/// <param name="title">Title for the image.</param>

/// <param name="description">Description for the image.</param>

/// <param name="categories">Array of categories to associate with the image. Not currently supported by the data model.</param>

/// <param name="filename">The non-path image filename including extension. Note that currently filenames must be unique within a gallery.</param>

/// <param name="data">Image file data in on-disk format matching the filename's extension.</param>

/// <returns>A url in the form http://blogs.mydomain.com/myblog/8/o_filename.jpg, where 8 is the integer CategoryID assigned to the gallery.

/// The returned url is an absolute url with a "o_" prefix on the filename.

/// Caller can make the prefix "t_" for thumbnail and "r_" for standard size.</returns>

[WebMethod(MessageName="AddImageToGallery",Description="Insert an image into a gallery with Categories",EnableSession=false)]

public string AddImageToGallery

      ( string username

      , string password

      , string gallery

      , DateTime postdate

      , string title

      , string description

      , string[] categories

      , string filename

      , byte[] data

      ) {

 

      BlogConfig config = Config.CurrentBlog(Context);

      CheckUser(username,password);

 

      int categoryID = 0;

 

      // Lookup the categoryID of gallery (gallery is the title).

      LinkCategoryCollection lcc = Links.GetCategories(CategoryType.ImageCollection, false);

      foreach (LinkCategory lc in lcc) if (string.Compare(lc.Title, gallery, true) == 0) { categoryID = lc.CategoryID; break; }

 

      // If gallery doesn't exist, try creating it.

      if (categoryID == 0) {

            LinkCategory category = new LinkCategory();

            category.CategoryType = CategoryType.ImageCollection;

            category.Title = gallery;

            category.IsActive = false;

            category.Description = "Images uploaded with new posts.";

            categoryID = Links.CreateLinkCategory(category);

            if (categoryID == 0) throw new Exception("CategoryID is zero");

      }

 

      // Insert the new image into the selected gallery.

      // This puts three copies (thumbnail, standard size, original size) of the image on disk under the "images" folder

      // and adds a record to the blog_Images table.

      Image image = new Image();

      image.CategoryID = categoryID;

      image.Title = title;

      image.IsActive = true;

      image.File = Images.GetFileName(filename);

      image.LocalFilePath = Images.LocalGalleryFilePath(Context, categoryID);

      int imageID = Images.InsertImage(image, data); 

 

      if (imageID == 0) throw new Exception("ImageID is zero");

 

      string baseImagePath = Images.HttpGalleryFilePath(Context, image.CategoryID);

 

      return baseImagePath + image.OriginalFile;

}

 

 

 

February 05, 2004

TonesNotes Documentation

TonesNotes

TonesNotes is a free add-in for Microsoft Word available here http://workspaces.gotdotnet.com/tonesnotes. It lets you post to a .Text blog from any open Word document.

Other places to look for (or leave) information about TonesNotes are the .Text Forum, the .Text Wiki, or my own blog Tone's Notes

The intended mode of operation is to use a single Word document in which the ideas you’re working on take shape. When an idea is baked, place the insertion point within its content, click the “Post” button on the TonesNotes toolbar, and the content is simultaneously posted to one or more blogs and archived as a separate Word document on your local file system.

The command bar has a “New” button which starts a new entry at the bottom of the active Word document. An entry is demarked by a paragraph with the style “Heading 1” by default. The “New” command inserts a paragraph with a date stamp which will become the post creation time. Complete the note heading with a comma separated list of categories and a title. Anything in the note heading paragraph not recognized as a date or category name becomes part of the title.

Since not all ideas are suitable for public posting, the behavior of the Post command is driven by assigning a category name to each configured blog. A note is posted to each blog whose category name is listed in the note heading, or simply archived if it isn't meant to be blogged.

In addition to the “New” and “Post” functions, the toolbar has a “Config” button which brings up the configuration dialog.

Getting Started

The installation was successful if you see a new toolbar with three buttons on it ("Post", "New", and "Config") when you launch Microsoft Word.

Drag the toolbar to place it next to your existing toolbars at a convenient location.

To get in the swing of things, it might be helpful to start by creating a dummy note which you will post and archive if you follow along with the examples below.

With a Word document open (doesn't matter which), click the "New" button. You should see something like this appear at the end of the document:

2004-02-12 12:56:32 Thu,

The paragraph style has been set to Heading 1 (this is configurable) and the insertion point should be blinking just after the comma. If you don't like the date or time format you can change them later. Complete the note heading so it looks like this:

2004-02-12 12:56:32 Thu, myblog, My first note using TonesNotes

The commas are important. "myblog" is the category name assigned to your blog by default. By sticking it in the note heading like this, you're saying that when the note gets posted, it should go to your blog. The rest of the heading will become the title of your blog posting.

Every note you post has to have a body, so type a return and some text like the following:

2004-02-12 12:56:32 Thu, myblog, My first note using TonesNotes

This is the body of my note. It can contain most of the formatting Word has to offer.

That's it, your first note is ready to Post, but before you click the "Post" button, it iss essential that you customize TonesNotes' configuration.

Click the "Config" button to set things up for your particular situation.

TonesNotes Configuration Dialog

Archive Configuration

The "Archive" tab controls how TonesNotes saves a copy of each note you post to your local file system.

If you just installed TonesNotes, you're initially configured to save each note under a folder called "Notebook" in your "My Documents" folder.

Here is the purpose of each item on the "Archive" tab:

Enabled
Check the box to save each note on your computer when you Post them. Clear the box to stop archiving notes locally.
File format
You can save each note either as an ordinary Word document with the ".doc" extension, or as Filtered HTML with a ".htm" extension. The .doc format has the advantage of always keeping your work in a single file. The .htm format may put things like images that you insert into your notes in separate files that are associated with the main .htm file.
Folder
Your notes will be saved in this folder. Every note that has at least on category in its heading is saved in a subfolder with the name of the first category.
Filename format
Controls how filenames are generated from note headings. {0} is replaced with the date and time. {1} is replaced by a comma separated list of categories. {2} is replaced with the note's title.
Heading format
Controls how the note heading will be formatted at the beginning of each saved note file. You can clear it if you don't want the heading in each file.
Add, Delete, Prev, Next
These buttons let you configure additional archive locations, each with its own format. Leave these buttons alone for now.

Blog Configuration

The "Blog" tab controls how TonesNotes posts each note to one or more blog servers. In this version of TonesNotes, you must be using a .Text (Dottext) blog server.

If you just installed TonesNotes, you will have to make changes to this tab's settings before you can post to your blog.

Here is the purpose of each item on the "Blog" tab:

Enabled
Check the box to post to this blog. Clear it to temporarily prevent posting.
Configm posting
Check the box if you want to a confimation dialog to appear before posting to your blog.
Category
This is the category that you will use in the heading of each note you want to post to this blog. Keep it short and don't including any commas or other unusual characters.
Username
Your blog server account's username.
Password
Your blog server account's password.
Service url
The full address of your blog server's posting service page. For .Text, add "Services/SimpleBlogService.asmx" to the usual base URL for your blog.
None, Original Size, Thumbnail
If you post a note containing embedded images (images you've inserted or dragged into your note), they can be automatically copied up to your blog server (provided it has bee upgraded with a minor modification to supprot this. Visit the TonesNotes workspace on GDN for information on obtaining and installing this modification.
"None" discards images when they are posted. This may be useful if you want to archive the images but not post them, or if you have multiple blogs, some with images and some without.
"Original Size" will display the full size image in your blog entry.
"Thumbnail" will display a thumbnail image in your blog entry which will automatically link to the original image.
File types
Only files with extensions in this list will be sent to your blog server.
Gallery
The title of the image gallery that will receive your images on your blog server. If a matching gallery doesn't already exist it will be created and marked as invisble so that it won't appear to your community by default.
Add, Delete, Prev, Next
These buttons let you configure additional blogs. Leave these buttons alone unless you have multiple blogs.
Add creates a new blog configuration. Prev and Next let you move between the configurations. Delete permanently removes the currently displayed blog configuration. You can assign multiple blogs either the same or a different category, depending on how you want to control which blogs you post to.

Advanced Configuration

The "Advanced" tab controls a number of important settings. You don't need to make changes here but you probably will eventually.

Here is the purpose of each item on the "Advanced" tab:

Microsoft Word Heading Style
TonesNotes identifies notes in a word document by searching for text with the formatting "style" that matches this property.
The default value is "TonesNotesHeading".
If the style doesn't already exist, it will be created for you.
You are free to redefine the style as long as it remains a paragraph style.
Recognized date formats
These are .NET standard DateTime format strings which define the date formats TonesNotes will recognize in a note heading.
The first format is also the format used by the "New" button when it inserts the start of a new note entry in the active document.
Log file folder
You can leave this alone unless you're working with the source code or helping debug a problem. Enter something like "C:\" to enable the generation of a log file while TonesNotes is running.
Open .config file in Notepad
Launches Notepad with the configuration file being manipulated by the Configuration dialog. This is an XML format file which will contain the settings from the time when you opened the Configuration dialog. Any changes you have just made have not been saved to this file yet.
One of the reasons for this button is to easily determine where your configuration information is being stored. In some cases, it may also be easier just to edit the xml file. If you close the dialog before saving the file, TonesNotes will automatically notice the change and update its configuration.

Appendix: Required .Text Modification for Image Posting

Add the following function to the SimpleBlogService.asmx.cs file:

  /// <summary>
  /// Add an image to a specified gallery and return the url by which it will be accessible.
  /// </summary>
  /// <param name="username"></param>
  /// <param name="password"></param>
  /// <param name="gallery">Title of the target gallery, gallery will be created if it doesn't exist.</param>
  /// <param name="postdate">Date to associate with the image. Not currently supported by the data model.</param>
  /// <param name="title">Title for the image.</param>
  /// <param name="description">Description for the image.</param>
  /// <param name="categories">Array of categories to associate with the image. Not currently supported by the data model.</param>
  /// <param name="filename">The non-path image filename including extension. Note that currently filenames must be unique within a gallery.</param>
  /// <param name="data">Image file data in on-disk format matching the filename's extension.</param>
  /// <returns>A url in the form http://blogs.mydomain.com/myblog/8/o_filename.jpg, where 8 is the integer CategoryID assigned to the gallery.
  /// The returned url is an absolute url with a "o_" prefix on the filename.
  /// Caller can make the prefix "t_" for thumbnail and "r_" for standard size.</returns>
  [WebMethod(MessageName="AddImageToGallery",Description="Insert an image into a gallery with Categories",EnableSession=false)]
  public string AddImageToGallery
   ( string username
   , string password
   , string gallery
   , DateTime postdate
   , string title
   , string description
   , string[] categories
   , string filename
   , byte[] data
   ) {

   BlogConfig config = Config.CurrentBlog(Context);
   CheckUser(username,password);

   int categoryID = 0;

   // Lookup the categoryID of gallery (gallery is the title).
   LinkCategoryCollection lcc = Links.GetCategories(CategoryType.ImageCollection, false);
   foreach (LinkCategory lc in lcc) if (string.Compare(lc.Title, gallery, true) == 0) { categoryID = lc.CategoryID; break; }

   // If gallery doesn't exist, try creating it.
   if (categoryID == 0) {
    LinkCategory category = new LinkCategory();
    category.CategoryType = CategoryType.ImageCollection;
    category.Title = gallery;
    category.IsActive = false;
    category.Description = "Images uploaded with new posts.";
    categoryID = Links.CreateLinkCategory(category);
    if (categoryID == 0) throw new Exception("CategoryID is zero");
   }

   // Insert the new image into the selected gallery.
   // This puts three copies (thumbnail, standard size, original size) of the image on disk under the "images" folder
   // and adds a record to the blog_Images table.
   Image image = new Image();
   image.CategoryID = categoryID;
   image.Title = title;
   image.IsActive = true;
   image.File = Images.GetFileName(filename);
   image.LocalFilePath = Images.LocalGalleryFilePath(Context, categoryID);
   int imageID = Images.InsertImage(image, data); 
  
   if (imageID == 0) throw new Exception("ImageID is zero");

   string baseImagePath = Images.HttpGalleryFilePath(Context, image.CategoryID);

   return baseImagePath + image.OriginalFile;
  }
  

February 04, 2004

Post to your .Text blog using this add-in for Word

I released the alpha version of my blog posting add-in for Microsoft Word 2003 or XP as a GotDotNet workspace: http://workspaces.gotdotnet.com/TonesNotes

TonesNotes is a free and lets you post to a .Text blog from any open Word document.

The intended mode of operation is to use a single Word document in which the ideas you’re working on take shape. When an idea is baked, place the insertion point within its content, click the “Post” button on the TonesNotes toolbar, and the content is simultaneously posted to one or more blogs and archived as a separate Word document on your local file system.

The command bar has a “New” button which starts a new entry at the bottom of the active Word document. An entry is demarked by a paragraph with the style “Heading 1” by default. The “New” command inserts a paragraph with a date stamp which will become the post creation time. Complete the note heading with a comma separated list of categories and a title. Anything in the note heading paragraph not recognized as a date or category name becomes part of the title.

Since not all ideas are suitable for public posting, the behavior of the Post command is driven by assigning a category name to each configured blog. A note is posted to each blog whose category name is listed in the entry heading, or simply archived if it isn't meant to be blogged.

In addition to the “New” and “Post” functions, the toolbar has a “Config” button which brings up the configuration dialog.

Here’s a topic page in the .Text wiki that lists pros, cons, and configuration for various authoring options including TonesNotes: http://dottextwiki.scottwater.com/default.aspx/Dottext.AuthoringOptions