Link to home
Start Free TrialLog in
Avatar of prem_kumar79
prem_kumar79

asked on

WMI using native code

I am trying to find the Reboot time (LastBootUpTime) of the machine, I was using a simple VB Script file to get it but I found one of the customers has disabled VB script

Using following method due to security restriction  
http://www.windowsecurity.com/whitepapers/Windows_Scripting_Host.html

following is the VB script I use cscript to get the reboot time.

strComputer = "."

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colOperatingSystems = objWMIService.ExecQuery _
    ("Select * from Win32_OperatingSystem")
 
For Each objOS in colOperatingSystems
    dtmBootup = objOS.LastBootUpTime
    dtmLastBootupTime = WMIDateStringToDate(dtmBootup)
      Wscript.Echo "System Booted at : " & dtmLastBootupTime
Next
 
Function WMIDateStringToDate(dtmBootup)
    WMIDateStringToDate = CDate(Mid(dtmBootup, 5, 2) & "/" & _
        Mid(dtmBootup, 7, 2) & "/" & Left(dtmBootup, 4) _
            & " " & Mid (dtmBootup, 9, 2) & ":" & _
                Mid(dtmBootup, 11, 2) & ":" & Mid(dtmBootup,13, 2))
End Function

I read there is way to make a WMI call using C++ but I am not that good in native code

Can someone point me to the native code in which I can get the reboot time using a WMI call.

Thanks in advance
Avatar of Zoppo
Zoppo
Flag of Germany image

Hi prem_kumar79,

here's a code which does this in a Win32 C++ console application - don't wonder that it's much longer than the VB-code you posted; in VB it is much easier to access WMI object than in C++. Further it has complete error checking ...

Hope that helps,

ZOPPO

#include <string>
#include <sstream>
#include <iostream>
#include <Wbemidl.h>
#include <atlconv.h>
#pragma comment (lib, "wbemuuid.lib")
 
bool
GetLastBootUpTime( std::string& strValue )
{
	USES_CONVERSION;
 
	CoInitialize(NULL);
 
	bool bRet = false;
 
	if( S_OK == CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0 ) )
	{
		IWbemLocator * pIWbemLocator = NULL;
		IWbemServices * pWbemServices = NULL;
		IEnumWbemClassObject * pEnumObject  = NULL;
 
		BSTR bstrNamespace = ( L"root\\cimv2" );
 
		if( S_OK != CoCreateInstance(
				CLSID_WbemAdministrativeLocator,
				NULL,
				CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
				IID_IUnknown,
				( void ** )&pIWbemLocator
				)
			)
		{
			return false;
		}
 
		if( S_OK != pIWbemLocator->ConnectServer(
				bstrNamespace,  // Namespace
				NULL,          // Userid
				NULL,           // PW
				NULL,           // Locale
				0,              // flags
				NULL,           // Authority
				NULL,           // Context
				&pWbemServices
				)
			)
		{
			pIWbemLocator->Release();
 
			return false;
		}
 
		if ( S_OK != pWbemServices->ExecQuery(
				L"WQL",
				L"Select * from Win32_OperatingSystem",
				WBEM_FLAG_RETURN_IMMEDIATELY,
				NULL,
				&pEnumObject
				)
			)
		{
			pIWbemLocator->Release();
			pWbemServices->Release();
 
			return false;
		}
		
		ULONG uCount = 1, uReturned;
		IWbemClassObject * pClassObject = NULL;
 
		if ( S_OK != pEnumObject->Reset() )
		{
			pIWbemLocator->Release();
			pWbemServices->Release();
			pEnumObject->Release();
 
			return false;
		}
 
		VARIANT vData;
 
		while( S_OK == pEnumObject->Next( WBEM_INFINITE, uCount, &pClassObject, &uReturned ) )
		{
			if ( S_OK == pClassObject->Get( L"LastBootUpTime", 0, &vData, 0, 0 ) )
			{
				bRet = true;
 
				strValue = OLE2A( vData.bstrVal );
 
				std::stringstream ss;
 
				ss << strValue.substr( 4, 2 ) << _T( "\\" )
					<< strValue.substr( 6, 2 ) << _T( "\\" )
					<< strValue.substr( 0, 4 ) << _T( " " )
					<< strValue.substr( 8, 2 ) << _T( ":" )
					<< strValue.substr( 10, 2 ) << _T( ":" )
					<< strValue.substr( 12, 2 );
 
				strValue = ss.str();
 
				VariantClear( &vData );
 
				break;
			}
		}
 
		pIWbemLocator->Release();
		pWbemServices->Release();
		pEnumObject->Release();
		pClassObject->Release();
	}
 
	CoUninitialize();
 
	return bRet;
}
 
int _tmain( int argc, char* argv[] )
{
	std::string strTmp;
 
	if ( false != GetLastBootUpTime( strTmp ) )
	{
		std::cout << "Last boot up time: " << strTmp << std::endl;
	}
	else
	{
		std::cout << "Error: Can't retrieve last boot up time!" << std::endl;
	}
 
	return 0;
}

Open in new window

Avatar of prem_kumar79
prem_kumar79

ASKER

Thanks for the code it works fine.
I just require one more change, the current VB script gives the output like

System Booted at : 5/4/2009 9:43:43 AM

This native code gives the output like
Last boot up time: 05\04\2009 09:43:43

That is in 24 hrs format I would like to have the output in 12 hr format with AM and PM.
It will be great if you can provide me with the changes.
ASKER CERTIFIED SOLUTION
Avatar of Zoppo
Zoppo
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks a lot for your help... :)
I found when that when I try in the exe windows 2003 box the exe is not returning the time it shows
Error: Can't retrieve last boot up time!
#ifndef _WIN32_DCOM
#define _WIN32_DCOM
#endif
 
#include <string>
#include <sstream>
#include <iostream>
#include <Wbemidl.h>
#include <atlbase.h>
#pragma comment (lib, "wbemuuid.lib")
 
bool
GetLastBootUpTime( std::string& strValue )
{
	USES_CONVERSION;
 
	CoInitialize(NULL);
 
	bool bRet = false;
 
	if( S_OK == CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0 ) )
	{
		IWbemLocator * pIWbemLocator = NULL;
		IWbemServices * pWbemServices = NULL;
		IEnumWbemClassObject * pEnumObject  = NULL;
 
		BSTR bstrNamespace = ( L"root\\cimv2" );
 
		if( S_OK != CoCreateInstance(
				CLSID_WbemAdministrativeLocator,
				NULL,
				CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
				IID_IUnknown,
				( void ** )&pIWbemLocator
				)
			)
		{
			return false;
		}
 
		if( S_OK != pIWbemLocator->ConnectServer(
				bstrNamespace,  // Namespace
				NULL,          // Userid
				NULL,           // PW
				NULL,           // Locale
				0,              // flags
				NULL,           // Authority
				NULL,           // Context
				&pWbemServices
				)
			)
		{
			pIWbemLocator->Release();
 
			return false;
		}
 
		if ( S_OK != pWbemServices->ExecQuery(
				L"WQL",
				L"Select * from Win32_OperatingSystem",
				WBEM_FLAG_RETURN_IMMEDIATELY,
				NULL,
				&pEnumObject
				)
			)
		{
			pIWbemLocator->Release();
			pWbemServices->Release();
 
			return false;
		}
		
		ULONG uCount = 1, uReturned;
		IWbemClassObject * pClassObject = NULL;
 
		if ( S_OK != pEnumObject->Reset() )
		{
			pIWbemLocator->Release();
			pWbemServices->Release();
			pEnumObject->Release();
 
			return false;
		}
 
		VARIANT vData;
 
		while( S_OK == pEnumObject->Next( WBEM_INFINITE, uCount, &pClassObject, &uReturned ) )
		{
			if ( S_OK == pClassObject->Get( L"LastBootUpTime", 0, &vData, 0, 0 ) )
			{
				bRet = true;
 
				strValue = OLE2A( vData.bstrVal );
 
				std::stringstream ss;
 
				ss << strValue.substr( 4, 2 ) << ( "/" )
					<< strValue.substr( 6, 2 ) << ( "/" )
					<< strValue.substr( 0, 4 ) << ( " " )
					<< strValue.substr( 8, 2 ) << ( ":" )
					<< strValue.substr( 10, 2 ) << ( ":" )
					<< strValue.substr( 12, 2 );
 
				strValue = ss.str();
 
				VariantClear( &vData );
 
				break;
			}
		}
 
		pIWbemLocator->Release();
		pWbemServices->Release();
		pEnumObject->Release();
		pClassObject->Release();
	}
 
	CoUninitialize();
 
	return bRet;
}
 
int _tmain( int argc, char* argv[] )
{
	std::string strTmp;
 
	if ( false != GetLastBootUpTime( strTmp ) )
	{
		std::cout << "Last boot up time: " << strTmp << std::endl;
	}
	else
	{
		std::cout << "Error: Can't retrieve last boot up time!" << std::endl;
	}
 
	return 0;
}

Open in new window

Well, I don't know why this code cannot retrieve that data in Win2003, but you can simply remove that message by deleting these lines (131-134):

> else
> {
>  std::cout << "Error: Can't retrieve last boot up time!" << std::endl;
> }