diff --git a/.editorconfig b/.editorconfig
index 6d04bb5..fc01090 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -11,3 +11,7 @@ end_of_line = crlf
[*.md]
trim_trailing_whitespace = false
+
+[*.ps1]
+indent_style = tab
+tab_width = 2
diff --git a/README.md b/README.md
index 069c4b9..f63cbbb 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,11 @@
# generator-nullfactory-xrm
-> Dynamics CRM Solution Template
+> Scaffolding Template for Dynamics CRM/365 Solutions
[![Build status](https://ci.appveyor.com/api/projects/status/4dmqta7pnueqxa11?svg=true)](https://ci.appveyor.com/project/shanec-/generator-nullfactory-xrm)
-A yeoman template for managing [Solution Packager](https://msdn.microsoft.com/en-us/library/jj602987.aspx)-compatible Dynamics CRM solutions.
+A yeoman tempate for scaffolding [Solution Packager](https://msdn.microsoft.com/en-us/library/jj602987.aspx)-compatible Dynamics CRM (365) solution structure.
+
+The generated project structure is built around the Solution Packager provided in the official SDK and the [Microsoft.Xrm.Data.PowerShell](https://github.com/seanmcne/Microsoft.Xrm.Data.PowerShell) module. It facilitates the quick creation of team builds and release strategies with minimal effort and enables you to maintain a single source of truth for you CRM solutions.
## Installation
@@ -48,7 +50,7 @@ Optionally, install the [`Microsoft.Xrm.Data.PowerShell`](https://github.com/sea
Install-Module -Name Microsoft.Xrm.Data.PowerShell -Scope CurrentUser -Force
```
-Even if you skip the above step, the sychrnoization powershell script would attempt to install it automatically.
+Even if you skip the above step, the sychrnoization PowerShell script would attempt to install it automatically. The PowerShell scripts require a minimum of PowerShell 5.0 and Microsoft.Xrm.Data.PowerShell 2.5.
## Syncing a Solution to the Project
@@ -71,6 +73,7 @@ More information on source control management, setting up continuous integration
- [Release Strategy for Dynamics CRM - Part 2 - Setting Up the Build](http://www.nullfactory.net/2016/11/release-strategy-for-dynamics-crm-setting-up-the-build-part-2/)
- [Release Strategy for Dynamics CRM - Part 3 - Setting Up the Release](http://www.nullfactory.net/2016/11/release-strategy-for-dynamics-crm-setting-up-the-release-part-3/)
- [Release Strategy for Dynamics CRM - Part 4 - Versioning](http://www.nullfactory.net/2017/02/release-strategy-for-dynamics-crm-versioning-part-4/)
+- [Release Strategy for Dynamics CRM - Part 5 - Deploy Third-Party Solutions](http://www.nullfactory.net/2017/04/release-strategy-for-dynamics-crm-deploying-third-party-solutions-part-5/)
## Feedback
diff --git a/generators/app/index.js b/generators/app/index.js
index dd545b6..4468583 100644
--- a/generators/app/index.js
+++ b/generators/app/index.js
@@ -131,9 +131,13 @@ module.exports = yeoman.Base.extend({
this.destinationPath('Nullfactory.Xrm.Tooling/_Install/Install-Microsoft.Xrm.Data.PowerShell.ps1')
);
- this.fs.copy(
+ this.fs.copyTpl(
this.templatePath('Nullfactory.Xrm.Tooling/Mappings/solution-mapping.xml'),
- this.destinationPath('Nullfactory.Xrm.Tooling/Mappings/' + this.props.crmSolutionName + '-mapping.xml')
+ this.destinationPath('Nullfactory.Xrm.Tooling/Mappings/' + this.props.crmSolutionName + '-mapping.xml'), {
+ visualStudioSolutionProjectPrefix: this.props.visualStudioSolutionProjectPrefix,
+ isAddPluginProject: this.props.isAddPluginProject,
+ isAddWorkflowProject: this.props.isAddWorkflowProject
+ }
);
this.fs.copy(
diff --git a/generators/app/templates/Nullfactory.Xrm.Tooling/Mappings/solution-mapping.xml b/generators/app/templates/Nullfactory.Xrm.Tooling/Mappings/solution-mapping.xml
index d6ec678..090f75a 100644
--- a/generators/app/templates/Nullfactory.Xrm.Tooling/Mappings/solution-mapping.xml
+++ b/generators/app/templates/Nullfactory.Xrm.Tooling/Mappings/solution-mapping.xml
@@ -3,4 +3,12 @@
+
+<% if (isAddPluginProject == true) { %>
+
+<% } %>
+<% if (isAddWorkflowProject == true) { %>
+
+<% } %>
+
diff --git a/generators/app/templates/Nullfactory.Xrm.Tooling/Nullfactory.Xrm.Tooling.csproj b/generators/app/templates/Nullfactory.Xrm.Tooling/Nullfactory.Xrm.Tooling.csproj
index ace5079..1d29aa3 100644
--- a/generators/app/templates/Nullfactory.Xrm.Tooling/Nullfactory.Xrm.Tooling.csproj
+++ b/generators/app/templates/Nullfactory.Xrm.Tooling/Nullfactory.Xrm.Tooling.csproj
@@ -1,4 +1,5 @@
+
@@ -30,23 +31,17 @@
4
-
-
-
-
-
-
@@ -56,6 +51,7 @@
+
diff --git a/generators/app/templates/Nullfactory.Xrm.Tooling/Scripts/ApplyVersionToArtifact.ps1 b/generators/app/templates/Nullfactory.Xrm.Tooling/Scripts/ApplyVersionToArtifact.ps1
index bcda55f..fd500fd 100644
--- a/generators/app/templates/Nullfactory.Xrm.Tooling/Scripts/ApplyVersionToArtifact.ps1
+++ b/generators/app/templates/Nullfactory.Xrm.Tooling/Scripts/ApplyVersionToArtifact.ps1
@@ -1,3 +1,27 @@
+<#
+ .SYNOPSIS
+ Recursively finds a list of files and uses a pattern to match and replace matches with a specified version number.
+ .DESCRIPTION
+ Recursively finds a list of files within a folder and uses a regular expression pattern to match and replace it with a specified version number.
+ .NOTES
+ Author: Shane Carvalho
+ Version: generator-nullfactory-xrm@1.4.0
+ .LINK
+ https://nullfactory.net
+ .PARAMETER BuildSourcePath
+ The root folder to search.
+ .PARAMETER versionFile
+ The pattern of file to be searched.
+ .PARAMETER regexPattern
+ The regex pattern to be searched.
+ .PARAMETER finalVersion
+ The new version number.
+ .PARAMETER encoding
+ The optional encoding. Common encoding values include ASCII, Unicode, UTF8, Default. Default uses the encoding of the system's current ANSI code page.
+ .EXAMPLE
+ ReplaceVersion ".\SourceRootFolder" "*AssemblyInfo.cs" "\d+\.\d+\.\d+\.\d+" "1.3.0"
+ Gets a list of all files starting with "*AssemblyInfo.cs" within the folder "SourceRootFolder". Within these files it attempts to match all instances of a version number ex. 0.0.0.0 and replace it with the new version number.
+#>
function ReplaceVersion([string]$BuildSourcePath, [string] $versionFile, [string] $regexPattern, [string]$finalVersion, [string]$encoding='Default')
{
[bool]$output = $false
@@ -19,6 +43,16 @@ function ReplaceVersion([string]$BuildSourcePath, [string] $versionFile, [string
return $output
}
+<#
+ .SYNOPSIS
+ Applies a specified version number to a list of file matching a pattern.
+ .PARAMETER BuildSourcePath
+ The root folder containing the source files.
+ .PARAMETER BuildBuildNumber
+ The new build number.
+ .EXAMPLE
+ ApplyVersionToAssemblies ".\RootFolder" "0.1.2"
+#>
function ApplyVersionToAssemblies
{
[CmdletBinding()]
@@ -40,6 +74,16 @@ function ApplyVersionToAssemblies
}
}
+<#
+ .SYNOPSIS
+ Applies a specified version number to a CRM solution.
+ .PARAMETER BuildSourcePath
+ The root folder containing the extracted (via solutio packager) CRM Solution.
+ .PARAMETER BuildBuildNumber
+ The new build number.
+ .EXAMPLE
+ ApplyVersionToCrmSolution ".\RootFolder" "0.1.2"
+#>
function ApplyVersionToCrmSolution
{
[CmdletBinding()]
diff --git a/generators/app/templates/Nullfactory.Xrm.Tooling/Scripts/CrmSolution.Common.ps1 b/generators/app/templates/Nullfactory.Xrm.Tooling/Scripts/CrmSolution.Common.ps1
index 12ac817..a6149a3 100644
--- a/generators/app/templates/Nullfactory.Xrm.Tooling/Scripts/CrmSolution.Common.ps1
+++ b/generators/app/templates/Nullfactory.Xrm.Tooling/Scripts/CrmSolution.Common.ps1
@@ -1,4 +1,19 @@
-function GetUsername($solutionName)
+<#
+ .SYNOPSIS
+ Retrieves the username for the specified CRM solution.
+ .DESCRIPTION
+ Retrieves the username for the specified CRM solution which is stored in a user-environmental variable. If one does not exist, the script would prompt the user for a new username, which is then stored in a new environment variable.
+ .NOTES
+ Author: Shane Carvalho
+ Version: generator-nullfactory-xrm@1.4.0
+ .LINK
+ https://nullfactory.net
+ .PARAMETER solutionName
+ The name of the CRM solution.
+ .EXAMPLE
+ $username = Get-CrmUsername("Nullfactory.Solution1")
+#>
+function Get-CrmUsername($solutionName)
{
$variableName = "nfac_" + $solutionName + "_username"
$username = [environment]::GetEnvironmentVariable($variableName, "User")
@@ -12,7 +27,18 @@ function GetUsername($solutionName)
return $username;
}
-function GetPassword($solutionName)
+<#
+ .SYNOPSIS
+ Retrieves the password for the specified CRM solution.
+ .DESCRIPTION
+ Retrieves the password for the specified CRM solution which is stored in a user-environmental variable. If one does not exist, the script would prompt the user for a new password, which is then stored in a new environment variable.
+ Note that the password is stored as plain-text.
+ .PARAMETER solutionName
+ The name of the CRM solution.
+ .EXAMPLE
+ $username = Get-CrmPassword("Nullfactory.Solution1")
+#>
+function Get-CrmPassword($solutionName)
{
$variableName = "nfac_" + $solutionName + "_password"
$plainTextPassword = [environment]::GetEnvironmentVariable($variableName, "User")
diff --git a/generators/app/templates/Nullfactory.Xrm.Tooling/Scripts/Deploy-CrmSolution.Param.ps1 b/generators/app/templates/Nullfactory.Xrm.Tooling/Scripts/Deploy-CrmSolution.Param.ps1
index 139d45b..ed21fa8 100644
--- a/generators/app/templates/Nullfactory.Xrm.Tooling/Scripts/Deploy-CrmSolution.Param.ps1
+++ b/generators/app/templates/Nullfactory.Xrm.Tooling/Scripts/Deploy-CrmSolution.Param.ps1
@@ -1,24 +1,47 @@
+<#
+ .SYNOPSIS
+ Manually deploy the CRM Solutions to the remote CRM servers.
+ .DESCRIPTION
+ Manually deploy the CRM solution to the configured remote CRM servers.
+ .NOTES
+ Author: Shane Carvalho
+ Version: generator-nullfactory-xrm@1.4.0
+ .LINK
+ https://nullfactory.net
+#>
+
# Importing common functions
. .\CrmSolution.Common.ps1
-Write-Host "Attempting to deploy solution(s)..."
+# Defaulting to increased verbosity for manual execution
+$oldverbose = $VerbosePreference
+$VerbosePreference = "continue"
-.\Deploy-CrmSolution.ps1 `
- -serverUrl "<%= crmServerUrl %>" `
- -username (GetUsername "<%= crmSolutionName %>") `
- -password (GetPassword "<%= crmSolutionName %>") `
- -solutionName "<%= crmSolutionName %>" `
- -publishChanges `
- -activatePlugins
+Write-Host "Attempting to deploy solution(s)..."
+try
+{
+ .\Deploy-CrmSolution.ps1 `
+ -serverUrl "<%= crmServerUrl %>" `
+ -username (Get-CrmUsername "<%= visualStudioSolutionProjectPrefix %>.<%= crmSolutionName %>") `
+ -password (Get-CrmPassword "<%= visualStudioSolutionProjectPrefix %>.<%= crmSolutionName %>") `
+ -solutionName "<%= visualStudioSolutionProjectPrefix %>.<%= crmSolutionName %>" `
+ -publishChanges `
+ -activatePlugins
-# Include new entry for each CRM solution to be released manually
+ # Include new entry for each CRM solution to be released manually
-# .\Deploy-CrmSolution.ps1 `
-# -serverUrl "http://servername/secondary" `
-# -username (GetUsername "env_secondary_username_key") `
-# -password (GetPassword "env_secondary_password_key") `
-# -solutionName "secondary" `
-# -publishChanges `
-# -activatePlugins
+ # .\Deploy-CrmSolution.ps1 `
+ # -serverUrl "http://servername/secondary" `
+ # -username (GetUsername "env_secondary_username_key") `
+ # -password (GetPassword "env_secondary_password_key") `
+ # -solutionName "secondary" `
+ # -publishChanges `
+ # -activatePlugins
-Write-Host "Deployment(s) complete." -ForegroundColor Green
+ Write-Host "Deployment(s) complete." -ForegroundColor Green
+}
+finally
+{
+ # Reset the verbosity to original level
+ $VerbosePreference = $oldverbose
+}
diff --git a/generators/app/templates/Nullfactory.Xrm.Tooling/Scripts/Deploy-CrmSolution.ps1 b/generators/app/templates/Nullfactory.Xrm.Tooling/Scripts/Deploy-CrmSolution.ps1
index 9032fba..6f7828a 100644
--- a/generators/app/templates/Nullfactory.Xrm.Tooling/Scripts/Deploy-CrmSolution.ps1
+++ b/generators/app/templates/Nullfactory.Xrm.Tooling/Scripts/Deploy-CrmSolution.ps1
@@ -1,6 +1,53 @@
-#
-# Deploy-CrmSolution.ps1
-#
+<#
+
+ .SYNOPSIS
+ Deploy a CRM Solution to a remote server.
+ .DESCRIPTION
+ This scripts automatically connect to a remote Dynamics CRM instance using the provided credentials and deploys the specified solution. Works with both on-premises and online solutions.
+
+ Pre-requisites:
+ - PowerShell V5 or greater
+ - Latest version of Solution Packager tool provided with the CRM SDK.
+ - Micrsoft.Xrm.Data.Powershell 2.4 or greater
+
+ .NOTES
+ Author: Shane Carvalho
+ Version: generator-nullfactory-xrm@1.4.0
+ .LINK
+ https://nullfactory.net
+ .PARAMETER serverUrl
+ Mandatory parameter that specifies the server url of the Dynamics CRM instance being deployed to.
+ .PARAMETER username
+ Mandatory paramater is the username used to connect to Dynamics CRM.
+ .PARAMETER password
+ Mandatory paramerter is the password of the user used to connect to Dynamics CRM.
+ .PARAMETER solutionName
+ Required paramter. The name of the solution that needs to be downloaded and extracted.
+ .PARAMETER isOnPremServer
+ This optional switch tells the script if the server is an OnPremises server. CRM Online is the default provider.
+ .PARAMETER deployManagedSolution
+ This optional switch tells the script that it should deploy the managed version of the solution`. The unmanaged version is selected by default.
+ .PARAMETER activatePlugIns
+ This optional switch tells the script that it should attempt to activate plugins that have been included as part of the solution. Defaults to false.
+ .PARAMETER publishChanges
+ This optional switch tells the script that it should publish changes once deployed. Defaults to false.
+ .PARAMETER importAsHoldingSolution
+ This optional switch tells the script that it should import the solution as a hold solution.
+ .EXAMPLE
+ .\Deploy-CrmSolution.ps1 -serverUrl "https://sndbx.crm6.dynamics.com" -username "admin@sndx.onmicrosoft.com" -password "P@ssw0rd!" -solutionName "RemoteSolutionName"
+ Deploys the unmanaged version of "RemoteSolutionName" to the "https://sndbx.crm6.dynamics.com" dynamics crm online server.
+ .EXAMPLE
+ .\Deploy-CrmSolution.ps1 -serverUrl "https://sndbx.crm6.dynamics.com" -username "admin@sndx.onmicrosoft.com" -password "P@ssw0rd!" -solutionName "RemoteSolutionName" -deployManagedSolution -isOnPremServer
+ Deploys the managed version of "RemoteSolutionName" to the "https://sndbx.crm6.dynamics.com" dynamics crm on premises server and extract it to the "RemoteSolutionRoot" folder using the "RemoteSolutionName-mapping.xml" mapping file.
+ .EXAMPLE
+ .\Deploy-CrmSolution.ps1 -serverUrl "https://onpremserver/orgname" -username "admin@sndx.onmicrosoft.com" -password "P@ssw0rd!" -solutionName "RemoteSolutionName" -isOnPremServer -activatePlugIns -publishChanges -importAsHoldingSolution
+ Deploys the unmanaged version of "RemoteSolutionName" to the "https://onpremserver/orgname" dynamics crm onprem server as an holding solution. Once deployed, activate plugins and publish changes.
+ .EXAMPLE
+ .\Deploy-CrmSolution.ps1 -serverUrl "https://sndbx.crm6.dynamics.com" -username "admin@sndx.onmicrosoft.com" -password "P@ssw0rd!" -externalSolutionFileName ".\ThirdPartySolution.zip" -activatePlugIns -publishChanges
+ Deploys "ThirdPartySolution.zip" solution to the "https://sndbx.crm6.dynamics.com" dynamics crm online. Once deployed, activate plugins and publish changes.
+
+#>
+[CmdletBinding(DefaultParameterSetName="Internal")]
param(
[Parameter(Mandatory=$true, Position=1)]
[string]$serverUrl,
@@ -8,18 +55,20 @@ param(
[string]$username,
[Parameter(Mandatory=$true, Position=3)]
[string]$password,
- [Parameter(Mandatory=$true, Position=4)]
+ [Parameter(ParameterSetName='Internal',Mandatory=$true, Position=4)]
[string]$solutionName,
+ [Parameter(ParameterSetName='Internal')]
+ [switch]$deployManagedSolution,
+ [Parameter(ParameterSetName='External',Mandatory=$true)]
+ [string]$externalSolutionFileName,
[Parameter(Mandatory=$false)]
[switch]$isOnPremServer,
[Parameter(Mandatory=$false)]
- [switch]$deployManagedSolution,
- [Parameter(Mandatory=$false)]
- [switch]$activatePlugIns,
+ [switch]$activatePlugIns,
[Parameter(Mandatory=$false)]
[switch]$publishChanges,
- [Parameter(Mandatory=$false)]
- [switch]$importAsHoldingSolution
+ [Parameter(Mandatory=$false)]
+ [switch]$importAsHoldingSolution
)
if (-Not (Get-Module -ListAvailable -Name Microsoft.Xrm.Data.PowerShell))
@@ -34,23 +83,37 @@ $creds = New-Object System.Management.Automation.PSCredential ($username, $secur
if($isOnPremServer)
{
Write-Verbose "Connecting to OnPrem CRM instance $serverUrl ..."
- Connect-CrmOnPremDiscovery -Credential $creds -ServerUrl $serverUrl
+ $connectionState = Connect-CrmOnPremDiscovery -Credential $creds -ServerUrl $serverUrl
}
else
{
Write-Verbose "Connecting to Online CRM instance $serverUrl ..."
- Connect-CrmOnline -Credential $creds -ServerUrl $serverUrl
+ $connectionState = Connect-CrmOnline -Credential $creds -ServerUrl $serverUrl
+}
+
+# Make sure that the connection was successful, else stop the script.
+if($connectionState.IsReady -eq $false)
+{
+ throw $connectionState.LastCrmError
}
$releaseZipFileName = "";
-if (-Not $deployManagedSolution){ $releaseZipFileName = Resolve-Path("..\..\$solutionName\*\*\$solutionName.zip") }
-else { $releaseZipFileName = Resolve-Path("..\..\$solutionName\*\*\$solutionName" + "_managed.zip") }
+# if deploying external third party solution
+if($externalSolutionFileName)
+{
+ $releaseZipFileName = Resolve-Path($externalSolutionFileName)
+}
+else
+{
+ if (-Not $deployManagedSolution){ $releaseZipFileName = Resolve-Path("..\..\$solutionName\*\*\$solutionName.zip") }
+ else { $releaseZipFileName = Resolve-Path("..\..\$solutionName\*\*\$solutionName" + "_managed.zip") }
+}
Write-Verbose "Importing the $releaseZipFileName solution into $serverUrl ..."
Import-CrmSolution `
-SolutionFilePath $releaseZipFileName `
-PublishChanges:$publishChanges `
-ActivatePlugIns:$activatePlugIns `
- -ImportAsHoldingSolution:$importAsHoldingSolution `
+ -ImportAsHoldingSolution:$importAsHoldingSolution `
-MaxWaitTimeInSeconds 900
diff --git a/generators/app/templates/Nullfactory.Xrm.Tooling/Scripts/Pull-CrmSolution.Param.ps1 b/generators/app/templates/Nullfactory.Xrm.Tooling/Scripts/Pull-CrmSolution.Param.ps1
index d7197dd..ff3f1c2 100644
--- a/generators/app/templates/Nullfactory.Xrm.Tooling/Scripts/Pull-CrmSolution.Param.ps1
+++ b/generators/app/templates/Nullfactory.Xrm.Tooling/Scripts/Pull-CrmSolution.Param.ps1
@@ -1,24 +1,47 @@
-# Importing common functions
+<#
+ .SYNOPSIS
+ Manually pull and extract CRM Solutions from remote servers.
+ .DESCRIPTION
+ Manually pull and extract CRM Solutions from configured remote servers.
+ .NOTES
+ Author: Shane Carvalho
+ Version: generator-nullfactory-xrm@1.4.0
+ .LINK
+ https://nullfactory.net
+#>
+
+# Importing common functions
. .\CrmSolution.Common.ps1
-Write-Host "Attempting to synchronize solution(s)..."
+# Defaulting to increased verbosity for manual execution
+$oldverbose = $VerbosePreference
+$VerbosePreference = "continue"
-.\Pull-CrmSolution.ps1 `
- -serverUrl "<%= crmServerUrl %>" `
- -username (GetUsername "<%= crmSolutionName %>") `
- -password (GetPassword "<%= crmSolutionName %>") `
- -solutionName "<%= crmSolutionName %>" `
- -solutionRootFolder "..\..\<%= visualStudioSolutionProjectPrefix %>.<%= crmSolutionName %>" `
- -solutionMapFile "..\..\Nullfactory.Xrm.Tooling\Mappings\<%= crmSolutionName %>-mapping.xml"
+Write-Host "Attempting to pull solution(s)..."
+try
+{
+ .\Pull-CrmSolution.ps1 `
+ -serverUrl "<%= crmServerUrl %>" `
+ -username (Get-CrmUsername "<%= visualStudioSolutionProjectPrefix %>.<%= crmSolutionName %>") `
+ -password (Get-CrmPassword "<%= visualStudioSolutionProjectPrefix %>.<%= crmSolutionName %>") `
+ -solutionName "<%= crmSolutionName %>" `
+ -solutionRootFolder "..\..\<%= visualStudioSolutionProjectPrefix %>.<%= crmSolutionName %>" `
+ -solutionMapFile "..\..\Nullfactory.Xrm.Tooling\Mappings\<%= crmSolutionName %>-mapping.xml"
-# Include a new entry for each CRM solution to be synced against a project folder
+ # Include a new entry for each CRM solution to be synced against a project folder
-# .\Pull-CrmSolution.ps1 `
-# -serverUrl "http://servername/secondary" `
-# -username (GetUsername "env_secondary_username_key") `
-# -password (GetPassword "env_secondary_password_key") `
-# -solutionName "secondary" `
-# -solutionRootFolder "..\..\Demo.Solutions.Secondary" `
-# -solutionMapFile "..\..\Nullfactory.Xrm.Tooling\Mappings\secondary-mapping.xml"
+ # .\Pull-CrmSolution.ps1 `
+ # -serverUrl "http://servername/secondary" `
+ # -username (GetUsername "env_secondary_username_key") `
+ # -password (GetPassword "env_secondary_password_key") `
+ # -solutionName "secondary" `
+ # -solutionRootFolder "..\..\Demo.Solutions.Secondary" `
+ # -solutionMapFile "..\..\Nullfactory.Xrm.Tooling\Mappings\secondary-mapping.xml"
-Write-Host "Synchronization complete." -ForegroundColor Green
+ Write-Host "Solution pull complete." -ForegroundColor Green
+}
+finally
+{
+ # Reset the verbosity to original level
+ $VerbosePreference = $oldverbose
+}
diff --git a/generators/app/templates/Nullfactory.Xrm.Tooling/Scripts/Pull-CrmSolution.ps1 b/generators/app/templates/Nullfactory.Xrm.Tooling/Scripts/Pull-CrmSolution.ps1
index f33b2c6..bcbcfdb 100644
--- a/generators/app/templates/Nullfactory.Xrm.Tooling/Scripts/Pull-CrmSolution.ps1
+++ b/generators/app/templates/Nullfactory.Xrm.Tooling/Scripts/Pull-CrmSolution.ps1
@@ -1,6 +1,45 @@
-#
-# Pull-CrmSolution.ps1
-#
+<#
+
+ .SYNOPSIS
+ Download a solution from a remote CRM server and extract to a specified folder location.
+ .DESCRIPTION
+ This scripts automatically connect to a remote dynamics CRM instance, downloads a specified CRM solution and unpacks it to the specified folder via the Solution Packager tool. Works with both on-premises and online solutions.
+
+ Pre-requisites:
+ - PowerShell V5 or greater
+ - Latest version of Solution Packager tool provided with the CRM SDK.
+ - Micrsoft.Xrm.Data.Powershell 2.4 or greater
+
+ .NOTES
+ Author: Shane Carvalho
+ Version: generator-nullfactory-xrm@1.4.0
+ .LINK
+ https://nullfactory.net
+ .PARAMETER serverUrl
+ Required parameter that specifies the server url of the Dynamics CRM instance.
+ .PARAMETER username
+ Mandatory paramater is the username used to connect to Dynamics CRM.
+ .PARAMETER password
+ Mandatory paramerter is the password of the user used to connect to Dynamics CRM.
+ .PARAMETER solutionName
+ Required paramter. The name of the solution that needs to be downloaded and extracted.
+ .PARAMETER solutionRootFolder
+ Required Parameter. The folder into which the solution will be extracted to.
+ .PARAMETER isOnPremServer
+ This optional switch that tells the script if the server is an OnPremises server. CRM Online is the default provider.
+ .PARAMETER solutionMapFile
+ This is an option parameter that specifies the path of the maping file used to be used by SolutionPackager.
+ .EXAMPLE
+ .\Pull-CrmSolution.ps1 -serverUrl "https://sndbx.crm6.dynamics.com" -username "admin@sndx.onmicrosoft.com" -password "P@ssw0rd!" -solutionName "RemoteSolutionName" -solutionRootFolder ".\RemoteSolutionRoot"
+ Download remote solution "RemoteSolutionName" from the "https://sndbx.crm6.dynamics.com" dynamics crm online server and extract it to the "RemoteSolutionRoot" folder.
+ .EXAMPLE
+ .\Pull-CrmSolution.ps1 -serverUrl "https://sndbx.crm6.dynamics.com" -username "admin@sndx.onmicrosoft.com" -password "P@ssw0rd!" -solutionName "RemoteSolutionName" -solutionRootFolder ".\RemoteSolutionRoot" -solutionMapFile ".\RemoteSolutionName-mapping.xml"
+ Download remote solution "RemoteSolutionName" from the "https://sndbx.crm6.dynamics.com" dynamics crm online server and extract it to the "RemoteSolutionRoot" folder using the "RemoteSolutionName-mapping.xml" mapping file.
+ .EXAMPLE
+ .\Pull-CrmSolution.ps1 -serverUrl "https://onpremserver.local/orgname" -username "admin@local" -password "P@ssw0rd!" -solutionName "RemoteSolutionName" -solutionRootFolder ".\RemoteSolutionRoot" -isOnPremServer
+ Download remote solution "RemoteSolutionName" from the "https://onpremserver/orgname" on premises server and extract it to the "RemoteSolutionRoot".
+
+#>
param(
[Parameter(Mandatory=$true)]
[string]$serverUrl,
@@ -30,17 +69,24 @@ $creds = New-Object System.Management.Automation.PSCredential ($username, $secur
if($isOnPremServer)
{
Write-Verbose "Connecting to the OnPrem crm instance $serverUrl ..."
- Connect-CrmOnPremDiscovery -Credential $creds -ServerUrl $serverUrl
+ $connectionState = Connect-CrmOnPremDiscovery -Credential $creds -ServerUrl $serverUrl
}
else
{
Write-Verbose "Connecting to the Online crm instance $serverUrl ..."
- Connect-CrmOnline -Credential $creds -ServerUrl $serverUrl
+ $connectionState = Connect-CrmOnline -Credential $creds -ServerUrl $serverUrl
+}
+
+# Make sure that the connection was successful, else stop the script.
+if($connectionState.IsReady -eq $false)
+{
+ throw $connectionState.LastCrmError
}
$exportZipFileName = $solutionName + "_export.zip"
$exportZipFileNameManaged = $solutionName + "_export_Managed.zip"
+# Clear previous instances of the exported solution file
if (Test-Path $exportZipFileName) { Remove-Item $exportZipFileName }
if (Test-Path $exportZipFileNameManaged) { Remove-Item $exportZipFileNameManaged }
@@ -53,7 +99,7 @@ Export-CrmSolution -SolutionName $solutionName -Managed -SolutionZipFileName $ex
Write-Verbose "Delete the source controlled artifacts while keeping the project file intact..."
Remove-Item -Recurse $solutionRootFolder -Force -exclude *.csproj
-Write-Verbose "Extracing previous generated solution..."
+Write-Verbose "Unpacking exported solution..."
if($solutionMapFile -eq "")
{
.\..\bin\coretools\SolutionPackager.exe `
@@ -65,7 +111,7 @@ if($solutionMapFile -eq "")
}
else
{
- Write-Verbose "using mapping file $solutionMapFile for packaging"
+ Write-Verbose "Using mapping file $solutionMapFile for unpacking"
.\..\bin\coretools\SolutionPackager.exe `
/a:extract `
/packagetype:both `
@@ -74,3 +120,13 @@ else
/ad:no `
/map:"$solutionMapFile"
}
+
+# Verify that the solution packager ran successfully.
+if($?)
+{
+ Write-Verbose "Unpack successful!"
+}
+else
+{
+ throw "SolutionPackager unpack failed."
+}
diff --git a/generators/app/templates/Nullfactory.Xrm.Tooling/packages.config b/generators/app/templates/Nullfactory.Xrm.Tooling/packages.config
index a2fa232..6fe5dda 100644
--- a/generators/app/templates/Nullfactory.Xrm.Tooling/packages.config
+++ b/generators/app/templates/Nullfactory.Xrm.Tooling/packages.config
@@ -1,4 +1,4 @@
-
+
\ No newline at end of file
diff --git a/generators/app/templates/Project.Solution.WebResources/Project.Solution.WebResources.csproj b/generators/app/templates/Project.Solution.WebResources/Project.Solution.WebResources.csproj
index 6738a70..1933054 100644
--- a/generators/app/templates/Project.Solution.WebResources/Project.Solution.WebResources.csproj
+++ b/generators/app/templates/Project.Solution.WebResources/Project.Solution.WebResources.csproj
@@ -1,4 +1,5 @@
+
@@ -67,4 +68,4 @@
-
\ No newline at end of file
+
diff --git a/generators/app/templates/Project.Xrm.Plugins/Project.Xrm.Plugins.csproj b/generators/app/templates/Project.Xrm.Plugins/Project.Xrm.Plugins.csproj
index 3359979..27b4610 100644
--- a/generators/app/templates/Project.Xrm.Plugins/Project.Xrm.Plugins.csproj
+++ b/generators/app/templates/Project.Xrm.Plugins/Project.Xrm.Plugins.csproj
@@ -1,4 +1,5 @@
+
@@ -37,7 +38,7 @@
- ..\packages\Microsoft.CrmSdk.CoreAssemblies.8.1.0.2\lib\net452\Microsoft.Crm.Sdk.Proxy.dll
+ ..\packages\Microsoft.CrmSdk.CoreAssemblies.8.2.0.2\lib\net452\Microsoft.Crm.Sdk.Proxy.dll
True
@@ -45,7 +46,7 @@
True
- ..\packages\Microsoft.CrmSdk.CoreAssemblies.8.1.0.2\lib\net452\Microsoft.Xrm.Sdk.dll
+ ..\packages\Microsoft.CrmSdk.CoreAssemblies.8.2.0.2\lib\net452\Microsoft.Xrm.Sdk.dll
True
@@ -73,11 +74,11 @@
-
-
\ No newline at end of file
+
diff --git a/generators/app/templates/Project.Xrm.Plugins/SimplePlugin.cs b/generators/app/templates/Project.Xrm.Plugins/SimplePlugin.cs
index 94d0935..dfc7785 100644
--- a/generators/app/templates/Project.Xrm.Plugins/SimplePlugin.cs
+++ b/generators/app/templates/Project.Xrm.Plugins/SimplePlugin.cs
@@ -9,15 +9,11 @@ public void Execute(IServiceProvider serviceProvider)
{
IPluginExecutionContext context =
(IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
-
IOrganizationServiceFactory serviceFactory =
(IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
-
IOrganizationService organizationService =
(IOrganizationService)serviceProvider.GetService(typeof(IOrganizationService));
-
-
}
}
}
diff --git a/generators/app/templates/Project.Xrm.Plugins/packages.config b/generators/app/templates/Project.Xrm.Plugins/packages.config
index 69eb01b..7d0c2c0 100644
--- a/generators/app/templates/Project.Xrm.Plugins/packages.config
+++ b/generators/app/templates/Project.Xrm.Plugins/packages.config
@@ -1,5 +1,5 @@
-
+
-
\ No newline at end of file
+
diff --git a/generators/app/templates/Project.Xrm.Workflows/Project.Xrm.Workflows.csproj b/generators/app/templates/Project.Xrm.Workflows/Project.Xrm.Workflows.csproj
index fe21959..e4291be 100644
--- a/generators/app/templates/Project.Xrm.Workflows/Project.Xrm.Workflows.csproj
+++ b/generators/app/templates/Project.Xrm.Workflows/Project.Xrm.Workflows.csproj
@@ -1,4 +1,5 @@
+
@@ -37,7 +38,7 @@
- ..\packages\Microsoft.CrmSdk.CoreAssemblies.8.1.0.2\lib\net452\Microsoft.Crm.Sdk.Proxy.dll
+ ..\packages\Microsoft.CrmSdk.CoreAssemblies.8.2.0.2\lib\net452\Microsoft.Crm.Sdk.Proxy.dll
True
@@ -45,11 +46,11 @@
True
- ..\packages\Microsoft.CrmSdk.CoreAssemblies.8.1.0.2\lib\net452\Microsoft.Xrm.Sdk.dll
+ ..\packages\Microsoft.CrmSdk.CoreAssemblies.8.2.0.2\lib\net452\Microsoft.Xrm.Sdk.dll
True
- ..\packages\Microsoft.CrmSdk.Workflow.8.1.0.2\lib\net452\Microsoft.Xrm.Sdk.Workflow.dll
+ ..\packages\Microsoft.CrmSdk.Workflow.8.2.0.2\lib\net452\Microsoft.Xrm.Sdk.Workflow.dll
True
@@ -83,11 +84,11 @@
-
-
\ No newline at end of file
+
diff --git a/generators/app/templates/Project.Xrm.Workflows/packages.config b/generators/app/templates/Project.Xrm.Workflows/packages.config
index 09b360b..56ce184 100644
--- a/generators/app/templates/Project.Xrm.Workflows/packages.config
+++ b/generators/app/templates/Project.Xrm.Workflows/packages.config
@@ -1,6 +1,6 @@
-
-
+
+
-
\ No newline at end of file
+
diff --git a/package.json b/package.json
index d21e4fd..34f27b8 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "generator-nullfactory-xrm",
- "version": "1.3.6",
+ "version": "1.4.0",
"description": "Dynamics CRM Solution Template",
"homepage": "http://www.nullfactory.net",
"author": {