February 2007 - Posts - Jon Galloway

February 2007 - Posts

Not really into Pokemon

Having trouble keeping up with the ever increasing torrent of new technologies? Randall Munroe has a pretty helpful tip - when you're not sure, use the Pokemon defense.

[SQL] Force the protocol (TCP, Named Pipes, etc.) in your connection string

Barry Dorrans recently mentioned that you can force the database connection protocol by specifying np: or tcp: before the server name in your connection string. I've jumped through some hoops before using localhost to target tcp and (local) to target named pipes, but it looks like there's a much better way to do this (since MDAC 2.6).

There's more info in MS KB Article 313295:

TCP/IP:

server=tcp:hostname
You can optionally specify a specific port number. By default, the port is 1433.
server=tcp:hostname, portNumber

Named Pipes:

server=np:hostname
You can optionally specify a specific named pipe.
server=np:\\hostname\pipe\pipeName

They recommend that you always use (local) to specify the local machine, and then specify a protocol. Sounds like the right way to connect to the local machine over TCP is to specify server=tcp:(local), and to use named pipes on the local machine you'd use np:(local). To specify a protocol when pointing to a server, you'd use server=tcp:DBSERVERNAME.

To quote my previous post:

There are many differences between TCP and Named Pipe connection, but if you're on localhost you're mostly concerned with simple access.

  • The default ASPNET account generally has an easier time with TCP, since the  ASPNET user doesn't have access to named pipes by default (http://support.microsoft.com/Default.aspx?id=315159).
  • If you're using impersonation, Named Pipes is usually simpler. If you're using impersonation with no username specified, you're running under the IIS Authenticating user. This defaults to IUSR_MACHINENAME if you're allowing annonymous access, which generally has access to the IPC$ share required for named pipe communications.  

You can target other supported protocols, too:

Multiprotocol = rpc
Shared Memory = lpc
NWlink  IPX / SPX = spx
Banyan VINES = vines
Apple Talk = adsp

[link] Shell command - Open folder as Website Project in VS 2005

Visual Studio 2005's Web Application Projects are easy to open from the filesystem by double clicking on the SLN (solution) file. Website Projects don't necessarily* have a SLN file, so I've had to open up Visual Studio and browse for the folder, which is really backwards from how I work.

Bradley posted a cool tip a while ago for how to simplify this. He uses a Visual Studio macro from a shell command (installed by a simple reg file) so I can just right click a folder and select "Open as Visual Studio Website".

*UPDATE - You can use an SLN file, and I guess you get one when you create the project in VS (per Luke's comment). I generally use Web Application Projects and end up with Website Projects which were created by other people and don't come with SLN's.

Posted by Jon Galloway | with no comments
Filed under:

Shell Command - Remove SVN Folders

The Subversion source control client maintains your local state in hidden folders named .svn inside your project, which can be a problem if you want to copy or share the project directory.  This REG file adds "Delete SVN Folders" to the context menu for folders. When you select it, it removes all folders named .svn inside the folder and it's children (it does nothing if the project's not under Subversion source control.

I'm not going to bother explaining reg file installation here - I figure if you're using SVN, you're good with reg files.

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\DeleteSVN]
@="Delete SVN Folders"

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\DeleteSVN\command]
@="cmd.exe /c \"TITLE Removing SVN Folders in %1 && COLOR 9A && FOR /r \"%1\" %%f IN (.svn) DO RD /s /q \"%%f\" \""

I got the idea from Wyatt Preul's post comparing Powershell and Command Prompt commands to delete SVN directories, so if you'd like to do this manually take a look at his scripts. 

Posted by Jon Galloway | 115 comment(s)
Filed under:

New Cropper Plugins Release (includes Flickr, OneNote, TinyPic)

Patrick Altman added his plugins to the Cropper Plugins bundle out on CodePlex. His SendToFlickr plugin has become an essential part of my blogging routine - I grab portions of the screen directly to Flickr, then add them to posts with the Flickr4Writer WindowsLiveWriter plugin.

It only takes a few minutes to set it up - the first time you launch the SendToFlickr plugin, you're prompted to login to Flickr and authorize the plugin. Once it's set up, you can add a screenshot to a blog post in a matter of seconds now, start to finish.

Cropper Plugins

Posted by Jon Galloway | with no comments

Sending files via the default e-mail client

I recently released a "Send To Email" plugin for Cropper, which makes it easy to grab a portion of your screen and send it as an e-mail attachment. It's easy enough to directly send an e-mail in .NET using System.Net.Mail, but there's no provision for sending a mail using the default client.

Spoiler - if you just want the code without the background, skip to the "Take Three" section below.

Take One - MailTo link

You can launch the default mail client by shelling out to a mailto link, and some e-mail Cropper - Send To Emailclients support an "attach" parameter:

mailto:dvader@deathstar.mil
?Subject=Rebel+Base+Detected
&Body=See+attached+pictures
&Attach="C:\Users\Fett\RebelBase[1].png

public static void Main() { SendMailWithMailTo( "dvader@deathstar.mil", "Rebel Base Detected", "Hoth, baybee!!", "\"C:\\Users\\Fett\\RebelBase[1].png\""); } public static void SendMailWithMailTo( string address, string subject, string body, string attach) { //Don't use this - just an example string mailto = string.Format( "mailto:{0}?Subject={1}&Body={2}&Attach={3}", address,subject,body,attach); System.Diagnostics.Process.Start(mailto); }

That's not really a good plan, though. The main reason is that the "attach" is an unofficial extension to the mailto protocol. It's not supported in a lot of e-mail clients, and those that implement it all work a little differently (for instance, some use "attachment" instead of "attach". I'd expect that fewer mail clients will be support attachments in the mailto protocol due to the obvious security issues (a mailto link on a website with an attachment reference to files in common locations, for instance). There was a security advisory for mailto attachments in Outlook 2003, for instance.

Take Two - Call MapiSendMail via PInvoke

MapiSendMail invokes the default e-mail client and supports attachments. There's a CodeProject article with C++ code, and the author supplied C# code to call MapiSendMail in the comments. It's reasonably straightforward, and it's easy to use. I'm going to skip over it, though, because it has one major problem - the call to MapiSendMail is modal. What that means is that your program hangs until the user edits and sends the e-mail. That's not at all what you'd expect as an end user - I'd want to be able to save the message as a draft and go on using the program.

Take Three - Call MapiSendMail Asynchronously

Andrew Baker's MAPI wrapper class does a great job of sending mail using the default e-mail client, and it does it asynchronously. The function you'll call, ShowDialog, just calls internal utility functions on a new thread and returns. It's very easy to use:

MapiMailMessage message = new MapiMailMessage(subject, body); message.Files.Add(file); message.ShowDialog();

Passing lists to SQL Server 2005 with XML Parameters

 

Overview

SQL Server 2005's XML capabilities make it a easier to pass lists to SQL Server procedures.

Background

I recently needed to write a stored procedure which took a list of ID's as a parameter. That's one of those things that seems like it would be really simple, but isn't. You'd think you could just pass in a comma delimited string of id's: @ids = '3,5,7,8' and use something like 'SELECT * FROM Products WHERE ID IN (@ids)'. Nope, it doesn't work. I still remember my surprise when I ran into that six or seven years ago.

There are a huge variety of workarounds for this issue - see Erland's comprehensive list ranging form SQL Server 6.5 to 2000. I've used several of these, and while they worked I never liked them. Probably the best method is to just use a SPLIT table valued function which splits your string and returns a table. It's clean, but all of your procedures depend on the existence of that function.

It was also possible to use OPENXML in SQL Server 2000. The syntax was obviously put together by C++ programmers (you have to prepare a document and work with an integer handle, which feels a lot like a pointer), and there were some limitations to be aware of, but it pretty much worked.

This time around, I decided to try this with SQL Server 2005's XML capabilities and see if it was any easier. It is.

Getting started with SQL Server 2005's XML Syntax

XML variables in SQL Server 2005 make it easy to "shred" XML strings into relational data. The main new methods you'll need to use are value() and nodes() which allow us to select values from XML documents.

 

DECLARE @productIds xml
SET @productIds ='<Products><id>3</id><id>6</id><id>15</id></Products>'

SELECT
ParamValues.ID.value(
'.','VARCHAR(20)')
FROM @productIds.nodes('/Products/id') as ParamValues(ID)

 

Which gives us the following three rows:

3
6
15

Alright, just show me how to pass a list in a procedure parameter already!

Here's a proc which takes a single XML parameter. We first declare a table variable (@Products) and load the XML values into it. Once that's done, we can join against the @Products table as if it were any other table in the database.

CREATE PROCEDURE SelectByIdList(@productIds xml) AS

DECLARE @Products TABLE (ID int)

INSERT INTO @Products (ID) SELECT ParamValues.ID.value('.','VARCHAR(20)')
FROM @productIds.nodes('/Products/id') as ParamValues(ID)

SELECT * FROM
Products
INNER JOIN
@Products p
ON Products.ProductID = p.ID

Now we can call it as follows:

 

EXEC SelectByIdList @productIds='<Products><id>3</id><id>6</id><id>15</id></Products>'

 

Which gives us the following:

ProductID ProductName SupplierID CategoryID QuantityPerUnit UnitPrice UnitsInStock UnitsOnOrder ReorderLevel Discontinued ID
3 Aniseed Syrup 1 2 12 - 550 ml bottles 10 13 100 25 0 3
6 Grandma's Boysenberry Spread 3 2 12 - 8 oz jars 25 120 0 25 0 6
15 Genen Shouyu 6 2 24 - 250 ml bottles 15.5 39 0 5 0 15

In order to use this, you'll need to an XML string with your ID's. In our application, Steve was handling the application code, and I talked him into doing this via quick and dirty string concatenation. His method worked great:

 

public static string BuildXmlString(string xmlRootName, string[] values)
{
StringBuilder xmlString
= new StringBuilder();

xmlString.AppendFormat(
"<{0}>", xmlRootName);
for (int i = 0; i < values.Length; i++)
{
xmlString.AppendFormat(
"<value>{0}</value>", values[i]);
}
xmlString.AppendFormat(
"</{0}>", xmlRootName);

return xmlString.ToString();
}

What's next?

This is a very simple use of XML in SQL Server. You can pass complex XML documents containing business objects to insert and update in your relational tables, for instance. If you're going to do that with a large amount of data, have a look at Ayende's clever use of SqlBulkCopy to handle that more efficiently.

Posted by Jon Galloway | 62 comment(s)
Filed under: ,

CropperPlugins on CodePlex

Cropper is my favorite screenshot application because it supports plugins. I've published a few over the years - Capture to AVI and Capture to Animated GIF. My favorite plugin is one that I didn't write - Patrick Altman's Send To Flickr plugin. Now that we've got a Cropper build that works in Vista, I set up a CodePlex project for my plugins and am releasing a few more. It looks like Patrick's gonna join me, and Brian is planning to release his Cropper Plugin documentation there as well.

In celebration of this glorious day, I'm releasing a few plugins I've been sitting on for a bit: "Send To Email" and "Countdown PNG".

Send To Email

Pretty much what you'd guess - select a portion of the screen and double click. Your default e-mail client pops up with a screenshot attached. Andrew Baker's MAPI wrapper does the heavy lifting since System.Net.Mail doesn't support sending via the default mail client.

Cropper - Send To Email

The default subject line and message body are configurable. I set them up that way partly to smoke test the new plugin options system for Brian. You'll see tokens like $COMPUTERNAME$ and $OPERATINGSYSTEM$ which I unwisely cut off in my screenshot above. You can also use any valid system environment variable (use start / run / "set" to see them), so on my system $NUMBER_OF_PROCESSORS$ would be replaced with 2. You can change the default subject line and message to anything you'd like. Well, as long as it's under 4GB, I guess. Anyhow.

Cropper - SendToEmail Options

Countdown PNG

I wrote this plugin to work around a problem several people have noticed - it's hard to set up a shot sometimes. With this plugin, you can set a time delay, then trigger the screenshot and set up your shot during the countdown. This one could be expanded using the new plugin options to allow other output formats, but it's pretty useful as it is.

Cropper - Coundown PNG

Where do I get them?

C'mon, man! The CodePlex CropperPlugins site, of course. Have you been paying attention?

What's next?

Well, I've been thinking about a "Send to OCR" which would invoke the Office OCR system if it's available. These plugins could all take more advantage of the new plugin options system. And I'm sure you've got some ideas kicking around... so join on in! Let me know if you want in on the fun, and I'll add you to the project.

Posted by Jon Galloway | 1 comment(s)
Filed under: ,

Inkscape 0.45 Released

Inkscape 0.45 is now officially released and available for download.

Inkscape is an Open Source vector graphics editor, with capabilities similar to Illustrator, Freehand, CorelDraw, or Xara X using the W3C standard Scalable Vector Graphics (SVG) file format.

This release brings the exciting new features developed by the Google Summer of Code 2006 participants, as well as tons of other improvements across the board. Most notably is the new Gaussian Blur feature, which allow softly and naturally blurring Inkscape objects like path, shapes, groups, text, and images. Gaussian blur enables a wide range of photorealistic effects: arbitrarily shaped shades and lights, depth of field, drop shadows, glows, etc. Also, blurred objects can be used as masks for other objects to achieve the "feathered mask" effect.

For more information, please see the Inkscape 0.45 Release Notes.

[via Inkscape.org]

I've been a fan of Inkscape for a while. It's simple and intuitive (I gave my 11 year old nephew lessons on it tonight and he picked it up quickly), and it uses SVG as its native file format. I'm planning to do a more in-depth overview as time permits, but I wanted to at least mention the new release.

I've always liked the "trace bitmap" feature in Inkscape, and I love how the new blur tool compliments it. The combination allows me to trace edges on a bitmap image (jpg, png, gif, etc.) to smooth vectorized shapes, then blur the shadow layer(s) to soften them a bit, which makes for a nice effect. The dorky portrait on my site is an example of that effect - I autotraced a picture, cleaned up the lines a bit, and put a blur on the shadows. The result is hopefully a little more interesting than a simple picture I had before (I was told it made me look like a serial killer), but it's not as harsh and blocky as if it had been completely posterized.

I'll hopefully get time to write up an actual walkthrough with a prettier subject (probably one of my daughters), but here's a sample to show the idea:

Jon Vectorized

Posted by Jon Galloway | 1 comment(s)
Filed under:
More Posts