Batch script to configure Paths for Indexed Locations

Discussion in 'Scripting' started by AeonX, Apr 28, 2019.

  1. AeonX

    AeonX MDL Senior Member

    May 24, 2013
    404
    252
    10
    Is it possible to configure the paths indexed by Windows Search using a batch script? What commands do I need?

    I tried to monitor registry changes with the RegistryChangesView but it is not very simple to understand the logic of the changes. I tried some group policies too but they did not work out as I would like.

    I want the only indexed path after installing Windows to be:
    Code:
    C:\ProgramData\Microsoft\Windows\Start Menu
    Or (preferably):
    Code:
    %ProgramData%\Microsoft\Windows\Start Menu
     
  2. Thomas Dubreuil

    Thomas Dubreuil MDL Member

    Aug 29, 2017
    212
    325
    10
    You can use Group Policy to "include" some paths or "exlude" others from indexation, but you can't remove default paths and rules already set from Indexing Options.
    I think is possible with Powershell and calling Interop .dll but documentation is quite rare and obscure...
    deserves a look at it :)
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  3. Thomas Dubreuil

    Thomas Dubreuil MDL Member

    Aug 29, 2017
    212
    325
    10
    #3 Thomas Dubreuil, May 6, 2019
    Last edited: May 13, 2019
    After a few tests, here you go... ;)
    Download Microsoft.Search.Interop.dll from here and place it next to the script.

    Code:
    @echo off
    
    setlocal
    set start=%time%
    set "scriptname=%TEMP%\SearchScopeTask.ps1"
    set "lock=%TEMP%\wait%random%.lock"
    cd /d "%~dp0"
    
    :: Get SID
       for /f "tokens=1,2 delims==" %%s IN ('wmic path win32_useraccount where name^='%username%' get sid /value ^| find /i "SID"') do set "SID=%%t"
    
    :: Make PS Script
       :: Call catalog
       @echo Add-Type -path "%~dp0Microsoft.Search.Interop.dll">>%scriptname%
       @echo $sm = New-Object Microsoft.Search.Interop.CSearchManagerClass>>%scriptname%
       @echo $catalog = $sm.GetCatalog^("SystemIndex"^)>>%scriptname%
       @echo $crawlman = $catalog.GetCrawlScopeManager^(^)>>%scriptname%
       :: Reset rules
       @echo $crawlman.RevertToDefaultScopes^(^)>>%scriptname%
       @echo $crawlman.SaveAll^(^)>>%scriptname%
       :: Remove rules
       @echo $crawlman.RemoveDefaultScopeRule^("file:///C:\Users\*"^)>>%scriptname%
       @echo $crawlman.SaveAll^(^)>>%scriptname%
       @echo $crawlman.RemoveDefaultScopeRule^("file:///C:\ProgramData\Microsoft\Windows\Start Menu\*"^)>>%scriptname%
       @echo $crawlman.SaveAll^(^)>>%scriptname%
       @echo $crawlman.RemoveDefaultScopeRule^("file:///C:\Users\*\AppData\Local\Microsoft\Windows\Temporary Internet Files\*"^)>>%scriptname%
       @echo $crawlman.SaveAll^(^)>>%scriptname%
       @echo $crawlman.RemoveDefaultScopeRule^("file:///C:\Users\*\AppData\Local\Temp\*"^)>>%scriptname%
       @echo $crawlman.SaveAll^(^)>>%scriptname%
       @echo $crawlman.RemoveDefaultScopeRule^("file:///C:\Users\*\AppData\*"^)>>%scriptname%
       @echo $crawlman.SaveAll^(^)>>%scriptname%
       @echo $crawlman.RemoveDefaultScopeRule^("iehistory://{%SID%}"^)>>%scriptname%
       @echo $crawlman.SaveAll^(^)>>%scriptname%
       :: Add start menu path
       @echo $crawlman.AddUserScopeRule^("file:///%ProgramData%\Microsoft\Windows\Start Menu\*",$true,$false,$null^)>>%scriptname%
       @echo $crawlman.SaveAll^(^)>>%scriptname%
       :: Remove automatically added favorites
       @echo $crawlman.RemoveDefaultScopeRule^("file:///%UserProfile%\Favorites\*"^)>>%scriptname%
       @echo $crawlman.SaveAll^(^)>>%scriptname%
       :: Reindex
       @echo $Catalog.Reindex^(^)>>%scriptname%
       :: Delete lock file
       @echo Remove-Item "%lock%">>%scriptname%
    
    :: Execute Task
       :: Create lock file
       @echo Locked>"%lock%"
       :: Launch ps script with admin and hidden
       PowerShell -NoProfile -ExecutionPolicy Bypass -c "& {Start-Process Powershell -ArgumentList '-ExecutionPolicy Unrestricted -File "%scriptname%" -force' -Verb RunAs -WindowStyle hidden}" >NUL 2>&1
       :: loop until lock file is deleted
       :Wait
       if exist "%lock%" goto :Wait
    
    :: Clean
       del "%scriptname%" /s /q >NUL 2>&1
    exit /b
    
    If you want to add more custom paths, here's an "interactive" (=not "post-install") hybrid script with a fancy browser :)

    Note: couldn't write the escape characters, so for the titles and colors to show/work,
    replace at lines 12, 15 and 145 ESC and BEL by "real" ESC and BEL signs (ANSI escape code 27 and 7: holding ALT key and type 027 or 07 in text editors).

    Edit: Added a little menu at start so user can choose to either set custom locations, add only windows start menus, reset to default, or remove everything from indexing options. :)

    Code:
    @if (@CodeSection == @Batch) @then
    
    
    @echo off
    setlocal
    set "Clean=OFF"
    set "Index=0"
    set "IndexedFolder="
    set "tmpfolder=%TEMP%\Indexing_Options_%random%.tmp"
    set "lock=%tmpfolder%\wait%random%.lock"
    set "scriptname=%tmpfolder%\SearchScopeTask.ps1"
    set "Shell_Title=ESC]0;Indexing OptionsBEL"
      
       mkdir "%tmpfolder%" >NUL 2>&1
       echo ESC[97m%Shell_Title%ESC[97m
       cls
       cd /d "%~dp0"
    
    :SmallMenu
       echo 1. Set custom locations& echo:
       echo 2. Add Windows start menus only& echo:
       echo 3. Remove all locations from indexing options& echo:
       echo 4. Default indexing options settings& echo: & echo:
       choice /c 12340 /n /m "Select your option, or 0 to exit: "
       if errorlevel 5 ( set "Clean=ON" & goto :Clean)
       if errorlevel 4 ( set "Style=default" & cls & goto :ScopeTask)
       if errorlevel 3 ( set "Style=reset" & cls & goto :ScopeTask)
       if errorlevel 2 ( set "Style=startmenus" & cls & goto :ScopeTask)
       if errorlevel 1 ( set "Style=custom" & goto :PathSelection)
       goto :eof
    
    :PathSelection
       setlocal EnableDelayedExpansion
       for /F "delims=" %%a in ('CScript //nologo //E:JScript "%~F0" "Select the folder or type the path you want to index, then click OK."') do (
           if %Index%==0 ( cls & set "IndexedFolder=%%a") else ( set "Index2_%Index%=%%a")
       )
       if "%IndexedFolder%" == "" ( cls & goto :SmallMenu)
       if %Index%==0 ( echo You selected "%IndexedFolder%") else ( echo You selected "!Index2_%Index%!")
       <nul set /p dummyName=Do you want to add another path to indexed locations? [Y/N]
       choice /C:YN /M "" >NUL 2>&1
       if errorlevel 2 ( echo No& goto :PathResult)
       set /a "Index+=1"
       echo Yes
       goto :PathSelection
    
    :PathResult
       echo:
       if %Index%==0 (
           echo Indexed location is "%IndexedFolder%"
           goto :SetCount
       )
       echo Indexed locations are
       echo "%IndexedFolder%"
    :SetCount
       set /a "Count=%Index%"
    
    :ResultLoop
       if "%Count%" == "0" ( echo: & goto :ScopeTask)
       set "Index2=!Index2_%Count%!"
       echo "%Index2%"
       set /a "Count-=1"
       goto :ResultLoop
    
    :ScopeTask
    :: Get SID
       <nul set /p dummyName=Setting Indexing Options...
       for /f "tokens=1,2 delims==" %%s IN ('wmic path win32_useraccount where name^='%username%' get sid /value ^| find /i "SID"') do set "SID=%%t"
    :: Make PS Script
       @echo Add-Type -path "%~dp0Microsoft.Search.Interop.dll">>%scriptname%
       @echo $sm = New-Object Microsoft.Search.Interop.CSearchManagerClass>>%scriptname%
       @echo $catalog = $sm.GetCatalog^("SystemIndex"^)>>%scriptname%
       @echo $crawlman = $catalog.GetCrawlScopeManager^(^)>>%scriptname%
       :: Reset rules
       @echo $crawlman.RevertToDefaultScopes^(^)>>%scriptname%
       @echo $crawlman.SaveAll^(^)>>%scriptname%
       :: Remove default rules
       if "%Style%" == "default" ( goto :MakeDefault)
       @echo $crawlman.RemoveDefaultScopeRule^("file:///C:\Users\*"^)>>%scriptname%
       @echo $crawlman.SaveAll^(^)>>%scriptname%
       @echo $crawlman.RemoveDefaultScopeRule^("file:///C:\ProgramData\Microsoft\Windows\Start Menu\*"^)>>%scriptname%
       @echo $crawlman.SaveAll^(^)>>%scriptname%
       @echo $crawlman.RemoveDefaultScopeRule^("file:///C:\Users\*\AppData\Local\Microsoft\Windows\Temporary Internet Files\*"^)>>%scriptname%
       @echo $crawlman.SaveAll^(^)>>%scriptname%
       @echo $crawlman.RemoveDefaultScopeRule^("file:///C:\Users\*\AppData\Local\Temp\*"^)>>%scriptname%
       @echo $crawlman.SaveAll^(^)>>%scriptname%
       @echo $crawlman.RemoveDefaultScopeRule^("file:///C:\Users\*\AppData\*"^)>>%scriptname%
       @echo $crawlman.SaveAll^(^)>>%scriptname%
       @echo $crawlman.RemoveDefaultScopeRule^("iehistory://{%SID%}"^)>>%scriptname%
       @echo $crawlman.SaveAll^(^)>>%scriptname%
       if "%Style%" == "default" ( goto :MakeDefault)
       if "%Style%" == "reset" ( goto :Finish_Ps)
       if "%Style%" == "startmenus" ( goto :AddStartMenus)
       if "%Style%" == "custom" ( goto :SetCustomPaths)
      
       :MakeDefault
       @echo $crawlman.AddUserScopeRule^("file:///C:\Users\*",$true,$false,$null^)>>%scriptname%
       @echo $crawlman.SaveAll^(^)>>%scriptname%
       @echo $crawlman.AddUserScopeRule^("file:///C:\ProgramData\Microsoft\Windows\Start Menu\*",$true,$false,$null^)>>%scriptname%
       @echo $crawlman.SaveAll^(^)>>%scriptname%
       @echo $crawlman.AddUserScopeRule^("iehistory://{%SID%}",$true,$false,$null^)>>%scriptname%
       @echo $crawlman.SaveAll^(^)>>%scriptname%  
       goto :Reindex
      
       :AddStartMenus
       :: Add start menu locations
       @echo $crawlman.AddUserScopeRule^("file:///%ProgramData%\Microsoft\Windows\Start Menu\Programs\*",$true,$false,$null^)>>%scriptname%
       @echo $crawlman.SaveAll^(^)>>%scriptname%
       @echo $crawlman.AddUserScopeRule^("file:///%AppData%\Microsoft\Windows\Start Menu\Programs\*",$true,$false,$null^)>>%scriptname%
       @echo $crawlman.SaveAll^(^)>>%scriptname%
       goto :Finish_Ps
      
       :SetCustomPaths
       :: Add custom path
       @echo $crawlman.AddUserScopeRule^("file:///%IndexedFolder%\*",$true,$false,$null^)>>%scriptname%
       @echo $crawlman.SaveAll^(^)>>%scriptname%
      
       :MorePathsLoop
       :: Loop until there is no more paths to add
       if %Index%==0 ( goto :Finish_Ps)
       set "Index2=!Index2_%Index%!"
       @echo $crawlman.AddUserScopeRule^("file:///%Index2%\*",$true,$false,$null^)>>%scriptname%
       @echo $crawlman.SaveAll^(^)>>%scriptname%
       set /a "Index-=1"
       goto :MorePathsLoop
      
       :Finish_Ps
       :: Remove automatically added favorites
       @echo $crawlman.RemoveDefaultScopeRule^("file:///%UserProfile%\Favorites\*"^)>>%scriptname%
       @echo $crawlman.SaveAll^(^)>>%scriptname%
       :Reindex
       @echo $Catalog.Reindex^(^)>>%scriptname%
       :: Delete lock file
       @echo Remove-Item "%lock%">>%scriptname%
    
    :: Execute Task
       :: Create lock file
       @echo Locked>"%lock%"
       :: Launch script
       PowerShell -NoProfile -ExecutionPolicy Bypass -c "& {Start-Process Powershell -ArgumentList '-ExecutionPolicy Unrestricted -File "%scriptname%" -force' -Verb RunAs -WindowStyle hidden}" >NUL 2>&1
       :: loop until lock file is deleted  
       :Wait
       if exist "%lock%" goto :Wait
    
    :Clean
       if "%Clean%" == "ON" ( cls & echo ESC[?25lNo indexing location has been set.) else ( echo ESC[?25lESC[92mDone.)
    :: loop to ensure temp files and folders are not anymore in use and can be deleted.
       :CleanCheck1  
       if not exist "%scriptname%" ( goto :CleanCheck2) else (
           del "%scriptname%" /f /s /q >NUL 2>&1
           goto :CleanCheck1
       )
       :CleanCheck2
       if not exist "%tmpfolder%" ( goto :End_Pause) else (
           rmdir "%tmpfolder%" /s /q >NUL 2>&1
           goto :CleanCheck2
       )
       :End_Pause
       timeout /t 2 /nobreak >NUL 2>&1
    goto :eof
    
    
    @end
    
    
    var shl = new ActiveXObject("Shell.Application");
    var folder = shl.BrowseForFolder(0, WScript.Arguments(0), 0x00000050,17);
    WScript.Stdout.WriteLine(folder ? folder.self.path : "");
    
    Sources:
    Powershell Bible page here and
    https://powertoe.wordpress.com/2010/05/17/powershell-tackles-windows-desktop-search/
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  4. Thomas Dubreuil

    Thomas Dubreuil MDL Member

    Aug 29, 2017
    212
    325
    10
    #4 Thomas Dubreuil, May 9, 2019
    Last edited: May 13, 2019
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  5. AeonX

    AeonX MDL Senior Member

    May 24, 2013
    404
    252
    10
    Thank you!! I will test as soon as I can and give feedback.
    I'm busy trying to finish a script for Windows 7 (searching, testing, refining the code ...).

    My goal is to create a script that works on both a live system and an offline image equally or as closely as possible.

    I would prefer to disable the windows search service but doing so will appear an unwanted message in windows explorer asking to activate the service or something like that every time I use the search. The reg tweak to disable this message only works if I remove the service (which I would not want to do without removing the rest of the component with NTLite or similar).

    I refer to this reg tweak:
    Code:
    reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\InfoBarsDisabled /v ServerMSSNotInstalled /t REG_DWORD /d 1 /f
    Source: https://superuser.com/questions/102...n-non-indexed-locations-banner-from-appearing
     
  6. Thomas Dubreuil

    Thomas Dubreuil MDL Member

    Aug 29, 2017
    212
    325
    10
    I'm not sure you can set indexed locations on an offline image, but you can make a install/deployment script like first one.

    I also leave indexing enabled, only for start menu locations (both paths), so that I type few letters and can very quickly launch programs from search box.
    And that's why found your question interesting, never thought I could also automate that task...

    Just an idea (never tried) on your case, through gpo/gpedit you can set a "disk space limit" for Search Index so that it stop indexing when reached that size limit.
    I'd (script would) remove every indexed locations + set gpo to enabled and value like, I want to keep 480 go free on my (480go) drive.
    or for an "everyone" script, something like: remove all indexed loc/get system disk space/set disk space to leave (reg add or gpo editing with powershell)
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...