Private/_Helpers.ps1
|
function Get-ManifestValue { #.Synopsis # Reads a specific value from a module manifest #.Description # By default Get-ManifestValue gets the ModuleVersion, but it can read any key in the Module Manifest, including the PrivateData, or the PSData inside the PrivateData. #.Example # Get-ManifestValue .\Configuration.psd1 # # Returns the module version number (as a string) #.Example # Get-ManifestValue .\Configuration.psd1 ReleaseNotes # # Returns the release notes! [CmdletBinding()] param( # The path to the module manifest file [Parameter(ValueFromPipelineByPropertyName = "True", Position = 0)] [Alias("PSPath")] [string]$Manifest, # The property to be read from the manifest. Get-ManifestValue searches the Manifest root properties, then the properties PrivateData, then the PSData [Parameter(ParameterSetName = "Overwrite", Position = 1)] [string]$PropertyName = 'ModuleVersion', [switch]$Passthru ) $ErrorActionPreference = "Stop" if (Test-Path $Manifest) { $ManifestContent = Get-Content $Manifest -Raw } else { $ManifestContent = $Manifest } $Tokens = $Null; $ParseErrors = $Null $AST = [System.Management.Automation.Language.Parser]::ParseInput( $ManifestContent, $Manifest, [ref]$Tokens, [ref]$ParseErrors ) $ManifestHash = $AST.Find( { $args[0] -is [System.Management.Automation.Language.HashtableAst] }, $true ) $KeyValue = $ManifestHash.KeyValuePairs.Where{ $_.Item1.Value -eq $PropertyName }.Item2 # Recursively search for PropertyName in the PrivateData and PrivateData.PSData if (!$KeyValue) { $global:devops_PrivateData = $ManifestHash.KeyValuePairs.Where{ $_.Item1.Value -eq 'PrivateData' }.Item2.PipelineElements.Expression $KeyValue = $PrivateData.KeyValuePairs.Where{ $_.Item1.Value -eq $PropertyName }.Item2 if (!$KeyValue) { $global:devops_PSData = $PrivateData.KeyValuePairs.Where{ $_.Item1.Value -eq 'PSData' }.Item2.PipelineElements.Expression $KeyValue = $PSData.KeyValuePairs.Where{ $(Write-Verbose "'$($_.Item1.Value)' -eq '$PropertyName'"); $_.Item1.Value -eq $PropertyName }.Item2 if (!$KeyValue) { Write-Error "Couldn't find '$PropertyName' to update in '$(Convert-Path $ManifestPath)'" return } } } if ($Passthru) { $KeyValue } else { $KeyValue.SafeGetValue() } } ### Internal Helpers function CrmTimerStart{ $script:crmtimer = New-Object -TypeName 'System.Diagnostics.Stopwatch' $script:crmtimer.Start() } function CrmTimerStop{ $crmtimerobj = Get-Variable crmtimer -Scope Script if($crmtimerobj.Value -ne $null) { $script:crmtimer = $crmtimerobj.Value $script:crmtimer.Stop() $perf = "The operation took " + $script:crmtimer.Elapsed.ToString() Remove-Variable crmtimer -Scope Script return $perf } } function Convert-CrmEntityToPsObject { [CmdletBinding()] PARAM( [parameter(Mandatory=$true)] [Microsoft.Xrm.Sdk.Entity]$Entity, [parameter(Mandatory=$false)] [string]$LogicalName ) $record = New-Object PSObject $record | Add-Member -MemberType NoteProperty -Name "Id" -Value $Entity.Id $record | Add-Member -MemberType NoteProperty -Name "LogicalName" -Value $Entity.LogicalName if(-not [string]::IsNullOrEmpty($LogicalName) -and $Entity.LogicalName -ne $LogicalName) { $record | Add-Member -MemberType NoteProperty -Name "RequestedLogicalName" -Value $LogicalName } foreach($attribute in $Entity.Attributes.GetEnumerator()) { $name = $attribute.Key $value = $attribute.Value if($value -is [Microsoft.Xrm.Sdk.AliasedValue]) { $value = $value.Value } $record | Add-Member -MemberType NoteProperty -Name $name -Value $value -Force } foreach($formattedValue in $Entity.FormattedValues.GetEnumerator()) { $formattedName = "$($formattedValue.Key)_FormattedValue" $record | Add-Member ` -MemberType NoteProperty ` -Name $formattedName ` -Value $formattedValue.Value ` -Force } return $record } function parseRecordsPage { PARAM( [parameter(Mandatory=$true)] [object]$records, [parameter(Mandatory=$true)] [string] $logicalname, [parameter(Mandatory=$true)] [xml] $xml ) $recordslist = New-Object 'System.Collections.Generic.List[System.Management.Automation.PSObject]' foreach($record in $records.Values){ $null = $record.Add("original",$record) $null = $record.Add("logicalname",$logicalname) if($record.ContainsKey("ReturnProperty_Id ")) { $null = $record.Add("ReturnProperty_Id",$record.'ReturnProperty_Id ') $null = $record.Remove("ReturnProperty_Id ") } #add entityReferences values as values ForEach($attribute in $record.Keys|Select) { if(-not $attribute.EndsWith("_Property")) { continue } #if aliased value BUT if it's an EntityRef... then ignore it if($record[$attribute].Value -is [Microsoft.Xrm.Sdk.AliasedValue]) { if($record[$attribute].Value.Value -isnot [Microsoft.Xrm.Sdk.EntityReference]) { $attName = $attribute.Replace("_Property","") $record[$attName] = $record[$attribute].Value.Value } } if($record[$attribute].Value -is [Microsoft.Xrm.Sdk.EntityReference]) { $attName = $attribute.Replace("_Property","") $record[$attName] = $record[$attribute].Value.Name } } $hashtable = $record -as [Hashtable] #adding Dynamic EntityReference if ($hashtable.ReturnProperty_Id -and $hashtable.ReturnProperty_EntityName) { $hashtable.EntityReference = New-CrmEntityReference -EntityLogicalName $hashtable.ReturnProperty_EntityName -Id $hashtable.ReturnProperty_Id } $recordslist.Add([pscustomobject]$hashtable) } $recordslist } function Coalesce { foreach($i in $args){ if($i -ne $null){ return $i } } } function VerifyCrmConnectionParam { [CmdletBinding()] PARAM( [parameter(Mandatory=$false)] [Microsoft.Xrm.Sdk.IOrganizationService]$conn, [parameter(Mandatory=$false)] [bool]$pipelineValue ) #we have a $conn value and we were not given a $conn value so we should try to find one if($conn -eq $null -and $pipelineValue -eq $false) { $connobj = Get-Variable conn -Scope global -ErrorAction SilentlyContinue if($connobj.Value -eq $null) { Write-Error "A connection to Dataverse is required, use Get-Dataverse to connect." throw 'A connection to Dataverse is required, use Get-Dataverse to connect.' } else { $conn = $connobj.Value } }elseif($conn -eq $null -and $pipelineValue -eq $true){ Write-Error "Connection object provided is null" throw "Connection object provided is null" } return $conn } function MapFieldTypeByFieldValue { PARAM( [Parameter(Mandatory=$true)][AllowNull()] [object]$Value ) $valueTypeToSdkTypeMapping = @{ "Boolean" = [System.Boolean] "DateTime" = [System.DateTime] "Decimal" = [System.Decimal] "Single" = [System.Single] "Money" = [Microsoft.Xrm.Sdk.Money] "Int32" = [System.Int32] "EntityReference" = [Microsoft.Xrm.Sdk.EntityReference] "OptionSetValue" = [Microsoft.Xrm.Sdk.OptionSetValue] "String" = [System.String] "Guid" = [System.Guid] } # default is RAW $crmDataType = $null if($Value -ne $null) { $valueType = $Value.GetType().Name if($valueTypeToCrmTypeMapping.ContainsKey($valueType)) { $crmDataType = $valueTypeToCrmTypeMapping[$valueType] } } return $crmDatatype } function GuessPrimaryKeyField() { PARAM( [Parameter(Mandatory=$true)] [object]$EntityLogicalName ) $standardActivityEntities = @( "opportunityclose", "socialactivity", "campaignresponse", "letter","orderclose", "appointment", "recurringappointmentmaster", "fax", "email", "activitypointer", "incidentresolution", "bulkoperation", "quoteclose", "task", "campaignactivity", "serviceappointment", "phonecall" ) # Some Entity has different pattern for id name. if($EntityLogicalName -eq "usersettings") { $primaryKeyField = "systemuserid" } elseif($EntityLogicalName -eq "systemform") { $primaryKeyField = "formid" } elseif($EntityLogicalName -in $standardActivityEntities) { $primaryKeyField = "activityid" } else { # default $primaryKeyField = $EntityLogicalName + "id" } $primaryKeyField } function AddTls12Support { #by default PowerShell will show Ssl3, Tls - since SSL3 is not desirable we will drop it and use Tls + Tls12 [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls -bor [System.Net.SecurityProtocolType]::Tls12 } function ApplyCrmServiceClientObjectTemplate { [CmdletBinding()] PARAM( [parameter(Mandatory=$true)] [Microsoft.Xrm.Sdk.IOrganizationService]$conn ) try{ $defaultPropsCrmServiceClient = @( 'IsReady', 'IsBatchOperationsAvailable', 'MaxRetryCount', 'RetryPauseTime', 'Authority', 'ActiveAuthenticationType', 'OAuthUserId', 'TenantId', 'EnvironmentId', 'ConnectedOrgId', 'CrmConnectOrgUriActual', 'ConnectedOrgFriendlyName', 'ConnectedOrgUniqueName', 'ConnectedOrgVersion', 'SdkVersionProperty', 'CallerId', 'CallerAADObjectId', 'DisableCrossThreadSafeties', 'SessionTrackingId', 'ForceServerMetadataCacheConsistency', 'LastCrmError' ) $defaultPropsSetCrmServiceClient=New-Object System.Management.Automation.PSPropertySet('DefaultDisplayPropertySet',[string[]]$defaultPropsCrmServiceClient) $PSStandardMembers = [System.Management.Automation.PSMemberInfo[]]@($defaultPropsSetCrmServiceClient) $conn| Add-Member MemberSet PSStandardMembers $PSStandardMembers -Force }Catch{ Write-Verbose "Failed to set a new PSStandardMember on connection object" } } ## Taken from CRM SDK sample code ## https://msdn.microsoft.com/en-us/library/microsoft.crm.sdk.messages.retrieveentityribbonresponse.compressedentityxml.aspx function UnzipCrmRibbon { PARAM( [parameter(Mandatory=$true)] [Byte[]]$Data ) $memStream = New-Object System.IO.MemoryStream $memStream.Write($Data, 0, $Data.Length) $package = [System.IO.Packaging.ZipPackage]::Open($memStream, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read) $part = $package.GetPart([System.Uri]::new('/RibbonXml.xml', [System.UriKind]::Relative)) try { $strm = $part.GetStream() $reader = [System.Xml.XmlReader]::Create($strm) $xmlDoc = New-Object System.Xml.XmlDocument $xmlDoc.Load($reader) return $xmlDoc } finally { if ($strm -ne $null) { $strm.Dispose() $strm = $null } if ($reader -ne $null) { $reader.Dispose() $reader = $null } } } |