This script create/delete crawled properties, managed properties, crawled property categories,
and property mappings. The script will also generate a sample configuration file as a starting point.
This script can be downloaded, along with many other SharePoint 2013 search related PowerShell scripts and tools via the following utility:
http://gallery.technet.microsoft.com/coming_soon :)
Bing SP2013ES
<#
.SYNOPSIS
This script create/delete crawled properties, managed properties, crawled property categories,
and property mappings. The script will also generate a sample configuration file as a starting point.
.DESCRIPTION
This script create/delete crawled properties, managed properties, crawled property categories,
and property mappings. The script will also generate a sample configuration file as a starting point.
This script can be downloaded, along with many other SharePoint 2013 search related
PowerShell scripts and tools via the following utility:
http://gallery.technet.microsoft.com/coming_soon :)
Quickly find SharePoint 2013 Enterprise Search resources!!
Bing SP2013ES
http://www.bing.com/search?q=sp2013es
.EXAMPLE
.\Maintain-SPEnterpriseSearchMetadataProperties.ps1 -GenerateSampleConfigurationFile
Generate a sample configuration file
.LINK
http://gallery.technet.microsoft.com/ScriptCenter
.NOTES
File Name : Maintain-SPEnterpriseSearchMetadataProperties.ps1
Author : Brent Groom, Matthew King
TODO List
-
#>
param
(
[string] $ConfigurationFile = $null,
# Specifies confuguration file name. The default is "this script name".config. i.e. Maintain-SearchMetadataProperties.config
[string] $SSAName = $global:ssaname,
# Specifies the search service application
[switch] $GenerateSampleConfigurationFile,
# Specifies whether the script should generate a sample configuration file. If you specify this flag,
# the script will generate the file and exit.
[switch] $DebugMode = $global:debug
# Signifies that the script should output debug statements
)
""
"<><><><><> Running script '$($MyInvocation.MyCommand.Definition)' <><><><><>"
""
Add-PSSnapin AdminSnapIn -erroraction SilentlyContinue
Add-PsSnapin Microsoft.SharePoint.PowerShell -erroraction SilentlyContinue
$spversion = get-spfarm|select BuildVersion
# used for recursive iteration, i.e. running this script multiple times, if caller script is not in this folder must change
$configurationname = $myinvocation.mycommand.Definition
# strip it down
$configurationname = $configurationname.replace('.ps1', '') -split "\\" | select -last 1
if ( $ConfigurationFile.length -eq 0)
{
$ConfigurationFile = "$configurationname.config"
if ($global:scriptsdir) {
$ConfigurationFile = Join-Path $global:scriptsdir $ConfigurationFile
}
}
$ssa = $false;
if ( !$SSAName -or $SSAName -eq "" ) { $ssa = Get-SPEnterpriseSearchServiceApplication }
else { $ssa = Get-SPEnterpriseSearchServiceApplication "$SSAName" }
if ( !$ssa )
{
write-host "Failed to retrieve Search Service Application...is this a SharePoint Admin node?" -fore red
$global:scriptsuccess = $false;
return
}
$fghighlight = "darkgreen"
#---------------------------- Functions -------------------------------
Function FunctionGenerateSampleConfigurationFile([string]$ConfigurationFile)
{
$funcname = "FunctionGenerateSampleConfigurationFile"
if ($DebugMode) { "Starting $funcname " }
Write-Host "Writing file $ConfigurationFile"
if (Test-Path $ConfigurationFile) {
if ($Confirm) {
$response = Read-Host "Overwite file '$ConfigurationFile'? y/n?"
if ($response -ne 'yes' -and $response -ne 'y') {
return
}
}
}
$selfdocumentingxml = @"
<Configuration>
<configurationSection>
<ManagedProperties>
<!-- Valid types: 1=Text, 2=Integer, 3=Boolean, 4=Float, 5=Decimal, 6=Datetime-->
<!-- This is an example showing what each configurable property means
<mproperty name="referencemanagedproperty" type="1">
<property name="RefinementEnabled">1</property>
<property name="Queryable">1</property>
<property name="SortableType">1</property>
<property name="MergeCrawledProperties">1</property>
Include values from all crawled properties mapped. All multi valued fields must have this value set to 1.
For example all taxonomy fields
<property name="MergeCrawledProperties">0</property>
Include values from a single crawled property based on the order specified.
</mproperty>
-->
<mproperty name="mptaxonomy1" type="1">
<property name="RefinementEnabled">1</property>
<property name="Queryable">1</property>
<property name="SortableType">1</property>
<property name="MergeCrawledProperties">1</property>
</mproperty>
<mproperty name="mpxmlmapper1" type="1">
<property name="RefinementEnabled">1</property>
<property name="Queryable">1</property>
<property name="SortableType">1</property>
<property name="MergeCrawledProperties">1</property>
</mproperty>
</ManagedProperties>
<CrawledProperties>
<CrawledProperty propertyName="cptaxonomy1" propertySet="e80ee0e8-71c0-4d8d-b918-360ad2fd7aa2" varType="31"/>
<CrawledProperty propertyName="cpxmlmapper1" propertySet="e80ee0e8-71c0-4d8d-b918-360ad2fd7aa2" varType="31"/>
</CrawledProperties>
<CrawledPropertyCategories>
<category name="Debug" propset="e80ee0e8-71c0-4d8d-b918-360ad2fd7aa2" MapToContents="1" DiscoverNewProperties="1"/>
<category name="JDBC" propset="4cc9f20a-c782-4c48-8961-c5356f8dff89" MapToContents="1" DiscoverNewProperties="1"/>
</CrawledPropertyCategories>
<Mappings>
<!-- Debug mappings -->
<mapping ManagedProperty="mpxmlmapper1" CrawledProperty="cpxmlmapper1" />
<mapping ManagedProperty="mptaxonomy1" CrawledProperty="cptaxonomy1" />
</Mappings>
</configurationSection>
</Configuration>
"@ | Out-File $ConfigurationFile
if ($DebugMode) { "Finished $funcname " }
}
# TODO split this into two functions. One for check if changed and one to change.
Function setProperty($objin, $propertyName, $propertyValue)
{
$funcname = "setProperty"
if ($DebugMode) { "Starting $funcname " }
if ( $propertyName -eq "MergeCrawledProperties") {return $false}
if ( $propertyName -eq "RefinementEnabled") {return $false}
$propertyChanged = $false
$fname = "$configurationname setProperty"
#if ( $debug) {$fname+" objin="+$objin+" propertyName="+$propertyName+" propertyValue="+$propertyValue;$objin}
$oldvalue = $objin.$propertyName
if ( $oldvalue -is [bool])
{
if ( $propertyvalue -eq "True")
{
if ($oldvalue -ne $true)
{
$propertyChanged = $true
$objin.$propertyName = $true;
}
}
elseif ( $propertyvalue -eq "False")
{
if ($oldvalue -ne $false)
{
$propertyChanged = $true
$objin.$propertyName = $false;
}
}
else
{
$intpropertyvalue = [int]$propertyvalue
$boolvalue = [bool]$intpropertyvalue;
if ($oldvalue -ne $boolvalue)
{
$propertyChanged = $true
$objin.$propertyName = $boolvalue;
}
}
}
else
{
if ($oldvalue -ne $propertyValue)
{
$propertyChanged = $true
#write-host ("hello1" ) -Foregroundcolor $fghighlight
$objin.$propertyName = $propertyValue;
#write-host ("hello2" ) -Foregroundcolor $fghighlight
}
}
if ($DebugMode) { "Finished $funcname " }
return $propertyChanged
}
Function manageCrawledPropertyCategory([xml]$thedata)
{
$funcname = "manageCrawledPropertyCategory"
if ($DebugMode) { "Starting $funcname " }
# handle all the Crawled Properties
$thecats = $thedata.SelectNodes("Configuration/configurationSection/CrawledPropertyCategories/category")
if ($DebugMode) { "Starting manageCrawledPropertyCategory: "+$thecats }
if ( !$thecats -or $thecats -eq $null -or $thecats.length -eq 0)
{
"No categories to manage"
}
write-host ("Creating Categories..." ) -Foregroundcolor $fghighlight
foreach ($thecat in $thecats)
{
$catname = $thecat.name
if ($DebugMode) { "catname: "+$catname }
Write-Host (".") -NoNewline
$catid = $thecat.propset
$maptocontents = $thecat.MapToContents -eq '1'
$discovernewprops = $thecat.DiscoverNewProperties -eq '1'
#"Looking at catname:$catname catid:$catid"
# get the category
$searchapp = $ssa
#$catobj = Get-SPEnterpriseSearchMetadataCategory -Identity $catname -SearchApplication $searchapp -ErrorAction:SilentlyContinue
$schema = new-object Microsoft.Office.Server.Search.Administration.Schema($searchapp)
$allCats = $schema.AllCategories
$doNotSkipThisCat = $True
if ( $allCats.Contains($catname) -eq $true)
{
$existingCat = $allCats.Item($catname)
#$doNotSkipThisCat = $False
#"The category name already exists: $catname"
}
$guid = new-object System.Guid($catid)
if ( $allCats.Contains($guid) -eq $true)
{
$existingCat = $allCats.Item($guid)
$doNotSkipThisCat = $False
#"The category id already exists: $catid"
}
if ( $doNotSkipThisCat -eq $True)
{
"Creating crawled category: $catname catid:$catid"
$catobj = $allCats.Create($catname, $catid)
# O15 PowerShell doesn't work yet
#$catobj = New-SPEnterpriseSearchMetadataCategory -Name $catname -Propset $catid -SearchApplication $searchapp -ErrorAction:SilentlyContinue
Set-SPEnterpriseSearchMetadataCategory -Identity $catname -MapToContents $maptocontents -DiscoverNewProperties $discovernewpropsi -SearchApplication $searchapp -ErrorAction:SilentlyContinue
}
if ($DebugMode) { "$configurationname manageCrawledPropertyCategory: Category name="+$catname }
}
write-host ("." )
write-host ("Done Creating Categories" ) -Foregroundcolor $fghighlight
if ($DebugMode) { "Finished $funcname " }
}
Function manageCrawledProperties([xml]$thedata)
{
# <CrawledProperty varType="31" propertyName="url" propertySet="11280615-f653-448f-8ed8-2915008789f2" />
$funcname = "manageSPEnterpriseSearchMetadataCrawledProperty"
if ($DebugMode) { "Starting $funcname " }
write-host ("Creating Crawled Properties..." ) -Foregroundcolor $fghighlight
# handle all the Crawled Properties
$thecps = $thedata.SelectNodes("Configuration/configurationSection/CrawledProperties/CrawledProperty")
foreach ($thecp in $thecps)
{
Write-Host (".") -NoNewline
$cpobj = $null
$cpname = $thecp.propertyName
$cppropset = $thecp.propertySet
$cpvarianttype = $thecp.varType
if (-not $cpvarianttype) { $cpvarianttype = 0 }
# get the property - using Set-SPEnterpriseSearchMetadataCrawledProperty ensures that a single crawledprop object is returned
#trap {write-host ("Creating Crawled property $cpname " ) -Foregroundcolor green; Continue}
$searchapp = $ssa
$cat = Get-SPEnterpriseSearchMetadataCategory -Identity $cppropset -SearchApplication $searchapp -ErrorAction:SilentlyContinue
if ( !$cat)
{
write-host ("Category with PropSet:$($cppropset) doesn't exist. Skipping crawled property:$($cpname)") -ForegroundColor Red
continue
}
$cpobj = Get-SPEnterpriseSearchMetadataCrawledProperty -Name $cpname -Category $cat -SearchApplication $searchapp -ErrorAction:SilentlyContinue
if ( !$cpobj)
{
<#
Debug helper
$searchapp = Get-SPEnterpriseSearchServiceApplication "Search Service Application"
$cppropset = "00130329-0000-0130-c000-000000131346"
$cpname = "ows_geographies"
$cpvarianttype = "4127"
$cat = Get-SPEnterpriseSearchMetadataCategory -Identity $cppropset -SearchApplication $searchapp -ErrorAction:SilentlyContinue
$cpobjget = Get-SPEnterpriseSearchMetadataCrawledProperty -Name $cpname -Category $cat -SearchApplication $searchapp
$cpobjnew = New-SPEnterpriseSearchMetadataCrawledProperty -Name $cpname -VariantType $cpvarianttype -Category $cat -Propset $cppropset -SearchApplication $searchapp -IsNameEnum $false
$cpobjget2 = Get-SPEnterpriseSearchMetadataCrawledProperty -Name $cpname -Category $cat -SearchApplication $searchapp
$cpobjget
$cpobjnew
$cpobjget2
# The above code may
#>
# TODO handle all the different variant types
# apparently all properties can be multivalued. you cannot set this variable as it is not used... -IsMultiValued 1
#New-SPEnterpriseSearchMetadataCrawledProperty -SearchApplication $searchapp -Category $cat -Propset -Name testcrawledproperty -IsNameEnum $false
#$cpobj = New-SPEnterpriseSearchMetadataCrawledProperty -Name $cpname -SearchApplication $searchapp -Category $cat -Propset $cppropset -IsNameEnum $false -ErrorAction:SilentlyContinue
# Try to leave off the category??
$cpobj = New-SPEnterpriseSearchMetadataCrawledProperty -Name $cpname -VariantType $cpvarianttype -Category $cat -Propset $cppropset -SearchApplication $searchapp -IsNameEnum $false
$cpobj = Get-SPEnterpriseSearchMetadataCrawledProperty -Name $cpname -Category $cat -SearchApplication $searchapp -ErrorAction:SilentlyContinue
# The new command outputs a strange message -- WARNING: Extra parameter ignored: '-SearchApplication'.
#$cpobj = New-SPEnterpriseSearchMetadataCrawledProperty -Name $cpname -VariantType $cpvarianttype -Category $cat -Propset $cppropset -IsNameEnum $false -ErrorAction:SilentlyContinue
if ( !$cpobj)
{
write-host ("Failed to create Crawled Property - name:'$cpname' variant:'$cpvarianttype' propset:'$($cppropset)' " ) -Foregroundcolor Red
}
else
{
write-host ("Created Crawled Property - name:'$cpname' variant:'$cpvarianttype' propset:'$($cppropset)' " ) -Foregroundcolor green
}
}
else
{
#TODO write-host ("Previously created Crawled property $cpname propset:$($cppropset)" ) -Foregroundcolor green
#$cpobj | Set-SPEnterpriseSearchMetadataCrawledProperty -propset $cppropset -ErrorAction:SilentlyContinue
}
if ($DebugMode) { "$configurationname mainwork: Crawled Property name="+$cpname }
}
if ($DebugMode) { "Finished $funcname " }
write-host ("." )
write-host ("Done Creating Crawled Properties." ) -Foregroundcolor $fghighlight
}
# TODO handle all the different types
# TODO handle changing the type delete/add
Function ManageManagedProperties([xml]$thedata)
{
$funcname = "ManageManagedProperties"
if ($DebugMode) { "Starting $funcname " }
write-host ("Creating Managed Properties..." ) -Foregroundcolor $fghighlight
$themps = $thedata.SelectNodes("Configuration/configurationSection/ManagedProperties/mproperty")
#manage-ManagedProperties
# handle all the Managed Properties
foreach ($themp in $themps)
{
Write-Host (".") -NoNewline
$mpname = $themp.name
# get the property
$searchapp = $ssa
$mpobj = Get-SPEnterpriseSearchMetadataManagedProperty -Identity $mpname -SearchApplication $searchapp -ErrorAction:SilentlyContinue
if ( !$mpobj)
{
$mptype = $themp.type
$mpobj = New-SPEnterpriseSearchMetadataManagedProperty -Name $mpname -Type $mptype -SearchApplication $searchapp
write-host ("Created managed property '$mpname'" ) -Foregroundcolor green
}
$objchanged = $false
foreach ($prop in $themp.property)
{
$propname = $prop.name
# type is a readonly property so continue. TODO have setProperty handle readonly properties
if ( $propname -eq "type")
{
continue
}
$propval = $prop.get_InnerText()
#if ( $DebugMode){"value before setProperty="+$mpobj.$propname}
$propchanged = setProperty $mpobj $propname $propval
if ( $propchanged -eq $True)
{
$objchanged = $True
}
#if ( $DebugMode){"value after setProperty="+$mpobj.$propname}
}
if ( $objchanged)
{
$mpobj.update()
#TODO write-host ("Updated managed property $mpname") -Foregroundcolor green
}
else
{
# TODO "No changes to managed property $mpname "
}
if ($DebugMode) { "$configurationname ManageManagedProperties: Managed Property name="+$mpname }
}
if ($DebugMode) { "Finished $funcname " }
write-host ("." )
write-host ("Done Creating Managed Properties." ) -Foregroundcolor $fghighlight
}
#TODO remove the mappings
Function manageMappings([xml]$thedata)
{
$funcname = "manageMappings"
if ($DebugMode) { "Starting $funcname " }
write-host ("Creating Crawled to Managed Property Mappings..." ) -Foregroundcolor $fghighlight
$searchapp = $ssa
# setup the property mappings
$themappings = $thedata.SelectNodes("Configuration/configurationSection/Mappings/mapping")
foreach ($themap in $themappings)
{
Write-Host (".") -NoNewline
$mpobj = $NULL
$cpobj = $NULL
$position = "first"
$mpname = $themap.ManagedProperty
$cpname = $themap.CrawledProperty
$propset = $themap.cppropset
$cpvarianttype = $themap.cpvarianttype
#$propset
if ($themap.position) {
$position = $themap.position
}
$mpobj = Get-SPEnterpriseSearchMetadataManagedProperty -Identity $themap.ManagedProperty -SearchApplication $searchapp -ErrorAction:SilentlyContinue
# need to add in the propset here !!!
$cpobj = Get-SPEnterpriseSearchMetadataCrawledProperty -Name $themap.CrawledProperty -PropSet $propset -SearchApplication $searchapp -ErrorAction:SilentlyContinue
#$cpobj
if ($mpobj -eq $NULL)
{
"manageMappings: Managed Property '$mpname' doesn't exist"
}
if ($cpobj -eq $NULL)
{
Write-Host("manageMappings: Crawled Property doesn't exist with name:'$cpname' variant type:'$cpvarianttype' propset:'$propset' ") -ForegroundColor Red
}
if ($mpobj -eq $NULL -or $cpobj -eq $NULL)
{
continue
}
#"mptype= $($mpobj.ManagedType)"
#"cpvarianttype = $cpvarianttype"
# See if this mapping already exists
$mplist = $cpobj.GetMappedManagedProperties()
$alreadymapped = $false
foreach ($mp in $mplist)
{
if ( $mpname -eq $mp.name)
{
$alreadymapped = $true
}
}
if ( !$alreadymapped)
{
write-host ("Creating new mapping - MP: '$($mpobj.Name)' $($mpobj.ManagedType) to CP: '$($cpobj.Name)' in $position position" ) -Foregroundcolor green
if ($position -eq 'last')
{
# this inserts at the end of the list
try
{
$newmap = New-SPEnterpriseSearchMetadataMapping -ManagedProperty $mpobj -CrawledProperty $cpobj -SearchApplication $searchapp
if ( !$newmap)
{
"Failed to create mapping of - MP: '$($mpobj.Name)' $($mpobj.ManagedType) to CP: '$($cpobj.Name)' $($cpobj.VariantType)"
}
}
catch [Exception]
{
#$_.Exception.GetType().FullName
#$_.Exception.Message
"Failed to create mapping of - MP: '$($mpobj.Name)' $($mpobj.ManagedType) to CP: '$($cpobj.Name)' $($cpobj.VariantType)"
}
}
else
{
try
{
$mappings = $mpobj.GetMappings()
# first get the existing crawled properties
$cplist = $mappings | % {
$map = $_;
Get-SPEnterpriseSearchMetadataCrawledProperty -Name $map.CrawledPropertyName -SearchApplication $searchapp -PropSet $map.CrawledPropset
}
# delete the mappings
$mappings | % {
Remove-SPEnterpriseSearchMetadataMapping $_ -SearchApplication $searchapp -Confirm:$false
}
# add ours in
$newmap = New-SPEnterpriseSearchMetadataMapping -ManagedProperty $mpobj -CrawledProperty $cpobj -SearchApplication $searchapp
if ( !$newmap)
{
"Failed to create mapping of - MP: '$($mpobj.Name)' $($mpobj.ManagedType) to CP: '$($cpobj.Name)' $($cpobj.VariantType)"
}
# add originals back in after it
$cplist | % { $cp = $_
New-SPEnterpriseSearchMetadataMapping -ManagedProperty $mpobj -CrawledProperty $cp -SearchApplication $searchapp | Out-Null
}
}
catch [Exception]
{
#$_.Exception.GetType().FullName
#$_.Exception.Message
"Failed to create mapping of - MP: '$($mpobj.Name)' $($mpobj.ManagedType) to CP: '$($cpobj.Name)' $($cpobj.VariantType)"
}
}
}
#else
#{
# TODO "No change to mapping: $cpname -> $mpname"
#}
}
if ($DebugMode) { "Finished $funcname " }
write-host ("." )
write-host ("Done Creating Crawaled Property to Managed Property Mappings." ) -Foregroundcolor $fghighlight
}
Function main([string]$ConfigurationFile)
{
$funcname = "main"
if ($DebugMode) { "Starting $funcname " }
[xml]$xmldata = [xml](Get-Content $ConfigurationFile)
if (-not $xmldata) { return }
if ( $DebugMode)
{
$ConfigurationFile
$xmldata.get_InnerXml()
}
manageCrawledPropertyCategory $xmldata
manageCrawledProperties $xmldata
manageManagedProperties $xmldata
manageMappings $xmldata
# TODO optimize the gets and store the objects in a hash so we don't have to get them again
if ($DebugMode) { "Finished $funcname " }
}
if ( $GenerateSampleConfigurationFile)
{
FunctionGenerateSampleConfigurationFile $ConfigurationFile
}
else
{
main $ConfigurationFile
}
<# .SYNOPSIS This script create/delete crawled properties, managed properties, crawled property categories, and property mappings. The script will also generate a sample configuration file as a starting point. .DESCRIPTION This script create/delete crawled properties, managed properties, crawled property categories, and property mappings. The script will also generate a sample configuration file as a starting point. This script can be downloaded, along with many other SharePoint 2013 search related PowerShell scripts and tools via the following utility: http://gallery.technet.microsoft.com/coming_soon :) Quickly find SharePoint 2013 Enterprise Search resources!! Bing SP2013ES http://www.bing.com/search?q=sp2013es .EXAMPLE .\Maintain-SPEnterpriseSearchMetadataProperties.ps1 -GenerateSampleConfigurationFile Generate a sample configuration file .LINK http://gallery.technet.microsoft.com/ScriptCenter .NOTES File Name : Maintain-SPEnterpriseSearchMetadataProperties.ps1 Author : Brent Groom, Matthew King TODO List - #> param ( [string] $ConfigurationFile = $null, # Specifies confuguration file name. The default is "this script name".config. i.e. Maintain-SearchMetadataProperties.config [string] $SSAName = $global:ssaname, # Specifies the search service application [switch] $GenerateSampleConfigurationFile, # Specifies whether the script should generate a sample configuration file. If you specify this flag, # the script will generate the file and exit. [switch] $DebugMode = $global:debug # Signifies that the script should output debug statements ) "" "<><><><><> Running script '$($MyInvocation.MyCommand.Definition)' <><><><><>" "" Add-PSSnapin AdminSnapIn -erroraction SilentlyContinue Add-PsSnapin Microsoft.SharePoint.PowerShell -erroraction SilentlyContinue $spversion = get-spfarm|select BuildVersion # used for recursive iteration, i.e. running this script multiple times, if caller script is not in this folder must change $configurationname = $myinvocation.mycommand.Definition # strip it down $configurationname = $configurationname.replace('.ps1', '') -split "\\" | select -last 1 if ( $ConfigurationFile.length -eq 0) { $ConfigurationFile = "$configurationname.config" if ($global:scriptsdir) { $ConfigurationFile = Join-Path $global:scriptsdir $ConfigurationFile } } $ssa = $false; if ( !$SSAName -or $SSAName -eq "" ) { $ssa = Get-SPEnterpriseSearchServiceApplication } else { $ssa = Get-SPEnterpriseSearchServiceApplication "$SSAName" } if ( !$ssa ) { write-host "Failed to retrieve Search Service Application...is this a SharePoint Admin node?" -fore red $global:scriptsuccess = $false; return } $fghighlight = "darkgreen" #---------------------------- Functions ------------------------------- Function FunctionGenerateSampleConfigurationFile([string]$ConfigurationFile) { $funcname = "FunctionGenerateSampleConfigurationFile" if ($DebugMode) { "Starting $funcname " } Write-Host "Writing file $ConfigurationFile" if (Test-Path $ConfigurationFile) { if ($Confirm) { $response = Read-Host "Overwite file '$ConfigurationFile'? y/n?" if ($response -ne 'yes' -and $response -ne 'y') { return } } } $selfdocumentingxml = @" <Configuration> <configurationSection> <ManagedProperties> <!-- Valid types: 1=Text, 2=Integer, 3=Boolean, 4=Float, 5=Decimal, 6=Datetime--> <!-- This is an example showing what each configurable property means <mproperty name="referencemanagedproperty" type="1"> <property name="RefinementEnabled">1</property> <property name="Queryable">1</property> <property name="SortableType">1</property> <property name="MergeCrawledProperties">1</property> Include values from all crawled properties mapped. All multi valued fields must have this value set to 1. For example all taxonomy fields <property name="MergeCrawledProperties">0</property> Include values from a single crawled property based on the order specified. </mproperty> --> <mproperty name="mptaxonomy1" type="1"> <property name="RefinementEnabled">1</property> <property name="Queryable">1</property> <property name="SortableType">1</property> <property name="MergeCrawledProperties">1</property> </mproperty> <mproperty name="mpxmlmapper1" type="1"> <property name="RefinementEnabled">1</property> <property name="Queryable">1</property> <property name="SortableType">1</property> <property name="MergeCrawledProperties">1</property> </mproperty> </ManagedProperties> <CrawledProperties> <CrawledProperty propertyName="cptaxonomy1" propertySet="e80ee0e8-71c0-4d8d-b918-360ad2fd7aa2" varType="31"/> <CrawledProperty propertyName="cpxmlmapper1" propertySet="e80ee0e8-71c0-4d8d-b918-360ad2fd7aa2" varType="31"/> </CrawledProperties> <CrawledPropertyCategories> <category name="Debug" propset="e80ee0e8-71c0-4d8d-b918-360ad2fd7aa2" MapToContents="1" DiscoverNewProperties="1"/> <category name="JDBC" propset="4cc9f20a-c782-4c48-8961-c5356f8dff89" MapToContents="1" DiscoverNewProperties="1"/> </CrawledPropertyCategories> <Mappings> <!-- Debug mappings --> <mapping ManagedProperty="mpxmlmapper1" CrawledProperty="cpxmlmapper1" /> <mapping ManagedProperty="mptaxonomy1" CrawledProperty="cptaxonomy1" /> </Mappings> </configurationSection> </Configuration> "@ | Out-File $ConfigurationFile if ($DebugMode) { "Finished $funcname " } } # TODO split this into two functions. One for check if changed and one to change. Function setProperty($objin, $propertyName, $propertyValue) { $funcname = "setProperty" if ($DebugMode) { "Starting $funcname " } if ( $propertyName -eq "MergeCrawledProperties") {return $false} if ( $propertyName -eq "RefinementEnabled") {return $false} $propertyChanged = $false $fname = "$configurationname setProperty" #if ( $debug) {$fname+" objin="+$objin+" propertyName="+$propertyName+" propertyValue="+$propertyValue;$objin} $oldvalue = $objin.$propertyName if ( $oldvalue -is [bool]) { if ( $propertyvalue -eq "True") { if ($oldvalue -ne $true) { $propertyChanged = $true $objin.$propertyName = $true; } } elseif ( $propertyvalue -eq "False") { if ($oldvalue -ne $false) { $propertyChanged = $true $objin.$propertyName = $false; } } else { $intpropertyvalue = [int]$propertyvalue $boolvalue = [bool]$intpropertyvalue; if ($oldvalue -ne $boolvalue) { $propertyChanged = $true $objin.$propertyName = $boolvalue; } } } else { if ($oldvalue -ne $propertyValue) { $propertyChanged = $true #write-host ("hello1" ) -Foregroundcolor $fghighlight $objin.$propertyName = $propertyValue; #write-host ("hello2" ) -Foregroundcolor $fghighlight } } if ($DebugMode) { "Finished $funcname " } return $propertyChanged } Function manageCrawledPropertyCategory([xml]$thedata) { $funcname = "manageCrawledPropertyCategory" if ($DebugMode) { "Starting $funcname " } # handle all the Crawled Properties $thecats = $thedata.SelectNodes("Configuration/configurationSection/CrawledPropertyCategories/category") if ($DebugMode) { "Starting manageCrawledPropertyCategory: "+$thecats } if ( !$thecats -or $thecats -eq $null -or $thecats.length -eq 0) { "No categories to manage" } write-host ("Creating Categories..." ) -Foregroundcolor $fghighlight foreach ($thecat in $thecats) { $catname = $thecat.name if ($DebugMode) { "catname: "+$catname } Write-Host (".") -NoNewline $catid = $thecat.propset $maptocontents = $thecat.MapToContents -eq '1' $discovernewprops = $thecat.DiscoverNewProperties -eq '1' #"Looking at catname:$catname catid:$catid" # get the category $searchapp = $ssa #$catobj = Get-SPEnterpriseSearchMetadataCategory -Identity $catname -SearchApplication $searchapp -ErrorAction:SilentlyContinue $schema = new-object Microsoft.Office.Server.Search.Administration.Schema($searchapp) $allCats = $schema.AllCategories $doNotSkipThisCat = $True if ( $allCats.Contains($catname) -eq $true) { $existingCat = $allCats.Item($catname) #$doNotSkipThisCat = $False #"The category name already exists: $catname" } $guid = new-object System.Guid($catid) if ( $allCats.Contains($guid) -eq $true) { $existingCat = $allCats.Item($guid) $doNotSkipThisCat = $False #"The category id already exists: $catid" } if ( $doNotSkipThisCat -eq $True) { "Creating crawled category: $catname catid:$catid" $catobj = $allCats.Create($catname, $catid) # O15 PowerShell doesn't work yet #$catobj = New-SPEnterpriseSearchMetadataCategory -Name $catname -Propset $catid -SearchApplication $searchapp -ErrorAction:SilentlyContinue Set-SPEnterpriseSearchMetadataCategory -Identity $catname -MapToContents $maptocontents -DiscoverNewProperties $discovernewpropsi -SearchApplication $searchapp -ErrorAction:SilentlyContinue } if ($DebugMode) { "$configurationname manageCrawledPropertyCategory: Category name="+$catname } } write-host ("." ) write-host ("Done Creating Categories" ) -Foregroundcolor $fghighlight if ($DebugMode) { "Finished $funcname " } } Function manageCrawledProperties([xml]$thedata) { # <CrawledProperty varType="31" propertyName="url" propertySet="11280615-f653-448f-8ed8-2915008789f2" /> $funcname = "manageSPEnterpriseSearchMetadataCrawledProperty" if ($DebugMode) { "Starting $funcname " } write-host ("Creating Crawled Properties..." ) -Foregroundcolor $fghighlight # handle all the Crawled Properties $thecps = $thedata.SelectNodes("Configuration/configurationSection/CrawledProperties/CrawledProperty") foreach ($thecp in $thecps) { Write-Host (".") -NoNewline $cpobj = $null $cpname = $thecp.propertyName $cppropset = $thecp.propertySet $cpvarianttype = $thecp.varType if (-not $cpvarianttype) { $cpvarianttype = 0 } # get the property - using Set-SPEnterpriseSearchMetadataCrawledProperty ensures that a single crawledprop object is returned #trap {write-host ("Creating Crawled property $cpname " ) -Foregroundcolor green; Continue} $searchapp = $ssa $cat = Get-SPEnterpriseSearchMetadataCategory -Identity $cppropset -SearchApplication $searchapp -ErrorAction:SilentlyContinue if ( !$cat) { write-host ("Category with PropSet:$($cppropset) doesn't exist. Skipping crawled property:$($cpname)") -ForegroundColor Red continue } $cpobj = Get-SPEnterpriseSearchMetadataCrawledProperty -Name $cpname -Category $cat -SearchApplication $searchapp -ErrorAction:SilentlyContinue if ( !$cpobj) { <# Debug helper $searchapp = Get-SPEnterpriseSearchServiceApplication "Search Service Application" $cppropset = "00130329-0000-0130-c000-000000131346" $cpname = "ows_geographies" $cpvarianttype = "4127" $cat = Get-SPEnterpriseSearchMetadataCategory -Identity $cppropset -SearchApplication $searchapp -ErrorAction:SilentlyContinue $cpobjget = Get-SPEnterpriseSearchMetadataCrawledProperty -Name $cpname -Category $cat -SearchApplication $searchapp $cpobjnew = New-SPEnterpriseSearchMetadataCrawledProperty -Name $cpname -VariantType $cpvarianttype -Category $cat -Propset $cppropset -SearchApplication $searchapp -IsNameEnum $false $cpobjget2 = Get-SPEnterpriseSearchMetadataCrawledProperty -Name $cpname -Category $cat -SearchApplication $searchapp $cpobjget $cpobjnew $cpobjget2 # The above code may #> # TODO handle all the different variant types # apparently all properties can be multivalued. you cannot set this variable as it is not used... -IsMultiValued 1 #New-SPEnterpriseSearchMetadataCrawledProperty -SearchApplication $searchapp -Category $cat -Propset -Name testcrawledproperty -IsNameEnum $false #$cpobj = New-SPEnterpriseSearchMetadataCrawledProperty -Name $cpname -SearchApplication $searchapp -Category $cat -Propset $cppropset -IsNameEnum $false -ErrorAction:SilentlyContinue # Try to leave off the category?? $cpobj = New-SPEnterpriseSearchMetadataCrawledProperty -Name $cpname -VariantType $cpvarianttype -Category $cat -Propset $cppropset -SearchApplication $searchapp -IsNameEnum $false $cpobj = Get-SPEnterpriseSearchMetadataCrawledProperty -Name $cpname -Category $cat -SearchApplication $searchapp -ErrorAction:SilentlyContinue # The new command outputs a strange message -- WARNING: Extra parameter ignored: '-SearchApplication'. #$cpobj = New-SPEnterpriseSearchMetadataCrawledProperty -Name $cpname -VariantType $cpvarianttype -Category $cat -Propset $cppropset -IsNameEnum $false -ErrorAction:SilentlyContinue if ( !$cpobj) { write-host ("Failed to create Crawled Property - name:'$cpname' variant:'$cpvarianttype' propset:'$($cppropset)' " ) -Foregroundcolor Red } else { write-host ("Created Crawled Property - name:'$cpname' variant:'$cpvarianttype' propset:'$($cppropset)' " ) -Foregroundcolor green } } else { #TODO write-host ("Previously created Crawled property $cpname propset:$($cppropset)" ) -Foregroundcolor green #$cpobj | Set-SPEnterpriseSearchMetadataCrawledProperty -propset $cppropset -ErrorAction:SilentlyContinue } if ($DebugMode) { "$configurationname mainwork: Crawled Property name="+$cpname } } if ($DebugMode) { "Finished $funcname " } write-host ("." ) write-host ("Done Creating Crawled Properties." ) -Foregroundcolor $fghighlight } # TODO handle all the different types # TODO handle changing the type delete/add Function ManageManagedProperties([xml]$thedata) { $funcname = "ManageManagedProperties" if ($DebugMode) { "Starting $funcname " } write-host ("Creating Managed Properties..." ) -Foregroundcolor $fghighlight $themps = $thedata.SelectNodes("Configuration/configurationSection/ManagedProperties/mproperty") #manage-ManagedProperties # handle all the Managed Properties foreach ($themp in $themps) { Write-Host (".") -NoNewline $mpname = $themp.name # get the property $searchapp = $ssa $mpobj = Get-SPEnterpriseSearchMetadataManagedProperty -Identity $mpname -SearchApplication $searchapp -ErrorAction:SilentlyContinue if ( !$mpobj) { $mptype = $themp.type $mpobj = New-SPEnterpriseSearchMetadataManagedProperty -Name $mpname -Type $mptype -SearchApplication $searchapp write-host ("Created managed property '$mpname'" ) -Foregroundcolor green } $objchanged = $false foreach ($prop in $themp.property) { $propname = $prop.name # type is a readonly property so continue. TODO have setProperty handle readonly properties if ( $propname -eq "type") { continue } $propval = $prop.get_InnerText() #if ( $DebugMode){"value before setProperty="+$mpobj.$propname} $propchanged = setProperty $mpobj $propname $propval if ( $propchanged -eq $True) { $objchanged = $True } #if ( $DebugMode){"value after setProperty="+$mpobj.$propname} } if ( $objchanged) { $mpobj.update() #TODO write-host ("Updated managed property $mpname") -Foregroundcolor green } else { # TODO "No changes to managed property $mpname " } if ($DebugMode) { "$configurationname ManageManagedProperties: Managed Property name="+$mpname } } if ($DebugMode) { "Finished $funcname " } write-host ("." ) write-host ("Done Creating Managed Properties." ) -Foregroundcolor $fghighlight } #TODO remove the mappings Function manageMappings([xml]$thedata) { $funcname = "manageMappings" if ($DebugMode) { "Starting $funcname " } write-host ("Creating Crawled to Managed Property Mappings..." ) -Foregroundcolor $fghighlight $searchapp = $ssa # setup the property mappings $themappings = $thedata.SelectNodes("Configuration/configurationSection/Mappings/mapping") foreach ($themap in $themappings) { Write-Host (".") -NoNewline $mpobj = $NULL $cpobj = $NULL $position = "first" $mpname = $themap.ManagedProperty $cpname = $themap.CrawledProperty $propset = $themap.cppropset $cpvarianttype = $themap.cpvarianttype #$propset if ($themap.position) { $position = $themap.position } $mpobj = Get-SPEnterpriseSearchMetadataManagedProperty -Identity $themap.ManagedProperty -SearchApplication $searchapp -ErrorAction:SilentlyContinue # need to add in the propset here !!! $cpobj = Get-SPEnterpriseSearchMetadataCrawledProperty -Name $themap.CrawledProperty -PropSet $propset -SearchApplication $searchapp -ErrorAction:SilentlyContinue #$cpobj if ($mpobj -eq $NULL) { "manageMappings: Managed Property '$mpname' doesn't exist" } if ($cpobj -eq $NULL) { Write-Host("manageMappings: Crawled Property doesn't exist with name:'$cpname' variant type:'$cpvarianttype' propset:'$propset' ") -ForegroundColor Red } if ($mpobj -eq $NULL -or $cpobj -eq $NULL) { continue } #"mptype= $($mpobj.ManagedType)" #"cpvarianttype = $cpvarianttype" # See if this mapping already exists $mplist = $cpobj.GetMappedManagedProperties() $alreadymapped = $false foreach ($mp in $mplist) { if ( $mpname -eq $mp.name) { $alreadymapped = $true } } if ( !$alreadymapped) { write-host ("Creating new mapping - MP: '$($mpobj.Name)' $($mpobj.ManagedType) to CP: '$($cpobj.Name)' in $position position" ) -Foregroundcolor green if ($position -eq 'last') { # this inserts at the end of the list try { $newmap = New-SPEnterpriseSearchMetadataMapping -ManagedProperty $mpobj -CrawledProperty $cpobj -SearchApplication $searchapp if ( !$newmap) { "Failed to create mapping of - MP: '$($mpobj.Name)' $($mpobj.ManagedType) to CP: '$($cpobj.Name)' $($cpobj.VariantType)" } } catch [Exception] { #$_.Exception.GetType().FullName #$_.Exception.Message "Failed to create mapping of - MP: '$($mpobj.Name)' $($mpobj.ManagedType) to CP: '$($cpobj.Name)' $($cpobj.VariantType)" } } else { try { $mappings = $mpobj.GetMappings() # first get the existing crawled properties $cplist = $mappings | % { $map = $_; Get-SPEnterpriseSearchMetadataCrawledProperty -Name $map.CrawledPropertyName -SearchApplication $searchapp -PropSet $map.CrawledPropset } # delete the mappings $mappings | % { Remove-SPEnterpriseSearchMetadataMapping $_ -SearchApplication $searchapp -Confirm:$false } # add ours in $newmap = New-SPEnterpriseSearchMetadataMapping -ManagedProperty $mpobj -CrawledProperty $cpobj -SearchApplication $searchapp if ( !$newmap) { "Failed to create mapping of - MP: '$($mpobj.Name)' $($mpobj.ManagedType) to CP: '$($cpobj.Name)' $($cpobj.VariantType)" } # add originals back in after it $cplist | % { $cp = $_ New-SPEnterpriseSearchMetadataMapping -ManagedProperty $mpobj -CrawledProperty $cp -SearchApplication $searchapp | Out-Null } } catch [Exception] { #$_.Exception.GetType().FullName #$_.Exception.Message "Failed to create mapping of - MP: '$($mpobj.Name)' $($mpobj.ManagedType) to CP: '$($cpobj.Name)' $($cpobj.VariantType)" } } } #else #{ # TODO "No change to mapping: $cpname -> $mpname" #} } if ($DebugMode) { "Finished $funcname " } write-host ("." ) write-host ("Done Creating Crawaled Property to Managed Property Mappings." ) -Foregroundcolor $fghighlight } Function main([string]$ConfigurationFile) { $funcname = "main" if ($DebugMode) { "Starting $funcname " } [xml]$xmldata = [xml](Get-Content $ConfigurationFile) if (-not $xmldata) { return } if ( $DebugMode) { $ConfigurationFile $xmldata.get_InnerXml() } manageCrawledPropertyCategory $xmldata manageCrawledProperties $xmldata manageManagedProperties $xmldata manageMappings $xmldata # TODO optimize the gets and store the objects in a hash so we don't have to get them again if ($DebugMode) { "Finished $funcname " } } if ( $GenerateSampleConfigurationFile) { FunctionGenerateSampleConfigurationFile $ConfigurationFile } else { main $ConfigurationFile }