Category: Azure

Significant updates to the SQL Azure Migration Wizard

Posted by Wade on December 15, 2009 | No comments

George Huey has done it again!  He has just published some significant updates to the SQL Azure Migration Wizard.

Previously, I’ve described the SQL Azure Migration Wizard as a tool that helps you migrate your SQL Server database into SQL Azure.  This is still true, but now, thanks to updates made by George Huey, you can also migrate from SQL Azure-to-SQL Server and SQL Azure-to-SQL Azure.  These are significant updates to the tool!

Please watch the following video for an updated explanation of the tool:

As I said, the updates made by George enable all the following scenarios for database migration …

  • SQL Server-to-SQL Azure
  • SQL Azure-to-SQL Server
  • SQL Azure-to-SQL Azure

These last two updates are significant!  Take a look at this thread on the SQL Azure Migration Wizard codeplex site – the user had a scenario where they wanted to migrate a 1 GB database in SQL Azure into a 10 GB database in SQL Azure.

Please take a look at the SQL Azure Migration Wizard up on Codeplex, where you can download the source code and/or binaries.

WI Azure User Group – Windows Azure Platform update

Posted by Wade on December 6, 2009 | One comment

Last week I presented at the Wisconsin Azure User Group for the second time, along with Clark Sell.  Our goal was to provide an overview of everything announced at the Professional Developers Conference (PDC) 2009.  We made a ton of announcements, and I recommend you check out the Microsoft PDC website for more information, including videos and decks from all the presentations.

Shameless plug: watch my session on migrating applications to the Windows Azure platform with Accenture, CCH, Dominos, and Original Digital – Lessons Learned: Migrating Applications to the Windows Azure Platform.

While I was supposed to only spend twenty minutes talking about updates to the Windows Azure platform, I ended up spending over an hour.  There was too much information to share; here’s a short outline:

  • Rebranding of the .NET Services as the Windows Azure platform AppFabric.
  • Microsoft Codename “Dallas”, a content brokerage and discovery platform available as a CTP at commercial launch.
  • Windows Azure platform integration with Microsoft Pinpoint.
  • Enhanced service architectures (i.e. inner role communication, worker roles exposed outside the datacenter, etc.).
  • Enhanced diagnostics in Windows Azure.
  • Ability to use existing NTFS APIs to store data in durable drives in Windows Azure (called Windows Azure XDrive).
  • Administrator privileges in the Windows Azure virtual machines.
  • Deployment of pre-configured virtual machine images while still benefiting from the Windows Azure service model.
  • User-selectable geo-locations for replicas of Azure storage.
  • Secondary indices on Windows Azure tables.
  • Content Delivery Network.
  • Remote terminal server access to virtual machines.
  • Tool for data synchronization called SQL Azure Data Sync, built on the Microsoft Synch Framework and ADO.NET Sync Services.
  • Claims-based access control for REST web services through the Access Control Service.
  • Commercial launch in and paid usage in February, 2010.
  • Datacenter options in USA, Europe, and Asia.

Thanks to everyone for their patience – especially Clark – as I went on, and on, and on …

Don’t forget that you can request and redeem tokens for the Commercial Technology Preview (CTP) at http://windowsazure.com/.  This provides you free usages, with quotas, through February 1, 2010.

Here’s the deck I presented:

Thanks to everyone that attended – I had a great time!

Preview of “Lessons Learned: Migrating Applications to the Windows Azure Platform”

Posted by Wade on November 7, 2009 | One comment

image It’s hard to believe that the Professional Developers Conference (PDC) 2009 is less than two weeks away.  It doesn’t seem that long ago that I sat behind the stage at PDC 2008 providing support for the RedPrairie keynote with Bob Muglia and spoke in a breakout session with Jack Greenfield on Multi-Enterprise Business Applications.  I’ll be back again this year, and I’m giving another talk – this time on lessons learned when migrating applications to the Windows Azure platform.

Rather than present this session entirely on my own, I decided to invite some of my customers to come and talk about their own experiences.  I am extremely excited that the following three customers will join me at PDC:

CCHCCH, a Wolters Kluwer Company – CCH is a Wolters Kluwer company, based in Riverwoods, Illinois, providing tax and business law information and software solutions. The company has approximately 700 products for the United States market.

accenture-logo Accenture – Launched originally as the business and technology consulting arm of Arthur Andersen, Accenture is now among the world’s largest consulting organizations. It employs more than 180,000 people in 52 countries.

Domino’s Pizza – See how Domino’s Pizza is running Java and Tomcat in Windows Azure to run their eCommerce application.  Windows Azure provides high scalability to handle Super Bowl load, interoperability with different platforms and technologies, and the ability to integrate to on-premises resources.

Our intent with this talk is to make it highly interactive – translation: ask us questions!  We have a lot of information to share with you, and while we like to present, we’d much rather engage in a meaningful conversation.  Thus, we plan to quickly provide the following information for each of the solutions migrated:

  1. Background on the application (i.e. what does it do? who uses it? what technology stack?).
  2. The previous architecture (before the migration to Windows Azure) and some of the challenges this architecture presented.
  3. The new architecture leveraging the Windows Azure platform.
  4. The migration process: what was easy, what was hard, what worked, and what didn’t.

After providing these details, we want to open the session up for Q&A.

We know that we won’t answer all of your questions in the time allotted to us, so we plan to stick around after the presentation so that we can talk to you 1-on-1 and answer your questions.

It’s going to be a great PDC – I hope you’re there!  If so, be sure and come to our presentation on Lessons Learned: Migrating Applications to the Windows Azure Platform.

Leveraging WMI in an Azure Web Role

Posted by Wade on November 4, 2009 | No comments

A few weeks ago I threw out a teaser on Twitter:

Want to read the event logs in Windows Azure?

This got the attention of a few folks, and I promised I’d follow-up on this with some details on how I got this to work.  Of course, I completely forgot to do so, and was only recently reminded (thanks, Roger Jennings).

You can still take a look at that application here (if nothing else, I find it interesting to look at the specifications of the CTP machines for Windows Azure): http://wmi.cloudapp.net/

In actuality, the solution is really quite straightforward – I used WMI.

What’s WMI?  Well, it stands for Windows Management Instrumentation.  Here’s quick blurb from MSDN:

Windows Management Instrumentation (WMI) is the infrastructure for management data and operations on Windows-based operating systems. You can write WMI scripts or applications to automate administrative tasks on remote computers but WMI also supplies management data to other parts of the operating system and products, for example System Center Operations Manager, formerly Microsoft Operations Manager (MOM), or Windows Remote Management.

For more information on how to use WMI in .NET, take a look at the WMI .NET Overview.  Lots of great information.

Assuming you’ve read the overview, it should be clear that this is really pretty easy.  At the heart of this are the following two lines of code …

ManagementClass mgmt = new ManagementClass(managementClass);
ManagementObjectCollection objCol = mgmt.GetInstances();

… where managementClass represent one of the Win32 classes (i.e. Win32_NTLogEventLog).

Now, to make this work, you need to iterate through the collection of management objects.  Something like the following works:

foreach (var obj in objCol)
{
    foreach (var prop in obj.Properties)
    {
        ...
    }
}

Now, I did two additional things to make this easy.

  1. I created a dropdown list with all the Win32 classes so that you can easily choose which class to review.
  2. I defined a querystring value that, if it exists, loads a specific Win32 class.

There are a lot of Win32 classes, so here’s the array I used – feel free to leverage it yourself:

public static string[] Win32Classes =
{
    "Win32_1394Controller",
    "Win32_1394ControllerDevice",
    "Win32_Account",
    "Win32_AccountSID",
    "Win32_ACE",
    "Win32_ActionCheck",
    "Win32_ActiveRoute",
    "Win32_AllocatedResource",
    "Win32_ApplicationCommandLine",
    "Win32_ApplicationService",
    "Win32_AssociatedBattery",
    "Win32_AssociatedProcessorMemory",
    "Win32_AutochkSetting",
    "Win32_BaseBoard",
    "Win32_BaseService",
    "Win32_Battery",
    "Win32_Binary",
    "Win32_BindImageAction",
    "Win32_BIOS",
    "Win32_BootConfiguration",
    "Win32_Bus",
    "Win32_CacheMemory",
    "Win32_CDROMDrive",
    "Win32_CheckCheck",
    "Win32_CIMLogicalDeviceCIMDataFile",
    "Win32_ClassicCOMApplicationClasses",
    "Win32_ClassicCOMClass",
    "Win32_ClassicCOMClassSetting",
    "Win32_ClassicCOMClassSettings",
    "Win32_ClassInfoAction",
    "Win32_ClientApplicationSetting",
    "Win32_CodecFile",
    "Win32_CollectionStatistics",
    "Win32_COMApplication",
    "Win32_COMApplicationClasses",
    "Win32_COMApplicationSettings",
    "Win32_COMClass",
    "Win32_ComClassAutoEmulator",
    "Win32_ComClassEmulator",
    "Win32_CommandLineAccess",
    "Win32_ComponentCategory",
    "Win32_ComputerShutdownEvent",
    "Win32_ComputerSystem",
    "Win32_ComputerSystemEvent",
    "Win32_ComputerSystemProcessor",
    "Win32_ComputerSystemProduct",
    "Win32_ComputerSystemWindowsProductActivationSetting",
    "Win32_COMSetting",
    "Win32_Condition",
    "Win32_ConnectionShare",
    "Win32_ControllerHasHub",
    "Win32_CreateFolderAction",
    "Win32_CurrentProbe",
    "Win32_CurrentTime",
    "Win32_DCOMApplication",
    "Win32_DCOMApplicationAccessAllowedSetting",
    "Win32_DCOMApplicationLaunchAllowedSetting",
    "Win32_DCOMApplicationSetting",
    "Win32_DefragAnalysis",
    "Win32_DependentService",
    "Win32_Desktop",
    "Win32_DesktopMonitor",
    "Win32_DeviceBus",
    "Win32_DeviceChangeEvent",
    "Win32_DeviceMemoryAddress",
    "Win32_DeviceSettings",
    "Win32_DFSNode",
    "Win32_DFSNodeTarget",
    "Win32_DFSTarget",
    "Win32_Directory",
    "Win32_DirectorySpecification",
    "Win32_DiskDrive",
    "Win32_DiskDrivePhysicalMedia",
    "Win32_DiskDriveToDiskPartition",
    "Win32_DiskPartition",
    "Win32_DiskQuota",
    "Win32_DisplayConfiguration",
    "Win32_DisplayControllerConfiguration",
    "Win32_DMAChannel",
    "Win32_DriverForDevice",
    "Win32_DriverVXD",
    "Win32_DuplicateFileAction",
    "Win32_Environment",
    "Win32_EnvironmentSpecification",
    "Win32_ExtensionInfoAction",
    "Win32_Fan",
    "Win32_FileSpecification",
    "Win32_FloppyController",
    "Win32_FloppyDrive",
    "Win32_FontInfoAction",
    "Win32_Group",
    "Win32_GroupInDomain",
    "Win32_GroupUser",
    "Win32_HeatPipe",
    "Win32_IDEController",
    "Win32_IDEControllerDevice",
    "Win32_ImplementedCategory",
    "Win32_InfraredDevice",
    "Win32_IniFileSpecification",
    "Win32_InstalledSoftwareElement",
    "Win32_IP4PersistedRouteTable",
    "Win32_IP4RouteTable",
    "Win32_IP4RouteTableEvent",
    "Win32_IRQResource",
    "Win32_JobObjectStatus",
    "Win32_Keyboard",
    "Win32_LaunchCondition",
    "Win32_LoadOrderGroup",
    "Win32_LoadOrderGroupServiceDependencies",
    "Win32_LoadOrderGroupServiceMembers",
    "Win32_LocalTime",
    "Win32_LoggedOnUser",
    "Win32_LogicalDisk",
    "Win32_LogicalDiskRootDirectory",
    "Win32_LogicalDiskToPartition",
    "Win32_LogicalFileAccess",
    "Win32_LogicalFileAuditing",
    "Win32_LogicalFileGroup",
    "Win32_LogicalFileOwner",
    "Win32_LogicalFileSecuritySetting",
    "Win32_LogicalMemoryConfiguration",
    "Win32_LogicalProgramGroup",
    "Win32_LogicalProgramGroupDirectory",
    "Win32_LogicalProgramGroupItem",
    "Win32_LogicalProgramGroupItemDataFile",
    "Win32_LogicalShareAccess",
    "Win32_LogicalShareAuditing",
    "Win32_LogicalShareSecuritySetting",
    "Win32_LogonSession",
    "Win32_LogonSessionMappedDisk",
    "Win32_LUID",
    "Win32_LUIDandAttributes",
    "Win32_ManagedSystemElementResource",
    "Win32_MappedLogicalDisk",
    "Win32_MemoryArray",
    "Win32_MemoryArrayLocation",
    "Win32_MemoryDevice",
    "Win32_MemoryDeviceArray",
    "Win32_MemoryDeviceLocation",
    "Win32_MethodParameterClass",
    "Win32_MIMEInfoAction",
    "Win32_ModuleLoadTrace",
    "Win32_ModuleTrace",
    "Win32_MotherboardDevice",
    "Win32_MountPoint",
    "Win32_MoveFileAction",
    "Win32_MSIResource",
    "Win32_NamedJobObject",
    "Win32_NamedJobObjectActgInfo",
    "Win32_NamedJobObjectLimit",
    "Win32_NamedJobObjectLimitSetting",
    "Win32_NamedJobObjectProcess",
    "Win32_NamedJobObjectSecLimit",
    "Win32_NamedJobObjectSecLimitSetting",
    "Win32_NamedJobObjectStatistics",
    "Win32_NetworkAdapter",
    "Win32_NetworkAdapterConfiguration",
    "Win32_NetworkAdapterSetting",
    "Win32_NetworkClient",
    "Win32_NetworkConnection",
    "Win32_NetworkLoginProfile",
    "Win32_NetworkProtocol",
    "Win32_NTDomain",
    "Win32_NTEventlogFile",
    "Win32_NTLogEvent",
    "Win32_NTLogEventComputer",
    "Win32_NTLogEventLog",
    "Win32_NTLogEventUser",
    "Win32_ODBCAttribute",
    "Win32_ODBCDataSourceAttribute",
    "Win32_ODBCDataSourceSpecification",
    "Win32_ODBCDriverAttribute",
    "Win32_ODBCDriverSoftwareElement",
    "Win32_ODBCDriverSpecification",
    "Win32_ODBCSourceAttribute",
    "Win32_ODBCTranslatorSpecification",
    "Win32_OnBoardDevice",
    "Win32_OperatingSystem",
    "Win32_OperatingSystemAutochkSetting",
    "Win32_OperatingSystemQFE",
    "Win32_OptionalFeature",
    "Win32_OSRecoveryConfiguration",
    "Win32_PageFile",
    "Win32_PageFileElementSetting",
    "Win32_PageFileSetting",
    "Win32_PageFileUsage",
    "Win32_ParallelPort",
    "Win32_Patch",
    "Win32_PatchFile",
    "Win32_PatchPackage",
    "Win32_PCMCIAController",
    "Win32_Perf",
    "Win32_PerfFormattedData",
    "Win32_PerfFormattedData_ASP_ActiveServerPages",
    "Win32_PerfFormattedData_ContentFilter_IndexingServiceFilter",
    "Win32_PerfFormattedData_ContentIndex_IndexingService",
    "Win32_PerfFormattedData_InetInfo_InternetInformationServicesGlobal",
    "Win32_PerfFormattedData_ISAPISearch_HttpIndexingService",
    "Win32_PerfFormattedData_MSDTC_DistributedTransactionCoordinator",
    "Win32_PerfFormattedData_NTFSDRV_SMTPNTFSStoreDriver",
    "Win32_PerfFormattedData_PerfDisk_LogicalDisk",
    "Win32_PerfFormattedData_PerfDisk_PhysicalDisk",
    "Win32_PerfFormattedData_PerfNet_Browser",
    "Win32_PerfFormattedData_PerfNet_Redirector",
    "Win32_PerfFormattedData_PerfNet_Server",
    "Win32_PerfFormattedData_PerfNet_ServerWorkQueues",
    "Win32_PerfFormattedData_PerfOS_Cache",
    "Win32_PerfFormattedData_PerfOS_Memory",
    "Win32_PerfFormattedData_PerfOS_Objects",
    "Win32_PerfFormattedData_PerfOS_PagingFile",
    "Win32_PerfFormattedData_PerfOS_Processor",
    "Win32_PerfFormattedData_PerfOS_System",
    "Win32_PerfFormattedData_PerfProc_FullImage_Costly",
    "Win32_PerfFormattedData_PerfProc_Image_Costly",
    "Win32_PerfFormattedData_PerfProc_JobObject",
    "Win32_PerfFormattedData_PerfProc_JobObjectDetails",
    "Win32_PerfFormattedData_PerfProc_Process",
    "Win32_PerfFormattedData_PerfProc_ProcessAddressSpace_Costly",
    "Win32_PerfFormattedData_PerfProc_Thread",
    "Win32_PerfFormattedData_PerfProc_ThreadDetails_Costly",
    "Win32_PerfFormattedData_PSched_PSchedFlow",
    "Win32_PerfFormattedData_PSched_PSchedPipe",
    "Win32_PerfFormattedData_RemoteAccess_RASPort",
    "Win32_PerfFormattedData_RemoteAccess_RASTotal",
    "Win32_PerfFormattedData_RSVP_ACSRSVPInterfaces",
    "Win32_PerfFormattedData_RSVP_ACSRSVPService",
    "Win32_PerfFormattedData_SMTPSVC_SMTPServer",
    "Win32_PerfFormattedData_Spooler_PrintQueue",
    "Win32_PerfFormattedData_TapiSrv_Telephony",
    "Win32_PerfFormattedData_Tcpip_ICMP",
    "Win32_PerfFormattedData_Tcpip_IP",
    "Win32_PerfFormattedData_Tcpip_NBTConnection",
    "Win32_PerfFormattedData_Tcpip_NetworkInterface",
    "Win32_PerfFormattedData_Tcpip_TCP",
    "Win32_PerfFormattedData_Tcpip_UDP",
    "Win32_PerfFormattedData_TermService_TerminalServices",
    "Win32_PerfFormattedData_TermService_TerminalServicesSession",
    "Win32_PerfFormattedData_W3SVC_WebService",
    "Win32_PerfRawData",
    "Win32_PerfRawData_ASP_ActiveServerPages",
    "Win32_PerfRawData_ContentFilter_IndexingServiceFilter",
    "Win32_PerfRawData_ContentIndex_IndexingService",
    "Win32_PerfRawData_InetInfo_InternetInformationServicesGlobal",
    "Win32_PerfRawData_ISAPISearch_HttpIndexingService",
    "Win32_PerfRawData_MSDTC_DistributedTransactionCoordinator",
    "Win32_PerfRawData_NTFSDRV_SMTPNTFSStoreDriver",
    "Win32_PerfRawData_PerfDisk_LogicalDisk",
    "Win32_PerfRawData_PerfDisk_PhysicalDisk",
    "Win32_PerfRawData_PerfNet_Browser",
    "Win32_PerfRawData_PerfNet_Redirector",
    "Win32_PerfRawData_PerfNet_Server",
    "Win32_PerfRawData_PerfNet_ServerWorkQueues",
    "Win32_PerfRawData_PerfOS_Cache",
    "Win32_PerfRawData_PerfOS_Memory",
    "Win32_PerfRawData_PerfOS_Objects",
    "Win32_PerfRawData_PerfOS_PagingFile",
    "Win32_PerfRawData_PerfOS_Processor",
    "Win32_PerfRawData_PerfOS_System",
    "Win32_PerfRawData_PerfProc_FullImage_Costly",
    "Win32_PerfRawData_PerfProc_Image_Costly",
    "Win32_PerfRawData_PerfProc_JobObject",
    "Win32_PerfRawData_PerfProc_JobObjectDetails",
    "Win32_PerfRawData_PerfProc_Process",
    "Win32_PerfRawData_PerfProc_ProcessAddressSpace_Costly",
    "Win32_PerfRawData_PerfProc_Thread",
    "Win32_PerfRawData_PerfProc_ThreadDetails_Costly",
    "Win32_PerfRawData_PSched_PSchedFlow",
    "Win32_PerfRawData_PSched_PSchedPipe",
    "Win32_PerfRawData_RemoteAccess_RASPort",
    "Win32_PerfRawData_RemoteAccess_RASTotal",
    "Win32_PerfRawData_RSVP_ACSRSVPInterfaces",
    "Win32_PerfRawData_RSVP_ACSRSVPService",
    "Win32_PerfRawData_SMTPSVC_SMTPServer",
    "Win32_PerfRawData_Spooler_PrintQueue",
    "Win32_PerfRawData_TapiSrv_Telephony",
    "Win32_PerfRawData_Tcpip_ICMP",
    "Win32_PerfRawData_Tcpip_IP",
    "Win32_PerfRawData_Tcpip_NBTConnection",
    "Win32_PerfRawData_Tcpip_NetworkInterface",
    "Win32_PerfRawData_Tcpip_TCP",
    "Win32_PerfRawData_Tcpip_UDP",
    "Win32_PerfRawData_TermService_TerminalServices",
    "Win32_PerfRawData_TermService_TerminalServicesSession",
    "Win32_PerfRawData_W3SVC_WebService",
    "Win32_PhysicalMedia",
    "Win32_PhysicalMemory",
    "Win32_PhysicalMemoryArray",
    "Win32_PhysicalMemoryLocation",
    "Win32_PingStatus",
    "Win32_PnPAllocatedResource",
    "Win32_PnPDevice",
    "Win32_PnPEntity",
    "Win32_PnPSignedDriver",
    "Win32_PnPSignedDriverCIMDataFile",
    "Win32_PointingDevice",
    "Win32_PortableBattery",
    "Win32_PortConnector",
    "Win32_PortResource",
    "Win32_POTSModem",
    "Win32_POTSModemToSerialPort",
    "Win32_PowerManagementEvent",
    "Win32_Printer",
    "Win32_PrinterConfiguration",
    "Win32_PrinterController",
    "Win32_PrinterDriver",
    "Win32_PrinterDriverDll",
    "Win32_PrinterSetting",
    "Win32_PrinterShare",
    "Win32_PrintJob",
    "Win32_PrivilegesStatus",
    "Win32_Process",
    "Win32_Processor",
    "Win32_ProcessStartTrace",
    "Win32_ProcessStartup",
    "Win32_ProcessStopTrace",
    "Win32_ProcessTrace",
    "Win32_Product",
    "Win32_ProductCheck",
    "Win32_ProductResource",
    "Win32_ProductSoftwareFeatures",
    "Win32_ProgIDSpecification",
    "Win32_ProgramGroup",
    "Win32_ProgramGroupContents",
    "Win32_ProgramGroupOrItem",
    "Win32_Property",
    "Win32_ProtocolBinding",
    "Win32_Proxy",
    "Win32_PublishComponentAction",
    "Win32_QuickFixEngineering",
    "Win32_QuotaSetting",
    "Win32_Refrigeration",
    "Win32_Registry",
    "Win32_RegistryAction",
    "Win32_RemoveFileAction",
    "Win32_RemoveIniAction",
    "Win32_ReserveCost",
    "Win32_ScheduledJob",
    "Win32_SCSIController",
    "Win32_SCSIControllerDevice",
    "Win32_SecurityDescriptor",
    "Win32_SecurityDescriptorHelper",
    "Win32_SecuritySetting",
    "Win32_SecuritySettingAccess",
    "Win32_SecuritySettingAuditing",
    "Win32_SecuritySettingGroup",
    "Win32_SecuritySettingOfLogicalFile",
    "Win32_SecuritySettingOfLogicalShare",
    "Win32_SecuritySettingOfObject",
    "Win32_SecuritySettingOwner",
    "Win32_SelfRegModuleAction",
    "Win32_SerialPort",
    "Win32_SerialPortConfiguration",
    "Win32_SerialPortSetting",
    "Win32_ServerConnection",
    "Win32_ServerFeature",
    "Win32_ServerSession",
    "Win32_Service",
    "Win32_ServiceControl",
    "Win32_ServiceSpecification",
    "Win32_ServiceSpecificationService",
    "Win32_Session",
    "Win32_SessionConnection",
    "Win32_SessionProcess",
    "Win32_SettingCheck",
    "Win32_ShadowBy",
    "Win32_ShadowContext",
    "Win32_ShadowCopy",
    "Win32_ShadowDiffVolumeSupport",
    "Win32_ShadowFor",
    "Win32_ShadowOn",
    "Win32_ShadowProvider",
    "Win32_ShadowStorage",
    "Win32_ShadowVolumeSupport",
    "Win32_Share",
    "Win32_ShareToDirectory",
    "Win32_ShortcutAction",
    "Win32_ShortcutFile",
    "Win32_ShortcutSAP",
    "Win32_SID",
    "Win32_SIDandAttributes",
    "Win32_SMBIOSMemory",
    "Win32_SoftwareElement",
    "Win32_SoftwareElementAction",
    "Win32_SoftwareElementCheck",
    "Win32_SoftwareElementCondition",
    "Win32_SoftwareElementResource",
    "Win32_SoftwareFeature",
    "Win32_SoftwareFeatureAction",
    "Win32_SoftwareFeatureCheck",
    "Win32_SoftwareFeatureParent",
    "Win32_SoftwareFeatureSoftwareElements",
    "Win32_SoundDevice",
    "Win32_StartupCommand",
    "Win32_SubDirectory",
    "Win32_SystemAccount",
    "Win32_SystemBIOS",
    "Win32_SystemBootConfiguration",
    "Win32_SystemConfigurationChangeEvent",
    "Win32_SystemDesktop",
    "Win32_SystemDevices",
    "Win32_SystemDriver",
    "Win32_SystemDriverPnPEntity",
    "Win32_SystemEnclosure",
    "Win32_SystemLoadOrderGroups",
    "Win32_SystemLogicalMemoryConfiguration",
    "Win32_SystemMemoryResource",
    "Win32_SystemNetworkConnections",
    "Win32_SystemOperatingSystem",
    "Win32_SystemPartitions",
    "Win32_SystemProcesses",
    "Win32_SystemProgramGroups",
    "Win32_SystemResources",
    "Win32_SystemServices",
    "Win32_SystemSetting",
    "Win32_SystemSlot",
    "Win32_SystemSystemDriver",
    "Win32_SystemTimeZone",
    "Win32_SystemTrace",
    "Win32_SystemUsers",
    "Win32_TapeDrive",
    "Win32_TCPIPPrinterPort",
    "Win32_TemperatureProbe",
    "Win32_Thread",
    "Win32_ThreadStartTrace",
    "Win32_ThreadStopTrace",
    "Win32_ThreadTrace",
    "Win32_TimeZone",
    "Win32_TokenGroups",
    "Win32_TokenPrivileges",
    "Win32_Trustee",
    "Win32_TypeLibraryAction",
    "Win32_UninterruptiblePowerSupply",
    "Win32_USBController",
    "Win32_USBControllerDevice",
    "Win32_USBHub",
    "Win32_UserAccount",
    "Win32_UserDesktop",
    "Win32_UserInDomain",
    "Win32_UTCTime",
    "Win32_VideoConfiguration",
    "Win32_VideoController",
    "Win32_VideoSettings",
    "Win32_VoltageProbe",
    "Win32_Volume",
    "Win32_VolumeChangeEvent",
    "Win32_VolumeQuota",
    "Win32_VolumeQuotaSetting",
    "Win32_VolumeUserQuota",
    "Win32_WindowsProductActivation",
    "Win32_WMIElementSetting",
    "Win32_WMISetting"
};

Other than attaching the results of the WMI query to a generic list and binding to a DataList, that’s pretty much it.  The end result is a web page that you can use to view system details via WMI:

image

As I’ve said, this is a very simple demonstration of WMI in Windows Azure.  What would be more interesting is to see how someone might combine the ability to spin up asynchronous processes in Windows Azure (as described in my post How to Leverage the RoleEntryPoint in an Azure Web Role) that query data via WMI and centralize it in Azure storage (i.e. combining and centralizing all event logs) – that would be very cool!

In case anyone wants to take a look, I’ve uploaded the code to SkyDrive.

Enjoy!

How to Leverage the RoleEntryPoint in an Azure Web Role

Posted by Wade on November 4, 2009 | 2 comments

Windows Azure One of the advantages to the approach our teams building the Windows Azure Platform have taken is flexibility.  Recently, when I spoke at the Day of Cloud presentation, I recall Don Schwarz from Google making these two points (you can see video of his talk here):

  • You can’t spin up your own threads in Google App Engine.
  • You build your applications according to how Google thinks your apps should be built (the argument being that Google knows how to run highly available services at scale, which I think is a fair statement).

Now to be fair, there are good reasons for this – the Google App Engine has a number of very good use cases (Don Schwarz demonstrated one of them when showing the audience a multiplayer game running on Google App Engine).

Note: I’d like state for the record that I mean no criticism of other cloud vendors (i.e. Amazon, Google, and SalesForce).  I think each of them have a place in the market, and exhibit various strengths.  That said, I do believe that the Windows Azure Platform stands out as the only real platform that can bridge the chasm between cloud services and on-premises software. (Note to self: back this statement up in a future blog post.)

I would argue, however, that most enterprise developers require a little more flexibility when building out enterprise class applications.  The Windows Azure Platform provides this flexibility (I mean, come on – sometimes you just want to execute some native code!).

I decided to test how far I could take this flexibility in Windows Azure.

I am a big fan of Worker Roles in Windows Azure.  I really like the idea of having an asynchronous, “headless” service that’s working for me in the background.  I wanted to see if I could spin up an equivalent to a Worker Role in a Web Role, so that in addition to having my Web application running in a Web Role I could also get a service running in the background.

Why would I want to do this?  Well, here are a few of reasons:

  • Asynchronous logging service running in every Azure instance (whether a web or worker role); this service might take information from the event log and write it to an Azure table.
  • Clean-up operations (i.e. temporary scratch writes, etc.)
  • Opening and managing socket connections to the service bus (this is my favorite scenario).

The list could go on.  Hopefully you get the point.

So, how would you do this?  Again, given the flexibility of the platform, there are many ways you can do this.  Below you’ll find one simple way.

1. Create a new cloud services project, and add a web role.

2. Create a new class and inherit from Microsoft.ServiceHosting.ServiceRuntime.RoleEntryPoint.  You’ll have to override the Start and RoleStatus methods.

using Microsoft.ServiceHosting.ServiceRuntime;
using System.Threading;

namespace Web
{
    public class MyWebWorkerRole : RoleEntryPoint
    {
        public override void Start()
        {
            while (true)
            {
                RoleManager.WriteToLog("Information", "The worker role is running.");

                Thread.Sleep(5000);
            }
        }

        public override RoleStatus GetHealthStatus()
        {
            return RoleStatus.Healthy;
        }
    }
}

3. Create a Global.asax page.

4. Create a method where you initialize and start and initialize your class that inherits from RoleEntryPoint.

private void StartWorkerRole()
{
    MyWebWorkerRole myWebWorkerRole = new MyWebWorkerRole();
    myWebWorkerRole.Initialize();
    myWebWorkerRole.Start();
}

5. Create local threading variables that you will use to run your method.

public class Global : System.Web.HttpApplication
{
    System.Threading.ThreadStart ts;
    System.Threading.Thread t;

    ...

5. Update the Application_BeginRequest method to invoke your method on a new thread.  Be sure and check to see if the thread is already running, otherwise it will get started multiple times.

protected void Application_BeginRequest(object sender, EventArgs e)
{
    if (t == null)
    {
        ts = new System.Threading.ThreadStart(StartWorkerRole);
        t = new System.Threading.Thread(ts);
        t.Start();
    }
}

And that should do it.  Now you have a class that will run asynchronously in all your Web Role instances.  And since it inherits from the RoleEntryPoint, you can leverage this technique for both your Web and Worker Role instances.  I’d recommend placing this class in a separate class library and adding a reference to it from your various projects.

Note: It is highly probable that there will be some changes to the APIs and assemblies come PDC.  While these concepts will stay valid, the underlying code will probably change.  If this happens, I’ll be sure and provide an update.

I hope this helps!