Friday, September 18, 2009

Copy full file path to clipboard from Windows Explorer

Till now, if I wanted to copy the full file path of a file to the clipboard, I would open the “run” window, drag the file from windows explorer to the “run” window, highlight the path in the “run” window and copy. It works but gets frustrating after having to do this several times.

I found this handy little utility that does this from the windows explorer context menu.

image

Wednesday, September 2, 2009

SMTP service on Windows 7

I recently installed Windows 7 on my notebook and so far am very impressed. However, as a developer that at times works in an offline mode, one of the features I miss is a local SMTP service. A SMTP service used to ship with IIS 6.0. However, IIS 7.0 does not ship a SMTP service.

After scouring around on the web and trying various SMTP service solutions, the one that I found to be pretty simple to install and configure is hMailServer. Just like the old SMTP that ships with IIS 6.0, hMailServer allows one to restrict access to the local machine (127.0.0.1) only in order to prevent being vulnerable to spam.

Some pointers on ensuring you restrict access to your local machine only.

Firstly, only allow SMTP protocol.

image

Next ensure that you restrict the IP address to the local host.

image

There are various other settings that can be tweaked, but out of the box with the above recommended settings should work well.

Technorati Tags: ,

Friday, April 24, 2009

Manipulate PDF documents from .Net

If you ever want to manipulate PDF documents from within .Net, take a look at iTextSharp. It’s a managed .Net library ported from the familiar iText Java library. I provides very rich functionality including but not limited to:

  • Construct a PDF document from scratch.
  • Concatenate multiple PDF documents.
  • PDF stamping.
  • etc…

Reading and saving BLOB data in SQL Server

Ever look for a quick way to read and store BLOB data in SQL Server. I needed something quick and did not want to write a quick c# console application that would do this for me. So, asking a few knowledgeable folks I know (thank you Mikey and Mark) and scouring the web, I came across  the following to very helpful commands you can use.

To read BLOB data out of SQL Server and save it to a file on disk, use the BCP command as follows. Keep in mind that any paths specified are relative the the server running the SQL Server instance.

bcp "select idocument from devimagebase.dbo.tbl_documentimage WHERE ndocumentid = 9992561 " queryout "c:\Temp\TestOut.pdf" -T -n -Slocalhost

To upload BLOB data into SQL Server, use the OPENROWSET function.
Update tbl_documentimage
set idocument = (Select bulkcolumn from Openrowset( Bulk 'C:\temp\Sample.pdf', Single_Blob) as x)
where ndocumentid = 9992561

Wednesday, March 25, 2009

VSTS Unit Test “Type is not resolved” exception

When running VS unit tests, VSTestHost is the process that initializes and runs the test. A new AppDomain gets created and the base directory for the AppDomain gets set to the unit test “Out” directory that contains all the assemblies and dependencies required to run the test. The test directory is called “TestResults” and is found in the same directory where the solution file resides. Within the “TestResults” directory you will find a bunch of sub-directories  for every test run.

The exception above only appears in the rare circumstance that one may place data in the thread calling context to cater for a multitude of different scenarios. In our scenario, we are flowing contextual data across service and AppDomain boundaries. Once the unit test has completed, the executing thread returns to the default AppDomain for the VSTestHost process. Part of the process for returning to the default AppDomain is to de-serialize objects in it’s calling context. However, the BaseDirectory has already been reset back to the directory containing the VSTestHost executable which is “C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE”. This then cause the de-serialization to fail since the type being de-serialized cannot be found in the VSTestHost directory. The exception reads something along the lines of:

Unit Test Adapter threw exception: Type is not resolved for member 'xxx,xxx, Version=2.0.3370.22002, Culture=neutral, PublicKeyToken=null'

More detail can be found at:

http://social.msdn.microsoft.com/forums/en-US/vststest/thread/f6325a92-0231-45f3-92a5-176cc45691ad/

http://social.msdn.microsoft.com/forums/en-US/vststest/thread/81814766-a522-4a19-8575-7bc7f581623c/

This has been confirmed in various blogs and forums to be a bug. I am running VSTS 2008 SP1. As suggested in these entries, the hack that worked for us was to create a directory in “C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE” called “UnitTestAssemblies”. I copied all the required assemblies into this directory. I then manually edited the VSTestHost configuration file called “VSTestHost.exe.config” to include the directory I had created as part of it’s probing path:

 

   1: <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
   2:     <probing privatePath="PrivateAssemblies;PublicAssemblies;UnitTestAssemblies"/>
   3: </assemblyBinding>
 

This will then force a lookup into the directory I created for any missing types during de-serialization. The folks at MS are apparently aware of this issue and hopefully will resole this soon. But for now, I guess this “hack” will work.

Tuesday, March 17, 2009

Linq-to-Xml vs. Regular Expression

I came across some code that was using a regular expression to extract a value from a HTML page (another way to do screen scraping). I was curious what the performance difference between a regular expression and a Linq-to-Xml query would be.

I wanted to use a pretty sizable XML document, so I grabbed the MSDB db schema file for SQL Server 2008 that ships with VS Database Edition GDR. The file is about 1.8 MB. A snippet of the XML I wanted to query:

   1: <Element Type="ISql90File" Name="[MSDBLog]">
   2:     <Property Name="FileName" Value="$(DefaultDataPath)$(DatabaseName)Log.ldf" />
   3:     <Property Name="MaxSize" Value="2097152" />
   4:     <Property Name="FileGrowth" Value="10" />
   5:     <Property Name="FileGrowthUnit" Value="1" />
   6:     <Property Name="IsLogFile" Value="True" />
   7: </Element>

I wrote 2 functions to extract the value of the “Value” attribute for the “FileName” property element. In essence, the location of the MSDB log file.

The query using Linq-to-Sql:

   1: XElement _Root = XElement.Parse(xmlToSearch);
   2: return _Root.Descendants("Element").
   3:     Where(n => n.Attribute("Name") != null && 
   4:         n.Attribute("Name").Value == "[MSDBLog]" && 
   5:         n.Element("Property").Attribute("Name").Value == "FileName").
   6:     Select(n => n.Element("Property").Attribute("Value").Value).SingleOrDefault() ?? "not found";

The query using regular expression:

   1: Regex _Regex = new Regex("^.*?Name=\"\\[MSDBLog\\]\".*?Property Name=\"FileName\" Value=\"(?<Location>.*?)\".*$", 
   2:     RegexOptions.IgnoreCase | 
   3:     RegexOptions.Multiline | 
   4:     RegexOptions.Singleline |
   5:     RegexOptions.CultureInvariant |
   6:     RegexOptions.Compiled);
   7: MatchCollection _Matches = _Regex.Matches(xmlToSearch);
   8: return ((from Match m in _Matches
   9:          where m.Groups["Location"] != null
  10:          select m.Groups["Location"].Value).SingleOrDefault()) ?? "not found";

One could argue that I am obscuring the results for the regular expression query because I am using Linq to extract the matched value from the matches found. The impact that the Linq query has on the overall result is minimal. Even with the Linq query commented out, the difference between the 2 queries remain comparably the same.

The results are as follows:

image

Linq-to-Xml outperforms the regular expression by about 24%.

Complete source code:

   1: static void Main(string[] args)
   2:         {
   3:             string _Xml = File.ReadAllText(@"C:\Program Files\Microsoft Visual Studio 9.0\VSTSDB\Extensions\SqlServer\2008\DBSchemas\msdb.dbschema");
   4:             Console.WriteLine("Read {0} characters\n", _Xml.Length);
   5:  
   6:             //search using linq-to-xml
   7:             TestFunction("Linq to Xml", _Xml, SearchLinqToXml);
   8:  
   9:             //search using regex
  10:             TestFunction("Regular Expression", _Xml, SearchRegex);
  11:  
  12:             //done
  13:             Console.WriteLine("\ndone...");
  14:             Console.ReadLine();
  15:         }
  16:  
  17:         private static void TestFunction(string name, string xmlToSearch, Func<string, string> searchFunction)
  18:         {
  19:             Stopwatch _Timer = new Stopwatch();
  20:             _Timer.Start();
  21:             Console.WriteLine("Result: {0}", searchFunction(xmlToSearch));
  22:             _Timer.Stop();
  23:             Console.WriteLine("{0} response: {1}", name, _Timer.ElapsedMilliseconds);
  24:         }
  25:  
  26:         private static string SearchRegex(string xmlToSearch)
  27:         {
  28:             Regex _Regex = new Regex("^.*?Name=\"\\[MSDBLog\\]\".*?Property Name=\"FileName\" Value=\"(?<Location>.*?)\".*$", 
  29:                 RegexOptions.IgnoreCase | 
  30:                 RegexOptions.Multiline | 
  31:                 RegexOptions.Singleline |
  32:                 RegexOptions.CultureInvariant |
  33:                 RegexOptions.Compiled);
  34:             MatchCollection _Matches = _Regex.Matches(xmlToSearch);
  35:             return ((from Match m in _Matches
  36:                      where m.Groups["Location"] != null
  37:                      select m.Groups["Location"].Value).SingleOrDefault()) ?? "not found";
  38:         }
  39:  
  40:         private static string SearchLinqToXml(string xmlToSearch)
  41:         {
  42:             XElement _Root = XElement.Parse(xmlToSearch);
  43:             return _Root.Descendants("Element").
  44:                 Where(n => n.Attribute("Name") != null && 
  45:                     n.Attribute("Name").Value == "[MSDBLog]" && 
  46:                     n.Element("Property").Attribute("Name").Value == "FileName").
  47:                 Select(n => n.Element("Property").Attribute("Value").Value).SingleOrDefault() ?? "not found";
  48:         }

Friday, March 13, 2009

TFS GUI tool

While reading Team Foundation Server 2008 in Action, I came across a tool that I found very helpful in providing a set of rich GUI based tools for TFS administrators and advanced users providing for administration and advanced version control tasks in multi-user TFS environments. Take a look at Team Foundation Sidekicks. It offers the following tools and also integrates in Visual Studio.

  • Permission Sidekick
  • Code Review Sidekick
  • Shelveset Sidekick
  • Labels Sidekick
  • History Sidekick
  • Status Sidekick
  • Workspace Sidekick