How to Enable Web Based Enterprise Management (WBEM) / Windows Management Instrumentation (WMI) for Remote Access under Windows 95, 98/98SE

System Requirements:

  • Windows 95
  • Windows 98
  • Windows 98 SE

 

The Problem:

This document outlines the steps required to connect to a Windows 98 or Windows 98 SE machine using WMI using either a Monkier (inherited session credentials) or SWbemLocator.ConnectServer (specific, stated logon credentials).

This is often difficult to achieve, especially in a domain environment or an environment where more modern versions of Windows need access to the remote WMI service.

 

More Info

Windows 95 and 98 First Edition (FE) do not ship with WBEM installed. Before you can access WMI in any form on these systems you must manually install the necessary services and resource files. This guide will show you how to properly install WMI in order to facilitate remote access connections over a Network. Please note that while this will enable WMI requests over a LAN, the settings will not discriminate between a LAN and an Internet connection. Consequently firewall technology should be employed when dealing with systems that expose a direct peer-to-peer Internet connection.

 

A Note on Windows 98 SE

While Windows 98 FE does not come with any WBEM components, Windows 98 SE does. The Windows 98 SE CD contains WBEM 1.10 components which can be installed from the Control Panel.

Windows 98 SE WBEM 1.10

It is important that you not use this version of WBEM on Windows 98 SE in order to connect remotely to the WMI service. This version of WMI is out of date (with the latest version being WBEM 1.5). Consequently if you are using Windows 98 SE, ensure that you have uninstalled ‘Web-Based Enterprise Mgmt’ from the Control Panel before following this guide.

More Info: WMI on computers running Windows 98, 98SE and Windows Millennium Edition

 

The Fix

The steps below will enable you to connect remotely over WMI under some circumstances (but not all). These steps must be applied to install WMI and configure it before you can change the advanced remote connection settings.

  1. Install DCOM 1.3 and do not reboot after the installation
    DCOM 1.3 Installer
  2. Install WMI 1.5 for Windows 9x
  3. When prompted, reboot the computer

Unlike the Windows NT installation of WMI, the WMI 1.5 installer does not include the rather useful DCOMCnfg.exe utility that is required for GUI configuration of WMI for remote access. Thankfully the DComConfig utility was made available separately for Windows 9x.

 

DCOM Config Installer

Configure DCOM

To configure DCOM run the DCOMCnfg utility found in c:\windows\system

DComCfg Utility Launch

  1. By default the “Enable Distributed COM on this computer” check box on the Default Properties tab should be ticked. Often if WMI isn’t working, this has inexplicably become unchecked, disabling DCOM completely.DcomCnfg Screen 1
  2. This will enable WMI to run on the local computer, but not from remote network connections. To enable the basic level of remote access check the “Enable remote connection” box on the Default Security tab. If this doesn’t work for you, keep reading!DcomCnfg Screen 2
  3. Restart the computer.

It is important to understand that unlike with Windows NT, Windows 9x doesn’t have the concept of a special system service. Consequently DCOM won’t start WMI when it is requested from the network. In order to enable on-demand access the WinMgmt.exe program in c:\windows\system\wbem needs to be running.

WinMgmt

This dos prompt command will run the process for the duration of the session. You can always confirm that it is running by pressing Ctrl + Alt + Del once and viewing the task manager.

WinMgmt Process in Ctrl + Alt + Del Screen

If you want to persistently run WinMgmt.exe as a ‘Service’ add the following information to the registry as shown.

 

Setup WinMgmt as a start service

Advanced Remote Access Settings

The above settings should work between NTLM enabled Windows 9x boxes and NT 4 systems, however you may have problems if the Active Directory extensions are installed or if you are attempting to connect from a Windows 2000, XP, 2003, Vista, 2008 or 7 machine.

Connection difficulties seem particularly true if you are using SWbemLocator.ConnectServer or are in any way connecting via IIS.

Do appreciate that this guide isn’t covering more basic things like “synchronise your accounts and passwords” between workgroup systems, ensure that you have IE 6.0 SP1 installed or that you have Windows Scripting Host 5.6 installed and so on.

First off, re-register the WinMgmt stack using the following command in the c:\windows\system folder

RegSvr Command for WMI

WBEM ships with an additional configuration utility, the WBEM Control app, found in c:\windows\system\wbem\

wbemcntl.exe

On the advanced tab enable the “Enable Anonymous Connection with share level security” setting and restart the computer.

Enable Anonymous Share Access

This setting allows WMI to respond to network requests that do not carry the required account credentials registered as having access to the WMI class hierarchy.

If you are now able to connect using SWbemLocator.ConnectServer you may like to try to reconfigure WMI to use WMICntl to assign permissions to WMI. To do that simply use the Security tab and, selecting Root, press the Security button and add in the user accounts that you want to gain remote access with to the security permissions list.

WMI Control Security

All being well, you should now have a working Windows 98 machine which supports Remote WMI from modern Windows systems.

If you would like to enable all of these settings without launching their respective utilities, you can use this registry script to automatically configure workstations with the remote access settings.

REGEDIT4

[HKEY_LOCAL_MACHINE\Software\Microsoft\OLE]
"EnableDCOM"="Y"
"EnableRemoteConnect"="Y"

[HKEY_LOCAL_MACHINE\Software\Microsoft\WBEM\CIMOM]
"EnableAnonConnections"="1"
"EnableStartupHeapPreallocation"=dword:00000000

[HKEY_LOCAL_MACHINE\Software\Microsoft\WBEM\Scripting]
"Enable for ASP"=dword:00000000

[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunServices]
"WinMgmt"="C:\\Windows\\System\\WBem\\WinMgmt.exe"

 

See Also

View: How to Enable Web Based Enterprise Management (WBEM) / Windows Management Instrumentation (WMI) for Remote Access under Windows NT 4.0

View: How to Enable Web Based Enterprise Management (WBEM) / Windows Management Instrumentation (WMI) for Remote Access under Windows Millennium Edition

ISO 3166-1 County & Nation State Data Stores

System Requirements:

  • A Country Code Problem
  • Text/CSV Viewer, Excel 2003, Access 2003

The Problem:

If you have ever been mildly curious over the country ID listing, or ever engaged in a project where language identification was important having to come up with a digital list of the global nation states can be a time consuming business.

This article simply saves you the time, having had me spend the time compile the list for you!

The Fix

If you need the country list, you can use my files below as a base for your project.

The data source has been taken from the latest revision of the ISO public states list (ISO 3166-1) registry, so any errors are universally the ISO’s problem if indeed there are any.

I have made the following three files available:

  • Comma Separated Variable (CSV) Text File
  • Office Excel 2010 Spreadsheet
  • Office Access 2003 Database

The CSV contains:

  1. Country Code
  2. Country Name
  3. 2 digit Alpha Numeric Code
  4. 3 digit Alpha Numeric Code

The Spreadsheet and MDB Database contain:

  1. Country Code
  2. Country Name
  3. 2 digit Alpha Numeric Code
  4. 3 digit Alpha Numeric Code

 

Download: CSV, Excel 2010, Access 2003 (42KB)

You may also be interested in my stores for RFC 1766 International Language Identification Codes.

Microsoft JET Database Engine error ‘80040e21’ – Multiple-step OLE DB operation generated errors. Check each OLE DB status value, if available. No work was done.

System Requirements:

  • Windows NT 4.0
  • Windows 2000
  • Windows XP
  • Windows Server 2003
  • Windows Vista
  • Windows Server 2008
  • Windows 7

The Problem:

When you attempt to connect to a Microsoft Access database using the ODBC provider Microsoft.Jet.OLEDB.4.0 you receive the error message:

Microsoft JET Database Engine error ‘80040e21’
Multiple-step OLE DB operation generated errors. Check each OLE DB status value, if available. No work was done./path/file.asp, line ##

 

More Information:

There are a number of issues that can cause this error, they are poorly documented elsewhere online but the information is there; connection string, registry values slightly offset and so fourth. This document deals with one specific issue which is related to the idea of this being caused by an incompatible type value.

The chances of you running into this are quite extreme, however it is an issue in JET (Microsoft Access) that doesn’t exist in Microsoft SQL Server and thus if you are dealing with code transitioning you may want to know about the problem in this very extreme and unlikely situation.

You shouldn’t need to reboot to solve the problem, it didn’t in my case. However, if nothing happens do restart before progressing to the next step.

SQL Example

The following SQL Statement will execute on Microsoft SQL Server and return a RecordSet however the same SQL on JET 4.0 will result in the error message outlined above.

SELECT
Student.StudentID,
Student.FirstName,
Student.LastName,
Student.EMail,
null AS studentPhotoBLOB,
Left(StudentID,1) AS YearPrefix
FROM Student;

No, it isn’t the T-SQL LEFT() statement that is the problem. The issue lies in the “null AS studentPhotoBLOB”.

The idea behind this is that space has been reserved in the record set. Why would you want to do this? If you want to drop the record set directly into an array, then ADO can do this for you using the GetRecords method. However if you want to change the structure you have to re-parse the array and relocate the data into a new structure. You can inset a null named record and use the space in the GetRecords array later for other purposes.

The problem here is that null is not a data type that is supported by JET; it is supported by Microsoft SQL Server however.

The simplest way to remedy the situation is to either change the SQL or dynamically detect JET to change the variable type to a commonly supported data type, for example a String.

SELECT
Student.StudentID,
Student.FirstName,
Student.LastName,
Student.EMail,
” AS studentPhotoBLOB,
Left(StudentID,1) AS YearPrefix
FROM Student;

This is naughty, however in a weak typed language such as ASP it isn’t a real problem given the situation outlined above. The use of ” instead of null forces the data type of the column into a string and thus it can be parsed by JET.

Returning multiple rows from a SQL generated record set as a concatenated string value using SQL in Microsoft Access

System Requirements:

  • Microsoft Access 97, 2000, 2002 (XP), 2003, 2007

The Problem:

If you have a one to many relationship in your database and you want to query the following (rudimentary and fairly poor) information:

table_Year

ID YearCode
1 2008
2 2009
3 2010

table_Semster

YearCode Semester
2008 A
2009 A
2009 B
2010 A
2010 B
2010 C

The query of:
SELECT table_Semester.YearCode, table_Semester.Semester FROM table_Semester WHERE table_Semester.YearCode = table_Year.YearCode AND table_Year.ID = 2;

Returns:

YearCode Semester
2009 A
B

But what if you (for some reason, the why here is your own business) want to return:

YearCode Semester
2009 A,B

or even just

2009 AB

 

More Information:

Larger database management systems such as MySQL, Oracle and Microsoft SQL Server can utilise built-in functions, stored procedures or cursor based logic to create a string from multiple rows, however Access is not powerful enough to support this.

However, it is possible (although not necessarily ideal) to retrieve a single string value from a one-to-many record set in access under one condition:

It only works IF there is a finite and definable number of “many” values.

Take the example above. An academic year has three semesters. Semester A, B and C. We have three values which we can enumerate as being true. As a consequence we can create a concatenated string output using a SQL SELECT statement similar to the following:

SELECT DISTINCT (

SELECT tblYear.YearCode, table_Semester.SemesterCode
FROM table_Year, table_Semester
WHERE (((table_Year.YearCode = table_Semester.Yearcode AND table_Year.ID = tblYear.ID AND SemesterCode=’A’)

) & (

SELECT table_Semester.SemesterCode
FROM table_Year, table_Semester
WHERE (((table_Year.YearCode = table_Semester.Yearcode AND table_Year.ID = tblYear.ID AND SemesterCode=’B’)

) & (

SELECT table_Semester.SemesterCode
FROM table_Year, table_Semester
WHERE (((table_Year.YearCode = table_Semester.Yearcode AND table_Year.ID = tblYear.ID AND SemesterCode=’C’)

) AS strSemester
FROM table_Year tblYear
WHERE tblYear.ID = 1 ;

What we are doing here is defining that there are three known options, searching for each option against the record sets join. Note the redefinition of table_Year as tblYear.

Each sub query returns a single permissible value from the many relationship and concatenates it to a string named “strSemester” (using the & character). The result of executing the query above would be:

YearCode Semester
2009 AB

If you wanted comma’s to separate the Semesters you would have to use

) & “, ” & (

This on its own would of course return excess commas on the example above, i.e.

YearCode Semester
2009 A,B,

Now, I can hear database administrators across the planet groaning right now, and yes I concur… but like I said above, the “why” that prompted you to do this is your own business. So I have no qualms in making this worse than it already is.

If you wanted to return the above without the stray comma’s at the end you would have to augment the SQL statement thusly:

SELECT DISTINCT (

SELECT tblYear.YearCode, table_Semester.SemesterCode
FROM table_Year, table_Semester
WHERE (((table_Year.YearCode = table_Semester.Yearcode AND table_Year.ID = tblYear.ID AND SemesterCode=’A’)

) & (SELECT “, ” as strComma FROM Faculty WHERE (
SELECT table_Semester.SemesterCode
FROM table_Year, table_Semester
WHERE (((table_Year.YearCode = table_Semester.Yearcode AND table_Year.ID = tblYear.ID AND SemesterCode=’A’)) <> NULL;
) & (

SELECT table_Semester.SemesterCode
FROM table_Year, table_Semester
WHERE (((table_Year.YearCode = table_Semester.Yearcode AND table_Year.ID = tblYear.ID AND SemesterCode=’B’)

) & (SELECT “, ” as strComma FROM Faculty WHERE (
SELECT table_Semester.SemesterCode
FROM table_Year, table_Semester
WHERE (((table_Year.YearCode = table_Semester.Yearcode AND table_Year.ID = tblYear.ID AND SemesterCode=’C’)) <> NULL;
) & (

SELECT table_Semester.SemesterCode
FROM table_Year, table_Semester
WHERE (((table_Year.YearCode = table_Semester.Yearcode AND table_Year.ID = tblYear.ID AND SemesterCode=’C’)

) AS strSemester
FROM table_Year tblYear
WHERE tblYear.ID = 1 ;

The horror of the above isn’t as complicated as it looks. We test for Semester A where the ID = 1 and send the result OR Null to the string. We then test it again, but this time we only send a result – the comma – back when the result is not Null, that means that if there is an instance of A the result is written out as:

A,

Repeat for B, but this time only if there is an instance of C the result is written out as:

B,

Giving us a not quite flawless answer (more tests are needed to cover every combination).For the example however the result would be:

YearCode Semester
2009 A,B

With no trailing comma!