DSCResources/MSFT_SPOSearchManagedProperty/MSFT_SPOSearchManagedProperty.psm1
function Get-TargetResource { [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param ( [Parameter(Mandatory = $true)] [System.String] $Name, [Parameter(Mandatory = $true)] [ValidateSet("Text", "Integer", "Decimal", "DateTime", "YesNo", "Double", "Binary")] [System.String] $Type, [Parameter()] [System.String] $Description, [Parameter()] [System.Boolean] $Searchable, [Parameter()] [System.String] $FullTextIndex, [Parameter()] [System.UInt32] $FullTextContext, [Parameter()] [System.Boolean] $Queryable, [Parameter()] [System.Boolean] $Retrievable, [Parameter()] [System.Boolean] $AllowMultipleValues, [Parameter()] [ValidateSet("No", "Yes - latent", "Yes")] [System.String] $Refinable, [Parameter()] [ValidateSet("No", "Yes - latent", "Yes")] [System.String] $Sortable, [Parameter()] [System.Boolean] $Safe, [Parameter()] [System.String[]] $Aliases, [Parameter()] [System.Boolean] $TokenNormalization, [Parameter()] [System.Boolean] $CompleteMatching, [Parameter()] [System.Boolean] $LanguageNeutralTokenization, [Parameter()] [System.Boolean] $FinerQueryTokenization, [Parameter()] [System.String[]] $MappedCrawledProperties, [Parameter()] [System.Boolean] $CompanyNameExtraction, [Parameter()] [ValidateSet("Present")] [System.String] $Ensure = "Present", [Parameter()] [System.Management.Automation.PSCredential] $GlobalAdminAccount, [Parameter()] [System.String] $ApplicationId, [Parameter()] [System.String] $TenantId, [Parameter()] [System.String] $CertificateThumbprint, [Parameter()] [System.String] $CertificatePath, [Parameter()] [System.Management.Automation.PSCredential] $CertificatePassword ) Write-Verbose -Message "Getting configuration for Managed Property instance $Name" $ConnectionMode = New-M365DSCConnection -Platform 'PnP' ` -InboundParameters $PSBoundParameters #region Telemetry $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace("MSFT_", "") $data = [System.Collections.Generic.Dictionary[[String], [String]]]::new() $data.Add("Resource", $ResourceName) $data.Add("Method", $MyInvocation.MyCommand) $data.Add("Principal", $GlobalAdminAccount.UserName) $data.Add("TenantId", $TenantId) $data.Add("ConnectionMode", $ConnectionMode) Add-M365DSCTelemetryEvent -Data $data #endregion $nullReturn = $PSBoundParameters $nullReturn.Ensure = "Absent" try { if ($null -eq $Script:RecentMPExtract) { $Script:RecentMPExtract = [Xml] (Get-PnPSearchConfiguration -Scope Subscription) } $property = $Script:RecentMPExtract.SearchConfigurationSettings.SearchSchemaConfigurationSettings.ManagedProperties.dictionary.KeyValueOfstringManagedPropertyInfoy6h3NzC8 ` | Where-Object -FilterScript { $_.Value.Name -eq $Name } if ($null -eq $property) { Write-Verbose -Message "The specified Managed Property {$($Name)} doesn't already exist." return $nullReturn } $CompanyNameExtraction = $false if ($property.Value.EntityExtractorBitMap -eq "4161") { $CompanyNameExtraction = $true } $FullTextIndex = $null if ([string] $property.Value.FullTextIndex -ne "System.Xml.XmlElement") { $FullTextIndex = [string] $property.Value.FullTextIndex } # Get Mapped Crawled Properties $currentManagedPID = [string] $property.Value.Pid $mappedProperties = $Script:RecentMPExtract.SearchConfigurationSettings.SearchSchemaConfigurationSettings.Mappings.dictionary.KeyValueOfstringMappingInfoy6h3NzC8 ` | Where-Object -FilterScript { $_.Value.ManagedPid -eq $currentManagedPID } $mappings = @() foreach ($mappedProperty in $mappedProperties) { $mappings += $mappedProperty.Value.CrawledPropertyName.ToString() } $fixedRefinable = "No" if ([boolean] $property.Value.Refinable) { $fixedRefinable = "Yes" } $fixedSortable = "No" if ([boolean] $property.Value.Sortable) { $fixedSortable = "Yes" } Write-Verbose -Message "Retrieved Property" return @{ Name = [string] $property.Value.Name Type = [string] $property.Value.ManagedType Description = [string] $property.Value.Description Searchable = [boolean] $property.Value.Searchable FullTextIndex = $FullTextIndex FullTextContext = [UInt32] $property.Value.Context Queryable = [boolean] $property.Value.Queryable Retrievable = [boolean] $property.Value.Retrievable AllowMultipleValues = [boolean] $property.Value.HasMultipleValues Refinable = $fixedRefinable Sortable = $fixedSortable Safe = [boolean] $property.Value.SafeForAnonymous Aliases = [boolean] $property.Value.Aliases TokenNormalization = [boolean] $property.Value.TokenNormalization CompleteMatching = [boolean] $property.Value.CompleteMatching LanguageNeutralTokenization = [boolean] $property.Value.LanguageNeutralWordBreaker FinerQueryTokenization = [boolean] $property.Value.ExpandSegments MappedCrawledProperties = $mappings CompanyNameExtraction = $CompanyNameExtraction Ensure = "Present" } } catch { try { Write-Verbose -Message $_ $tenantIdValue = "" if (-not [System.String]::IsNullOrEmpty($TenantId)) { $tenantIdValue = $TenantId } elseif ($null -ne $GlobalAdminAccount) { $tenantIdValue = $GlobalAdminAccount.UserName.Split('@')[1] } Add-M365DSCEvent -Message $_ -EntryType 'Error' ` -EventID 1 -Source $($MyInvocation.MyCommand.Source) ` -TenantId $tenantIdValue } catch { Write-Verbose -Message $_ } return $nullReturn } } function Set-TargetResource { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [System.String] $Name, [Parameter(Mandatory = $true)] [ValidateSet("Text", "Integer", "Decimal", "DateTime", "YesNo", "Double", "Binary")] [System.String] $Type, [Parameter()] [System.String] $Description, [Parameter()] [System.Boolean] $Searchable, [Parameter()] [System.String] $FullTextIndex, [Parameter()] [System.UInt32] $FullTextContext, [Parameter()] [System.Boolean] $Queryable, [Parameter()] [System.Boolean] $Retrievable, [Parameter()] [System.Boolean] $AllowMultipleValues, [Parameter()] [ValidateSet("No", "Yes - latent", "Yes")] [System.String] $Refinable, [Parameter()] [ValidateSet("No", "Yes - latent", "Yes")] [System.String] $Sortable, [Parameter()] [System.Boolean] $Safe, [Parameter()] [System.String[]] $Aliases, [Parameter()] [System.Boolean] $TokenNormalization, [Parameter()] [System.Boolean] $CompleteMatching, [Parameter()] [System.Boolean] $LanguageNeutralTokenization, [Parameter()] [System.Boolean] $FinerQueryTokenization, [Parameter()] [System.String[]] $MappedCrawledProperties, [Parameter()] [System.Boolean] $CompanyNameExtraction, [Parameter()] [ValidateSet("Present")] [System.String] $Ensure = "Present", [Parameter()] [System.Management.Automation.PSCredential] $GlobalAdminAccount, [Parameter()] [System.String] $ApplicationId, [Parameter()] [System.String] $TenantId, [Parameter()] [System.String] $CertificateThumbprint, [Parameter()] [System.String] $CertificatePath, [Parameter()] [System.Management.Automation.PSCredential] $CertificatePassword ) Write-Verbose -Message "Setting configuration for Managed Property instance $Name" #region Telemetry $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace("MSFT_", "") $data = [System.Collections.Generic.Dictionary[[String], [String]]]::new() $data.Add("Resource", $ResourceName) $data.Add("Method", $MyInvocation.MyCommand) $data.Add("Principal", $GlobalAdminAccount.UserName) $data.Add("TenantId", $TenantId) Add-M365DSCTelemetryEvent -Data $data #endregion $ConnectionMode = New-M365DSCConnection -Platform 'PnP' ` -InboundParameters $PSBoundParameters $SearchConfigTemplatePath = Join-Path -Path $PSScriptRoot ` -ChildPath "..\..\Dependencies\SearchConfigurationSettings.xml" ` -Resolve $SearchConfigXML = [Xml] (Get-Content $SearchConfigTemplatePath -Raw) # Get the managed property back if it already exists. if ($null -eq $Script:RecentMPExtract) { $Script:RecentMPExtract = [XML] (Get-PnPSearchConfiguration -Scope Subscription) } $property = $Script:RecentMPExtract.SearchConfigurationSettings.SearchSchemaConfigurationSettings.ManagedProperties.dictionary.KeyValueOfstringManagedPropertyInfoy6h3NzC8 ` | Where-Object -FilterScript { $_.Value.Name -eq $Name } if ($null -ne $property) { $currentPID = $property.Value.Pid } $prop = $SearchConfigXml.ChildNodes[0].SearchSchemaConfigurationSettings.ManagedProperties.dictionary $newManagedPropertyElement = $SearchConfigXML.CreateElement("d4p1:KeyValueOfstringManagedPropertyInfoy6h3NzC8", ` "http://schemas.microsoft.com/2003/10/Serialization/Arrays") $keyNode = $SearchConfigXML.CreateElement("d4p1:Key", ` "http://schemas.microsoft.com/2003/10/Serialization/Arrays") $keyNode.InnerText = $Name $newManagedPropertyElement.AppendChild($keyNode) | Out-Null $valueNode = $SearchConfigXML.CreateElement("d4p1:Value", ` "http://schemas.microsoft.com/2003/10/Serialization/Arrays") $node = $SearchConfigXML.CreateElement("d3p1:Name", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $node.InnerText = $Name $valueNode.AppendChild($node) | Out-Null $node = $SearchConfigXML.CreateElement("d3p1:CompleteMatching", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $node.InnerText = $CompleteMatching.ToString().Replace("$", "").ToLower() $valueNode.AppendChild($node) | Out-Null $node = $SearchConfigXML.CreateElement("d3p1:Context", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $node.InnerText = $FullTextContext.ToString() $valueNode.AppendChild($node) | Out-Null $node = $SearchConfigXML.CreateElement("d3p1:DeleteDisallowed", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $node.InnerText = "false" $valueNode.AppendChild($node) | Out-Null $node = $SearchConfigXML.CreateElement("d3p1:Description", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $node.InnerText = $Description $valueNode.AppendChild($node) | Out-Null $node = $SearchConfigXML.CreateElement("d3p1:EnabledForScoping", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $node.InnerText = "false" $valueNode.AppendChild($node) | Out-Null #region EntiryExtractionBitMap $node = $SearchConfigXML.CreateElement("d3p1:EntityExtractorBitMap", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") if ($CompanyNameExtraction) { $node.InnerText = "4161" } else { $node.InnerText = "0" } $valueNode.AppendChild($node) | Out-Null #endregion $node = $SearchConfigXML.CreateElement("d3p1:ExpandSegments", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $node.InnerText = $FinerQueryTokenization.ToString().Replace("$", "").ToLower() $valueNode.AppendChild($node) | Out-Null $node = $SearchConfigXML.CreateElement("d3p1:FullTextIndex", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $node.InnerText = $FullTextIndex $valueNode.AppendChild($node) | Out-Null $node = $SearchConfigXML.CreateElement("d3p1:HasMultipleValues", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $node.InnerText = $AllowMultipleValues.ToString().Replace("$", "").ToLower() $valueNode.AppendChild($node) | Out-Null $node = $SearchConfigXML.CreateElement("d3p1:IndexOptions", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $node.InnerText = "0" $valueNode.AppendChild($node) | Out-Null $node = $SearchConfigXML.CreateElement("d3p1:IsImplicit", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $node.InnerText = "false" $valueNode.AppendChild($node) | Out-Null $node = $SearchConfigXML.CreateElement("d3p1:IsReadOnly", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $node.InnerText = "false" $valueNode.AppendChild($node) | Out-Null #region LanguageNeutralWordBreaker if ($LanguageNeutralTokenization -and $CompleteMatching) { throw "You cannot have CompleteMatching set to True if LanguageNeutralTokenization is set to True" } $node = $SearchConfigXML.CreateElement("d3p1:LanguageNeutralWordBreaker", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $node.InnerText = $LanguageNeutralTokenization.ToString().Replace("$", "").ToLower() $valueNode.AppendChild($node) | Out-Null #endregion $node = $SearchConfigXML.CreateElement("d3p1:ManagedType", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $node.InnerText = $Type $valueNode.AppendChild($node) | Out-Null $node = $SearchConfigXML.CreateElement("d3p1:MappingDisallowed", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $node.InnerText = "false" $valueNode.AppendChild($node) | Out-Null #region PID if ($null -ne $currentPID) { $node = $SearchConfigXML.CreateElement("d3p1:Pid", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $node.InnerText = $currentPid $valueNode.AppendChild($node) | Out-Null } #endregion $node = $SearchConfigXML.CreateElement("d3p1:Queryable", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $node.InnerText = $Queryable.ToString().Replace("$", "").ToLower() $valueNode.AppendChild($node) | Out-Null #region Refinable $value = $false if ($Refinable -eq "Yes") { $value = $true } $node = $SearchConfigXML.CreateElement("d3p1:Refinable", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $node.InnerText = $value.ToString().Replace("$", "").ToLower() $valueNode.AppendChild($node) | Out-Null $node = $SearchConfigXML.CreateElement("d3p1:RefinerConfiguration", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $subNode = $SearchConfigXML.CreateElement("d3p1:Anchoring", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $subNode.InnerText = "Auto" $node.AppendChild($subNode) | Out-Null $subNode = $SearchConfigXML.CreateElement("d3p1:CutoffMaxBuckets", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $subNode.InnerText = "1000" $node.AppendChild($subNode) | Out-Null $subNode = $SearchConfigXML.CreateElement("d3p1:Divisor", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $subNode.InnerText = "1" $node.AppendChild($subNode) | Out-Null $subNode = $SearchConfigXML.CreateElement("d3p1:Intervals", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $subNode.InnerText = "4" $node.AppendChild($subNode) | Out-Null $subNode = $SearchConfigXML.CreateElement("d3p1:Resolution", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $subNode.InnerText = "1" $node.AppendChild($subNode) | Out-Null $subNode = $SearchConfigXML.CreateElement("d3p1:Type", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $subNode.InnerText = "Deep" $node.AppendChild($subNode) | Out-Null $valueNode.AppendChild($node) | Out-Null #endregion $node = $SearchConfigXML.CreateElement("d3p1:RemoveDuplicates", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $node.InnerText = "true" $valueNode.AppendChild($node) | Out-Null $node = $SearchConfigXML.CreateElement("d3p1:RespectPriority", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $node.InnerText = "false" $valueNode.AppendChild($node) | Out-Null $node = $SearchConfigXML.CreateElement("d3p1:Retrievable", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $node.InnerText = $Retrievable.ToString().Replace("$", "").ToLower() $valueNode.AppendChild($node) | Out-Null $node = $SearchConfigXML.CreateElement("d3p1:SafeForAnonymous", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $node.InnerText = $Safe.ToString().Replace("$", "").ToLower() $valueNode.AppendChild($node) | Out-Null $node = $SearchConfigXML.CreateElement("d3p1:Searchable", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $node.InnerText = $Searchable.ToString().Replace("$", "").ToLower() $valueNode.AppendChild($node) | Out-Null #region Sortable $value = $false if ($Sortable -eq "Yes") { $value = $true } $node = $SearchConfigXML.CreateElement("d3p1:Sortable", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $node.InnerText = $value.ToString().Replace("$", "").ToLower() $valueNode.AppendChild($node) | Out-Null #endregion $node = $SearchConfigXML.CreateElement("d3p1:SortableType", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $node.InnerText = "Enabled" $valueNode.AppendChild($node) | Out-Null $node = $SearchConfigXML.CreateElement("d3p1:TokenNormalization", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $node.InnerText = $TokenNormalization.ToString().Replace("$", "").ToLower() $valueNode.AppendChild($node) | Out-Null $newManagedPropertyElement.AppendChild($valueNode) $prop.AppendChild($newManagedPropertyElement) | Out-Null $tempPath = Join-Path -Path $ENV:TEMP ` -ChildPath ((New-Guid).ToString().Split('-')[0] + ".config") $SearchConfigXML.OuterXml | Out-File $tempPath # Create the Managed Property if it doesn't already exist Set-PnPSearchConfiguration -Scope Subscription -Path $tempPath #region Aliases if ($null -ne $Aliases) { $aliasesArray = $Aliases.Split(';') $aliasProp = $SearchConfigXml.ChildNodes[0].SearchSchemaConfigurationSettings.Aliases.dictionary if ($null -eq $currentPID) { # Get the managed property back. This is the only way to ensure we have the right PID $currentConfigXML = [XML] (Get-PnPSearchConfiguration -Scope Subscription) $property = $currentConfigXML.SearchConfigurationSettings.SearchSchemaConfigurationSettings.ManagedProperties.dictionary.KeyValueOfstringManagedPropertyInfoy6h3NzC8 ` | Where-Object -FilterScript { $_.Value.Name -eq $Name } $currentPID = $property.Value.Pid $node = $SearchConfigXML.CreateElement("d3p1:Pid", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $node.InnerText = $currentPID # The order in which we list the properties matters. Pid is to appear right after MappingDisallowed. $namespaceMgr = New-Object System.Xml.XmlNamespaceManager($SearchConfigXML.NameTable); $namespaceMgr.AddNamespace("d3p1", "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $previousNode = $SearchConfigXML.SelectSingleNode("//d3p1:MappingDisallowed", $namespaceMgr) $previousNode.ParentNode.InsertAfter($node, $previousNode) | Out-Null } foreach ($alias in $aliasesArray) { $mainNode = $SearchConfigXML.CreateElement("d4p1:KeyValueOfstringAliasInfoy6h3NzC8", ` "http://schemas.microsoft.com/2003/10/Serialization/Arrays") $keyNode = $SearchConfigXML.CreateElement("d4p1:Key", ` "http://schemas.microsoft.com/2003/10/Serialization/Arrays") $keyNode.InnerText = $alias $valueNode = $SearchConfigXML.CreateElement("d4p1:Value", ` "http://schemas.microsoft.com/2003/10/Serialization/Arrays") $node = $SearchConfigXML.CreateElement("d3p1:Name", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $node.InnerText = $alias $valueNode.AppendChild($node) | Out-Null $node = $SearchConfigXML.CreateElement("d3p1:ManagedPid", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $node.InnerText = $currentPID $valueNode.AppendChild($node) | Out-Null $node = $SearchConfigXML.CreateElement("d3p1:SchemaId", ` "http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration") $node.InnerText = "6408" $valueNode.AppendChild($node) | Out-Null $mainNode.AppendChild($keyNode) | Out-Null $mainNode.AppendChild($valueNode) | Out-Null $aliasProp.AppendChild($mainNode) | Out-Null } $tempPath = Join-Path -Path $ENV:TEMP ` -ChildPath ((New-Guid).ToString().Split('-')[0] + ".config") Write-Verbose -Message "Configuring SPO Search Schema with the following XML Document" Write-Verbose $SearchConfigXML.OuterXML $SearchConfigXML.OuterXml | Out-File $tempPath # Create the aliases on the Managed Property Set-PnPSearchConfiguration -Scope Subscription -Path $tempPath } } function Test-TargetResource { [CmdletBinding()] [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] [System.String] $Name, [Parameter(Mandatory = $true)] [ValidateSet("Text", "Integer", "Decimal", "DateTime", "YesNo", "Double", "Binary")] [System.String] $Type, [Parameter()] [System.String] $Description, [Parameter()] [System.Boolean] $Searchable, [Parameter()] [System.String] $FullTextIndex, [Parameter()] [System.UInt32] $FullTextContext, [Parameter()] [System.Boolean] $Queryable, [Parameter()] [System.Boolean] $Retrievable, [Parameter()] [System.Boolean] $AllowMultipleValues, [Parameter()] [ValidateSet("No", "Yes - latent", "Yes")] [System.String] $Refinable, [Parameter()] [ValidateSet("No", "Yes - latent", "Yes")] [System.String] $Sortable, [Parameter()] [System.Boolean] $Safe, [Parameter()] [System.String[]] $Aliases, [Parameter()] [System.Boolean] $TokenNormalization, [Parameter()] [System.Boolean] $CompleteMatching, [Parameter()] [System.Boolean] $LanguageNeutralTokenization, [Parameter()] [System.Boolean] $FinerQueryTokenization, [Parameter()] [System.String[]] $MappedCrawledProperties, [Parameter()] [System.Boolean] $CompanyNameExtraction, [Parameter()] [ValidateSet("Present")] [System.String] $Ensure = "Present", [Parameter()] [System.Management.Automation.PSCredential] $GlobalAdminAccount, [Parameter()] [System.String] $ApplicationId, [Parameter()] [System.String] $TenantId, [Parameter()] [System.String] $CertificateThumbprint, [Parameter()] [System.String] $CertificatePath, [Parameter()] [System.Management.Automation.PSCredential] $CertificatePassword ) #region Telemetry $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace("MSFT_", "") $data = [System.Collections.Generic.Dictionary[[String], [String]]]::new() $data.Add("Resource", $ResourceName) $data.Add("Method", $MyInvocation.MyCommand) $data.Add("Principal", $GlobalAdminAccount.UserName) $data.Add("TenantId", $TenantId) Add-M365DSCTelemetryEvent -Data $data #endregion Write-Verbose -Message "Testing configuration for Managed Property instance $Name" $CurrentValues = Get-TargetResource @PSBoundParameters Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` -Source $($MyInvocation.MyCommand.Source) ` -DesiredValues $PSBoundParameters ` -ValuesToCheck @("Ensure", ` "Name", "Type") Write-Verbose -Message "Test-TargetResource returned $TestResult" return $TestResult } function Export-TargetResource { [CmdletBinding()] [OutputType([System.String])] param ( [Parameter()] [System.Management.Automation.PSCredential] $GlobalAdminAccount, [Parameter()] [System.String] $ApplicationId, [Parameter()] [System.String] $TenantId, [Parameter()] [System.String] $CertificateThumbprint, [Parameter()] [System.String] $CertificatePath, [Parameter()] [System.Management.Automation.PSCredential] $CertificatePassword ) $ConnectionMode = New-M365DSCConnection -Platform 'PnP' ` -InboundParameters $PSBoundParameters #region Telemetry $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace("MSFT_", "") $data = [System.Collections.Generic.Dictionary[[String], [String]]]::new() $data.Add("Resource", $ResourceName) $data.Add("Method", $MyInvocation.MyCommand) $data.Add("Principal", $GlobalAdminAccount.UserName) $data.Add("TenantId", $TenantId) $data.Add("ConnectionMode", $ConnectionMode) Add-M365DSCTelemetryEvent -Data $data #endregion try { $SearchConfig = [Xml] (Get-PnPSearchConfiguration -Scope Subscription) [array]$properties = $SearchConfig.SearchConfigurationSettings.SearchSchemaConfigurationSettings.ManagedProperties.dictionary.KeyValueOfstringManagedPropertyInfoy6h3NzC8 $dscContent = "" $i = 1 Write-Host "`r`n" -NoNewline foreach ($property in $properties) { Write-Host " |---[$i/$($properties.Length)] $($property.Value.Name)" -NoNewline $Params = @{ GlobalAdminAccount = $GlobalAdminAccount Name = $property.Value.Name Type = $property.Value.ManagedType ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint CertificatePath = $CertificatePath CertificatePassword = $CertificatePassword } $Results = Get-TargetResource @Params $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` -Results $Results $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` -ConnectionMode $ConnectionMode ` -ModulePath $PSScriptRoot ` -Results $Results ` -GlobalAdminAccount $GlobalAdminAccount $dscContent += $currentDSCBlock Save-M365DSCPartialExport -Content $currentDSCBlock ` -FileName $Global:PartialExportFileName $i++ Write-Host $Global:M365DSCEmojiGreenCheckmark } return $dscContent } catch { try { Write-Verbose -Message $_ $tenantIdValue = "" if (-not [System.String]::IsNullOrEmpty($TenantId)) { $tenantIdValue = $TenantId } elseif ($null -ne $GlobalAdminAccount) { $tenantIdValue = $GlobalAdminAccount.UserName.Split('@')[1] } Add-M365DSCEvent -Message $_ -EntryType 'Error' ` -EventID 1 -Source $($MyInvocation.MyCommand.Source) ` -TenantId $tenantIdValue } catch { Write-Verbose -Message $_ } return "" } } Export-ModuleMember -Function *-TargetResource |