Microsoft.Xrm.OnlineManagementAPI.psm1
function Get-CrmLanguages { <# .SYNOPSIS Get languages .DESCRIPTION The Get-CrmLanguages cmdlet retrieves all languages supported by Dynamics 365 Customer Enagagement (online) for the specified service release. Use Get-Help Get-CrmLanguages -Examples for more detail. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER MaxCrmConnectionTimeOutMinutes Maximum number in minutes to wait before quitting the operation. .PARAMETER ServiceReleaseId Release Id for a release of Microsoft Dynamics 365 (online). You can find the ServiceReleaseId by running the Get-CrmServiceVersions cmdlet. .EXAMPLE Get-CrmLanguages Get languages. #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $false)] [object]$Credential, [Parameter(Mandatory = $false)] [int]$MaxCrmConnectionTimeOutMinutes = 30, [Parameter(Mandatory = $false)] [string]$ServiceReleaseId ) process { AuthenticationAndLoadModule -Credential $Credential $location = UrlToLocationMapping -ApiUrl $ApiUrl Write-Verbose "Calling Get-AdminPowerAppCdsDatabaseLanguages." $response = Get-AdminPowerAppCdsDatabaseLanguages -LocationName $location -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) $languages = @() foreach ($language in $response) { $languages += CreateLanguageObject -Language $language } return $languages } } function Get-CrmTemplates { <# .SYNOPSIS Get templates .DESCRIPTION The Get-CrmTemplates cmdlet retrieves a list of application templates supported for provisioning a Dynamics 365 Customer Engagement (online) instance. Use Get-Help Get-CrmTemplates -Examples for more detail. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER MaxCrmConnectionTimeOutMinutes Maximum number in minutes to wait before quitting the operation. .EXAMPLE Get-CrmTemplates Get templates. #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $false)] [object]$Credential, [Parameter(Mandatory = $false)] [int]$MaxCrmConnectionTimeOutMinutes = 30 ) process { AuthenticationAndLoadModule -Credential $Credential $location = UrlToLocationMapping -ApiUrl $ApiUrl Write-Verbose "Calling Get-AdminPowerAppCdsDatabaseTemplates." $response = Get-AdminPowerAppCdsDatabaseTemplates -LocationName $location -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) $templates = @() foreach ($template in $response) { $templates += CreateTemplateObject -Template $template } return $templates } } function Get-CrmCurrencies { <# .SYNOPSIS Get templates .DESCRIPTION The Get-CrmCurrencies cmdlet returns a list of currencies that are available for all instances within the same tenant. Use Get-Help Get-CrmCurrencies -Examples for more detail. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER MaxCrmConnectionTimeOutMinutes Maximum number in minutes to wait before quitting the operation. .EXAMPLE Get-CrmCurrencies Get templates. #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $false)] [object]$Credential, [Parameter(Mandatory = $false)] [int]$MaxCrmConnectionTimeOutMinutes = 30 ) process { AuthenticationAndLoadModule -Credential $Credential $location = UrlToLocationMapping -ApiUrl $ApiUrl Write-Verbose "Calling Get-AdminPowerAppCdsDatabaseCurrencies." $response = Get-AdminPowerAppCdsDatabaseCurrencies -LocationName $location -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) $currencies = @() foreach ($currency in $response) { $currencies += CreateCurrencyObject -Currency $currency } return $currencies } } function Get-CrmServiceVersions { <# .SYNOPSIS Get service version .DESCRIPTION The Get-CrmServiceVersions cmdlet retrieves information about all currently supported releases for Dynamics 365 Customer Engagement (online). Use Get-Help Get-CrmServiceVersions -Examples for more detail. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .EXAMPLE Get-CrmServiceVersions Get service version #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $false)] [object]$Credential ) process { $versions = @() $versions += CreateServiceVersionObject return $versions } } function Get-CrmInstances { <# .SYNOPSIS Get Dynamics 365 Customer Engagement (online) instances .DESCRIPTION The Get-CrmInstances cmdlet retrieves details for Dynamics 365 Customer Engagement (online) instances that are in your tenant. Use Get-Help Get-CrmInstances -Examples for more detail. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .EXAMPLE Get-CrmInstances Get Dynamics 365 Customer Engagement (online) instances #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $false)] [object]$Credential = $null ) process { AuthenticationAndLoadModule -Credential $Credential Write-Verbose "Calling Get-AdminPowerAppEnvironment." $response = Get-AdminPowerAppEnvironment -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) $instances = @() foreach ($environment in $response) { if ($environment.Internal.properties.linkedEnvironmentMetadata -ne $null) { $instances += CreateInstanceObject -Environment $environment } } return $instances } } function Get-CrmProtectedInstances { <# .SYNOPSIS Get Dynamics 365 Customer Engagement (online) instances .DESCRIPTION The Get-CrmProtectedInstances cmdlet retrieves details for Dynamics 365 Customer Engagement (online) instances that are in your tenant. Use Get-Help Get-CrmProtectedInstances -Examples for more detail. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .EXAMPLE Get-CrmProtectedInstances Get Dynamics 365 Customer Engagement (online) instances #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $false)] [object]$Credential ) process { AuthenticationAndLoadModule -Credential $Credential Write-Verbose "Calling Get-AdminPowerAppEnvironment." $response = Get-AdminPowerAppEnvironment -GetProtectedEnvironment -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) $instances = @() foreach ($environment in $response) { if ($environment.Internal.properties.linkedEnvironmentMetadata -ne $null) { $instances += CreateInstanceObject -Environment $environment } } return $instances } } function Get-CrmInstance { <# .SYNOPSIS Get Dynamics 365 Customer Engagement (online) instance .DESCRIPTION The Get-CrmInstance cmdlet retrieves a Dynamics 365 Customer Engagement (online) instance in your Office 365 tenant. Use Get-Help Get-CrmInstance -Examples for more detail. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER Id Instance Id for the specific instance of Dynamics 365 Customer Engagement (online). Use the Get-CrmInstances cmdlet to find all instance Ids within the same tenant. .EXAMPLE Get-CrmInstance -Id $InstanceId Get Dynamics 365 Customer Engagement (online) instance on Id #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $true)] [string]$Id, [Parameter(Mandatory = $false)] [object]$Credential ) process { AuthenticationAndLoadModule -Credential $Credential $environment = Get-AdminPowerAppEnvironment -InstanceId $Id -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) return CreateInstanceObject -Environment $environment } } function New-CrmInstanceInfo { <# .SYNOPSIS Create CrmInstanceInfo object .DESCRIPTION The New-CrmInstanceInfo cmdlet creates the object that defines the parameters used to create a new instance of Dynamics 365 Customer Enagagement (online) by using the New-CrmInstance cmdlet. Use Get-Help Get-CrmInstances -Examples for more detail. .PARAMETER BaseLanguage Required parameter. The base language for the instance. For a list of available languages, run the Get-CrmLanguages cmdlet. .PARAMETER DomainName Required parameter. Used for part of the domain namespace and appears in the application url. .PARAMETER InitialUserEmail Required parameter. Email address to receive notifications about the instance. .PARAMETER ServiceVersionId Required parameter. Specifies the service release of the instance. For a list of available service releases, run the Get-CrmServiceVersions cmdlet. .PARAMETER InstanceType Required parameter. Sets the instance type, such as Sandbox or Production. For a full list, run the Get-CrmInstanceTypes cmdlet. .PARAMETER FriendlyName Required parameter. This is typically the name of your organization and is displayed in the Microsoft Dynamics 365 application. .PARAMETER TemplateList Optional parameter. Specifies the apps you want provisioned in the instance. For a list of available template names, run the Get-CrmTemplates cmdlet. .PARAMETER Purpose Optional parameter. A description used to associate the instance with a specific intent. Only tenant administrators will see this description. .PARAMETER SecurityGroupId Optional parameter. This value is used to determine the security group that includes the users who will have access to this instance of Microsoft Dynamics 365 (online). .PARAMETER CurrencyCode Optional parameter. The currency region code to use for the instance. You can find a list of currency region codes by running the Get-CrmCurrencies cmdlet. .PARAMETER CurrencyName Optional parameter. The currency name to use for the instance. You can find a list of currency names by running the Get-CrmCurrencies cmdlet. .PARAMETER CurrencyPrecision Optional parameter. Set the pricing decimal precision. Valid values are 0-4. .PARAMETER CurrencySymbol Optional parameter. Set the symbol that will represent the currency. .EXAMPLE New-CrmInstanceInfo -BaseLanguage 1033 -DomainName "Test" -InitialUserEmail admin@test.onmicrosoft.com -ServiceVersionId $ServiceVersions[0].Id -InstanceType Sandbox -FriendlyName "Test" -Purpose "TestPurpose" -CurrencyCode USD -CurrencySymbol "$" -CurrencyName "US Dollar" Create CrmInstanceInfo object #> param ( [Parameter(Mandatory = $true)] [int]$BaseLanguage, [Parameter(Mandatory = $true)] [string]$DomainName, [Parameter(Mandatory = $true)] [string]$InitialUserEmail, [Parameter(Mandatory = $true)] [guid]$ServiceVersionId, [Parameter(Mandatory = $true)] [string]$InstanceType, [Parameter(Mandatory = $true)] [string]$FriendlyName, [Parameter(Mandatory = $false)] [string[]]$TemplateList, [Parameter(Mandatory = $false)] [string]$Purpose, [Parameter(Mandatory = $false)] [guid]$SecurityGroupId, [Parameter(Mandatory = $false)] [string]$CurrencyCode, [Parameter(Mandatory = $false)] [string]$CurrencyName, [Parameter(Mandatory = $false)] [int]$CurrencyPrecision, [Parameter(Mandatory = $false)] [string]$CurrencySymbol ) $currency = New-Object -TypeName Microsoft.Xrm.Services.Admin.Client.Models.Currency($CurrencyCode, $CurrencyPrecision, $CurrencySymbol, $CurrencyName) return New-Object -TypeName Microsoft.Xrm.Services.Admin.Client.Models.NewInstance( ` $ServiceVersionId, ` $InstanceType, ` $FriendlyName, ` $DomainName, ` $InitialUserEmail, ` $currency, ` $TemplateList, ` $Purpose, ` $BaseLanguage, ` $SecurityGroupId) } function New-CrmInstance { <# .SYNOPSIS Provisions Dynamics 365 Customer Engagement (online) instance .DESCRIPTION The New-CrmInstance cmdlet provisions (creates) a Dynamics 365 Customer Engagement (online) instance in your Office 365 tenant. Use Get-Help New-CrmInstance -Examples for more detail. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER NewInstanceInfo Object created by using the New-CrmInstanceInfo cmdlet that contains the information used to provision the instance. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER MaxCrmConnectionTimeOutMinutes Maximum number in minutes to wait before quitting the operation. .PARAMETER ValidateOnly Indicates whether to validate that an instance can be provisioned with the provided parameters or create an instance. Set 1 to validate; set 0 to create. .EXAMPLE New-CrmInstance -ApiUrl $connecthost -Credential $cred -Verbose -NewInstanceInfo $instanceInfo Provisions Dynamics 365 Customer Engagement (online) instance #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $true)] [object]$NewInstanceInfo, [Parameter(Mandatory = $false)] [object]$Credential, [Parameter(Mandatory = $false)] [int]$MaxCrmConnectionTimeOutMinutes = 10, [Parameter(Mandatory = $false)] [switch]$ValidateOnly ) process { if ($ValidateOnly) { $context = New-Object -TypeName Microsoft.Xrm.Services.Admin.Client.Models.OperationContext return CreateOperationStatusObject ` -OperationId "00000000-0000-0000-0000-000000000000" ` -Status "NotStarted" ` -Context $context } $waitUntilFinished = $true if ($MaxCrmConnectionTimeOutMinutes -eq 0) { $waitUntilFinished = $false } AuthenticationAndLoadModule -Credential $Credential $location = UrlToLocationMapping -ApiUrl $ApiUrl $geoType = UrlToGeoTypeMapping -ApiUrl $ApiUrl Write-Verbose "Calling New-AdminPowerAppEnvironment." $response = New-AdminPowerAppEnvironment ` -DisplayName $NewInstanceInfo.FriendlyName ` -LocationName $location ` -EnvironmentSku $NewInstanceInfo.Type ` -ProvisionDatabase ` -CurrencyName $NewInstanceInfo.Currency.Name` -LanguageName $NewInstanceInfo.BaseLanguage` -Templates $NewInstanceInfo.Templates` -SecurityGroupId $NewInstanceInfo.SecurityGroupId` -DomainName $NewInstanceInfo.DomainName ` -WaitUntilFinished $waitUntilFinished ` -TimeoutInMinutes $MaxCrmConnectionTimeOutMinutes ` -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) return CreateOperationStatusByResponse -Response $response -GeoType $geoType } } function Remove-CrmInstance { <# .SYNOPSIS Removes Dynamics 365 Customer Engagement (online) instance .DESCRIPTION The Remove-CrmInstance cmdlet removes (deletes) the specified Dynamics 365 Customer Engagement (online) instance. Use Get-Help Remove-CrmInstance -Examples for more detail. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER Id Instance Id for the specific instance of Dynamics 365 Customer Engagement (online). Use the Get-CrmInstances cmdlet to find all instance Ids within the same tenant. .PARAMETER MaxCrmConnectionTimeOutMinutes Maximum number in minutes to wait before quitting the operation. .EXAMPLE Remove-CrmInstance -ApiUrl $connecthost -Credential $cred -Verbose -NewInstanceInfo $instanceInfo Removes Dynamics 365 Customer Engagement (online) instance #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $false)] [object]$Credential, [Parameter(Mandatory = $true)] [string]$Id, [Parameter(Mandatory = $false)] [int]$MaxCrmConnectionTimeOutMinutes = 30 ) process { AuthenticationAndLoadModule -Credential $Credential $environment = Get-AdminPowerAppEnvironment -InstanceId $Id -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) Write-Verbose "Calling Remove-AdminPowerAppEnvironment." $response = Remove-AdminPowerAppEnvironment -EnvironmentName $environment.EnvironmentName -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) return CreateOperationStatusByResponse -Response $response } } function Get-CrmInstanceTypes { <# .SYNOPSIS Get information about all the instance types .DESCRIPTION The Get-CrmInstanceTypes cmdlet retrieves information about all the instance types available, such as production, sandbox, support, preview, and trial, in the Dynamics 365 Customer Engagement (online) tenant. Use Get-Help Get-CrmInstanceTypes -Examples for more detail. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .EXAMPLE Get-CrmInstanceTypes Get information about all the instance types #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $false)] [object]$Credential ) process { AuthenticationAndLoadModule -Credential $Credential Write-Verbose "Calling Get-AdminPowerAppTenantConsumedQuota." $response = Get-AdminPowerAppTenantConsumedQuota return CreateInstanceTypes -InstanceTypeInfo $response } } function Get-CrmInstanceType { <# .SYNOPSIS Get information about all the instance types .DESCRIPTION The Get-CrmInstanceType cmdlet retrieves information about a Dynamics 365 Customer Engagement (online) instance type. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER InstanceType The instance type.The following are valid instance types: Production, Sandbox, Support, Preview, Trial .EXAMPLE Get-CrmInstanceType Get information about the instance type #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $false)] [object]$Credential, [Parameter(Mandatory = $true)] [string]$InstanceType ) process { AuthenticationAndLoadModule -Credential $Credential Write-Verbose "Calling Get-AdminPowerAppTenantConsumedQuota." $response = Get-AdminPowerAppTenantConsumedQuota $instanceTypes = CreateInstanceTypes -InstanceTypeInfo $response return ($instanceTypes | Where-Object { $_.Type -eq $InstanceType })[0] } } function Get-CrmOperationStatus { <# .SYNOPSIS Get Dynamics 365 Customer Engagement (online) instances .DESCRIPTION The Get-CrmOperationStatus cmdlet retrieves the status for an operation from your Dynamics 365 Customer Engagement (online) instance. Use Get-Help Get-CrmOperationStatus -Examples for more detail. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER OperationLocation Operation location of a long-running process, such as a backup, restore, new instance, or delete operation. For example, when you run the Get-CrmInstanceBackup cmdlet, the operation Id is returned from the cmdlet. .EXAMPLE Get-CrmOperationStatus -ApiUrl $ApiUrl -Credential $Credential -OperationLocation $OperationLocation Get Dynamics 365 Customer Engagement (online) instances #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $true)] [string]$OperationLocation, [Parameter(Mandatory = $false)] [object]$Credential ) process { AuthenticationAndLoadModule -Credential $Credential Write-Verbose "Calling Get-AdminPowerAppOperationStatus." $response = Get-AdminPowerAppOperationStatus -OperationStatusUrl $OperationLocation -Verbose:($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) $operationId = (($OperationLocation -split "operations/")[1]).Substring(0, 36) return CreateOperationStatusByResponse -Response $response -OperationId $operationId } } function Disable-CrmManagementApp { <# .SYNOPSIS Disable the specified registered Azure Active Directory Web app/API application .DESCRIPTION The Disable-CrmManagementApp cmdlet disables the specified registered Azure Active Directory Web app/API application. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER Id The registration id for the app. You can find the registration ids for all registered Azure Active Directory Web app/API applications by running the Get-CrmManagementApps cmdlet. .EXAMPLE Disable-CrmManagementApp -ApiUrl $ApiUrl -Credential $Credential -Id $Id Disable the specified registered Azure Active Directory Web app/API application #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $false)] [object]$Credential, [Parameter(Mandatory = $true)] [string]$Id ) process { throw "Disable-CrmManagementApp is not supported." } } function Enable-CrmManagementApp { <# .SYNOPSIS Enable the specified registered Azure Active Directory Web app/API application .DESCRIPTION The Enable-CrmManagementApp cmdlet enables the specified registered Azure Active Directory Web app/API application for use with the Microsoft.Xrm.OnlineManagementAPI PowerShell module. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER Id The registration id for the app. You can find the registration ids for all registered Azure Active Directory Web app/API applications by running the Get-CrmManagementApps cmdlet. .EXAMPLE Enable-CrmManagementApp -ApiUrl $ApiUrl -Credential $Credential -Id $Id Enable the specified registered Azure Active Directory Web app/API application #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $false)] [object]$Credential, [Parameter(Mandatory = $true)] [string]$Id ) process { throw "Enable-CrmManagementApp is not supported." } } function Get-CrmManagementApps { <# .SYNOPSIS Get Azure Active Directory Web app/API application list .DESCRIPTION The Get-CrmManagementApps cmdlet returns a list of all registered Azure Active Directory Web app/API applications under the tenant. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .EXAMPLE Get-CrmManagementApps -ApiUrl $ApiUrl -Credential $Credential Get Azure Active Directory Web app/API application list #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $false)] [object]$Credential ) process { AuthenticationAndLoadModule -Credential $Credential Write-Verbose "Calling Get-PowerAppManagementApps." $response = Get-PowerAppManagementApps -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) if ($response.value.Count -gt 0) { $applications = New-Object -TypeName 'system.collections.generic.list[Microsoft.Xrm.Services.Admin.Client.Models.TenantApplicationIdentity]' foreach ($app in $response.value) { $appIdentity = CreateTenantApplicationIdentity -Application $app $applications.Add($appIdentity) } return $applications } } } function Get-CrmManagementApp { <# .SYNOPSIS Get Azure Active Directory Web app/API application .DESCRIPTION The Get-CrmManagementApp cmdlet returns the specified registered Azure Active Directory Web app/API application. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER Id The registration id for the app. You can find the registration ids for all registered Azure Active Directory Web app/API applications by running the Get-CrmManagementApps cmdlet. .EXAMPLE Get-CrmManagementApp -ApiUrl $ApiUrl -Credential $Credential Get Azure Active Directory Web app/API application #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $false)] [object]$Credential, [Parameter(Mandatory = $true)] [string]$Id ) process { AuthenticationAndLoadModule -Credential $Credential Write-Verbose "Calling Get-PowerAppManagementApp." $response = Get-PowerAppManagementApp -ApplicationId $Id -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) return CreateTenantApplicationIdentity -Application $response } } function New-CrmManagementApp { <# .SYNOPSIS Registers an Azure Active Directory Web app/API .DESCRIPTION The New-CrmManagementApp cmdlet registers an Azure Active Directory Web app/API based on the app Id so it can be used with the Microsoft.Xrm.OnlineManagementAPI PowerShell module. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER AppId The application Id of the the Azure Active Directory Web app / API app. You can find the application Ids for Azure Active Directory Web app / API applications by running the Get-AzureADApplication Azure Active Directory PowerShell cmdlet or from the Azure Active Directory admin center. .PARAMETER Enable Enables the app for use with the Microsoft.Xrm.OnlineManagmentAPI PowerShell module. .EXAMPLE New-CrmManagementApp -AppId $Id -ApiUrl $connectionhost -Credential $cred Registers an Azure Active Directory Web app/API #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $false)] [object]$Credential, [Parameter(Mandatory = $true)] [string]$AppId, [Parameter(Mandatory = $false)] [switch]$Enable ) process { AuthenticationAndLoadModule -Credential $Credential Write-Verbose "Calling New-PowerAppManagementApp." $response = New-PowerAppManagementApp -ApplicationId $AppId -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) return CreateTenantApplicationIdentity -Application $response } } function Remove-CrmManagementApp { <# .SYNOPSIS Removes the specified registered Azure Active Directory Web app/API application .DESCRIPTION The Remove-CrmManagementApp cmdlet removes the specified registered Azure Active Directory Web app/API application so it cannot be used with Microsoft.Xrm.OnlineManagementAPI PowerShell module. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER Id The application Id of the the Azure Active Directory Web app / API app. You can find the application Ids for Azure Active Directory Web app / API applications by running the Get-AzureADApplication Azure Active Directory PowerShell cmdlet or from the Azure Active Directory admin center. .EXAMPLE Remove-CrmManagementApp -ApiUrl $ApiUrl -Credential $Credential -Id $Id Removes the specified registered Azure Active Directory Web app/API application #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $false)] [object]$Credential, [Parameter(Mandatory = $true)] [string]$Id ) process { AuthenticationAndLoadModule -Credential $Credential Write-Verbose "Calling Remove-PowerAppManagementApp." Remove-PowerAppManagementApp -ApplicationId $Id -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) > $null } } function Add-CrmFlightAudience { <# .SYNOPSIS Adds the specified environment to a particular flight. .DESCRIPTION The Add-CrmFlightAudience cmdlet adds the specified environment to a particular flight. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER FlightId Uniquely identifies a particular flight. Use the Get-CrmFlights cmdlet to return all available flights. .PARAMETER InstanceId Id for the specific Common Data Service environment. Use the Get-CrmInstances cmdlet to find all Ids within the same tenant. .EXAMPLE Add-CrmFlightAudience -ApiUrl $ApiUrl -Credential $Credential -FlightId $FlightId -InstanceId $InstanceId Adds the specified environment to a particular flight. #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $false)] [object]$Credential, [Parameter(Mandatory = $true)] [string]$FlightId, [Parameter(Mandatory = $true)] [string]$InstanceId ) process { throw "Add-CrmFlightAudience is not supported." } } function Get-CrmFlights { <# .SYNOPSIS Lists all flights that are available for opt-in or opt-out. .DESCRIPTION The Get-CrmFlights cmdlet lists all flights that are available for opt-in or opt-out. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER MaxCrmConnectionTimeOutMinutes Maximum number in minutes to wait before quitting the operation. .EXAMPLE Get-CrmFlights -ApiUrl $ApiUrl -Credential $Credential Lists all flights that are available for opt-in or opt-out. #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $false)] [object]$Credential, [Parameter(Mandatory = $false)] [int]$MaxCrmConnectionTimeOutMinutes = 30 ) process { throw "Get-CrmFlights is not supported." } } function Remove-CrmFlightAudience { <# .SYNOPSIS Removes the environment as an audience to a particular flight. .DESCRIPTION The Remove-CrmFlightAudience cmdlet removes the environment as an audience to a particular flight. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER FlightId Uniquely identifies a particular flight. Use the Get-CrmFlights cmdlet to return all available flights. .PARAMETER InstanceId Id for the specific Common Data Service environment. Use the Get-CrmInstances cmdlet to find all Ids within the same tenant. .PARAMETER MaxCrmConnectionTimeOutMinutes Maximum number in minutes to wait before quitting the operation. .EXAMPLE Remove-CrmFlightAudience -ApiUrl $ApiUrl -Credential $Credential -FlightId $FlightId -InstanceId $InstanceId Removes the environment as an audience to a particular flight. #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $false)] [object]$Credential, [Parameter(Mandatory = $true)] [string]$FlightId, [Parameter(Mandatory = $true)] [string]$InstanceId, [Parameter(Mandatory = $false)] [int]$MaxCrmConnectionTimeOutMinutes = 30 ) process { throw "Remove-CrmFlightAudience is not supported." } } function New-CrmAdminModeSetting { <# .SYNOPSIS Create InstanceAdminModeSettings object .DESCRIPTION The New-CrmAdminModeSetting cmdlet defines the object that can be passed to the Enable-CrmAdminMode and Enable-CrmAdminMode cmdlets to enable or disable administration mode for an instance of Dynamics 365 Customer Engagement (online). .PARAMETER OverrideUserAADObjectId Azure Active Directory object Id that can be used as the authentication identity instead of the user's credentials. .PARAMETER NotificationText Optional parameter that diplays as a message when any user attempts to sign in to the instance. .PARAMETER AllowBackgroundOperations Optional parameter that determines whether the instance can run background operations. 1 or $true to allow background operations. 0 or $false to not allow background operations. Background operations are asynchronous operations, such as workflows and synchronization with Microsoft Exchange. When set to false, emails will not be sent and server-side synchronization for appointments, contacts, and tasks are disabled. .EXAMPLE New-CrmAdminModeSetting -OverrideUserAADObjectId $OverrideUserAADObjectId -NotificationText $NotificationText -AllowBackgroundOperations $true #> param ( [Parameter(Mandatory = $false)] [string]$NotificationText, [Parameter(Mandatory = $false)] [string]$OverrideUserAADObjectId, [Parameter(Mandatory = $false)] [bool]$AllowBackgroundOperations ) return New-Object -TypeName PSObject ` | Add-Member -PassThru -MemberType NoteProperty -Name OverrideUserAADObjectId -Value $OverrideUserAADObjectId ` | Add-Member -PassThru -MemberType NoteProperty -Name AdminMode -Value $null ` | Add-Member -PassThru -MemberType NoteProperty -Name BackgroundOperationsEnabled -Value $AllowBackgroundOperations ` | Add-Member -PassThru -MemberType NoteProperty -Name NotificationText -Value $NotificationText } function Enable-CrmAdminMode { <# .SYNOPSIS Enable AdminMode .DESCRIPTION The Enable-CrmAdminMode cmdlet enables administration mode on a sandbox instance. When you place a Sandbox instance in administration mode only users with Dynamics 365 System Administrator or System Customizer security roles will be able to sign in to that instance. Administration mode is useful when you want to make operational changes and not have regular users affect your work, and not have your work affect regular users. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER InstanceId Id for the specific Common Data Service environment. Use the Get-CrmInstances cmdlet to find all Ids within the same tenant. .PARAMETER AdminModeSettings You create the object for this parameter by running the New-CrmAdminModeSetting cmdlet. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER MaxCrmConnectionTimeOutMinutes Maximum number in minutes to wait before quitting the operation. .PARAMETER ValidateOnly Indicates whether to validate that an instance can be provisioned with the provided parameters or create an instance. Set 1 to validate; set 0 to create. .EXAMPLE Enable-CrmAdminMode -ApiUrl $connecthost -Credential $cred -Verbose -AdminModeSettings $adminModeSettings Enable AdminMode #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $true)] [string]$InstanceId, [Parameter(Mandatory = $false)] [object]$AdminModeSettings, [Parameter(Mandatory = $false)] [object]$Credential, [Parameter(Mandatory = $false)] [int]$MaxCrmConnectionTimeOutMinutes = 30, [Parameter(Mandatory = $false)] [switch]$ValidateOnly ) process { if ($ValidateOnly) { return CreateOperationStatusObject ` -OperationId "00000000-0000-0000-0000-000000000000" ` -Status "NotStarted" } UpdateRuntimeState ` -ApiUrl $ApiUrl ` -InstanceId $InstanceId ` -RuntimeState "AdminMode" ` -Credential $Credential ` -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) } } function Disable-CrmAdminMode { <# .SYNOPSIS Disable AdminMode .DESCRIPTION The Disable-CrmAdminMode cmdlet enables administration mode on a sandbox instance. When you place a Sandbox instance in administration mode only users with Dynamics 365 System Administrator or System Customizer security roles will be able to sign in to that instance. Administration mode is useful when you want to make operational changes and not have regular users affect your work, and not have your work affect regular users. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER InstanceId Id for the specific Common Data Service environment. Use the Get-CrmInstances cmdlet to find all Ids within the same tenant. .PARAMETER AdminModeSettings You create the object for this parameter by running the New-CrmAdminModeSetting cmdlet. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER MaxCrmConnectionTimeOutMinutes Maximum number in minutes to wait before quitting the operation. .PARAMETER ValidateOnly Indicates whether to validate that an instance can be provisioned with the provided parameters or create an instance. Set 1 to validate; set 0 to create. .EXAMPLE Disable-CrmAdminMode -ApiUrl $connecthost -Credential $cred -Verbose -AdminModeSettings $adminModeSettings Disable AdminMode #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $true)] [string]$InstanceId, [Parameter(Mandatory = $false)] [object]$AdminModeSettings, [Parameter(Mandatory = $false)] [object]$Credential, [Parameter(Mandatory = $false)] [int]$MaxCrmConnectionTimeOutMinutes = 30, [Parameter(Mandatory = $false)] [switch]$ValidateOnly ) process { if ($ValidateOnly) { return CreateOperationStatusObject ` -OperationId "00000000-0000-0000-0000-000000000000" ` -Status "NotStarted" } UpdateRuntimeState ` -ApiUrl $ApiUrl ` -InstanceId $InstanceId ` -RuntimeState "Enabled" ` -Credential $Credential ` -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) } } function New-CrmInstanceCopyRequestInfo { <# .SYNOPSIS Create CopyRequestInfo object .DESCRIPTION The New-CrmInstanceCopyRequestInfo cmdlet creates the object that defines the parameters used to copy a instance of Dynamics 365 Customer Enagagement (online) by using the Copy-CrmInstance cmdlet. .PARAMETER FriendlyName Required parameter. This is typically the name of your organization and is displayed in the Microsoft Dynamics 365 application. .PARAMETER TargetInstanceId Required parameter. This value is used to determine the target instance for the copy operation. .PARAMETER CopyType Required parameter. This value is used to determine the target instance for the copy operation. .PARAMETER SecurityGroupId Optional parameter. This value is used to determine the security group that includes the users who will have access to this instance of Microsoft Dynamics 365 (online). .EXAMPLE New-CrmInstanceCopyRequestInfo -OverrideUserAADObjectId $OverrideUserAADObjectId -NotificationText $NotificationText -AllowBackgroundOperations $true #> param ( [Parameter(Mandatory = $true)] [string]$FriendlyName, [Parameter(Mandatory = $true)] [guid]$TargetInstanceId, [Parameter(Mandatory = $true)] [Microsoft.Xrm.Services.Admin.Client.Models.CopyType]$CopyType, [Parameter(Mandatory = $false)] [guid]$SecurityGroupId ) return New-Object -TypeName Microsoft.Xrm.Services.Admin.Client.Models.CopyRequest( ` $FriendlyName, ` $SecurityGroupId, ` $TargetInstanceId, ` $CopyType) } function Copy-CrmInstance { <# .SYNOPSIS Disable AdminMode .DESCRIPTION The Copy-CrmInstance cmdlet performs a copy operation on a Dynamics 365 Customer Engagement (online) instance to another Sandbox instance in your Office 365 tenant. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER SourceInstanceIdToCopy Id of the source instance to copy. .PARAMETER CopyInstanceRequestDetails Object created by using the New-CrmInstanceCopyRequestInfo cmdlet that contains the information used to copy the instance. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER MaxCrmConnectionTimeOutMinutes Maximum number in minutes to wait before quitting the operation. .EXAMPLE Copy-CrmInstance -ApiUrl $connectionhost -CopyInstanceRequestDetails $CopyInstanceRequestDetails -Credential $cred -SourceInstanceIdToCopy <Guid> Disable AdminMode #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $true)] [string]$SourceInstanceIdToCopy, [Parameter(Mandatory = $true)] [object]$CopyInstanceRequestDetails, [Parameter(Mandatory = $false)] [object]$Credential, [Parameter(Mandatory = $false)] [int]$MaxCrmConnectionTimeOutMinutes = 0 ) process { $sourceEnvironment = Get-AdminPowerAppEnvironment -InstanceId $SourceInstanceIdToCopy -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) $targetEnvironment = Get-AdminPowerAppEnvironment -InstanceId $CopyInstanceRequestDetails.TargetInstanceId -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) $copyToRequest = [pscustomobject]@{ SourceEnvironmentId = $sourceEnvironment.EnvironmentName TargetEnvironmentName = $CopyInstanceRequestDetails.FriendlyName TargetSecurityGroupId = $CopyInstanceRequestDetails.SecurityGroupId CopyType = $CopyInstanceRequestDetails.CopyType.ToString() } $waitUntilFinished = $true if ($MaxCrmConnectionTimeOutMinutes -eq 0) { $waitUntilFinished = $false } Write-Verbose "Calling Copy-PowerAppEnvironment." $response = Copy-PowerAppEnvironment ` -EnvironmentName $targetEnvironment.EnvironmentName ` -CopyToRequestDefinition $copyToRequest ` -WaitUntilFinished $waitUntilFinished ` -TimeoutInMinutes $MaxCrmConnectionTimeOutMinutes ` -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) return CreateOperationStatusByResponse -Response $response } } function Get-CrmInstanceBackups { <# .SYNOPSIS Get instance backups. .DESCRIPTION The Get-CrmInstanceBackups cmdlet retrieves all backups for a Dynamics 365 Customer Engagement (online) instance. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER InstanceId Instance Id for the specific instance of Dynamics 365 Customer Engagement (online). Use the Get-CrmInstances cmdlet to find all instance Ids within the same tenant. .EXAMPLE Get-CrmInstanceBackups -ApiUrl $ApiUrl -Credential $Credential -InstanceId $InstanceId Get instance backups. #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $false)] [object]$Credential, [Parameter(Mandatory = $true)] [string]$InstanceId ) process { AuthenticationAndLoadModule -Credential $Credential $environment = Get-AdminPowerAppEnvironment -InstanceId $InstanceId -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) Write-Verbose "Calling Get-PowerAppEnvironmentBackups." $response = Get-PowerAppEnvironmentBackups -EnvironmentName $environment.EnvironmentName -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) $manualBackups = New-Object -TypeName 'system.collections.generic.list[Microsoft.Xrm.Services.Admin.Client.Models.ManualBackup]' foreach ($backup in $response.value) { $manualBackup = CreateManualBackupObject -Backup $backup -InstanceId $InstanceId $manualBackups.Add($manualBackup) } $systemBackups = New-Object -TypeName 'system.collections.generic.list[Microsoft.Xrm.Services.Admin.Client.Models.SystemBackup]' $datetime = (Get-Date).ToUniversalTime() $datetime -= New-TimeSpan -Minutes 15 $systemBackup = New-Object -TypeName Microsoft.Xrm.Services.Admin.Client.Models.SystemBackup $systemBackup.InstanceId = $environment.Internal.Properties.LinkedEnvironmentMetadata.ResourceId $systemBackup.BackupStartTimeUtc = $environment.Internal.Properties.RetentionDetails.BackupsAvailableFromDateTime $systemBackup.BackupEndTimeUtc = $datetime $systemBackups.Add($systemBackup) $instanceBackup = New-Object -TypeName Microsoft.Xrm.Services.Admin.Client.Models.InstanceBackups $instanceBackup.ManualBackups = $manualBackups $instanceBackup.SystemBackups = $systemBackups return $instanceBackup } } function Backup-CrmInstance { <# .SYNOPSIS Backup instance. .DESCRIPTION The Backup-CrmInstance cmdlet initiates a back up of a Dynamics 365 Customer Engagement (online) instance. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER InstanceId Instance Id for the specific instance of Dynamics 365 Customer Engagement (online). Use the Get-CrmInstances cmdlet to find all instance Ids within the same tenant. .PARAMETER Label Add a label to use to reference the backup. .PARAMETER Notes Add comments about the backup. .EXAMPLE Backup-CrmInstance -ApiUrl $ApiUrl -Credential $Credential -InstanceId $InstanceId -Label $Label -Notes $Notes Backup instance. #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $false)] [object]$Credential, [Parameter(Mandatory = $true)] [string]$InstanceId, [Parameter(Mandatory = $true)] [string]$Label, [Parameter(Mandatory = $true)] [string]$Notes ) process { AuthenticationAndLoadModule -Credential $Credential $environment = Get-AdminPowerAppEnvironment -InstanceId $InstanceId -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) $backupRequest = [pscustomobject]@{ Label = $Label Notes = $Notes } Write-Verbose "Calling Backup-PowerAppEnvironment." $response = Backup-PowerAppEnvironment -EnvironmentName $environment.EnvironmentName -BackupRequestDefinition $backupRequest -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) if ($response -ne $null -and $response.label -eq $Label -and $response.notes -eq $Notes) { return CreateOperationStatusObject ` -OperationId "00000000-0000-0000-0000-000000000000" ` -Status "Created" } $errorMessage = $response.Internal.Error.message $errorCode = $response.Internal.Error.code $errors = New-Object -TypeName 'system.collections.generic.list[Microsoft.Xrm.Services.Admin.Client.Models.ItemDescription]' $errorObject = CreateItemDescription -Code $errorCode -Description $errorMessage $errors.Add($errorObject) return CreateOperationStatusObject ` -OperationId "00000000-0000-0000-0000-000000000000" ` -Status "Failed" ` -Errors $errors } } function Restore-CrmInstance { <# .SYNOPSIS Restore instance. .DESCRIPTION The Restore-CrmInstance cmdlet restores a Dynamics 365 Customer Engagement (online) instance from the specified backup and instance restore point ids. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER SourceInstanceId Instance where Backup is picked up from. .PARAMETER RestoreTimeUtc Backup TimeStamp to restore to. .PARAMETER MaxCrmConnectionTimeOutMinutes Maximum number in minutes to wait before quitting the operation. .PARAMETER FriendlyName Allows you to change the friendly name on restore. .PARAMETER SecurityGroupId Allows you to change the friendly name on restore. .PARAMETER ValidateOnly Indicates whether to validate that an instance can be provisioned with the provided parameters or create an instance. Set 1 to validate; set 0 to create. .EXAMPLE Restore-CrmInstance -ApiUrl $ApiUrl -Credential $Credential -SourceInstanceId $SourceInstanceId Restore instance. #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $false)] [object]$Credential, [Parameter(Mandatory = $true)] [string]$SourceInstanceId, [Parameter(Mandatory = $true)] [string]$TargetInstanceId, [Parameter(Mandatory = $true)] [datetime]$RestoreTimeUtc, [Parameter(Mandatory = $false)] [int]$MaxCrmConnectionTimeOutMinutes = 0, [Parameter(Mandatory = $false)] [string]$FriendlyName, [Parameter(Mandatory = $false)] [string]$SecurityGroupId, [Parameter(Mandatory = $false)] [switch]$ValidateOnly ) process { if ($ValidateOnly) { return CreateOperationStatusObject ` -OperationId "00000000-0000-0000-0000-000000000000" ` -Status "NotStarted" } AuthenticationAndLoadModule -Credential $Credential $sourceEnvironment = Get-AdminPowerAppEnvironment -InstanceId $SourceInstanceId -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) if ([string]::IsNullOrEmpty($FriendlyName)) { $FriendlyName = $sourceEnvironment.DisplayName } $restoreRequest = [pscustomobject]@{ SourceEnvironmentId = $sourceEnvironment.EnvironmentName TargetEnvironmentName = $FriendlyName TargetSecurityGroupId = $SecurityGroupId RestorePointDateTime = $RestoreTimeUtc.ToString("yyyy-MM-dd HH:mm:ss") } $waitUntilFinished = $true if ($MaxCrmConnectionTimeOutMinutes -eq 0) { $waitUntilFinished = $false } Write-Verbose "Calling Restore-PowerAppEnvironment." $response = Restore-PowerAppEnvironment ` -EnvironmentName $sourceEnvironment.EnvironmentName ` -RestoreToRequestDefinition $restoreRequest ` -WaitUntilFinished $waitUntilFinished ` -TimeoutInMinutes $MaxCrmConnectionTimeOutMinutes ` -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) return CreateOperationStatusByResponse -Response $response } } function New-CrmInstanceResetRequestInfo { <# .SYNOPSIS Creates the object that defines the parameters used to reset a instance of Dynamics 365 Customer Enagagement (online) by using the Reset-CrmInstance cmdlet. .DESCRIPTION The New-CrmInstanceResetRequestInfo cmdlet creates the object that defines the parameters used to reset a instance of Dynamics 365 Customer Enagagement (online) by using the Reset-CrmInstance cmdlet. .PARAMETER BaseLanguage Required parameter. The base language for the instance. For a list of available languages, run the Get-CrmLanguages cmdlet. .PARAMETER CurrencyCode Optional parameter. The currency region code to use for the instance. You can find a list of currency region codes by running the Get-CrmCurrencies cmdlet. .PARAMETER CurrencyName Optional parameter. The currency name to use for the instance. You can find a list of currency names by running the Get-CrmCurrencies cmdlet. .PARAMETER CurrencyPrecision Optional parameter. Set the pricing decimal precision. Valid values are 0-4. .PARAMETER CurrencySymbol Optional parameter. Set the symbol that will represent the currency. .PARAMETER DomainName Required parameter. Used for part of the domain namespace and appears in the application url. For example, if you use contoso as the DomainName, the url will appear similar to https://contoso.crm.dynamics.com. .PARAMETER FriendlyName Required parameter. This is typically the name of your organization and is displayed in the Microsoft Dynamics 365 application. .PARAMETER Purpose Optional parameter. A description used to associate the instance with a specific intent. Only tenant administrators will see this description. .PARAMETER SecurityGroupId Optional parameter. This value is used to determine the security group that includes the users who will have access to this instance of Microsoft Dynamics 365 (online). .PARAMETER TemplateList Optional parameter. Specifies the apps you want provisioned in the instance. For a list of available template names, run the Get-CrmTemplates cmdlet. .PARAMETER TargetReleaseName Required parameter. The name of the target release. .PARAMETER PreferredCulture Optional parameter. Indicates if the customer prefers a certain culture for formatting for the new instance. .EXAMPLE New-CrmInstanceResetRequestInfo -OverrideUserAADObjectId $OverrideUserAADObjectId -NotificationText $NotificationText -AllowBackgroundOperations $true #> param ( [Parameter(Mandatory = $true)] [int]$BaseLanguage, [Parameter(Mandatory = $false)] [string]$CurrencyCode, [Parameter(Mandatory = $false)] [string]$CurrencyName, [Parameter(Mandatory = $false)] [int]$CurrencyPrecision, [Parameter(Mandatory = $false)] [string]$CurrencySymbol, [Parameter(Mandatory = $true)] [string]$DomainName, [Parameter(Mandatory = $true)] [string]$FriendlyName, [Parameter(Mandatory = $false)] [string]$Purpose, [Parameter(Mandatory = $false)] [string]$SecurityGroupId, [Parameter(Mandatory = $false)] [string[]]$TemplateList, [Parameter(Mandatory = $true)] [string]$TargetReleaseName, [Parameter(Mandatory = $false)] [int]$PreferredCulture ) $currency = New-Object -TypeName Microsoft.Xrm.Services.Admin.Client.Models.Currency($CurrencyCode, $CurrencyPrecision, $CurrencySymbol, $CurrencyName) <# Blocked by BAP error: Could not find member 'TargetRelease' on object of type 'ResetRequestDefinition'. $resetRequest = New-Object -TypeName Microsoft.Xrm.Services.Admin.Client.Models.ResetRequest $resetRequest.FriendlyName = $FriendlyName $resetRequest.DomainName = $DomainName $resetRequest.Purpose = $Purpose $resetRequest.SecurityGroupId = $SecurityGroupId $resetRequest.TargetRelease = $TargetReleaseName $resetRequest.BaseLanguageCode = $BaseLanguage $resetRequest.Currency = $currency $resetRequest.ApplicationNames = $TemplateList return $resetRequest #> return New-Object -TypeName PSObject ` | Add-Member -PassThru -MemberType NoteProperty -Name FriendlyName -Value $FriendlyName ` | Add-Member -PassThru -MemberType NoteProperty -Name DomainName -Value $DomainName ` | Add-Member -PassThru -MemberType NoteProperty -Name SecurityGroupId -Value $SecurityGroupId ` | Add-Member -PassThru -MemberType NoteProperty -Name Purpose -Value $Purpose ` | Add-Member -PassThru -MemberType NoteProperty -Name BaseLanguageCode -Value $BaseLanguage ` | Add-Member -PassThru -MemberType NoteProperty -Name Currency -Value $currency ` | Add-Member -PassThru -MemberType NoteProperty -Name Templates -Value $TemplateList } function Reset-CrmInstance { <# .SYNOPSIS Reset instance. .DESCRIPTION The Reset-CrmInstance cmdlet performs a reset operation on a Dynamics 365 Customer Engagement (online) Sandbox instance in your Office 365 tenant. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER MaxCrmConnectionTimeOutMinutes Maximum number in minutes to wait before quitting the operation. .PARAMETER ResetInstanceRequestDetails Object created by using the New-CrmInstanceResetRequestInfo cmdlet that contains the information used to reset the instance. .PARAMETER TargetInstanceIdToReset Id of the instance to reset .EXAMPLE Reset-CrmInstance -ApiUrl $connectionhost -ResetInstanceRequestDetails ResetInstanceRequestDetails -Credential $cred -TargetInstanceIdToReset $InstanceId Reset instance. #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $false)] [object]$Credential, [Parameter(Mandatory = $true)] [string]$TargetInstanceIdToReset, [Parameter(Mandatory = $false)] [int]$MaxCrmConnectionTimeOutMinutes = 0, [Parameter(Mandatory = $true)] [object]$ResetInstanceRequestDetails ) process { AuthenticationAndLoadModule -Credential $Credential $environment = Get-AdminPowerAppEnvironment -InstanceId $TargetInstanceIdToReset -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) $waitUntilFinished = $true if ($MaxCrmConnectionTimeOutMinutes -eq 0) { $waitUntilFinished = $false } Write-Verbose "Calling Reset-PowerAppEnvironment" $response = Reset-PowerAppEnvironment ` -EnvironmentName $environment.EnvironmentName ` -ResetRequestDefinition $ResetInstanceRequestDetails ` -WaitUntilFinished $waitUntilFinished ` -TimeoutInMinutes $MaxCrmConnectionTimeOutMinutes ` -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) return CreateOperationStatusByResponse -Response $response } } function Get-CrmGenerateProtectionKey { <# .SYNOPSIS Get a new protection key. .DESCRIPTION The Get-CrmGenerateProtectionKey cmdlet returns a new protection key. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER MaxCrmConnectionTimeOutMinutes Maximum number in minutes to wait before quitting the operation. .PARAMETER KeyPassword Key password for the protection key. .PARAMETER SubjectName Subject name for the protection key .EXAMPLE Get-CrmGenerateProtectionKey -ApiUrl $connectionhost -Credential $cred Get a new protection key. #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $false)] [object]$Credential, [Parameter(Mandatory = $true)] [string]$SubjectName, [Parameter(Mandatory = $false)] [int]$MaxCrmConnectionTimeOutMinutes = 0, [Parameter(Mandatory = $true)] [string]$KeyPassword ) process { AuthenticationAndLoadModule -Credential $Credential $location = UrlToLocationMapping -ApiUrl $ApiUrl Write-Verbose "Calling Get-PowerAppGenerateProtectionKey" $response = Get-PowerAppGenerateProtectionKey -LocationName $location -KeyName $SubjectName -KeyPassword $KeyPassword -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) if (-not [string]::IsNullOrEmpty($response.keyBytes)) { $keyBytes = [System.Convert]::FromBase64String($response.keyBytes) return $keyBytes } return CreateOperationStatusByResponse -Response $response } } function Get-CrmRetrieveTenantProtectionKey { <# .SYNOPSIS Get the current tenant protection key. .DESCRIPTION The Get-CrmRetrieveTenantProtectionKey cmdlet returns the current tenant protection key. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER MaxCrmConnectionTimeOutMinutes Maximum number in minutes to wait before quitting the operation. .EXAMPLE Get-CrmRetrieveTenantProtectionKey -ApiUrl $connectionhost -Credential $cred Get the current tenant protection key. #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $false)] [object]$Credential, [Parameter(Mandatory = $false)] [int]$MaxCrmConnectionTimeOutMinutes = 0 ) process { AuthenticationAndLoadModule -Credential $Credential $location = UrlToLocationMapping -ApiUrl $ApiUrl Write-Verbose "Calling Get-PowerAppRetrieveTenantProtectionKey" $response = Get-PowerAppRetrieveTenantProtectionKey -LocationName $location -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) if (-not [string]::IsNullOrEmpty($response.KeyName)) { return CreateProtectionKeyObject -Key $response } return CreateOperationStatusByResponse -Response $response } } function Get-CrmRetrieveAvailableTenantProtectionKeys { <# .SYNOPSIS Get the available protection keys for current tenant. .DESCRIPTION The Get-CrmRetrieveAvailableTenantProtectionKeys cmdlet returns the available tenant protection keys. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER MaxCrmConnectionTimeOutMinutes Maximum number in minutes to wait before quitting the operation. .EXAMPLE Get-CrmRetrieveAvailableTenantProtectionKeys -ApiUrl $connectionhost -Credential $cred Get the available protection keys for current tenant. #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $false)] [object]$Credential, [Parameter(Mandatory = $false)] [int]$MaxCrmConnectionTimeOutMinutes = 0 ) process { AuthenticationAndLoadModule -Credential $Credential $location = UrlToLocationMapping -ApiUrl $ApiUrl Write-Verbose "Calling Get-PowerAppRetrieveAvailableTenantProtectionKeys" $response = Get-PowerAppRetrieveAvailableTenantProtectionKeys -LocationName $location -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) if ($response.value -ne $null) { $result = @() foreach ($key in $response.value) { $result += CreateProtectionKeyObject -Key $key } return $result } return CreateOperationStatusByResponse -Response $response } } function New-CrmImportProtectionKey { <# .SYNOPSIS Import a new protection key. .DESCRIPTION The New-CrmImportProtectionKey cmdlet add a new protection key. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER KeyName Name for the protection key .PARAMETER KeyType Type of the protection key .PARAMETER Key Content of the protection key .PARAMETER KeyPassword Key password for the protection key. .PARAMETER MaxCrmConnectionTimeOutMinutes Maximum number in minutes to wait before quitting the operation. .EXAMPLE New-CrmImportProtectionKey -ApiUrl $connectionhost -Credential $cred -KeyName $keyName -Key $keyContent -KeyType 0 -KeyPassword $keyPassword Import a new protection key. #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $false)] [object]$Credential, [Parameter(Mandatory = $true)] [string]$KeyName, [Parameter(Mandatory = $true)] [int]$KeyType, [Parameter(Mandatory = $true)] [byte[]]$Key, [Parameter(Mandatory = $true)] [string]$KeyPassword, [Parameter(Mandatory = $false)] [int]$MaxCrmConnectionTimeOutMinutes = 0 ) process { AuthenticationAndLoadModule -Credential $Credential $location = UrlToLocationMapping -ApiUrl $ApiUrl Write-Verbose "Calling New-PowerAppImportProtectionKey" $response = New-PowerAppImportProtectionKey -LocationName $location -KeyName $KeyName -KeyType $KeyType -KeyPassword $KeyPassword -Key $key -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) return CreateOperationStatusByResponse -Response $response } } function Set-CrmLockTenantProtectedInstances { <# .SYNOPSIS Lock all the instances associated with the tenant. .DESCRIPTION Set-CrmLockTenantProtectedInstances locks all the instances associated with the tenant. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER KeyName Name for the protection key .PARAMETER MaxCrmConnectionTimeOutMinutes Maximum number in minutes to wait before quitting the operation. .EXAMPLE Set-CrmLockTenantProtectedInstances -ApiUrl $connectionhost -Credential $cred -KeyName $keyName Lock all the instances associated with the tenant. #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $false)] [object]$Credential, [Parameter(Mandatory = $true)] [string]$KeyName, [Parameter(Mandatory = $false)] [int]$MaxCrmConnectionTimeOutMinutes = 0 ) process { AuthenticationAndLoadModule -Credential $Credential $location = UrlToLocationMapping -ApiUrl $ApiUrl Write-Verbose "Calling Set-PowerAppLockAllEnvironments" $response = Set-PowerAppLockAllEnvironments -LocationName $location -KeyName $KeyName -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) return CreateOperationStatusByResponse -Response $response } } function Set-CrmUnlockTenantProtectedInstance { <# .SYNOPSIS Unlock the instance associated with the tenant. .DESCRIPTION Set-CrmUnlockTenantProtectedInstance unlocks the instance associated with the tenant. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER InstanceId Instance Id .PARAMETER MaxCrmConnectionTimeOutMinutes Maximum number in minutes to wait before quitting the operation. .EXAMPLE Set-CrmUnlockTenantProtectedInstance -ApiUrl $connectionhost -Credential $cred -InstanceId $instanceId Unlock the instance associated with the tenant. #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $false)] [object]$Credential, [Parameter(Mandatory = $true)] [string]$InstanceId, [Parameter(Mandatory = $false)] [int]$MaxCrmConnectionTimeOutMinutes = 0 ) process { AuthenticationAndLoadModule -Credential $Credential $location = UrlToLocationMapping -ApiUrl $ApiUrl $environment = Get-AdminPowerAppEnvironment -InstanceId $TargetInstanceIdToReset -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) Write-Verbose "Calling Set-PowerAppUnlockEnvironment" $response = Set-PowerAppUnlockEnvironment -EnvironmentName $environment.EnvironmentName return CreateOperationStatusByResponse -Response $response } } function Set-CrmProtectWithMicrosoftKey { <# .SYNOPSIS Protects an instance with default Microsoft key. .DESCRIPTION The Set-CrmProtectWithMicrosoftKey cmdlet Protects an instance with default microsoft key. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER InstanceId Instance Id .PARAMETER MaxCrmConnectionTimeOutMinutes Maximum number in minutes to wait before quitting the operation. .EXAMPLE Set-CrmProtectWithMicrosoftKey -ApiUrl $connectionhost -Credential $cred -InstanceId $InstanceId Protects an instance with default Microsoft key. #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $false)] [object]$Credential, [Parameter(Mandatory = $true)] [string]$InstanceId, [Parameter(Mandatory = $false)] [int]$MaxCrmConnectionTimeOutMinutes = 0 ) process { AuthenticationAndLoadModule -Credential $Credential $location = UrlToLocationMapping -ApiUrl $ApiUrl $environment = Get-AdminPowerAppEnvironment -InstanceId $InstanceId -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) $waitUntilFinished = $true if ($MaxCrmConnectionTimeOutMinutes -eq 0) { $waitUntilFinished = $false } Write-Verbose "Calling Set-PowerAppProtectionStatus" $response = Set-PowerAppProtectionStatus ` -EnvironmentName $environment.EnvironmentName ` -ProtectionKeyManagedBy "Microsoft" ` -WaitUntilFinished $waitUntilFinished ` -TimeoutInMinutes $MaxCrmConnectionTimeOutMinutes ` -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) return CreateOperationStatusByResponse -Response $response } } function Set-CrmProtectWithTenantKey { <# .SYNOPSIS Protects and Instance with the Tenant Key. .DESCRIPTION The Set-CrmProtectWithTenantKey cmdlet protects a given instance with the Tenant Key and returns operation status. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER InstanceId Instance Id .PARAMETER MaxCrmConnectionTimeOutMinutes Maximum number in minutes to wait before quitting the operation. .EXAMPLE Set-CrmProtectWithTenantKey -ApiUrl $connectionhost -Credential $cred -InstanceId $InstanceId Protects and Instance with the Tenant Key. #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $false)] [object]$Credential, [Parameter(Mandatory = $true)] [string]$InstanceId, [Parameter(Mandatory = $false)] [int]$MaxCrmConnectionTimeOutMinutes = 0 ) process { AuthenticationAndLoadModule -Credential $Credential $location = UrlToLocationMapping -ApiUrl $ApiUrl $environment = Get-AdminPowerAppEnvironment -InstanceId $InstanceId -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) $waitUntilFinished = $true if ($MaxCrmConnectionTimeOutMinutes -eq 0) { $waitUntilFinished = $false } Write-Verbose "Calling Set-PowerAppProtectionStatus" $response = Set-PowerAppProtectionStatus ` -EnvironmentName $environment.EnvironmentName ` -ProtectionKeyManagedBy "Customer" ` -WaitUntilFinished $waitUntilFinished ` -TimeoutInMinutes $MaxCrmConnectionTimeOutMinutes ` -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) return CreateOperationStatusByResponse -Response $response } } function Set-CrmTenantProtectionKey { <# .SYNOPSIS Sets an existing tenant protection key. .DESCRIPTION The Set-CrmTenantProtectionKey cmdlet sets an existing tenant protection key and returns the operation status. .PARAMETER ApiUrl The URL of the Dynamics 365 Customer Engagement (online) root service endpoint. .PARAMETER Credential User credential for signing in to Microsoft Dynamics 365 Customer Engagement (online). .PARAMETER KeyName Key name .PARAMETER MaxCrmConnectionTimeOutMinutes Maximum number in minutes to wait before quitting the operation. .EXAMPLE Set-CrmTenantProtectionKey -ApiUrl $connectionhost -Credential $cred Sets an existing tenant protection key. #> param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $false)] [object]$Credential, [Parameter(Mandatory = $true)] [string]$KeyName, [Parameter(Mandatory = $false)] [int]$MaxCrmConnectionTimeOutMinutes = 0 ) process { AuthenticationAndLoadModule -Credential $Credential $location = UrlToLocationMapping -ApiUrl $ApiUrl $waitUntilFinished = $true if ($MaxCrmConnectionTimeOutMinutes -eq 0) { $waitUntilFinished = $false } Write-Verbose "Calling Set-PowerAppTenantProtectionKey" $response = Set-PowerAppTenantProtectionKey ` -LocationName $location ` -KeyName $KeyName ` -WaitUntilFinished $waitUntilFinished ` -TimeoutInMinutes $MaxCrmConnectionTimeOutMinutes ` -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) if ($response.geo -ne $null) { return ConvertCdsOperationToOperationStatus -CdsOperation $response } else { return CreateOperationStatusByResponse -Response $response } } } #internal, helper function function UrlToLocationMapping { param ( [Parameter(Mandatory = $true)] [string]$ApiUrl ) $hostName = ($ApiUrl -split "/")[2] $apiUrlMapping = @{ "admin.services.crm.dynamics.com" = "unitedstates"; "admin.services.crm2.dynamics.com" = "southamerica"; "admin.services.crm3.dynamics.com" = "canada"; "admin.services.crm4.dynamics.com" = "europe"; "admin.services.crm5.dynamics.com" = "asia"; "admin.services.crm6.dynamics.com" = "australia"; "admin.services.crm7.dynamics.com" = "japan"; "admin.services.crm8.dynamics.com" = "india"; "admin.services.crm10.dynamics.com" = "unitedstates"; "admin.services.crm11.dynamics.com" = "unitedkingdom"; "admin.services.crm16.dynamics.com" = "germany"; "admin.services.crm12.dynamics.com" = "france"; "admin.services.crm14.dynamics.com" = "southafrica"; "admin.services.crm15.dynamics.com" = "unitedarabemirates"; "admin.services.crm9.dynamics.com" = "usgov"; "admin.services.crm.microsoftdynamics.us" = "usgovhigh"; "admin.services.crm.appsplatform.us" = "usgovdod"; "admin.services.crm.dynamics.cn" = "china"; } return $apiUrlMapping[$hostName]; } function UrlToGeoTypeMapping { param ( [Parameter(Mandatory = $true)] [string]$ApiUrl ) $hostName = ($ApiUrl -split "/")[2] $apiUrlMapping = @{ "admin.services.crm.dynamics.com" = "Na"; "admin.services.crm2.dynamics.com" = "Sam"; "admin.services.crm3.dynamics.com" = "Can"; "admin.services.crm4.dynamics.com" = "Emea"; "admin.services.crm5.dynamics.com" = "Apac"; "admin.services.crm6.dynamics.com" = "Oce"; "admin.services.crm7.dynamics.com" = "Jpn"; "admin.services.crm8.dynamics.com" = "Ind"; "admin.services.crm10.dynamics.com" = "Na"; "admin.services.crm11.dynamics.com" = "Gbr"; "admin.services.crm16.dynamics.com" = "Ger"; "admin.services.crm12.dynamics.com" = "Fra"; "admin.services.crm14.dynamics.com" = "Zaf"; "admin.services.crm15.dynamics.com" = "Uae"; "admin.services.crm9.dynamics.com" = "Usg"; "admin.services.crm.microsoftdynamics.us" = "Usg"; "admin.services.crm.appsplatform.us" = "Dod"; "admin.services.crm.dynamics.cn" = "Chn"; } return $apiUrlMapping[$hostName]; } function AuthenticationAndLoadModule { param ( [Parameter(Mandatory = $true)] [AllowNull()] [object]$Credential = $null ) LoadModule -ModuleName "Microsoft.PowerApps.Administration.PowerShell" -MinimumVersion 2.0.72 Write-Verbose "Calling Add-PowerAppsAccount." if ($Credential -eq $null) { Add-PowerAppsAccount -Audience "https://service.apps.appsplatform.us/" } else { $endpoint = "prod" if ($Credential.Endpoint -ne $null) { $endpoint = $Credential.Endpoint } if ([string]::IsNullOrEmpty($Credential.TenantID)) { Add-PowerAppsAccount ` -Endpoint $endpoint ` -Password $Credential.Password ` -UserName $Credential.UserName } else { Add-PowerAppsAccount ` -Endpoint $endpoint ` -TenantID $Credential.TenantID ` -SecureClientSecret $Credential.Password ` -ApplicationId $Credential.UserName } } } function LoadModule { param ( [Parameter(Mandatory = $true)] [object]$ModuleName, [Parameter(Mandatory = $true)] [string]$MinimumVersion ) # If the correct version of the module is not installed, but is in online gallery then install and import if ((Get-InstalledModule -Name $ModuleName -MinimumVersion $MinimumVersion -ErrorAction SilentlyContinue) -eq $null) { Install-Module -Name $ModuleName -Force Import-Module $ModuleName } else { # Check if module is imported if (-not (Get-Module | Where-Object {$_.Name -eq $ModuleName})) { # If module is not imported, but available on disk then import if (Get-Module -ListAvailable | Where-Object {$_.Name -eq $ModuleName}) { Import-Module $ModuleName } } } } function CreateLanguageObject { param ( [Parameter(Mandatory = $true)] [object]$Language ) return New-Object -TypeName Microsoft.Xrm.Services.Admin.Client.Models.Language($Language.LanguageName, $Language.LanguageDisplayName, $Language.LanguageLocalizedDisplayName) } function CreateTemplateObject { param ( [Parameter(Mandatory = $true)] [object]$Template ) $supportedRelease = New-Object -TypeName Microsoft.Xrm.Services.Admin.Client.Models.SupportedReleases($null, "Dynamics 365, version 9.0") $supportedReleases = New-Object 'system.collections.generic.list[Microsoft.Xrm.Services.Admin.Client.Models.SupportedReleases]' $supportedReleases.Add($supportedRelease) return New-Object -TypeName Microsoft.Xrm.Services.Admin.Client.Models.Template($Template.TemplateName, $Template.TemplateDisplayName, "", $supportedReleases) } function CreateCurrencyObject { param ( [Parameter(Mandatory = $true)] [object]$Currency ) return New-Object -TypeName Microsoft.Xrm.Services.Admin.Client.Models.Currency($Currency.CurrencyCode, 0, $Currency.CurrencySymbol, $Currency.CurrencyName) } function CreateInstanceObject { param ( [Parameter(Mandatory = $true)] [object]$Environment ) $stateIsSupportedForDelete = $true if ($Environment.Internal.properties.linkedEnvironmentMetadata.InstanceState -ne "Ready") { $stateIsSupportedForDelete = $false } $additionalProperties = New-Object 'system.collections.generic.dictionary[[string],[string]]' $additionalProperties.Add("CreatedOnUTC", ([System.DateTimeOffset]$Environment.Internal.properties.linkedEnvironmentMetadata.createdTime).ToString()) $adminMode = $false if ($Environment.Internal.properties.states.runtime.id.ToString() -eq "AdminMode") { $adminMode = $true } $protectionStatus = "MicrosoftEncrypted" if ($Environment.Internal.properties.protectionStatus.keyManagedBy -eq "Customer") { $protectionStatus = "TenantEncrypted" } $instance = New-Object -TypeName Microsoft.Xrm.Services.Admin.Client.Models.Instance $instance.Id = $Environment.Internal.properties.linkedEnvironmentMetadata.ResourceId $instance.UniqueName = $Environment.Internal.properties.linkedEnvironmentMetadata.UniqueName $instance.Version = $Environment.Internal.properties.linkedEnvironmentMetadata.Version $instance.ApplicationUrl = $Environment.Internal.properties.linkedEnvironmentMetadata.instanceUrl $instance.ApiUrl = $Environment.Internal.properties.linkedEnvironmentMetadata.InstanceApiUrl $instance.State = $Environment.Internal.properties.linkedEnvironmentMetadata.InstanceState $instance.Type = $Environment.EnvironmentType $instance.FriendlyName = $Environment.Internal.properties.linkedEnvironmentMetadata.FriendlyName $instance.InitialUserPrincipalName = $Environment.CreatedBy.userPrincipalName $instance.StateIsSupportedForDelete = $stateIsSupportedForDelete $instance.AdminMode = $adminMode $instance.DomainName = $Environment.Internal.properties.linkedEnvironmentMetadata.domainName $instance.BaseLanguage = $Environment.Internal.properties.linkedEnvironmentMetadata.baseLanguage $instance.IsLocked = $Environment.Internal.properties.linkedEnvironmentMetadata.isLocked $instance.ProtectionStatus = $protectionStatus $instance.AdditionalProperties = $additionalProperties $instance.SecurityGroupId = $Environment.Internal.properties.linkedEnvironmentMetadata.securityGroupId return $instance } function CreateServiceVersionObject { param ( ) $serviceVersion = New-Object Microsoft.Xrm.Services.Admin.Client.Models.ServiceVersion $serviceVersion.LocalizedName = "Dynamics 365, version 9.0" $serviceVersion.LCID = 1033 $serviceVersion.Version = "9.0" $serviceVersion.Id = "bce9abbf-90fd-42e7-b0e5-1ced6df22fa1" $serviceVersion.Name = "Dynamics 365, version 9.0" return $serviceVersion } function CreateOperationStatusObject { param ( [Parameter(Mandatory = $true)] [guid]$OperationId, [Parameter(Mandatory = $true)] [string]$Status, [Parameter(Mandatory = $false)] [system.collections.generic.list[Microsoft.Xrm.Services.Admin.Client.Models.ItemDescription]]$Errors, [Parameter(Mandatory = $false)] [system.collections.generic.list[Microsoft.Xrm.Services.Admin.Client.Models.ItemDescription]]$Information, [Parameter(Mandatory = $false)] [string]$OperationLocation = $null, [Parameter(Mandatory = $false)] [string]$ResourceLocation = $null, [Parameter(Mandatory = $false)] [Microsoft.Xrm.Services.Admin.Client.Models.OperationContext]$Context ) if ($Errors -eq $null) { $Errors = New-Object -TypeName 'system.collections.generic.list[Microsoft.Xrm.Services.Admin.Client.Models.ItemDescription]' } if ($Information -eq $null) { $Information = New-Object -TypeName 'system.collections.generic.list[Microsoft.Xrm.Services.Admin.Client.Models.ItemDescription]' } return New-Object -TypeName Microsoft.Xrm.Services.Admin.Client.Models.OperationStatus( ` $OperationId, ` $Status, ` $Errors, ` $Information, ` $OperationLocation, ` $ResourceLocation, ` $context) } function CreateInstanceTypes { param ( [Parameter(Mandatory = $true)] [object]$InstanceTypeInfo ) $instanceTypeInfos = New-Object -TypeName 'system.collections.generic.list[Microsoft.Xrm.Services.Admin.Client.Models.InstanceTypeInfo]' if ($InstanceTypeInfo.value.production -ne $null) { $instanceType = CreateInstanceType -Type "Production" -Total $InstanceTypeInfo.value.production -Consumed 0 } else { $instanceType = CreateInstanceType -Type "Production" -Total 0 -Consumed 0 } $instanceTypeInfos.Add($instanceType) if ($InstanceTypeInfo.value.sandbox -ne $null) { $instanceType = CreateInstanceType -Type "Sandbox" -Total $InstanceTypeInfo.value.sandbox -Consumed 0 } else { $instanceType = CreateInstanceType -Type "Sandbox" -Total 0 -Consumed 0 } $instanceTypeInfos.Add($instanceType) if ($InstanceTypeInfo.value.preview -ne $null) { $instanceType = CreateInstanceType -Type "Preview" -Total $InstanceTypeInfo.value.preview -Consumed 0 } else { $instanceType = CreateInstanceType -Type "Preview" -Total 0 -Consumed 0 } $instanceTypeInfos.Add($instanceType) if ($InstanceTypeInfo.value.support -ne $null) { $instanceType = CreateInstanceType -Type "Support" -Total $InstanceTypeInfo.value.support -Consumed 0 } else { $instanceType = CreateInstanceType -Type "Support" -Total 0 -Consumed 0 } $instanceTypeInfos.Add($instanceType) if ($InstanceTypeInfo.value.trial -ne $null) { $instanceType = CreateInstanceType -Type "Trial" -Total $InstanceTypeInfo.value.trial -Consumed 0 } else { $instanceType = CreateInstanceType -Type "Trial" -Total 0 -Consumed 0 } $instanceTypeInfos.Add($instanceType) if ($InstanceTypeInfo.value.default -ne $null) { $instanceType = CreateInstanceType -Type "Default" -Total $InstanceTypeInfo.value.default -Consumed 0 } else { $instanceType = CreateInstanceType -Type "Default" -Total 0 -Consumed 0 } $instanceTypeInfos.Add($instanceType) if ($InstanceTypeInfo.value.developer -ne $null) { $instanceType = CreateInstanceType -Type "Developer" -Total $InstanceTypeInfo.value.developer -Consumed 0 } else { $instanceType = CreateInstanceType -Type "Developer" -Total 0 -Consumed 0 } $instanceTypeInfos.Add($instanceType) if ($InstanceTypeInfo.value.subscriptionBasedTrial -ne $null) { $instanceType = CreateInstanceType -Type "SubscriptionBasedTrial" -Total $InstanceTypeInfo.value.subscriptionBasedTrial -Consumed 0 } else { $instanceType = CreateInstanceType -Type "SubscriptionBasedTrial" -Total 0 -Consumed 0 } $instanceTypeInfos.Add($instanceType) if ($InstanceTypeInfo.value.teams -ne $null) { $instanceType = CreateInstanceType -Type "Teams" -Total $InstanceTypeInfo.value.teams -Consumed 0 } else { $instanceType = CreateInstanceType -Type "Teams" -Total 0 -Consumed 0 } $instanceTypeInfos.Add($instanceType) return $instanceTypeInfos } function CreateInstanceType { param ( [Parameter(Mandatory = $true)] [string]$Type, [Parameter(Mandatory = $true)] [int]$Total, [Parameter(Mandatory = $true)] [int]$Consumed ) return New-Object -TypeName Microsoft.Xrm.Services.Admin.Client.Models.InstanceTypeInfo($Type, $Total, $Consumed) } function CreateTenantApplicationIdentity { param ( [Parameter(Mandatory = $true)] [object]$application ) $tenantApplicationIdentity = New-Object -TypeName Microsoft.Xrm.Services.Admin.Client.Models.TenantApplicationIdentity $tenantApplicationIdentity.Id = $application.applicationId $tenantApplicationIdentity.AadApplicationId = $application.applicationId $tenantApplicationIdentity.TenantId = $global:currentSession.tenantId $tenantApplicationIdentity.Enabled = $true $tenantApplicationIdentity.CreatedOn = (Get-Date -Format "dddd MM/dd/yyyy HH:mm K") return $tenantApplicationIdentity } function CreateProtectionKeyObject { param ( [Parameter(Mandatory = $true)] [object]$Key ) $protectionKey = New-Object -TypeName Microsoft.Xrm.Services.Admin.Client.Models.Key $protectionKey.KeyName = $Key.keyName $protectionKey.TenantId = $Key.tenantId $protectionKey.KeyState = $Key.keyState $protectionKey.CreatedOn = $Key.createdDateTime $protectionKey.LockedOn = $Key.lockedDateTime return $protectionKey } function UpdateRuntimeState { param ( [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $true)] [string]$InstanceId, [Parameter(Mandatory = $true)] [string]$RuntimeState, [Parameter(Mandatory = $false)] [object]$Credential ) process { AuthenticationAndLoadModule -Credential $Credential $environment = Get-AdminPowerAppEnvironment -InstanceId $InstanceId -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) $response = Set-AdminPowerAppEnvironmentRuntimeState ` -EnvironmentName $environment.EnvironmentName ` -RuntimeState $RuntimeState ` -Verbose:($script:MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) if ($response.Code -eq 204 -or $response.Code -eq 200) { return CreateOperationStatusObject ` -OperationId "00000000-0000-0000-0000-000000000000" ` -Status "Succeeded" } return CreateOperationStatusObject ` -OperationId "00000000-0000-0000-0000-000000000000" ` -Status "Failed" ` -Errors $response.Errors } } function CreateManualBackupObject { param ( [Parameter(Mandatory = $true)] [object]$Backup, [Parameter(Mandatory = $true)] [string]$InstanceId ) $manualBackup = New-Object -TypeName Microsoft.Xrm.Services.Admin.Client.Models.ManualBackup $manualBackup.Notes = $Backup.Notes $manualBackup.Label = $Backup.Label $manualBackup.CreatedByUserPrincipalName = $Backup.CreatedBy.UserPrincipalName $manualBackup.InstanceId = $InstanceId $manualBackup.Id = $Backup.Id $manualBackup.TimestampUtc = $Backup.BackupPointDateTime $manualBackup.ExpiryTimeUtc = $Backup.BackupExpiryDateTime return $manualBackup } function CreateItemDescription { param ( [Parameter(Mandatory = $false)] [string]$Subject, [Parameter(Mandatory = $false)] [string]$Description, [Parameter(Mandatory = $false)] [string]$Code ) return New-Object -TypeName Microsoft.Xrm.Services.Admin.Client.Models.ItemDescription($Subject, $Description, $Code) } function CreateOperationStatusByResponse { param ( [Parameter(Mandatory = $true)] [object]$Response, [Parameter(Mandatory = $false)] [string]$GeoType, [Parameter(Mandatory = $false)] [string]$OperationId = "00000000-0000-0000-0000-000000000000" ) $errors = New-Object -TypeName 'system.collections.generic.list[Microsoft.Xrm.Services.Admin.Client.Models.ItemDescription]' $context = New-Object -TypeName Microsoft.Xrm.Services.Admin.Client.Models.OperationContext if ($Response -ne $null) { if ($Response.Code -eq 200) { return CreateOperationStatusObject ` -OperationId $OperationId ` -Status "Succeeded" ` -Context $context } elseif ($Response.Code -eq 202) { if ($Response.Headers['Operation-Location'] -ne $null) { $operationLocation = $Response.Headers['Operation-Location'] } else { $operationLocation = $Response.Headers['Location'] } $operationId = (($operationLocation -split "operations/")[1]).Substring(0, 36) return CreateOperationStatusObject ` -OperationId $operationId ` -Status "Running" ` -OperationLocation $operationLocation ` -Context $context } elseif ($Response.Code -eq 204) { return CreateOperationStatusObject ` -OperationId "00000000-0000-0000-0000-000000000000" ` -Status "Succeeded" ` -Context $context } elseif ($Response.CommonDataServiceDatabaseProvisioningState -ne $null -and $Response.CommonDataServiceDatabaseProvisioningState -eq "Succeeded") { # New-CrmInstance returns environment $items = New-Object 'system.collections.generic.dictionary[[string],[object]]' $items.Add("admin.InstanceId", $response.Internal.properties.linkedEnvironmentMetadata.ResourceId) $items.Add("InstanceState", "Ready") $resourceLocation = "https://admin.powerplatform.microsoft.com/environments/instance/{instanceId}/hub?geo={geoType}" ` | ReplaceMacro -Macro "{instanceId}" -Value $response.Internal.properties.linkedEnvironmentMetadata.ResourceId ` | ReplaceMacro -Macro "{geoType}" -Value $GeoType $context = New-Object -TypeName Microsoft.Xrm.Services.Admin.Client.Models.OperationContext($items) return CreateOperationStatusObject ` -OperationId "00000000-0000-0000-0000-000000000000" ` -Status "Succeeded" ` -ResourceLocation $resourceLocation ` -Context $context } if ($response.Errors -ne $null) { foreach ($error in $response.Errors) { $errorObject = CreateErrorObject -Error $error $errors.Add($errorObject) } } else { $errorObject = CreateErrorObject -Error $response.Error $errors.Add($errorObject) } } else { $errorObject = CreateItemDescription -Code "NotSpecified" -Description "Response is null" $errors.Add($errorObject) } return CreateOperationStatusObject ` -OperationId "00000000-0000-0000-0000-000000000000" ` -Status "Failed" ` -Errors $errors } function CreateErrorObject { param ( [Parameter(Mandatory = $true)] [object]$Error ) if ($Error -ne $null -and $Error.code) { $errorCode = $Error.code } if ($Error -ne $null -and $Error.message -ne $null) { $errorMessage = $Error.message } return CreateItemDescription -Code $errorCode -Description $errorMessage } function ConvertCdsOperationToOperationStatus { param ( [Parameter(Mandatory = $true)] [object]$CdsOperation ) $operationLocation = "https://api.bap.microsoft.com/providers/Microsoft.BusinessAppPlatform/locations/{location}/protectionKeyOperations/{operationId}?api-version=2020-05-01" ` | ReplaceMacro -Macro "{location}" -Value $CdsOperation.Geo ` | ReplaceMacro -Macro "{operationId}" -Value $CdsOperation.Id; $errors = New-Object -TypeName 'system.collections.generic.list[Microsoft.Xrm.Services.Admin.Client.Models.ItemDescription]' if ($CdsOperation.Errors -ne $null) { foreach($error in $CdsOperation.Errors) { $errorObject = CreateErrorObject -Error $error $errors.Add($errorObject) } } $Information = New-Object -TypeName 'system.collections.generic.list[Microsoft.Xrm.Services.Admin.Client.Models.ItemDescription]' $context = New-Object -TypeName Microsoft.Xrm.Services.Admin.Client.Models.OperationContext return New-Object -TypeName Microsoft.Xrm.Services.Admin.Client.Models.OperationStatus( ` $CdsOperation.Id, ` $CdsOperation.State, ` $errors, ` $Information, ` $operationLocation, ` $null, ` $context) } # SIG # Begin signature block # MIIjgwYJKoZIhvcNAQcCoIIjdDCCI3ACAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBwmbQ35xEkrdQI # xkISLBTwwsv057qXLbhbhq08QWK4YKCCDYEwggX/MIID56ADAgECAhMzAAABh3IX # chVZQMcJAAAAAAGHMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p # bmcgUENBIDIwMTEwHhcNMjAwMzA0MTgzOTQ3WhcNMjEwMzAzMTgzOTQ3WjB0MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB # AQDOt8kLc7P3T7MKIhouYHewMFmnq8Ayu7FOhZCQabVwBp2VS4WyB2Qe4TQBT8aB # znANDEPjHKNdPT8Xz5cNali6XHefS8i/WXtF0vSsP8NEv6mBHuA2p1fw2wB/F0dH # sJ3GfZ5c0sPJjklsiYqPw59xJ54kM91IOgiO2OUzjNAljPibjCWfH7UzQ1TPHc4d # weils8GEIrbBRb7IWwiObL12jWT4Yh71NQgvJ9Fn6+UhD9x2uk3dLj84vwt1NuFQ # itKJxIV0fVsRNR3abQVOLqpDugbr0SzNL6o8xzOHL5OXiGGwg6ekiXA1/2XXY7yV # Fc39tledDtZjSjNbex1zzwSXAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUhov4ZyO96axkJdMjpzu2zVXOJcsw # UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1 # ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDU4Mzg1MB8GA1UdIwQYMBaAFEhu # ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu # bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w # Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3 # Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx # MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAixmy # S6E6vprWD9KFNIB9G5zyMuIjZAOuUJ1EK/Vlg6Fb3ZHXjjUwATKIcXbFuFC6Wr4K # NrU4DY/sBVqmab5AC/je3bpUpjtxpEyqUqtPc30wEg/rO9vmKmqKoLPT37svc2NV # BmGNl+85qO4fV/w7Cx7J0Bbqk19KcRNdjt6eKoTnTPHBHlVHQIHZpMxacbFOAkJr # qAVkYZdz7ikNXTxV+GRb36tC4ByMNxE2DF7vFdvaiZP0CVZ5ByJ2gAhXMdK9+usx # zVk913qKde1OAuWdv+rndqkAIm8fUlRnr4saSCg7cIbUwCCf116wUJ7EuJDg0vHe # yhnCeHnBbyH3RZkHEi2ofmfgnFISJZDdMAeVZGVOh20Jp50XBzqokpPzeZ6zc1/g # yILNyiVgE+RPkjnUQshd1f1PMgn3tns2Cz7bJiVUaqEO3n9qRFgy5JuLae6UweGf # AeOo3dgLZxikKzYs3hDMaEtJq8IP71cX7QXe6lnMmXU/Hdfz2p897Zd+kU+vZvKI # 3cwLfuVQgK2RZ2z+Kc3K3dRPz2rXycK5XCuRZmvGab/WbrZiC7wJQapgBodltMI5 # GMdFrBg9IeF7/rP4EqVQXeKtevTlZXjpuNhhjuR+2DMt/dWufjXpiW91bo3aH6Ea # jOALXmoxgltCp1K7hrS6gmsvj94cLRf50QQ4U8Qwggd6MIIFYqADAgECAgphDpDS # AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK # V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0 # IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0 # ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5MDlaFw0yNjA3MDgyMTA5MDla # MH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS # ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMT # H01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTEwggIiMA0GCSqGSIb3DQEB # AQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQTTS68rZYIZ9CGypr6VpQqrgG # OBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULTiQ15ZId+lGAkbK+eSZzpaF7S # 35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYSL+erCFDPs0S3XdjELgN1q2jz # y23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494HDdVceaVJKecNvqATd76UPe/7 # 4ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZPrGMXeiJT4Qa8qEvWeSQOy2u # M1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5bmR/U7qcD60ZI4TL9LoDho33 # X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGSrhwjp6lm7GEfauEoSZ1fiOIl # XdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADhvKwCgl/bwBWzvRvUVUvnOaEP # 6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON7E1JMKerjt/sW5+v/N2wZuLB # l4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xcv3coKPHtbcMojyyPQDdPweGF # RInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqwiBfenk70lrC8RqBsmNLg1oiM # CwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFEhuZOVQ # BdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1Ud # DwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFHItOgIxkEO5FAVO # 4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwubWljcm9zb2Z0 # LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y # Mi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUFBzAChkJodHRwOi8vd3d3Lm1p # Y3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y # Mi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGCNy4DMIGDMD8GCCsGAQUFBwIB # FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2RvY3MvcHJpbWFyeWNw # cy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AcABvAGwAaQBjAHkA # XwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAGfyhqWY # 4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4sPvjDctFtg/6+P+gKyju/R6mj # 82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKLUtCw/WvjPgcuKZvmPRul1LUd # d5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7pKkFDJvtaPpoLpWgKj8qa1hJ # Yx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft0N3zDq+ZKJeYTQ49C/IIidYf # wzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4MnEnGn+x9Cf43iw6IGmYslmJ # aG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxvFX1Fp3blQCplo8NdUmKGwx1j # NpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG0QaxdR8UvmFhtfDcxhsEvt9B # xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96 # eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7 # r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I # RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIVWDCCFVQCAQEwgZUwfjELMAkG # A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx # HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z # b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAYdyF3IVWUDHCQAAAAABhzAN # BglghkgBZQMEAgEFAKCBoDAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor # BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgUctVG0S8 # ThjNP68I9jfRNc8ODcEOKDwFLZS7qN6HXsAwNAYKKwYBBAGCNwIBDDEmMCSgEoAQ # AFQAZQBzAHQAUwBpAGcAbqEOgAxodHRwOi8vdGVzdCAwDQYJKoZIhvcNAQEBBQAE # ggEAoTxCqP1CNrO9e81mNGpTpuX75rCKfRTDsK3+31EYzxQEmYQ61lsIKKlypsNL # ze3hUXDOplYZy9Fo6sMmpcCOTvsdxNgXnNB0Fs/X49E1Lgyxq6no73ZiYn+s7Wxh # Yc6APZxqTRw2F57TWfIdrgLx5gk6Vp0GsRQkc89iFDh8jpqKk7AtzgqHAJkyuY6n # MeROcdt0+ljHRkI718oWr6syXEOyvQopJoutMLuafZfOIqgwu9/UYy9WFl2yyA+o # taVONq1e5DgBkTinZFssDUXv6vVLvPw2Rkq9fAVxfmbAl5NrerPRqebqddu+llRX # 5KwdCEWTpc/O1sT7r04aHAOUKqGCEvAwghLsBgorBgEEAYI3AwMBMYIS3DCCEtgG # CSqGSIb3DQEHAqCCEskwghLFAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFUBgsqhkiG # 9w0BCRABBKCCAUMEggE/MIIBOwIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFlAwQC # AQUABCANkH+Qi/JGNTNDDKz7g+51kFltHfwtWPBJuIsgip9WugIGX3SUej1TGBIy # MDIwMTAwNTE3MjMxNi41MlowBIACAfSggdSkgdEwgc4xCzAJBgNVBAYTAlVTMRMw # EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN # aWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRp # b25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjozMkJELUUz # RDUtM0IxRDElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaCC # DkQwggT1MIID3aADAgECAhMzAAABLqjSGQeT9GvoAAAAAAEuMA0GCSqGSIb3DQEB # CwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQH # EwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNV # BAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMB4XDTE5MTIxOTAxMTUw # NVoXDTIxMDMxNzAxMTUwNVowgc4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo # aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y # cG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1ZXJ0byBS # aWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjozMkJELUUzRDUtM0IxRDElMCMG # A1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZTCCASIwDQYJKoZIhvcN # AQEBBQADggEPADCCAQoCggEBAK7TTKJRU196LFIjMQ9q/UjpPhz43m5RnHgHAVp2 # YGni74+ltsYoO1nZ58rTbJhCQ8GYHy8B4devgbqqYPQNU3i+drpEtEcNLbsMr4ME # q3SM+vO3a6QMFd1lDRy7IQLPJNLKvcM69Nt7ku1YyM5NnPNDcRJsnUb/8Yx/zcW5 # cWjnoj8s9fQ93BPf/J74qM1ql2CdzQV74PBisMP/tppAnSuNwo8I7+uWr6vfpByn # SWDvJeMDrcsa62Xsm7DbB1NnSsPGAGt3RzlBV9KVicize4U3fo4chdoB2+QLu17P # aEmj07qq700CG5XJkpEYOjedNFiByApF7YRvQrOZQ07QYiMCAwEAAaOCARswggEX # MB0GA1UdDgQWBBSGmokmTguJN7uqSTQ1UhLwt1RObDAfBgNVHSMEGDAWgBTVYzpc # ijGQ80N7fEYbxTNoWoVtVTBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1p # Y3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNUaW1TdGFQQ0FfMjAxMC0w # Ny0wMS5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3 # Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1RpbVN0YVBDQV8yMDEwLTA3LTAx # LmNydDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMIMA0GCSqGSIb3 # DQEBCwUAA4IBAQCN4ARqpzCuutNqY2nWJDDXj35iaidlgtJ/bspYsAX8atJl19If # UKIzTuuSVU3caXZ6/YvMMYMcbsNa/4J28us23K6PWZAljIj0G8QtwDMlQHjrKnrc # r4FBAz6ZqvB6SrN3/Wbb0QSK/OlxsU0mfD7z87R2JM4gwKJvH6EILuAEtjwUGSB1 # NKm3Twrm51fCD0jxvWxzaUS2etvMPrh8DNrrHLJBR3UHvg/NXS2IzdQn20xjjsW0 # BUAiTf+NCRpxUvu/j80Nb1++vnejibfpQJ2IlXiJdIi+Hb+OL3XOr8MaDDSYOaRF # AIfcoq3VPi4BkvSC8QGrvhjAZafkE7R6L5FJMIIGcTCCBFmgAwIBAgIKYQmBKgAA # AAAAAjANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh # c2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBD # b3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUg # QXV0aG9yaXR5IDIwMTAwHhcNMTAwNzAxMjEzNjU1WhcNMjUwNzAxMjE0NjU1WjB8 # MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVk # bW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1N # aWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCCASIwDQYJKoZIhvcNAQEBBQAD # ggEPADCCAQoCggEBAKkdDbx3EYo6IOz8E5f1+n9plGt0VBDVpQoAgoX77XxoSyxf # xcPlYcJ2tz5mK1vwFVMnBDEfQRsalR3OCROOfGEwWbEwRA/xYIiEVEMM1024OAiz # Qt2TrNZzMFcmgqNFDdDq9UeBzb8kYDJYYEbyWEeGMoQedGFnkV+BVLHPk0ySwcSm # XdFhE24oxhr5hoC732H8RsEnHSRnEnIaIYqvS2SJUGKxXf13Hz3wV3WsvYpCTUBR # 0Q+cBj5nf/VmwAOWRH7v0Ev9buWayrGo8noqCjHw2k4GkbaICDXoeByw6ZnNPOcv # RLqn9NxkvaQBwSAJk3jN/LzAyURdXhacAQVPIk0CAwEAAaOCAeYwggHiMBAGCSsG # AQQBgjcVAQQDAgEAMB0GA1UdDgQWBBTVYzpcijGQ80N7fEYbxTNoWoVtVTAZBgkr # BgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw # AwEB/zAfBgNVHSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvXzpoYxDBWBgNVHR8ETzBN # MEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0 # cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYIKwYBBQUHAQEETjBMMEoG # CCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01p # Y1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNydDCBoAYDVR0gAQH/BIGVMIGSMIGPBgkr # BgEEAYI3LgMwgYEwPQYIKwYBBQUHAgEWMWh0dHA6Ly93d3cubWljcm9zb2Z0LmNv # bS9QS0kvZG9jcy9DUFMvZGVmYXVsdC5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABl # AGcAYQBsAF8AUABvAGwAaQBjAHkAXwBTAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJ # KoZIhvcNAQELBQADggIBAAfmiFEN4sbgmD+BcQM9naOhIW+z66bM9TG+zwXiqf76 # V20ZMLPCxWbJat/15/B4vceoniXj+bzta1RXCCtRgkQS+7lTjMz0YBKKdsxAQEGb # 3FwX/1z5Xhc1mCRWS3TvQhDIr79/xn/yN31aPxzymXlKkVIArzgPF/UveYFl2am1 # a+THzvbKegBvSzBEJCI8z+0DpZaPWSm8tv0E4XCfMkon/VWvL/625Y4zu2JfmttX # QOnxzplmkIz/amJ/3cVKC5Em4jnsGUpxY517IW3DnKOiPPp/fZZqkHimbdLhnPkd # /DjYlPTGpQqWhqS9nhquBEKDuLWAmyI4ILUl5WTs9/S/fmNZJQ96LjlXdqJxqgaK # D4kWumGnEcua2A5HmoDF0M2n0O99g/DhO3EJ3110mCIIYdqwUB5vvfHhAN/nMQek # kzr3ZUd46PioSKv33nJ+YWtvd6mBy6cJrDm77MbL2IK0cs0d9LiFAR6A+xuJKlQ5 # slvayA1VmXqHczsI5pgt6o3gMy4SKfXAL1QnIffIrE7aKLixqduWsqdCosnPGUFN # 4Ib5KpqjEWYw07t0MkvfY3v1mYovG8chr1m1rtxEPJdQcdeh0sVV42neV8HR3jDA # /czmTfsNv11P6Z0eGTgvvM9YBS7vDaBQNdrvCScc1bN+NR4Iuto229Nfj950iEkS # oYIC0jCCAjsCAQEwgfyhgdSkgdEwgc4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpX # YXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQg # Q29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1ZXJ0 # byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjozMkJELUUzRDUtM0IxRDEl # MCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcGBSsO # AwIaAxUA+1/CN6BILeU1yDGo+b6WkpLoQpuggYMwgYCkfjB8MQswCQYDVQQGEwJV # UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE # ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGlt # ZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIFAOMlqlMwIhgPMjAyMDEw # MDUxODIxMDdaGA8yMDIwMTAwNjE4MjEwN1owdzA9BgorBgEEAYRZCgQBMS8wLTAK # AgUA4yWqUwIBADAKAgEAAgIoagIB/zAHAgEAAgIR+jAKAgUA4yb70wIBADA2Bgor # BgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIBAAIDB6EgoQowCAIBAAID # AYagMA0GCSqGSIb3DQEBBQUAA4GBAHDwXAHBW1gWoIgpBGLXl5Z9jh53ubLzeQ3c # PyjqFVRS+w/XoCQW/nogGDt4sLz8+LWQHIQ1wId9Sy5w1pyuYlYt8hmW5zsPqAIO # 3Hhvqy3lwakFGY2AFEkP+9oPySWtKQk+MFmUajdKEMGYDRBsdHODEFOW+E5uIvJ+ # CkuPrBzCMYIDDTCCAwkCAQEwgZMwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh # c2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBD # b3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIw # MTACEzMAAAEuqNIZB5P0a+gAAAAAAS4wDQYJYIZIAWUDBAIBBQCgggFKMBoGCSqG # SIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQxIgQgYYrqNRRxNs95 # lhrUDcRqtyoKFCa94NK6z1Z5jSGW9BswgfoGCyqGSIb3DQEJEAIvMYHqMIHnMIHk # MIG9BCDa/s3O8YhWiqpVN0kTeK+x2m0RAh17JpR6DiFoTILJKTCBmDCBgKR+MHwx # CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt # b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1p # Y3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAABLqjSGQeT9GvoAAAAAAEu # MCIEIIfthjHoMwXzQ/9MRUrr6tiOJEs9RhOOpx2n05jQEBUIMA0GCSqGSIb3DQEB # CwUABIIBABU0jGCIJx8NUkU8R5j2dxCPzlDx8n817BGJI835Ja8pY36BbzrNhZmt # di3Lycv3W5YDQPd6EO4OjcRrPyC6kY2iH9FDvufjq+6AaT9un7nIv7kskLDD9yxK # 8HuH2/eA4yq+VduavgP0W5CMVRHeL8v8dTxV7jUL3l+fxLVNy71oCMtH6c/AvQat # wUc0AbfG576fEf/08ipxWO1H+2qlTdZUi/TH+pxPNad1oh8lKWAlrIc3PyEonVuT # eL5NfjxDl5dkAZncfvvvR4XFfIrEjybleCt3UXqOUxz6lIVpB3D1IBwgJ2qZ16/U # MDVAiEmEsiBIyn8vUgUn3al539gzWG4= # SIG # End signature block |