Click here to Skip to main content
15,887,683 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
Hi,

Im looking into some struct array work with WMI for multiple devices, such as CPU, memory, hard drive etc... and i've come accross a bridge i can't seem to cross...

Basically im using WMI and querying "Win32_LogicalDisk" to gather freespace, size, etc... and backing this up to an array. The problem i have is with my SmartStatus. The Status in "Win32_LogicalDisk" is blank, so i can't query this here. The Status in "Win32_DiskDrive" however is not blank, but doesn't contain drive letters or free space. So i do need to query both.

What i need to do is add the result i get from the query on "Win32_DiskDrive"->"Status" to the data in array.

Im bad at explaining but the first query will add to the array like so:

3
C:
 <- BLANK
19658754
11235
60%


Second query will find "Status" and i need to add it to the above Blank area, so when i print the result its all there.

CODE:
C++
struct DriveInfo
{
	int		nType;
	char	DriveLetter[10];
	char	SmartStatus[50];
	float	TotalSpace;
	float	FreeSpace;
	float	PercentFree;
};

vector< ServiceInfo* >	ServiceList;
ServiceInfo	*FoundService	= NULL;

vector< DriveInfo* >	DriveList;
DriveInfo	*FoundDrive		= NULL;
UINT ContinueCommands( CXenoClientDlg *pThis )
{
	char pBuffer[100];
	int	StatusInfo;
	FoundService	=	new ServiceInfo( );
	FoundDrive		=	new DriveInfo( );

	while( true )
	{
		if( App.LoggedIn )
		{
			CWMIReader *Services = new CWMIReader( );
			if( !Services->Initialized ) { Services->Initialized = Services->Setup( ); }

			if( Services->Initialized )
			{
				if( Services->GetFirstDevice( L"Win32_Service" ) )
				{
					Services->ReadPropertyString( L"DisplayName", FoundService->Name );
					Services->ReadPropertyString( L"StartMode", FoundService->StartupType );
					Services->ReadPropertyBool( L"Started", FoundService->Started );
					if( !strcmp( FoundService->StartupType, "Auto" ) )
					{
						Tools.Log( "Service: [%s] - [%s] - [%s]", FoundService->Name, FoundService->StartupType, !strcmp( FoundService->Started, "1" ) ? "Started" : "Not Started" );

						ServiceList.push_back( FoundService );
						FoundService = new ServiceInfo;
						ZeroMemory( FoundService, sizeof( ServiceInfo ) );

						while( Services->GetNextDevice( ) )
						{
							Services->ReadPropertyString( L"DisplayName", FoundService->Name );
							Services->ReadPropertyString( L"StartMode", FoundService->StartupType );
							Services->ReadPropertyBool( L"Started", FoundService->Started );
							if( !strcmp( FoundService->StartupType, "Auto" ) )
							{
								Tools.Log( "Service: [%s] - [%s] - [%s]", FoundService->Name, FoundService->StartupType, !strcmp( FoundService->Started, "1" ) ? "Started" : "Not Started" );

								ServiceList.push_back( FoundService );
								FoundService = new ServiceInfo;
								ZeroMemory( FoundService, sizeof( ServiceInfo ) );
							}
						}

						Services->EndQuery( );
					}
				}

				if( Services->GetFirstDevice( L"Win32_LogicalDisk" ) )
				{
					Services->ReadPropertyInt( L"DriveType", pBuffer ); FoundDrive->nType = atoi( pBuffer );
					if( FoundDrive->nType == 3 )
					{
						Services->ReadPropertyString( L"DeviceID", FoundDrive->DriveLetter );
						Services->ReadPropertyString( L"Size", pBuffer ); FoundDrive->TotalSpace = atof( pBuffer )/1024.0f/1024.0f/1024.0f;
						Services->ReadPropertyString( L"FreeSpace", pBuffer ); FoundDrive->FreeSpace = atof( pBuffer )/1024.0f/1024.0f/1024.0f;
						FoundDrive->PercentFree = ( ( FoundDrive->FreeSpace / FoundDrive->TotalSpace ) * 100.0f );

						DriveList.push_back( FoundDrive );
						FoundDrive = new DriveInfo;
						ZeroMemory( FoundDrive, sizeof( DriveInfo ) );

						while( Services->GetNextDevice( ) )
						{
							Services->ReadPropertyInt( L"DriveType", pBuffer ); FoundDrive->nType = atoi( pBuffer );
							if( FoundDrive->nType == 3 )
							{
								Services->ReadPropertyString( L"DeviceID", FoundDrive->DriveLetter );
								Services->ReadPropertyString( L"Size", pBuffer ); FoundDrive->TotalSpace = atof( pBuffer )/1024.0f/1024.0f/1024.0f;
								Services->ReadPropertyString( L"FreeSpace", pBuffer ); FoundDrive->FreeSpace = atof( pBuffer )/1024.0f/1024.0f/1024.0f;
								FoundDrive->PercentFree = ( ( FoundDrive->FreeSpace / FoundDrive->TotalSpace ) * 100.0f );

								DriveList.push_back( FoundDrive );
								FoundDrive = new DriveInfo;
								ZeroMemory( FoundDrive, sizeof( DriveInfo ) );
							}
						}

						Services->EndQuery( );
					}
				}

				if( Services->GetFirstDevice( L"Win32_DiskDrive" ) )
				{
					Services->ReadPropertyString( L"MediaType", pBuffer );
					if( strstr( pBuffer, "Fixed" ) )
					{
						Services->ReadPropertyString( L"Status", FoundDrive->SmartStatus );

						while( Services->GetNextDevice( ) )
						{
							Services->ReadPropertyString( L"MediaType", pBuffer );
							if( strstr( pBuffer, "Fixed" ) )
							{
								Services->ReadPropertyString( L"Status", FoundDrive->SmartStatus );
							}
						}
						Services->EndQuery( );
					}
				}

				for( int i = 0; i < DriveList.size( ); ++i )
				{
					DriveInfo* CurrentDrive = DriveList.at( i );
					Tools.Log( "Drive %s\\ has a status of \"%s\". %.0fGB Free Space, %.0fGB Total Space. %.0f%% Free Space", CurrentDrive->DriveLetter, CurrentDrive->SmartStatus, CurrentDrive->FreeSpace, CurrentDrive->TotalSpace, CurrentDrive->PercentFree );
				}
			}

			ExitThread( 0 );
		}
	}

	return 0;
}
Posted
Updated 22-Aug-12 8:17am
v3
Comments
Legor 22-Aug-12 6:18am    
I'm not sure if i understood right. Do you want to access an element of the struct (e.g. SmartStatus) which you stored on in the vector before?
If so you can use the vector for example to access the first element like
DriveList[0]->SmartStatus;
sjsteve33171 22-Aug-12 7:27am    
I updated the question, so hopefully it will make more sense.

Thanks
JackDingler 22-Aug-12 11:16am    
I don't understand the question either.

How did you get all of the other data in there?
Would you just add another field, the same way you added the ones you have?
sjsteve33171 22-Aug-12 14:22pm    
If i run the current code the output is like so:
Drive C:\ has a status of "". 127GB Free Space, 238GB Total Space. 53% Free Space

If i alter the last query to this:
if( Services->GetFirstDevice( L"Win32_DiskDrive" ) )
{
Services->ReadPropertyString( L"MediaType", pBuffer );
if( strstr( pBuffer, "Fixed" ) )
{
Services->ReadPropertyString( L"Status", FoundDrive->SmartStatus );

DriveList.push_back( FoundDrive );
FoundDrive = new DriveInfo;
ZeroMemory( FoundDrive, sizeof( DriveInfo ) );

while( Services->GetNextDevice( ) )
{
Services->ReadPropertyString( L"MediaType", pBuffer );
if( strstr( pBuffer, "Fixed" ) )
{
Services->ReadPropertyString( L"Status", FoundDrive->SmartStatus );

DriveList.push_back( FoundDrive );
FoundDrive = new DriveInfo;
ZeroMemory( FoundDrive, sizeof( DriveInfo ) );
}
}
Services->EndQuery( );
}
}

It outputs:
Drive C:\ has a status of "". 127GB Free Space, 238GB Total Space. 53% Free Space
Drive \ has a status of "OK". 0GB Free Space, 0GB Total Space. 0% Free Space

What i want is for it to output in one like:
Drive C:\ has a status of "OK". 127GB Free Space, 238GB Total Space. 53% Free Space

1 solution

It looks like you've coded this so that you only get two entries of in 'DriveList'

You might split those into separate records.

Or just remove the for loop and change the log line:

C++
Tools.Log( "Drive %s\\ has a status of \"%s\". %.0fGB Free Space, %.0fGB Total Space. %.0f%% Free Space", 
    CurrentDrive[0]->DriveLetter, 
    CurrentDrive[1]->SmartStatus,
    CurrentDrive[0]->FreeSpace,
    CurrentDrive[0]->TotalSpace, 
    CurrentDrive[0]->PercentFree 
);


It looks messy though. I'd probably split the info into two variables with different names, to be clear on what they represent.
 
Share this answer
 
v2
Comments
sjsteve33171 22-Aug-12 14:48pm    
Is there no way to merge it into the array so in the second query merges it?

Almost instead of having

DriveList.push_back( FoundDrive );
FoundDrive = new DriveInfo;
ZeroMemory( FoundDrive, sizeof( DriveInfo ) );

Maybe do something like this:
DriveList.Append( DriveInfo->SmartStatus, FoundDrive->SmartStatus );

This is the affect im after, because although your solution will work for one drive, it's not compatible with 2 drives. The log is put within a loop that prints based on the index of the array your in.
JackDingler 22-Aug-12 15:20pm    
The way I'd do it is to define my own class to hold the data I want to keep for the drive. I'd make the DriveInfo instances, local to the portions of code that need them.

When I make the queries, I would then copy the pertinent data to that class.
After that, the queries and instance of the class could be pushed onto the array.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900