Linux to Windows Migration

Taking Advantage of Windows 2000 and .NET Platform

By Jan Dubois,

David Ascher

On This Page

Abstract
Introduction
System Administration: Configuration Files vs. APIs
The power of a standardized component model
Visual Studio.NET Integration
Deployment Tools and Execution Environments
Performance Notes
Other useful Tools
Summary
For More Information

Abstract

ActiveState Tool Corp.

This paper shows how the Perl, PHP, Python and Tcl scripting languages can help you take advantage of the component architecture offered by Windows 2000. It includes sample code highlighting how the powerful component subsystems supplied by Windows 2000 can be leveraged from all these languages.

An overview of some of the technologies (such as COM and the registry) and services (such as remote administration through WMI) available in Windows is presented, along with explanations of how to take advantage of them using scripting languages. In addition, a variety of tools that can boost the productivity of script developers are surveyed, including integrated development environments such as the Visual Perl and Visual Python plug-ins for Microsoft Visual Studio.NET, which provide the script developer with the full power of the Visual Studio development environment that Visual Basic and C++ programmers have long enjoyed. Throughout the paper, you will find some techniques and tools that can help you make your programs run more efficiently on Windows 2000. The .NET platform, which promises to revolutionize the way software is developed through the use of web services and a new generation component model is briefly presented. The paper describes the PerlNET component builder, which allows seamless interoperability between "old world" applications and components that live in the "new world" of .NET through Perl, and includes some notes on how to optimize applications on Windows 2000.

Acknowledgements

Paul Prescod, Senior Developer, ActiveState.

Glossary

This is a glossary of common terms in the Windows environment to be discussed in this paper that you may not be familiar with. The terms are defined in alphabetical order.

Active Server Pages (ASP): A specification for a dynamically created Web page that utilizes ActiveX scripting. ASP pages are similar to CGI scripts, except they are usually written in VB Script or Jscript. However, they can be written in any language that can act as an ActiveX scripting host.

ActiveX Data Objects (ADO): The ADO programming model is the highest-level API for access to data objects.

Application Programming Interface (API): A definition of how programs can call specific functions of other programs or components.

Collaboration Data Objects (CDO): An API allowing applications to support collaborative work. CDO works through Microsoft Exchange.

Common Gateway Interface (CGI): A specification for transferring information between a Web server and a CGI program. A CGI program is any program designed to accept and return data that conforms to the CGI specification. The program could be written in any programming language.

Component Object Model (COM): A set of APIs that allows cross-language and cross-application calls through a well-specified binary interface.

Internet Information Server (IIS): Microsoft's brand of Web server software, utilizing Hypertext Transfer Protocol to deliver World Wide Web documents. It incorporates various functions for security, allows for CGI programs, and also provides for Gopher and FTP servers.

Messaging Application Programming Interface (MAPI): This API enable it to provide a consistent way for developers to work with and use different messaging systems in a seamless fashion.

Windows Management Instrumentation (WMI): WMI is the Microsoft implementation of WBEM, the Web-Based Enterprise Management standard. This API allows programmers to access and manage information on the state of system memory, inventories of currently installed client applications, and other information on client status.

Introduction

Porting software from one operating system such as Linux to another, such as Windows 2000 is typically a two-staged process. The first process, described in detail in the white paper titled "Linux to Windows 2000 Scripting Portability", consists of making the necessary changes to the programs so that they execute correctly on Windows 2000. However, once that process is finished, many programmers unaccustomed to the Windows 2000 platform will find themselves like recent immigrants the natives seem to get along just fine, but their customs can be mysterious. This paper presents a crash-course in the differences between Linux/Unix and Windows 2000, as well as explains the benefits offered by some of the features of the Windows 2000 operating system. Along the way, we present some tools which make using Windows 2000 with scripting languages much more efficient, and when appropriate mention performance and optimization techniques which can help you take full advantage of the Windows 2000 architecture. The information presented in this paper can be useful to people with many different roles, from system administration to application developer to 'savvy user' in brief, to anyone who knows how to use an Open Source scripting language (Perl, Python, Tcl, PHP) on Linux and is transitioning to using Windows 2000.

In order to frame the rest of the paper, let us consider an analogy that Linux is like the 1970's car, while Windows 2000 is like today's car. The former is easily configured, with hobbyists and mechanics particularly enjoying the ability to get under the hood and 'tweak' every aspect of the car, from the combustion system to the gear ratios, the ability to add nitrous oxide boosters, cut off the roof, or what not. Scripting languages thrived in this world, where their ability to morph and adapt to pretty much anything made them especially useful when wanting to automate "tweaking" of systems. In contrast, the modern car, in order to meet consumer demands regarding fuel efficiency, features, safety and the like, is not designed to be tweaked by going to the 'bare metal'. Instead, the system should be monitored, controlled and modified via well-defined interfaces, plug-in boards, etc. Equivalently, scripting languages are most often used in Windows 2000 to "drive" systems through APIs, as opposed to though modification of configuration files. Understanding this difference in philosophy is key to effective use of scripting languages on the Windows 2000 platform.

Continuing on the car analogy, it could be said that the .NET platform offers some of the same benefits as electric vehicles. By radically changing some of the fundamental aspects of the internal machinery of the system, car manufacturers hope to solve some of the well-known problems of current cars, including cost of operation, environmental impact, noise, etc. The promise of the .NET vision includes the same kind of impact, from moving application methodologies from client-server to web service-based models, solving component incompatibility issues and cross-platform deployment with on-demand compilation, etc. This paper introduces some Perl technologies and products which will help you make the transition to the .NET platform.

System Administration: Configuration Files vs. APIs

The starkest difference between Linux/Unix and Windows 2000 from the perspective of system administration and configuration is that the two different operating systems have very different models of how the operating system is monitored and managed. Linux, because of its roots in the text-only 1960's, uses almost entirely text-based configuration files. Thus, almost all configuration tasks, be that of the account and group database, network services, networking, or of file systems, is done through editing of "plain text files" and invoking command-line tools which process these files. This design decision allows a Unix system to be configured even in very adverse conditions, and with a variety of tools. Not surprisingly, scripting languages such as Perl, Python and Tcl, which are particularly well suited at processing and creating text files, have been used extensively to read and write such configuration files. The Windows 2000 platform presents a very different approach, where almost all configuration data is stored in a standardized, centralized hierarchical database (the Windows Registry) and accessed and modified through the use of GUI tools (such as the "regedit" program) or through programmable interfaces (APIs). The former provides an easy-to-use, modern way of reading and modifying the data on a case-by-case basis, and the latter allows for automation of such tasks.

The registry can be browsed through a GUI tool called "regedit":

Dd316440.takadv01(en-us,TechNet.10).gif

This screenshot shows that there are five "hives" in which data is stored: "HKEY_CLASSES_ROOT", "HKEY_CURRENT_USER", "HKEY_LOCAL_MACHINE", "HKEY_USERS", and "HKEY_CURRENT_CONFIG". Most of the data used by users, administrators and application developers is stored in either of KHEY_CURRENT_USER (also known as HKCU) or HKEY_LOCAL_MACHINE (also known as HKLM).

Perl, Python and Tcl all provide interfaces to the registry. For example, the following Python code adds the path "C:\" to your system PATH environment variable, as stored in the HKLM registry:

import _winreg
hklm=_winreg.ConnectRegistry(None,_winreg.HKEY_LOCAL_MACHINE)
environment = _winreg.OpenKey(hklm, r"SYSTEM\CurrentControlSet\Control\Session Manager\Environment")
path = _winreg.QueryValueEx(environment,"path")[0]
key=_winreg.OpenKey(hklm, r"SYSTEM\CurrentControlSet\Control\Session
Manager\Environment", 0,_winreg.KEY_ALL_ACCESS)
_winreg.SetValueEx(key,"path",0,_winreg.REG_EXPAND_SZ,path+r";C:\")
_winreg.CloseKey(key)
_winreg.CloseKey(hklm)

While the APIs for the registry are fairly complex, the fact that all configuration data is stored in a single database makes it easy for the script programmer to configure virtually all Windows applications. See the paper "Linux to Windows 2000 Scripting Portability" for samples in all the languages.

Registry APIs Reading and modifying the registry

Perl

Python

Tcl

Windows Services

Windows services are processes that run independently of the foreground user session; they can be started automatically when the operating system loads and stop when it shuts down. In concept, they are similar to Unix daemon processes in that they are typically used to perform periodic or administrative tasks. Unlike Unix daemons, they have to respond to windows messages instead of signals, and have a richer API. Furthermore, all Windows services can be administered through a common user interface (the Service Manager), and services can be administered remotely.

Perl Creating Standalone Services with PerlSvc

PerlSvc, part of ActiveState's Perl Dev Kit, creates a Windows service from a Perl application. These Windows services written in Perl can also be deployed to any computer running the Windows operating system; no Perl installation is necessary on the target machine.

Creating, installing and starting a service is as easy as:

perlsvc f MyApp.pl
MyApp install
net start myapp

Python Creating Services with win32service

Creating services with Python can be done with the win32service and win32serviceutil modules which are part of ActivePython

Logging and Monitoring

Windows 2000 supports other standardized features with the same benefits as those described for Services, namely consistent interfaces and remote administration two of these are the event log mechanism and the performance monitor. The event log allows any Windows application to store information about the running of the application, indicating either informational data points, warnings, or error notices. A similar API is used for logging of performance data. Since these services are available through generic APIs, all programming languages with a COM API (as described below) can be used to either log events or to analyze the event and performance logs and build custom reporting tools.

Event Log Reference

Python API

Performance Monitor Reference

Python API

The power of a standardized component model

Windows 2000 leverages extensively the success of the Microsoft family of component models (COM, COM+, DCOM, and now .NET). Indeed, the vast majority of operating-system features are controllable via COM, the Component Object Model. This section presents a brief overview of component-based programming, and then describes some of the technologies layered on top of COM.

Component-Based Programming

The primary goal of component-based programming is to provide a language and compiler-independent mechanism for deploying "components" of an application independently of one another. Components are packaged in DLLs (dynamically loaded libraries) or EXEs (executables). A component is a binary unit of functionality, with a well defined interface. Thanks to both of these facts, the nature of the programming language used to implement a component, in fact even the behavior of these components, is not relevant to whether the component "fits" within a system. This modularity allows the development of scalable applications based on reusable components, written in any one of several programming languages. Components can be created using a programming language this refers to the act of building a module of code, which exposes the interface of that component. Components can also be "consumed", "used", or "called", by code that need not be in the same programming language. Windows 2000 consists of assemblies of components from the operating system up to the end-user applications like Microsoft Word. This means that any language with a COM binding (Perl, Python, Tcl included) can "drive" any operating system service and most applications. Thus, COM makes the choice of implementation language mostly irrelevant when dealing with component-based software systems. While there are component models available for Linux such as CORBA, the lack of standardization means that application developers need to ship their own component model, complicate the system prerequisites, or forsake component-based programming altogether, which is the most frequent choice.

Windows 2000 extends COM into the network world with DCOM, distributed COM, which allows remote invocation of components. Full DCOM support by scripting languages such as Perl and Python means that scripts can readily be written which coordinate processes occurring on multiple computers at once, using a standard messaging system.

To summarize, while from an end-user's perspective, the Windows operating system and many of its applications look like huge monolithic entities, they are implemented using many smaller components as building blocks. Many of these components are accessible from the outside. They can either be either used to build different applications or to automate the processing behavior of existing ones. The component nature of Windows 2000 makes software development extremely efficient by allowing programmers to assemble applications out of components written in any language.

COM Overview

The Component Object Model (COM) is the standard mechanism on Windows to represent components to the outside world. It exposes language-neutral interfaces that can be utilized both from scripting languages (late binding) and from traditional strongly typed languages (early binding):

Early Binding

Early binding is also referred to as using native interfaces or VTBL interfaces. These interfaces are strongly typed and can be completely resolved at compile-time using type maps from an interface description language (IDL). Virtually all VTBL interfaces that are described in a type library can be both used from and implemented by the dynamically typed Python programming language.

Late Binding

Late binding is also known as dynamic dispatch, OLE Automation or the IDispatch interface. This interface defers resolution of method calls to the run-time, when parameter types etc. can be determined in dynamically typed scripting languages. Perl, Python, PHP and Tcl all support late binding COM to other components. It is also possible to implement components supporting Automation in Perl, Python and Tcl.

Many modern applications are developed in a mix of early-bound languages and late-bound languages. Early-bound languages are often used to implement reusable components. Late-bound languages allow developers to combine the components into business applications. Windows makes the combination of early and late-bound code much easier than other platforms.

Because most applications are composed of COM components, all Windows programmers have access to hundreds of reusable objects. This is especially important for users of languages with smaller user bases. On Linux, it is common to have a component that is only compatible with one of Perl, PHP, Python or TCL. On Windows, these languages can share components and can even share components with C++, C# and Visual Basic.

Understanding APIs

Windows 2000 consists of hundreds of components, exposing thousands of method calls. To understand them, two complementary approaches are recommended: reading the documentation for those interfaces which are documented, and browsing the interfaces which are automatically exposed by the components themselves.

Ultimate Windows Documentation: MSDN

MSDN is the Microsoft Developer Network. It consists of a set of products and a content site. The products allow you to get periodic media (CD-ROMs or DVDs) containing complete access to all of the technical information regarding programming Microsoft tools and operating systems, including sample code, API documentation, SDKs, and more. Part of MSDN is the website (MSDN.Microsoft.com), which is the authoritative source of all documentation on Microsoft technology. All published APIs are discussed in detail on the website, which is free.

http://MSDN.microsoft.com/

When All Else Fails: The COM/OLE Browser

Sometimes, one has to work against a COM component for which documentation is not available, either because its APIs are not 'official', or because the component vendor did not expect it to be programmed by third-parties. In these cases, tools like the COM/OLE browser that ships as part of Visual Studio 6 can be a godsend. This GUI tool will allow you to explore all of the interfaces exposed by arbitrary components, including all of the signatures for the methods exposed by these interfaces. Naturally, the names of the interfaces and their method names and signatures cannot always provide all the information one needs, but they can typically provide a great deal of insight into how a given component works.

The following screenshot shows the COM browser browsing type libraries, and drills down into one particular type library to show the interfaces it supports:

Dd316440.takadv02(en-us,TechNet.10).gif

Using Components

Windows 2000 exposes its powerful functionality through a range of layered technologies. The lowest level, COM/OLE, is supported by all major languages. Higher-level APIs such as ADO, CDO, MAPI and WMI have varying levels of support across the language spectrum.

OLE Automation

Perl, PHP, Python and Tcl all support OLE automation through an add-on module. Existing OLE Automation-based components give programmers access to many large-grained components for working with databases, multimedia, networking and much more.

Perl

Perl supports OLE Automation through the Win32::OLE module. It is already installed by every ActivePerl distribution and is also available in source form from CPAN.

The Win32::OLE documentation can be found on ASPN

The Perl Journal printed a Win32::OLE tutorial in issue #10:

PerlMonth features a tutorial about using OLE events with Perl:

Python

The ActivePython distribution comes with compiled HTML help (Microsoft CHM format) for the win32com module. It contains all the information about COM interoperability including information about Python and Active Server pages (ASP), Microsoft Transaction Server (MTS) and Active Directory Services Interface (ADSI).

In addition, the book "Python Programming on Win32" (O'Reilly & Associates) is entirely devoted to using Python to take full advantage of a Windows APIs and services, and includes several chapters on COM, DCOM, Automation, and more.

PHP

COM support has been added to PHP version 4. The sample code in this whitepaper requires PHP version 4.0.6 or later.

PHP COM support functions for Windows

PHPBuilder article on using the COM Functions in PHP4

Tcl

There are two extension modules for Tcl providing OLE Automation support, "Tcl COM" and "Open Tcl":

Tcl COM extension

Open Tcl

ADO ActiveX Data Objects

ActiveX Data Objects enables your client applications to access and manipulate data from a database server through an OLE DB provider. Its primary benefits are ease of use, high speed, low memory overhead, and a small disk footprint. ADO allows any programming language to talk to any data source anywhere on the network. ADO is more standardized than the mix of modules available for making each scripting language talk to each different type of data source on Linux.

ADO is designed to provide developers with a powerful, logical object model for programmatically accessing, editing, and updating a wide variety of data sources through OLE DB system interfaces. The most common usage of ADO is to query a table or tables in a relational database, retrieve and display the results in an application, and perhaps allow users to make and save changes to the data. Other things that can be done programmatically with ADO include:

  • Querying a database using SQL and displaying the results.

  • Accessing information in a file store over the Internet.

  • Manipulating messages and folders in an e-mail system.

  • Saving data from a database into an XML file.

  • Executing commands described with XML and retrieving an XML stream.

  • Saving data into a binary or XML stream.

  • Allowing a user to review and make changes to data in database tables.

  • Creating and reusing parameterized database commands.

  • Executing stored procedures.

  • Dynamically creating a flexible structure, called a Recordset, to hold, navigate, and manipulate data.

  • Performing transactional database operations.

  • Filtering and sorting local copies of database information based on run-time criteria.

  • Creating and manipulating hierarchical results from databases.

  • Binding database fields to data-aware components.

  • Creating remote, disconnected Recordsets.

The following sample program will connect to the Northwind sample database, which is distributed with Microsoft's SQL Server. It executes a simple SQL query and prints the names and values for each result set. Adapting an ADO application to a different database engine is as simple as changing the connection string.

Alternatively, an ADO application can use an ODBC Data Source Name (DSN). This completely decouples the data source definition from the program code.

use Win32::OLE qw(in);
use Win32::OLE::Variant;
my $Conn = Win32::OLE->new("ADODB.Connection");
$Conn->Open(<<EOT);
Provider=SQLOLEDB;
User ID=sa;
Password=;
Initial Catalog=Northwind;
Data Source=IBRIK\\NetSDK;
EOT
my $RS = $Conn->Execute(<<EOT);
SELECT ShipName, ShipAddress, ShipCity, ShipPostalCode, ShipCountry
FROM  Orders
WHERE OrderId IN ('10248', '10249')
EOT
until ($RS->EOF) {
print join("\n", map "$_->{Name}: $_->{Value}", in $RS->Fields), "\n\n";
$RS->MoveNext;
}
$RS->Close;
$Conn->Close;

The output of this sample program looks like this:

ShipName: Vins et alcools Chevalier
ShipAddress: 59 rue de l'Abbaye
ShipCity: Reims
ShipPostalCode: 51100
ShipCountry: France
ShipName: Toms Spezialitten
ShipAddress: Luisenstr. 48
ShipCity: Mnster
ShipPostalCode: 44087
ShipCountry: Germany

The ADO start page in the MSDN library

ODBC Data Source reference

There have been attempts to similarly standardize data access on Linux through a port of the older Windows ODBC library. This form of data access has failed to gain traction in any of the scripting language communities. Windows remains the only platform with a consistent, language-neutral database access layer.

ADSI Active Directory Service Interface

Active Directory Service Interfaces is a set of COM interfaces used to access the capabilities of directory services from different network providers in a distributed computing environment, to present a single set of directory service interfaces for managing network resources. Administrators and developers can use ADSI services to enumerate and manage the resources in a directory service, no matter which network environment contains the resource. Script programmers can use ADSI to manage accounts and network resources even on heterogeneous networks.

ADSI makes it easier to perform common administrative tasks, such as adding new users, managing printers, and locating resources throughout the distributed computing environment.

This sample program connects to the Primary Domain Controller (PDC) of a domain and browses the list of all available objects in the "computer" container. It collects a list of all users that ever logged into the domain and a list of all groups with their descriptions. The collected information is then printed out.

The strings "DOMAIN" and "PDC" in the AdsPath below need to be changed to the actual domain name and the name of the PDC before the program is executed.

use Win32::OLE qw(in);
use Win32::OLE::Variant;
my $AdsPath = "WinNT://DOMAIN/PDC,computer";
my $Container = Win32::OLE->GetObject($AdsPath) or die;
my (@User,@Group);
foreach my $Object (in $Container) {
my $Class = $Object->{Class};
if ($Class eq "User" && defined $Object->{LastLogin}) {
push @User, [$Object->{Name}, $Object->{LastLogin}];
}
elsif ($Class eq "Group") {
push @Group, [$Object->{Name}, $Object->{Description}];
}
}
printf "%-24sLast Login\n", "Users";
printf "  %-20s: %s\n", @$_ foreach @User;
printf "\n%-24sDescription\n", "Groups";
printf "  %-20s: %s\n", @$_ foreach @Group;

The (abbreviated) output may look like this:

Users                   Last Login
Administrator       : 5/24/2001 1:36:09 PM
backup              : 5/24/2001 5:20:35 AM
IUSR_MOCHA          : 5/17/2001 2:36:11 PM
IWAM_MOCHA          : 5/16/2001 12:25:03 PM
sqlman              : 5/24/2001 6:59:43 AM
upsadmin            : 4/6/2001 8:50:55 PM
-
Groups                  Description
Administrators      : Members can fully administer the computer/domain
Users               : Ordinary users
Guests              : Users granted guest access to the computer/domain
Account Operators   : Members can administer domain user and group accounts
Server Operators    : Members can administer domain servers
Print Operators     : Members can administer domain printers
Backup Operators    : Members can bypass file security to back up files
Replicator          : Supports file replication in a domain

The ADSI start page

CDO Collaboration Data Objects

Collaboration Data Objects is a COM component designed to simplify writing programs that create or manipulate Internet messages. With CDO, script developers can create sophisticated groupware-like applications with a minimum of code. The CDO interfaces are standardized across languages and are designed to be extremely easy to use. Where Linux applications would typically work directly with the syntax of the headers and the protocols, Windows programmers usually work with clean, abstracted object oriented interfaces.

Dd316440.takadv03(en-us,TechNet.10).gif

This CDO sample program creates a short email message. It uses HTML for the body and adds a couple of MIME attachments. CDO will automatically add a pure-text version of the body text as well.

use Win32::OLE qw(with);
my $Message = Win32::OLE->new("CDO.Message");
with($Message,
To       => 'Receiver@Company.com',
From     => 'Sender@MyCompany.com',
Subject  => "This is a subject line",
HTMLBody => "<html><body>This is <b>the</b> body!</body></html>",
);
$Message->AddAttachment('http://www.ActiveState.com');
$Message->AddAttachment('C:\Data\MyFile.txt');
$Message->Send();

The message shows up in the recipient's mailbox like this:

About CDO for Windows 2000

Navigating CDO Interfaces with VBScript

The same sample written in PHP looks like this:

<?
$message = new COM("CDO.Message");
$message->To = 'Receiver@Company.com';
$message->From = 'Sender@MyCompany.com';
$message->Subject = "This is a subject line";
$message->HTMLBody = "<html><body>This is <b>the</b> body!</body></html>";
$message->AddAttachment('http://www.ActiveState.com');
$message->AddAttachment('D:\\tmp\\Report.xls');
$message->Send();
?>

Written in Python:

from win32com.client import Dispatch
message = Dispatch("CDO.MESSAGE")
message.To = "Receiver@Company.com"
message.From = "Sender@MyCompany.com"
message.Subject = "This is a subject line"
message.HTMLBody = "<html><body>This is <b>the</b> body!</body></html>"
message.AddAttachment('http://www.ActiveState.com')
message.AddAttachment('d:\\tmp\\Report.xls')
message.Send()

Using Tcl COM:

package require tcom
set mesg [tcom::ref createobject CDO.Message]
$mesg To "Receiver@Company.com"
$mesg From "Sender@MyCompany.com"
$mesg Subject "This is a subject line"
$mesg HTMLBody "<html><body>This is <b>the</b> body!</body></html>"
$mesg AddAttachment http://www.ActiveState.com/
$mesg AddAttachment d:\\tmp\\Report.xls
$mesg Send
tcom::release $mesg

Using Open Tcl:

set msg [optcl::new CDO.Message]
$msg : To "Receiver@Company.com"
$msg : From "Sender@MyCompany.com"
$msg : Subject "This is a subject line"
$msg : HTMLBody "<html><body>This is <b>the</b> body!</body></html>"
$msg AddAttachment "http://www.ActiveState.com" 0 0
$msg AddAttachment "d:\\tmp\\Report.xls" 0 0
$msg Send

WMI Windows Management Instrumentation

Windows Management Instrumentation (WMI) is the Microsoft implementation of Web-Based Enterprise Management (WBEM), which is an industry initiative to develop a standard technology for accessing management information in an enterprise environment. WMI uses the Common Information Model (CIM) industry standard to represent systems, applications, networks, devices, and other managed components in an enterprise environment. Using WMI, scripting language developers can create tools and technologies that reduce the complexity and costs of enterprise management.

use strict;
use Math::BigFloat;
use Win32::OLE qw(in with);
# Define list of server names
my @Server = qw(Ibrik Occam);
# Collect capacity information about each disk in each server
my %Data;
foreach my $Server (@Server) {
my @Data;
my $WMI = Win32::OLE->GetObject(
"winmgmts:{impersonationLevel=impersonate}//$Server");
my $DiskSet = $WMI->ExecQuery(<<QUERY);
select Name, FreeSpace, Size
from Win32_LogicalDisk
where DriveType=3
QUERY
# FreeSpace and Size are int64 quantities returned as strings!
sub bignum { Math::BigFloat->new(shift) }
push @Data, [$Server, qw(Free Used)];
foreach my $Disk (in $DiskSet) {
my $Ratio = bignum($Disk->FreeSpace)/bignum($Disk->Size);
push @Data, ["Drive $Disk->{Name}", $Ratio, 1-$Ratio];
}
$Data{$Server} = \@Data;
}
use Win32::OLE::Const 'Microsoft Excel';
my $Excel = Win32::OLE->new("Excel.Application");
with($Excel, SheetsInNewWorkbook => 1, Visible => 1);
my $Book = $Excel->Workbooks->Add;
my $Sheet = $Book->Worksheets(1);
for my $Col (0..@Server-1) {
my $Data = $Data{$Server[$Col]};
# Define cell range for data destination
my $Column = 4*$Col+1;
my $Cell1 = $Sheet->Cells(1,$Column);
my $Cell2 = $Sheet->Cells(int @$Data, $Column+2);
my $Range = $Sheet->Range($Cell1, $Cell2);
# Put data into spreadsheet and format numbers as percentages
$Range->{Value} = $Data;
$Range->Columns($_)->{NumberFormat} = "0.0%" for 2, 3;
# Create a row of pie charts, one for each disk of this server
for my $Row (2..@$Data) {
# Create new chart object and put it in the right spot
my @Pos = (120*($Row-2), 120*($Col+1), 120, 120);
my $Chart = $Sheet->ChartObjects->Add(@Pos)->Chart;
$Chart->Location({Where => xlLocationAsObject,
Name  => $Sheet->{Name}});
# Create pie chart itself
my $Source = $Excel->Union($Range->Rows(1), $Range->Rows($Row));
$Chart->SetSourceData({Source => $Source});
$Chart->{ChartType} = xlPie;
$Chart->Legend->{Position} = xlBottom;
$Chart->ChartTitle->Characters->{Text} =
"$Server[$Col]: $$Data[$Row-1][0]";
}
}

Dd316440.takadv04(en-us,TechNet.10).gif

The WMI start page in the MSDN library

Win32 classes' reference

Whitepaper "Windows Management Instrumentation Scripting"

Technical article "Managing Windows with WMI" with sample code (in VBScript)

Creating Components

ActiveX Scripting Engines

One of the core aspects of COM is the notion that by defining a "scripting interface", any COM-based application can be scripted by any language that supports ActiveScripting. Windows already includes the JScript and VBScript scripting engines. However, Python, Perl and Tcl also all support ActiveScripting, meaning that a wide variety of Windows 2000 applications can be scripted with those languages (or with other ActiveScripting languages such as Visual Basic and JScript). This feature of Windows 2000 allows application developers to provide their customers with scripting solutions very efficiently.

A variety of scripting host applications can therefore use all 'registered' scripting engines, including

  • Internet Explorer (IE)

  • Internet Information Server (IIS)

  • Windows Script Host (WSH)

  • Windows Script Control (WSC)

In other words, wherever it is possible to use one scripting engine, it is equally possible to use another. This preserves developers right to choose their language. It also means that any application developer can allow end-users to write "macros" in any scripting language. This degree of language-independence is not readily available on the Linux platform. Many Linux applications allow macro writers use Perl or PHP or Python, but very few allow the end-user to choose. ActiveX Scripting Engine implementations are available for both Perl and Python and are installed by default with the ActivePerl and ActivePython distributions.

Perl ActiveX Scripting Engine

The Perl scripting engine is installed using the "PerlScript" language identifier.

PerlScript documentation

Python ActiveX Scripting Engine

The Python scripting engine is registered under the "Python" language identifier.

ASP Active Server Pages

Active Server Pages is a server-side scripting environment that you can use to create interactive Web pages and build powerful Web applications. When the server receives a request for an ASP file, it processes server-side scripts contained in the file to build the Web page that is sent to the browser. In addition to server-side scripts, ASP files can contain HTML (including related client-side scripts) as well as calls to COM components that perform a variety of tasks, such as connecting to a database or processing business logic. ASP is designed to make it as easy as possible to build sophisticated web applications.

Although there are script-embedding technologies available for particular scripting languages on Linux, none of them are language-independent. ASP is a cornerstone of modern web application development on Windows. Thanks to the Windows Script Host, it is just as usable from Perl and Python as from VBScript and Jscript.

<%@Language=PerlScript%>
<HTML>
<TITLE>PerlScript Example</TITLE>
<BODY>
<% for (my $i=2; $i<=8; $i+=2) { %>
<FONT SIZE=<%=$i%>>Hello World!</FONT><BR>
<% } %>
</BODY>
</HTML>

Dd316440.takadv05(en-us,TechNet.10).gif

ActivePerl ASP tutorial

ActivePython ASP tutorial

The Microsoft "Active Server Pages Guide"

DHTML Client Side Scripting with Dynamic HTML

The Windows 2000 operating system embeds a sophisticated Dynamic HTML and XML control that can be used in any application. It is just a COM object so it is not surprising that it can be embedded into programs written in COM-aware languages like Perl, PHP, Python and TCL. It is interesting to note that it is also possible to embed the WSH-enabled scripting languages in HTML documents. Just as ASP allows a mix of HTML and script on the server side, DHTML allows it on the client side.

A complex sample of using dynamic HTML for client side scripting is the OLE browser included in the ActivePerl documentation. It is normally installed under

C:\Perl\html\site\lib\Win32\OLE\Browser\Browser.htmlC:\Perl\html\site\lib\Win32\OLE\Browser\Browser.dhtml

The .HTML file contains just the FRAMESET; the .DHTML file is almost exclusively code implementing the dynamic behavior of the page elements.

Windows Script Components

Microsoft Windows Script Components provide you with an easy way to create COM components using any ActiveX scripting languages, including PerlScript and Python.

Using PerlScript with Windows Script Components

Microsoft Windows Script Components

PerlCtrl Write standalone ActiveX controls in Perl

Windows Script Components support creation of ActiveX control using PerlScript, but every target system must have ActivePerl installed in order for the control to work. PerlCtrl from the ActiveState Perl Development Kit supports creating standalone controls as a single DLL. This DLL can then be deployed on any Windows machine. There is no easier way to deploy a standalone Perl-coded component available for any other platform.

PerlCtrl Documentation

PerlNET Write .NET components on Perl

The Microsoft .NET Framework is a multi-language software component architecture. Among other things, it makes it easy to create sophisticated XML-based Web services. .NET provides programmers with an unprecedented level of interoperability between languages. Where COM has always allowed components to call from one language to another, .NET allows cross-language inheritance and exception handling. The .NET framework is scalable, includes consistent cross-language error handling and debugging capabilities, and will reduce the amount of 'plumbing' code programmers need to write.

Languages that work in the .NET framework run entirely or partially in an environment called the Common Language Runtime (CLR). The Common Language Runtime manages the execution of code and provides services that make the development process easier. Code that runs on the CLR benefits from features such as cross-language integration, cross-language exception handling, enhanced security, versioning and deployment support, a simplified model for component interaction, and debugging and profiling services.

Here is an example of Perl code which can be compiled by PerlNET into a full .NET assembly:

package Sample::WordCount;
#-----------------------------------------------------------------------
# Create new 'Sample::WordCount' object, optionally setting 'Text' property
=for interface
static WordCount WordCount();
static WordCount WordCount(str text);
=cut
sub new {
my ($package,$text) = @_;
my $self = bless {} => $package;
$self->Text($text);
return $self;
}
#-----------------------------------------------------------------------
# Get or set 'Text' property and update word counts
=for interface
str Text;
=cut
sub Text {
my ($self,$text) = @_;
return $self->{Text} unless defined $text;
$self->{Text} = $text;
$self->{Count} = {};
# convert all non-alphas to single space
$text =~ tr/a-zA-Z/ /cs;
# split lowercase text on single space and count words
++$self->{Count}->{$_} foreach split(' ', lc $text);
}
#-----------------------------------------------------------------------
# 'Count' returns number of occurances or throws an exception
=for interface
int Count();
int Count(str word);
=cut
sub Count {
my ($self,$word) = @_;
# Without arguments: return number of distinct words
return int keys %{$self->{Count}} unless defined $word;
# Throw exception if $word does not exist in 'Text'
die "Word '$word' not found" unless defined $self->{Count}->{$word};
# Return number of occurances
return $self->{Count}->{$word};
}
#-----------------------------------------------------------------------
# 'Words' returns alphabetically sorted *list* of all words in 'Text'
=for interface
str[] Words();
=cut
sub Words {
my ($self) = @_;
return sort keys %{$self->{Count}};
}
1;

And here is a bit of 'stub' C# code which can call the above Perl code

using System;
using Sample;
class main
{
public static void Main(string[] args)
{
String text = "The quick brown fox jumps over the lazy dog.";
// Create new 'Sample.WordCount' object; make sure it gets destroyed too
using (WordCount obj = new WordCount(text)) {
// Get 'Text' property
Console.WriteLine("Text is '{0}'", obj.Text);
// Set 'Text' property
obj.Text = "To be or not to be?";
// 'Count' method without argument returns number of words
Console.WriteLine("There are {0} distinct words in '{1}'",
obj.Count(), obj.Text);
// 'Words' method returns a 'String[]' array
// 'Count' method returns number of occurances of word
foreach (String word in obj.Words())
Console.WriteLine("{0} appears {1} times", word, obj.Count(word));
// Calling 'Count' for a word not in 'Text' throws an exception
try {
String word = "unknown";
Console.WriteLine("{0} appears {1} times", word, obj.Count(word));
}
catch (Exception e) {
Console.WriteLine("Exception: {0}", e.Message);
}
}
}
}

Once a language has been integrated with the .NET framework, it is a first-class citizen of that framework, with access to all of the features available. One of the impressive new capabilities available is the Windows Forms Framework. This is a language-independent graphical development framework for Windows applications. Under .NET, the same palette of graphical tools is available to all programming languages.

Debugging of PerlNET components is provided by the Visual Perl plug-in for Microsoft Visual Studio.NET. It supports seamless step-through debugging from other supported .NET languages.

The major benefit of PerlNET is that you can easily build .NET applications that leverage the large amounts of existing Perl code, whether publicly available code such as that in CPAN (the Comprehensive Perl Archive Network), or your existing code. You could even use Perl and PerlNET to link existing non-Perl applications with .NET applications.

The Microsoft .NET home page

More information about PerlNET

More information about Visual Perl for Visual Studio .NET

Comprehensive Perl Archive Network

Perl and ASP.NET

ASP.NET is more than the next version of Active Server Pages; it is a unified Web development platform that provides the services necessary for developers to build enterprise-class Web applications. While ASP.NET is largely syntax compatible with ASP, it also provides a new programming model and infrastructure that enables a powerful new class of applications. You can feel free to augment your existing ASP applications by incrementally adding ASP.NET functionality to them.

PerlNET support for ASP.NET pages is currently under development by ActiveState.

Introduction to ASP.NET

Embedding Scripting Languages

It is possible to use the normal techniques (see the perlembed.pod help file) for embedding a Perl interpreter into an application on Windows 2000 too. But there are a number of additional technologies available, which can make this task easier.

PerlEz Easy embedding of Perl into C

The PerlEz library provides a very simple C API to embed a Perl interpreter. It works from every language supporting C calling conventions. However, all data must be passed back and forth as strings.

The following sample program uses the Finance::YahooQuote Perl module to get a few stock quotes from Yahoo. The C program prints out the values returned by the Perl method.

#include <stdio.h>
#include <windows.h>
#include <PerlEz.h>
char *symbols[] = {"CPQ","IBM","MSFT",0};
int main(void)
{
char cmd[80];
char buffer[200];
char **symbol = symbols;
PERLEZHANDLE perl = PerlEzCreate(NULL, "-MFinance::YahooQuote");
if (!perl)
return 1;
while (*symbol) {
sprintf(cmd, "join ' ', (getonequote('%s'))[3,4,2]", *symbol);
if (PerlEzEvalString(perl, cmd, buffer, sizeof(buffer)) == 0)
printf("%-4s %s\n", *symbol, buffer);
++symbol;
}
PerlEzDelete(perl);
return 0;
}

The \Perl\lib\CORE directory needs to be added to both the INCLUDE and LIB paths:

set INCLUDE=I:\Perl\lib\CORE;%INCLUDE%
set LIB=I:\Perl\lib\CORE;%LIB%
cl -W3 embed.c PerlEz.lib

The output of the sample program looks like:

CPQ  5/24/2001 4:01PM 17.55
IBM  5/24/2001 4:01PM 119.60
MSFT 5/24/2001 4:01PM 71.72

PerlEz documentation

Finance::YahooQuote module documentation

Microsoft Script Control

The Script Control is an ActiveX control that provides an easy way for developers to make applications scriptable. Users can extend application functionality through scripts, much as they do with macros today. In the following example, Perl's Win32::OLE module is used to instantiate a Script Control, which is then filled with JScript code, and executed.

use strict;
use Win32::OLE;
my $script = Win32::OLE->new('ScriptControl');
$script->{Language} = 'JScript';
$script->AddObject('Script', $script);
$script->AddCode(<<JS);
function Concat(Prefix)
{
return Prefix.concat(" from ").concat(Script.Language);
}
JS
print $script->Run('Concat', 'Hello'), "\n";

It simply prints:

Hello from Jscript

Microsoft Script Control home page

Visual Studio.NET Integration

One significant difference between Linux and Windows 2000 is the environment that developers expect from the operating system and accompanying tools. The only tools which are almost guaranteed to exist on a Linux development system are the command-line compilers (gcc and friends) and some text-only editors (vi, sometimes emacs). While Linux users typically "grow" their environment to include a wide variety of additional tools, there are currently no tools with the depth of the Visual Studio integrated development environment (IDE) available on Windows. This IDE provides a rich editor for both code and code-related artifacts such as bitmaps, resources, and web pages, templates and code creation wizards, rich project handling with automatic dependency discovery, a very powerful cross-language debugger, test tools, "message spying" tools, integration with MSDN and rich on-line help. While Visual Studio 6 only provided support for Microsoft-supported languages like C++ and VB, with the advent of Visual Studio.NET Microsoft opened up the interfaces to its integrated development environment. This allows third parties to add support for additional languages and tools at the same level as the Microsoft supplied ones.

ActiveState has developed Visual Perl, Visual Python and Visual XSLT as plug-ins to Visual Studio.NET. Visual Tcl is currently under development. Visual Perl and Visual Python are described briefly.

Visual Studio.NET home

Visual Studio Integration information

Visual Perl

Visual Perl supports development of both "traditional" Perl application and Perl for .NET components using PerlNET. It supports all the popular Visual Studio features such as a rich syntax aware editor, with code folding, method tips, syntax highlighting and on-the-fly syntax checking.

The Visual Perl debugger supports both local and remote debugging of Perl applications. For PerlNET components, the debugger allows seamless step-through debugging from other languages like C# or Visual Basic into Perl and vice versa.

Dd316440.takadv06(en-us,TechNet.10).gif

Visual Perl product information

Visual Python

VisualPython provides a full IDE for Python that fits naturally within the VisualStudio.NET environment, with a rich editor with Python-specific Intellisense, a rich debugger, on-line help, and more.

Visual Python product information

If you use Perl or Python in conjunction with other language such as C# or VB, solutions like Visual Perl and Visual Python can help simplify code and project organization, as well as help leverage the learning curve of the IDE over all the languages.

Deployment Tools and Execution Environments

Having covered some of the technologies made available by Windows 2000 and some of the tools available to help develop application, let us now focus on how to execute the code, as well as how to deploy it to users.

Standalone Executables and Services

One of the advantages of the Windows operating system is that many of the portability problems involved in shipping applications on Linux platforms are alleviated by the standardization of the Intel chipset. However, since scripting language programs are typically interpreted, users need to have both the scripts and the interpreters. To alleviate this problem in the case of Perl program, the ActiveState Perl Dev Kit can be used to create applications and Windows services which are standalone executables: they will run on any Windows computer, even if it doesn't have Perl installed. Similar solutions for Python and Tcl are under development.

Perl Dev Kit product information

PerlApp Creating Standalone Applications

PerlApp compiles the Perl application code, all used modules, and even the Perl interpreter itself into a single standalone executable. It is possible to add additional modules and resources to the application that might be required at runtime. The application can be marked as a GUI application, not requiring a command shell window for execution.

To conserve space, it is possible to exclude the Perl interpreter and runtime DLL from the generated executable. This makes sense when many Perl applications are wrapped with PerlApp, PerlCtrl or PerlSvc and deployed to the same computer.

Internet Information Services (IIS)

Many scripts are used in web sites. The standard web server on Windows 2000 is Internet Information Services, IIS. While porting scripts to IIS from a Linux web server is described in greater detail in the paper "Linux to Windows 2000 Scripting Portability", there are some performance points that are worthy of mention here. Windows 2000 applications run most efficiently when process creation is eschewed for thread creation. Switching to using threads instead of processes may require considerable work for many CGI systems developed on Linux. To alleviate the apparent performance penalty, two solutions are available:

PHP and Perl for ISAPI Run Perl CGI scripts in-process

ActivePerl comes with an IIS plug in, Perl for ISAPI. This allows Perl CGI programs to execute "in process" inside the IIS web server. This avoids the overhead of creating a new process for each page request and can noticeably speed up Perl CGI script. There is a similar tool for PHP.

Perl for ISAPI FAQ

The PHP ISAPI Plugin comes with PHP.

PerlEx High Speed Perl Support for IIS

For high-traffic websites, running Perl CGI programs in-process may not be fast enough. To alleviate this, the ActiveState PerlEx product can be used to provide caching of precompiled Perl scripts inside IIS, similar to the mod_perl module for the Apache web server.

PerlEx product information

Performance Notes

Overall, performance of interpreted scripts such as Perl, Python, Tcl and PHP scripts will be similar between Linux and Windows 2000, given equivalent hardware. Differences in performance are likely to be fairly minor, and due to particular system-level calls which might be implemented more or less efficiently in one operating system compared to another.

General Optimization Techniques

There are two general kinds of optimization techniques generic techniques and operating-system specific techniques. The former consists of application-specific optimizations, such as redesigning an algorithm, optimizing for common code paths, caching, precomputing results, etc. Those techniques are language and operating-system neutral, and can and should be used in any application or system in need of optimization. The second set of techniques relies on the operating system, and here Windows 2000 can help. We discuss two specifically threads and memory mapping,

The Benefits of Threads

Many users of scripting languages are unfamiliar with thread-based programming. Much like component-based programming (and complementary to it), threads offer a variety of opportunities for optimization thanks to division of tasks between different "threads of execution". A very typical architecture for a GUI application, for example, is to have a thread dedicated to the user interface, and at least one other thread dedicated to the 'business logic' of the application. These two threads communicate through well-defined synchronization points, which are hopefully rare. This allows the user interface to be very responsive and 'snappy', even if the operations performed by the program are slow (such as fetching data from a file system, network resource or a Web Service). The topic of thread-based programming is beyond the scope of this paper, but it should be noted that Windows 2000 was designed with threads in mind thus thread creation and context switches between threads are quite cheap in Windows 2000, compared to process creation. Thus, if your application appears sluggish and you suspect that process creation or inter-process communication is to blame, consider reworking the application to use multiple threads instead.

Memory Mapping

Memory mapping is a technique available in most modern operating systems by which the user specifies that some files are meant to be accessed as strings or arrays of bytes directly. Instead of having the programmer worry about actually transferring the data from disk to memory, developing efficient ways of dealing with, for example, files larger than the main memory of the computer, memory mapped files allow the operating system kernel to do that transfer and the kernel tends to do the job much better than programmers, since the kernel knows of all the demands on the CPU, disk and memory subsystems, etc.

Windows 2000 supports memory mapped files quite well, and Perl, Tcl and Python all provide interfaces to those APIs as well. For programmers dealing with large files, learning about memory mapped files can dramatically increase the performance of your programs.

Other useful Tools

We close by mentioning some useful tools which can be useful to users discovering Windows 2000.

Windows Terminal Services (TS)

Windows Terminal Services offers some of the same benefits of the X-Windows system, or of the VNC Virtual Network Computing tool. With Windows Terminal Services, full control of a machine can be performed over a network connection. While some use Windows Terminal Services as a way to run Windows application on a big server while displaying the user interface on an inexpensive client, it may make a lot of sense to install Terminal Services at least in Remote Administration mode on Windows servers. This allows administrators to open a desktop session on the server from any remote windows client on the network without requiring physical access to the machine.

Windows Terminal Services

Virtual Network Computing

Web Application Stress Test (WAST)

Another little known but very useful tool is Web Application Stress Test. It is not included in Windows 2000 but currently available as a free download from Microsoft.

As the name already implies, this tool can be used to simulate heavy load on a web server. It can be run on multiple clients simultaneously and simulates possibly thousands of users accessing the same website at the same time. User behavior can be modeled either by recording interactive sessions or by writing script files.

/downloads/details.aspx?FamilyID=e2c0585a-062a-439e-a67d-75a89aa36495&DisplayLang=en

Summary

If you are a recent immigrant to the world of Windows 2000, we hope that this paper has given you a glimpse as to the types of operating system features available to you, and how scripting languages such as Perl, Python, PHP and Tcl can help you use these features to make your code more fully integrated with the operating system and network.

For More Information

For the latest information on Windows 2000, go to the Windows 2000 Web site at http://www.microsoft.com/windows2000/

For the latest information on ActiveState products, check out the ActiveState Web site at http://www.ActiveState.com/