February 2011 - Posts

Move to the Cloud, Use the Cloud and Be a Cloud

As you might already know, there are 3 general types of cloud offerings out there.

  • Infrastructure as a Service (IaaS)
  • Platform as a Service (PaaS)
  • Software as a Service (SaaS)

Each gives you a different level of control and benefits.  I won't bother you with the detail on each.  It's not what this blog entry is about.  If you like to compare and contrast these offerings, see this.

A different perspective on the cloud offerings has been suggested to me:

  • Move to the cloud
  • Use the cloud
  • Be a cloud

Moving to the Cloud

Moving to the cloud is like outsourcing one more of your services such as e-mail, CRM, portal solution, and even some business productivity tools.  A lot of cloud players are playing in this field including Microsoft Office 365 and other Microsoft Online Services, third party / partner hosted services, Google docs, .and salesforce.com.

The benefits for this is you no longer need to maintain the infrastructure necessary for these "IT commodity" services, instead you can utilize your resources to do more strategic stuffs and let the cloud provider deals with the day-to-day administration.

The disadvantage for this is you might not have the ability to do full customization on top of the solution that you have outsourced since most of the time, the provider will configure the solution to run on multi-tenancy architecture that makes it a bit difficult to customize for a specific tenant.  Maybe, if you are lucky, and depending on your service level with the provider, you might be able to do this, but expect to treat this offerings the same way as shopping for cloths from a department store instead of going to the tailor to make a custom suit / dress.  You have your choices of colors and sizes and that's that.  No addditional pockets, replacing buttons, etc.

Use the Cloud

Think of this as not moving the entire solution to the cloud like in Move to the Cloud above, but rather, you still have something on-premise that is reaching out to the cloud for additional things.  Or your internal solutions are using some cloud services.   Seasonal business activities like internet campaign marketing / promotion can defintely take advantage of the public cloud services such as using Windows Azure or other platform like Google AppEngine as your workhorse during the promotional period by quickly adding the necessary computing power without the need to put down the huge capital cost for hardware up front.  The ability to pay as you go is definitely something to consider when you want to cut down the capital cost.  Once you are done with the seasonal activity, you don't need to worry about what to do with the extra computing capacity that won't be doing anything if you were to implement the solution in house using your own hardware (that you have to purchase up front).

Be a Cloud

A couple of example for this are a hosting business offering elastic computing based on private cloud technology or your company itself decided that you want to keep your data and computing power inside the company but still wants the elasticity that a cloud offering can provide.  A good scenario for considering this kind of solution is when your company or country you operate in has regulation that requires your data to stay within a certain physical boundary or you are considering being a cloud provider for others.  Another good case for this is when you have a cloud solution that you want to sell as a service (SaaS) to others.  With the right VM infrastructure and management solution, it is definitely possible to be a cloud.  An example of this is Microsoft Private Cloud solutions such as Hyper-V Cloud and Windows Azure Platfrom Appliance described here.  Another vendor that is also playing in this area is VMWare.

Things to Consider

Different level of IT maturity is required for operating in the cloud.  Before you can move to the cloud, your IT infrastructure, staff, and procedures must be at a certain level of maturity.  If you are putting out fire most of the time, you are probably not ready to move yet.  How easy you can integrate your internal IT systems such as security & identity with the cloud offering is another thing that you might want to consider before making your move. 

Share this post: | | | |
Posted by Jimmy Chandra | with no comments
Filed under:

How to Change the Active Printer to Specific Printer in Excel Using .NET and How the Heck Can I Find the Right Printer Name and Port Combination that Excel Wants?

A client of mine was having a problem trying to automate Excel to print to a specific (non default) printer.  They know which printer they want to use, but are having trouble trying to get Excel to understand it.

Excel’s Application.ActivePrinter property is quite picky about what it will accept.  The right pattern to feed to the property is something like PrinterName on PortName:.

For example, if you want to print to Microsoft XPS Document Writer, you need to do something like this:

var excel = new Excel.Application();
var workbook = excel.Workbooks.Open("....");
var worksheet = workbook.ActiveSheet;

excel.ActivePrinter = “Microsoft XPS Document Writer on ne01:”;
worksheet.PrintOut();

excel.Quit();

And this of course assuming that the selected printer (Microsoft XPS Document Writer) is on port ne01.

Getting the right name for the printer is somewhat trivial.  You can poke around the Devices and Printers control panel item on Windows and see their name.

The problem is… the port name information is not so obvious to find.

So, how would you know where to get the port name?

Trying to enumerate the attached printers as described by this StackOverflow question does not gives you the right port name… See the sample code and output below…

The Code:

using System;
using System.Management;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var oquery = new ObjectQuery("SELECT * FROM Win32_Printer");
            var mosearcher = new ManagementObjectSearcher(oquery);
            var moc = mosearcher.Get();            

            foreach (var o in moc)
            {
                var pdc = o.Properties;

                foreach (var p in pdc)
                {
                    if (p.Name == "Name" || p.Name == "PortName")
                    {

                        Console.WriteLine("{0}: {1}", p.Name, o[p.Name]);
                    }
                }
            }
        }
    }
}

The result:

Name: Xerox WorkCentre 3119 Series
PortName: USB001
Name: Send To OneNote 2010
PortName: nul:
Name: Microsoft XPS Document Writer
PortName: XPSPort:
Name: CAMPUS-R101-DC236
PortName: 192.168.100.21
Name: CAMPUS-R217-DC236
PortName: 192.168.100.22
Name: Fax
PortName: SHRFAX:
Name: \\TIGER\Canon Inkjet MP140 series
PortName: USB001

You just have to trust me the port name here is not the port name that Excel wants to use.

So, where else can you get this particular information?

After looking around the web, I found this post that gives some clues on how to do this from VBA that can easily be adapted for .NET.

It turns out that the key to this is to poke around in the registry. in particular HKCU\Software\Microsoft\Windows NT\CurrentVersion\Devices.

So I came up with the code below to test it and lo and behold.  It works perfectly.  Basically I enumerate through all the devices in that particular registry location, did some string manipulation on the port (remove the winspool, prefix from the port name) and concatenate the stripped version of the port name with the printer / device name to form the PrinterName on PortName: combination that is required by Excel.

using System;
using Microsoft.Win32;
using System.Runtime.InteropServices;
using Excel = Microsoft.Office.Interop.Excel;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var excelApp = new Excel.Application();
            excelApp.Visible = true;

            var workbook = excelApp.Workbooks.Add();
            var worksheet = workbook.ActiveSheet;

            var key = Registry.CurrentUser;
            var subkey = key.OpenSubKey(@"Software\Microsoft\Windows NT\CurrentVersion\Devices");

            var printerNames = subkey.GetValueNames();

            //Should be able to complete this loop without throwing an exception
            //if all the names matches to what Excel is expecting.
            foreach (var printerName in printerNames)
            {
                var excelPrinterName = ConvertToExcelPrinterFriendlyName(printerName);
                Console.WriteLine(excelPrinterName);

                excelApp.ActivePrinter = excelPrinterName;
            }

            GC.Collect();
            GC.WaitForPendingFinalizers();

            Marshal.FinalReleaseComObject(worksheet);

            workbook.Close(false);
            Marshal.FinalReleaseComObject(workbook);

            excelApp.Quit();
            Marshal.FinalReleaseComObject(excelApp);
        }

        public static string ConvertToExcelPrinterFriendlyName(string printerName)
        {
            var key = Registry.CurrentUser;
            var subkey = key.OpenSubKey(@"Software\Microsoft\Windows NT\CurrentVersion\Devices");

            var value = subkey.GetValue(printerName);
            if (value == null) throw new Exception(string.Format("Device not found: {0}", printerName));

            var portName = value.ToString().Substring(9);  //strip away the winspool, 
 
            return string.Format("{0} on {1}", printerName, portName);;
        }
    }
}

Hope this is useful for those who need it… Enjoy.

Share this post: | | | |
Posted by Jimmy Chandra | with no comments
Filed under: ,

How come System.Web.Extensions.dll cannot be found in the Add Reference dialog?

I was perusing stackoverflow.com questions and came upon a question regarding JavaScriptSerializer that I found quite interesting.  I decided to do a quick spike in Visual Studio to find out if I can get answer for the question.  Fired up Visual Studio 2010, created a new Console Application and tried to instantiate a JavaScriptSerializer in my code, but of course, the IDE did not recognize JavaScriptSerializer since I haven't added a reference to the necessary assembly.  In trying to fix that, I launched the Add Reference dialog and chose the .NET tab and scrolled down... and guess what.... no System.Web.Extensions... hmmm...

 Thinking the problem through I know System.Web.Extensions is part of .NET 4 (which was installed when I installed VS 2010), so how come it is not available in the Add Reference dialog?

 After a bit more thinking I came to realize that it's probably because Console Application is targetting the .NET Framework 4 Client Profile which does not include all the web stuffs in it.  Switching the Target framework to .NET Framework 4 (Full profile) from the Project Property, Application tab, solved the problem.

Share this post: | | | |
Posted by Jimmy Chandra | with no comments
Filed under: