3

I've been trying to figure out a way to get information on the indexing progress programmatically (how many files to go or "indexing complete"). I stumbled upon the class Win32_PerfFormattedData_WSearchIdxPi_SearchIndexer and was surprised by the number of zeros it showed me, especially the zero next to "IndexSize".

enter image description here

Indexing Options show 5055 items indexed so, to my simple mind, the size of the index should be nonzero.

enter image description here

What is the information these zeros represent? Am I not looking at the right class? If I am, should I do something to get different numbers?

This is on Windows 8.1, but the computers I'd actually like to do things like this on are Windows 7 and Windows 10 systems.

I'm working from a Windows 10 machine right now, and it looks a bit different. ActiveConnections shows 2 instead of 0 here. I've also noticed that on both computers some of the properties missing in FormattedData, Frequency_Sys100NS, are shown in RawData:

RawData:

PS C:\WINDOWS\system32> gwmi Win32_PerfRawData_WSearchIdxPi_SearchIndexer


__GENUS                    : 2
__CLASS                    : Win32_PerfRawData_WSearchIdxPi_SearchIndexer
__SUPERCLASS               : Win32_PerfRawData
__DYNASTY                  : CIM_StatisticalInformation
__RELPATH                  : Win32_PerfRawData_WSearchIdxPi_SearchIndexer.Name="SystemIndex"
__PROPERTY_COUNT           : 72
__DERIVATION               : {Win32_PerfRawData, Win32_Perf, CIM_StatisticalInformation}
__SERVER                   : WRW-MXM0121
__NAMESPACE                : root\cimv2
__PATH                     : \\WRW-MXM0121\root\cimv2:Win32_PerfRawData_WSearchIdxPi_SearchIndexer.Name="SystemIndex"
ActiveConnections          : 2
Caption                    : 
CleanWidSets               : 0
Description                : 
DirtyWidSets               : 0
DocumentsFiltered          : 0
Frequency_Object           : 0
Frequency_PerfTime         : 0
Frequency_Sys100NS         : 10000000
IndexSize                  : 0
L0IndexesWordlists         : 1
L0MergeFlushCount          : 0
L0MergeFlushSpeedAverage   : 0
L0MergeFlushSpeedLast      : 0
L0MergesflushesNow         : 0
L1MergeCount               : 0
L1MergesNow                : 0
L1MergeSpeedaverage        : 0
L1MergeSpeedlast           : 0
L2MergeCount               : 0
L2MergesNow                : 0
L2MergeSpeedaverage        : 0
L2MergeSpeedlast           : 0
L3MergeCount               : 0
L3MergesNow                : 0
L3MergeSpeedaverage        : 0
L3MergeSpeedlast           : 0
L4MergeCount               : 0
L4MergesNow                : 0
L4MergeSpeedaverage        : 0
L4MergeSpeedlast           : 0
L5MergeCount               : 0
L5MergesNow                : 0
L5MergeSpeedaverage        : 0
L5MergeSpeedlast           : 0
L6MergeCount               : 0
L6MergesNow                : 0
L6MergeSpeedaverage        : 0
L6MergeSpeedlast           : 0
L7MergeCount               : 0
L7MergesNow                : 0
L7MergeSpeedaverage        : 0
L7MergeSpeedlast           : 0
L8MergeCount               : 0
L8MergesNow                : 0
L8MergeSpeedaverage        : 0
L8MergeSpeedlast           : 0
MasterIndexLevel           : 0
MasterMergeProgress        : 0
MasterMergesNow            : 0
MasterMergestoDate         : 0
Name                       : SystemIndex
PersistentIndexes          : 4
PersistentIndexesL1        : 0
PersistentIndexesL2        : 0
PersistentIndexesL3        : 0
PersistentIndexesL4        : 0
PersistentIndexesL5        : 0
PersistentIndexesL6        : 0
PersistentIndexesL7        : 0
PersistentIndexesL8        : 0
Queries                    : 520
QueriesFailed              : 1
QueriesSucceeded           : 519
ShadowMergeLevels          : 0
ShadowMergeLevelsThreshold : 0
Timestamp_Object           : 0
Timestamp_PerfTime         : 0
Timestamp_Sys100NS         : 131122139817760000
UniqueKeys                 : 0
WorkItemsCreated           : 0
WorkItemsDeleted           : 0
PSComputerName             : WRW-MXM0121

FormattedData:

PS C:\WINDOWS\system32> gwmi Win32_PerfRawData_WSearchIdxPi_SearchIndexer
__GENUS                    : 2
__CLASS                    : Win32_PerfFormattedData_WSearchIdxPi_SearchIndexer
__SUPERCLASS               : Win32_PerfFormattedData
__DYNASTY                  : CIM_StatisticalInformation
__RELPATH                  : Win32_PerfFormattedData_WSearchIdxPi_SearchIndexer.Name="SystemIndex"
__PROPERTY_COUNT           : 72
__DERIVATION               : {Win32_PerfFormattedData, Win32_Perf, CIM_StatisticalInformation}
__SERVER                   : WRW-MXM0121
__NAMESPACE                : root\cimv2
__PATH                     : \\WRW-MXM0121\root\cimv2:Win32_PerfFormattedData_WSearchIdxPi_SearchIndexer.Name="SystemIn
                             dex"
ActiveConnections          : 2
Caption                    : 
CleanWidSets               : 0
Description                : 
DirtyWidSets               : 0
DocumentsFiltered          : 0
Frequency_Object           : 
Frequency_PerfTime         : 
Frequency_Sys100NS         : 
IndexSize                  : 0
L0IndexesWordlists         : 1
L0MergeFlushCount          : 0
L0MergeFlushSpeedAverage   : 0
L0MergeFlushSpeedLast      : 0
L0MergesflushesNow         : 0
L1MergeCount               : 0
L1MergesNow                : 0
L1MergeSpeedaverage        : 0
L1MergeSpeedlast           : 0
L2MergeCount               : 0
L2MergesNow                : 0
L2MergeSpeedaverage        : 0
L2MergeSpeedlast           : 0
L3MergeCount               : 0
L3MergesNow                : 0
L3MergeSpeedaverage        : 0
L3MergeSpeedlast           : 0
L4MergeCount               : 0
L4MergesNow                : 0
L4MergeSpeedaverage        : 0
L4MergeSpeedlast           : 0
L5MergeCount               : 0
L5MergesNow                : 0
L5MergeSpeedaverage        : 0
L5MergeSpeedlast           : 0
L6MergeCount               : 0
L6MergesNow                : 0
L6MergeSpeedaverage        : 0
L6MergeSpeedlast           : 0
L7MergeCount               : 0
L7MergesNow                : 0
L7MergeSpeedaverage        : 0
L7MergeSpeedlast           : 0
L8MergeCount               : 0
L8MergesNow                : 0
L8MergeSpeedaverage        : 0
L8MergeSpeedlast           : 0
MasterIndexLevel           : 0
MasterMergeProgress        : 0
MasterMergesNow            : 0
MasterMergestoDate         : 0
Name                       : SystemIndex
PersistentIndexes          : 4
PersistentIndexesL1        : 0
PersistentIndexesL2        : 0
PersistentIndexesL3        : 0
PersistentIndexesL4        : 0
PersistentIndexesL5        : 0
PersistentIndexesL6        : 0
PersistentIndexesL7        : 0
PersistentIndexesL8        : 0
Queries                    : 523
QueriesFailed              : 1
QueriesSucceeded           : 522
ShadowMergeLevels          : 0
ShadowMergeLevelsThreshold : 0
Timestamp_Object           : 
Timestamp_PerfTime         : 
Timestamp_Sys100NS         : 
UniqueKeys                 : 0
WorkItemsCreated           : 0
WorkItemsDeleted           : 0
PSComputerName             : WRW-MXM0121

And here's an example of what the Search Indexer performance counters look like in mmc.exe (this is again on the Windows 10 computer, but it looks the same on the the Windows 8.1 computer). It's just a vertical line moving across the screen - the counter is Index Size in this case.

enter image description here

And a screenshot from Powershell's get-counter in action:

enter image description here

2 Answers 2

3
+50

That WMI class appears to be broken in some way. Fortunately, there's a workaround, though it does involve a bit more work. You'll need to download the Windows Search 3 SDK. It's just a self-extracting ZIP, and you can put the files wherever you like. We're only interested in one, Microsoft.Search.Interop.dll under the Managed folder. Load that DLL into PowerShell:

Add-Type -Path "Microsoft.Search.Interop.dll"

Then you need a search manager object. If you want to get the one for the local machine, it's just this:

$manager = New-Object Microsoft.Search.Interop.CSearchManagerClass

If you want to access a remote machine, it's time for a detour.


We'll need the GUID of the COM class, which I extracted from some C header somewhere:

$guid = New-Object guid "{7D096C5F-AC08-4F1F-BEB7-5C22C517CE39}"

And we'll create the COM type in such a way that Windows will do the RPC for us:

$managerType = [Type]::GetTypeFromCLSID($guid, $targetMachine, $true)

Instantiate the type:

$comManager = [Activator]::CreateInstance($managerType)

Turn that COM object back into a normal .NET object:

$manager = [System.Runtime.InteropServices.Marshal]::CreateWrapperOfType($comManager, [Microsoft.Search.Interop.CSearchManagerClass])

Detour complete. That object will now refer to the search manager of the target machine.


Then get the catalog object for the main catalog:

$cat = $manager.GetCatalog("SystemIndex")

The GetCatalogStatus function tells you whether it's currently indexing, but that function uses "out" parameters, so we need to pass references:

$indexStatus = 0
$indexPauseReason = 0
$cat.GetCatalogStatus([ref]$indexStatus, [ref]$indexPauseReason)

Those two variables now contain a vaguely human-readable status if you force them to be strings. [string]$indexStatus currently produces CATALOG_STATUS_PAUSED for me. If the indexer is paused, that second variable is the reason it's not doing work.

Getting the number of items indexed is pretty easy:

$cat.NumberOfItems()

Windows is presumably done indexing when there are no more things left to index, so we'll use the NumberOfItemsToIndex function, again with references:

$incrementalCount = 0
$notificationQueue = 0
$highPriQueue = 0
$cat.NumberOfItemsToIndex([ref]$incrementalCount, [ref]$notificationQueue, [ref]$highPriQueue)

If all three of those variables come out zero, then indexing is complete.

All of these functions give the expected/correct results on Windows 8.1, while WMI does for me the same thing it did for you.

5
  • Thank you for this answer. I actually asked a separate question about this on StackOverflow. The problem with this is that it doesn't seem to be able to connect to a remote catalog. (+1 of course) Jul 6, 2016 at 23:16
  • Ah, I didn't know that was a requirement. One way to do it would be to wrap the whole script in an Invoke-Command: Invoke-Command -ComputerName server1, server2 { <commands here> }. Anything you return from that script block will appear at the local machine. Unfortunately, the DLL will need to be placed on a network share or otherwise made accessible to all targets.
    – Ben N
    Jul 6, 2016 at 23:46
  • That's a good idea, thanks. I've tested the program from the other question with PsExec too and it also works OK. It would just be nice to have something that isn't a hack :) Are you saying that there's no way to use that DLL (or some other one) to connect to a remote computer? If I knew how that GetCatalog method is implemented maybe I could just extend it somehow, but neither do I know how to find that out nor am I a C++ programmer... I'll be putting a bounty on the other question, in case you feel like answering. Jul 6, 2016 at 23:55
  • @ymar Unfortunately, I can't find a single instance on the Internet in which people have successfully used that interface (either in C++ or .NET) to work with a remote machine.
    – Ben N
    Jul 6, 2016 at 23:56
  • @ymar I updated my answer with a detour for remote machines. It will almost certainly require both computers to be part of the same domain and that the script run as administrator. It works for me when I specify my own computer's name as the target, but I don't have a domain to test on here.
    – Ben N
    Jul 7, 2016 at 17:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .