Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't query SystemIndex on my own machine when I specify the machine name

I'm trying to write a simple program that would connect to remote machines and query the indexing status.

Here's the code that does it on my machine. This works OK.

using System;
using Microsoft.Search.Interop;

namespace IndexStatus
{
    class Program
    {
        static void Main(string[] args)
        {
            CSearchManager manager = new CSearchManager();
            CSearchCatalogManager catalogManager = manager.GetCatalog("SystemIndex");
            _CatalogPausedReason pReason;
            _CatalogStatus pStatus;
            Console.WriteLine(catalogManager.NumberOfItems().ToString());
            int plIncrementalCount;
            int plNotificationQueue;
            int plHighPriorityQueue;
            catalogManager.NumberOfItemsToIndex(out plIncrementalCount, out plNotificationQueue, out plHighPriorityQueue);
            Console.WriteLine(plIncrementalCount.ToString());
            Console.WriteLine(plNotificationQueue.ToString());
            Console.WriteLine(plHighPriorityQueue.ToString());
            catalogManager.GetCatalogStatus(out pStatus, out pReason);
            Console.WriteLine(pStatus.ToString() + " " + pReason.ToString());
            Console.ReadLine();
        }
    }
}

However, when I call GetCatalog on "mycomputername.SystemIndex" instead of "SystemIndex", I get

An unhandled exception of type 'System.Runtime.InteropServices.COMException' occurred in IndexStatus.exe

Additional information: Exception from HRESULT: 0x80042103

enter image description here

Visual Studio 2015 is running with admin permissions on Windows 8.1. The target computers will be Windows 7 systems mostly and the program will mostly be run from a Windows 10 system. I'm using Microsoft.Search.Interop.dll from Microsoft Windows Search 3.X SDK downloaded from here. I turned the firewall off in case that had anything to do with it, but apparently not.

I've checked that I get the same exception if I call the function on complete nonsense like "sdfd". And I've found this:

MSS_E_CATALOGNOTFOUND - 0x80042103 - (8451) WindowsSearchErrors.h

The specified catalog was not found. Check to see if it was deleted, or if there are errors in your application code.

I've tried to use "localhost" instead of the machine name, but that didn't help.

The MSDN docs say this:

Currently Microsoft Windows Desktop Search (WDS) 3.0 supports only one catalog and it is named SystemIndex.

I'm not sure how to understand this. Perhaps the method is not able to choose between different machines? If so, is there a way to connect to a remote catalog and make these queries, other than using something like PsExec?

Re Ben N's answer: This is starting to become deep water for me, but I'm more fascinated than afraid. :) Your code worked for me after several modifications:

CSearchManagerClass manager = System.Runtime.InteropServices.Marshal.CreateWrapperOfType(comManager, typeof(CSearchManagerClass));would not compile on Visual Studio 2015 and would give the following errors:

enter image description here enter image description here

The second error was easy to fix by just adding a cast:

CSearchManagerClass manager = (CSearchManagerClass)System.Runtime.InteropServices.Marshal.CreateWrapperOfType(comManager, typeof(CSearchManagerClass));

As for the "Interop type cannot be embedded" error message, I found this question. There are two suggested solutions:

  • Change the Embed Interop Types property of the Microsoft.Search.Interop reference to False.

  • Change CSearchManagerClass to CSearchManager.

The first solution makes the program compile, but it affects portability. Now the program won't run on a computer that doesn't have the .dll on it. The second solution compiles but throws

An unhandled exception of type 'System.ArgumentException' occurred in mscorlib.dll

Additional information: The type must be __ComObject or be derived from __ComObject.

on that exact line when I run it against my own machine.

But there is another problem, and this one I have no clue about. When I run it against my colleague's machine (I'm an administrator on his computer and Visual Studio is running with admin permissions), I'm getting

An unhandled exception of type 'System.UnauthorizedAccessException' occurred in mscorlib.dll

Additional information: Retrieving the COM class factory for remote component with CLSID {7D096C5F-AC08-4F1F-BEB7-5C22C517CE39} from machine computername failed due to the following error: 80070005 computername.

This does scare me a little bit because I know next to nothing about COM. I've checked that DCOM is enabled on his computer and on mine. But when I try to go to his computer in Component Services it shows as a enter image description here and DCOM Config is missing from the tree. And the same happens for other computers on the domain (even though I have admin rights on all workstations). This blog suggests it could be a firewall issue and if it is, it's not something that will be feasible to overcome.

Both of your answers are definitely bounty worthy already, but if you have any suggestions or would be able to shed some light on what's happening, I would be very grateful. If I can't make it work, it's fine, but I would definitely like to take as much knowledge as possible from this.

like image 725
Michał Masny Avatar asked Nov 09 '22 12:11

Michał Masny


1 Answers

GetCatalog doesn't support reaching out to a remote machine, but we can use COM to create a search manager object that refers to the service on the target computer.

// Assume targetMachine has the name of the target computer
Guid guid = new Guid("{7D096C5F-AC08-4F1F-BEB7-5C22C517CE39}");
Type managerType = Type.GetTypeFromCLSID(guid, targetMachine, true);
var comManager = Activator.CreateInstance(managerType);
CSearchManagerClass manager = (CSearchManagerClass)System.Runtime.InteropServices.Marshal.CreateWrapperOfType(comManager, typeof(CSearchManagerClass));

You should then the able to use manager as though it were the manager of the local machine. If there's a problem contacting the remote computer, a COMException will be thrown on the CreateInstance call.

For the PowerShell version of this, see my answer to your Super User question.

like image 149
Ben N Avatar answered Nov 14 '22 21:11

Ben N