@@ -1851,7 +1851,7 @@ function Get-CrmEntityOptionSet{
18511851}
18521852
18531853# ImportSolutionToCrmAsync
1854- function Import-CrmSolutionAsync {
1854+ function Import-CrmSolutionAsync {
18551855# . ExternalHelp Microsoft.Xrm.Data.PowerShell.Help.xml
18561856 [CmdletBinding ()]
18571857 PARAM (
@@ -1872,7 +1872,9 @@ function Import-CrmSolutionAsync{
18721872 [parameter (Mandatory = $false , Position = 7 )]
18731873 [switch ]$ImportAsHoldingSolution ,
18741874 [parameter (Mandatory = $false , Position = 8 )]
1875- [switch ]$BlockUntilImportComplete
1875+ [switch ]$BlockUntilImportComplete ,
1876+ [parameter (Mandatory = $false , Position = 9 )]
1877+ [int64 ]$PollingDelayInSeconds = 5
18761878 )
18771879 $conn = VerifyCrmConnectionParam $conn
18781880 $importId = [guid ]::Empty
@@ -1884,7 +1886,7 @@ function Import-CrmSolutionAsync{
18841886 throw [System.IO.FileNotFoundException ] " $SolutionFilePath not found."
18851887 }
18861888
1887- Write-Output " Importing solution file $SolutionFilePath into: $ ( $conn.CrmConnectOrgUriActual ) "
1889+ Write-Verbose " Importing solution file $SolutionFilePath into: $ ( $conn.CrmConnectOrgUriActual ) "
18881890 Write-Verbose " OverwriteCustomizations: $OverwriteUnManagedCustomizations "
18891891 Write-Verbose " SkipDependancyCheck: $SkipDependancyOnProductUpdateCheckOnInstall "
18901892 Write-Verbose " ImportAsHoldingSolution: $ImportAsHoldingSolution "
@@ -1913,16 +1915,16 @@ function Import-CrmSolutionAsync{
19131915 $asyncRequest = New-Object Microsoft.Xrm.Sdk.Messages.ExecuteAsyncRequest
19141916 $asyncRequest.Request = $request ;
19151917
1916- Write-Verbose " ExecuteCrmOrganizationRequest with ExecuteAsyncRequest containing ImportSolutionRequest() this process can take a while..."
1918+ Write-Verbose " Importing solution. This process can take a while..."
19171919 try
19181920 {
19191921 $asyncResponse = ($conn.ExecuteCrmOrganizationRequest ($asyncRequest , " AsyncImportRequest" ) -as [Microsoft.Xrm.Sdk.Messages.ExecuteAsyncResponse ])
19201922 $importId = $asyncResponse.AsyncJobId
19211923
1922- Write-Verbose " ImportId (asyncoperationid): $importId "
1924+ Write-Verbose " Async Operation ID (asyncoperationid): $importId "
19231925 if ($importId -eq $null -or $importId -eq [Guid ]::Empty)
19241926 {
1925- throw " Import request failed, asyncoperationid is: $importId "
1927+ throw " Import request failed for Async Operation { $importId } "
19261928 }
19271929 # if the caller wants to get the ID and does NOT want to wait
19281930 if ($BlockUntilImportComplete -eq $false ){
@@ -1932,52 +1934,55 @@ function Import-CrmSolutionAsync{
19321934 catch
19331935 {
19341936 throw LastCrmConnectorException($conn )
1935- }
1937+ }
1938+
19361939 $pollingStart = Get-Date
19371940 $isProcessing = $true
19381941 $secondsSpentPolling = 0
1939- $pollingDelaySeconds = 5
19401942 $transientFailureCount = 0 ;
1941- Write-Verbose " Import of file completed , waiting on completion of AsyncOperationId: $importId "
1943+ Write-Verbose " Solution import requested , waiting on completion of Async Operation { $importId }... "
19421944
19431945 try {
19441946 while (($isProcessing -and $secondsSpentPolling -lt $MaxWaitTimeInSeconds ) -or ($isProcessing -and $MaxWaitTimeInSeconds -eq -1 )){
19451947 # delay
1946- Start-Sleep - Seconds $pollingDelaySeconds
1948+ Start-Sleep - Seconds $PollingDelayInSeconds
1949+
19471950 # check the import job for success/fail/inProgress
19481951 try {
1949- $import = Get-CrmRecord - conn $conn - EntityLogicalName asyncoperation - Id $importId - Fields statuscode
1952+ $import = Get-CrmRecord - conn $conn - EntityLogicalName asyncoperation - Id $importId - Fields statuscode, completedon , friendlymessage
19501953 } catch {
19511954 $transientFailureCount ++ ;
19521955 Write-Verbose " Import Job status check did not succeed: $ ( $_.Exception ) "
19531956 }
1954- $status = $import.statuscode_Property.value.Value ;
1957+
1958+ $statuscode = $import.statuscode_Property.value.Value ;
1959+
19551960 # Check for import completion - https://msdn.microsoft.com/en-us/library/gg309288.aspx
1956- if ($status -lt 30 ){
1957- $isProcessing = $true
1961+ if ($statuscode -lt 30 ){
19581962 $secondsSpentPolling = ([Int ]((Get-Date ) - $pollingStart ).TotalSeconds)
1959- Write-Output " $ ( $secondsSPentPolling.ToString (" 000" )) sec of: $MaxWaitTimeInSeconds - ImportStatus : $ ( $import.statuscode ) "
1963+ Write-Verbose " Executing for $ ( $secondsSPentPolling.ToString (" 000" )) / $MaxWaitTimeInSeconds seconds | Status : $ ( $import.statuscode ) ( $ statuscode )"
19601964 }
1961- elseif ($status -eq 31 -or $status -eq 32 ){
1965+ elseif ($statuscode -eq 31 -or $statuscode -eq 32 ){
19621966 $isProcessing = $false
1963- throw " $ ( $import.statuscode ) - AsyncOperation with Id: $importId has been either cancelled or has failed. "
1967+ throw " Status: $ ( $import.statuscode ) ( $statuscode ) | Operation has been either cancelled or has failed for Async Operation { $importId }. `n $ ( $import .friendlymessage ) "
19641968 break ;
19651969 }
1966- elseif ($status -eq 30 ){
1970+ elseif ($statuscode -eq 30 ){
19671971 $isProcessing = $false
1968- Write-Verbose " Processing Completed at: $ ( $import.completedon ) "
1972+ Write-Verbose " Processing Completed at: $ ( $import.completedon ) "
19691973 if ($PublishChanges ){
1970- Write-Verbose " PublishChanges set, executing: Publish-CrmAllCustomization using the same connection."
1974+ Write-Verbose " SUCCESS: PublishChanges set, executing: Publish-CrmAllCustomization using the same connection."
19711975 Publish-CrmAllCustomization - conn $conn
1972- return $asyncResponse
1976+ return $import
19731977 }
19741978 else {
1975- Write-Output " Import Complete, don't forget to publish customizations."
1976- return $asyncResponse
1979+ Write-Verbose " SUCCESS: Import Complete, don't forget to publish customizations."
1980+ return $import
19771981 }
19781982 break ;
19791983 }
19801984 }
1985+
19811986 # User provided timeout and exit function with an error
19821987 if ($secondsSpentPolling -gt $MaxWaitTimeInSeconds ){
19831988 Write-Warning " Import-CrmSolutionAsync exited due to exceeding the maximum timeout of $MaxWaitTimeInSeconds . The import will continue in CRM async until it either succeeds or fails."
@@ -2026,7 +2031,7 @@ function Import-CrmSolution{
20262031 {
20272032 throw [System.IO.FileNotFoundException ] " $SolutionFilePath not found."
20282033 }
2029- Write-Host " Importing solution file $SolutionFilePath into: $ ( $conn.CrmConnectOrgUriActual ) "
2034+ Write-Verbose " Importing solution file $SolutionFilePath into: $ ( $conn.CrmConnectOrgUriActual ) "
20302035 Write-Verbose " OverwriteCustomizations: $OverwriteUnManagedCustomizations "
20312036 Write-Verbose " SkipDependancyCheck: $SkipDependancyOnProductUpdateCheckOnInstall "
20322037 Write-Verbose " ImportAsHoldingSolution: $ImportAsHoldingSolution "
@@ -2189,6 +2194,103 @@ function Import-CrmSolution{
21892194 }
21902195}
21912196
2197+ # MergeHoldingSolution
2198+ function Merge-HoldingSolutionAsync {
2199+ [CmdletBinding ()]
2200+ PARAM (
2201+ [parameter (Mandatory = $true )]
2202+ [Microsoft.Xrm.Tooling.Connector.CrmServiceClient ]$conn ,
2203+ [parameter (Mandatory = $true , Position = 1 )]
2204+ [string ]$CrmSolutionName ,
2205+ [parameter (Mandatory = $false , Position = 2 )]
2206+ [int64 ]$TimeoutInSeconds ,
2207+ [parameter (Mandatory = $false , Position = 3 )]
2208+ [switch ]$BlockAsync ,
2209+ [parameter (Mandatory = $false , Position = 4 )]
2210+ [int64 ]$PollingDelayInSeconds = 5
2211+ )
2212+
2213+ $conn = VerifyCrmConnectionParam $conn
2214+
2215+ $request = New-Object Microsoft.Crm.Sdk.Messages.DeleteAndPromoteRequest
2216+ $request.UniqueName = $CrmSolutionName
2217+
2218+ $asyncRequest = New-Object Microsoft.Xrm.Sdk.Messages.ExecuteAsyncRequest
2219+ $asyncRequest.Request = $request ;
2220+
2221+ try
2222+ {
2223+ Write-Verbose " Applying async solution upgrade for solution '$CrmSolutionName '"
2224+ $asyncResponse = ($conn.ExecuteCrmOrganizationRequest ($asyncRequest , " AsyncImportRequest" ) -as [Microsoft.Xrm.Sdk.Messages.ExecuteAsyncResponse ])
2225+ $asyncOperationId = $asyncResponse.AsyncJobId
2226+
2227+ Write-Verbose " Async Operation ID (asyncoperationid): $asyncOperationId "
2228+ if (($asyncOperationId -eq $null ) -or ($asyncOperationId -eq [Guid ]::Empty))
2229+ {
2230+ throw " Async request failed!"
2231+ }
2232+
2233+ # if the caller wants to get the ID and does NOT want to wait
2234+ if ($BlockAsync -eq $false ){
2235+ return $asyncResponse ;
2236+ }
2237+ }
2238+ catch
2239+ {
2240+ throw LastCrmConnectorException($conn )
2241+ }
2242+
2243+ $pollingStart = Get-Date
2244+ $isProcessing = $true
2245+ $secondsSpentPolling = 0
2246+ $transientFailureCount = 0 ;
2247+ Write-Verbose " Async Delete and Promote requested, waiting on completion..."
2248+
2249+ try {
2250+ while (($isProcessing -and $secondsSpentPolling -lt $TimeoutInSeconds ) -or ($isProcessing -and $TimeoutInSeconds -eq -1 )) {
2251+ # delay
2252+ Start-Sleep - Seconds $PollingDelayInSeconds
2253+
2254+ # check the async job for success/fail/inProgress
2255+ try {
2256+ $asyncOperation = Get-CrmRecord - conn $conn - EntityLogicalName asyncoperation - Id $asyncOperationId - Fields statuscode, completedon, friendlymessage
2257+ } catch {
2258+ $transientFailureCount ++ ;
2259+ Write-Verbose " Async job status check did not succeed: $ ( $_.Exception ) "
2260+ }
2261+
2262+ $statuscode = $asyncOperation.statuscode_Property.value.Value ;
2263+
2264+ # Check for import completion - https://msdn.microsoft.com/en-us/library/gg309288.aspx
2265+ if ($statuscode -lt 30 ){
2266+ $secondsSpentPolling = ([Int ]((Get-Date ) - $pollingStart ).TotalSeconds)
2267+ Write-Verbose " Executing for $ ( $secondsSPentPolling.ToString (" 000" )) /$TimeoutInSeconds seconds | Status: $ ( $asyncOperation.statuscode ) ($statuscode )"
2268+ }
2269+ elseif ($statuscode -eq 31 -or $statuscode -eq 32 ){
2270+ $isProcessing = $false
2271+ throw " Status: $ ( $asyncOperation.statuscode ) ($statuscode ) | Operation has been either cancelled or has failed.`n $ ( $asyncOperation.friendlymessage ) "
2272+ break ;
2273+ }
2274+ elseif ($statuscode -eq 30 ){
2275+ $isProcessing = $false
2276+ Write-Verbose " Processing Completed at: $ ( $asyncOperation.completedon ) "
2277+ Write-Verbose " SUCCESS: Delete and Promote successfully completed."
2278+ return $asyncOperation
2279+ }
2280+ }
2281+
2282+ # User provided timeout and exit function with an error
2283+ if ($secondsSpentPolling -gt $TimeoutInSeconds ){
2284+ Write-Warning " Delete and Promote request exited due to exceeding the maximum timeout of $TimeoutInSeconds . The import will continue in CRM asynchronously until it either succeeds or fails."
2285+ }
2286+
2287+ # at this point request appears to have succeeded
2288+ return $asyncResponse ;
2289+ } catch {
2290+ throw " AsyncOperation with ID: $asyncOperationId has encountered an exception: $_ "
2291+ }
2292+ }
2293+
21922294# InstallSampleDataToCrm
21932295function Add-CrmSampleData {
21942296# . ExternalHelp Microsoft.Xrm.Data.PowerShell.Help.xml
@@ -5506,4 +5608,4 @@ function UnzipCrmRibbon {
55065608 $reader = $null
55075609 }
55085610 }
5509- }
5611+ }
0 commit comments