Wednesday, December 12, 2012

Upgrading to AX2012 R2 from AX 2012

I would like to share my story on the upgrade process from AX2012 (RTM) without Feature Pack, but with CU4. The upgrade is supported for AX2012 with or without Feature Pack, and you need at least CU3 installed.

Having a working environment with AX2012 on CU4, and code in ISV, VAR, CUS and USR I was ready to begin. I have a FPK-layer with Data Migration Framework elements, but I plan to remove it before the in-place upgrade.

Microsoft has published a good presentation from the latest Dynamics AX Technical Conference, along with the PowerPoint presentation. But for those without access to InformationSource, the guide at MSDN pretty much sums it up. I would strongly advice anyone who is going to do this upgrade to follow the guide on MSDN.

The upgrade from an existing AX2012 RTM (version 6.0.x.x) to AX2012 R2 (version 6.2.x.x / 6.2.158.0) is best done in-place. This means we want to take our existing application and code and upgrade it directly on top of the old version. But before we can do this, we need to prepare an R2 compatible application code so we ensure no data loss. This is the time consuming part of the upgrade, as it involves installation of a seperate R2 environments and developers need to go through any custom code that needs to be adjusted in case it doesn't compile on top of the new R2 SYS layer.

On a high level, the upgrade process looks like this:

  1. Freeze AX2012 code and make sure the environment compiles and works as expected. 
  2. Setup a new server since R2 components can not co-exist with RTM components. 
  3. Duplicate the AX2012 database into a new database intended for "R2 Test".
  4. Run setup and let it create the initial basis for a new R2 environment. Point to the test-database and install AOS, client and debugger for R2.
  5. With Test up, duplicate it to a new environment intended for "R2 development". The AOS can be installed on same server as test. This will be where code review will be done in order to fix code and prepare it for R2. Complete the code upgrade.
  6. Let testers test R2 when it is ready for testing. 
  7. Upgrade AX2012 Live with already prepared R2 compatible axmodels, making sure both code compiles properly and there is no data loss in production.
Now there are a lot of details in each of these steps, all explained in the MSDN article

Right now I am going through the process of preparing all my axmodels for R2 (Step 5), and since I need to go through these axmodels layer by layer, the entire process might take some time. So far the process has gone by as expected. I look forward to run step 7, though. :-)

A couple of tips:
  • Make sure there are enough available disk space on the disks containing your user hive (typically c-disk) and on the database server when running the AX2012 R2 setup. 
  • If you chose to upgrade the Help Server content, you need to uninstall previous translated content - not the Help Server itself, but just the translated content. Use "Programs and Features" (Windows 2008) to locate the packages and just uninstall them one by one.
  • Set aside a lot of time, since the whole process involves multiple time consuming steps (like full compilation).

Sunday, December 2, 2012

Microsoft Dynamics AX 2012 R2

The awaited R2 release of Microsoft Dynamics AX 2012 is here!

Microsoft Dynamics Partners can download the image from here

Also, check out this landing page for AX2012 R2.

Enjoy!

Monday, October 1, 2012

Use Powershell to increment build on AX 2012 Model


I have been working on a new version of my PowerShell script I use to export models to disk. I wanted to increment the build number each time a model was exported, so I started with my export script and added a single method and hooking things up.

The PowerShell method looks like this:

Function Update-Version ([string]$model, [string]$server, [string]$database, [int]$incrementBuildBy)
{
 $manifest = Get-AXModelManifest -Server $server -Database $database -Model $model
 $manifestVersion = $manifest.Version
 $manifestVersionSplit = $manifestVersion.Split('.')
 $manifestVersionSplit[3] = $incrementBuildBy + $manifestVersionSplit[3]
 $ofs = "."
 $versionStr = [string] $manifestVersionSplit
 $manifestVersion = "Version=" + $versionStr
 Edit-AXModelManifest -Server $server -Database $database -Model $model -ManifestProperty $manifestVersion
 return $manifest
}

Given this method I changed my export to look more like this:

$backupFilePath = New-BackupFolder($axBackupFolder)
$models = Get-AXModel -Server $server -Database $database

foreach ($model in $models)
{
 $backupFileName = ""
 $elementCount  = ""
 $nameToBackup  = $model.Name.ToString()
 $layer    = $model.Layer.ToString()
 $elementCount  = $model.ElementCount.ToString() 
 $versionStr  = $model.Version.ToString()
 $backupFileName = $backupFilePath + "\" + $nameToBackup + ".axmodel"    
 
 if ($layer.ToUpper().Contains($layerFilter.ToUpper()) -and $nameToBackup.ToUpper().Contains($modelFilter.ToUpper()))
 {
  Update-Version $nameToBackup $server $database $incrementBuildBy 
  $backupFileName = $backupFilePath + "\" + $nameToBackup + "_" + $versionStr + ".axmodel"
  "Exporting " + $elementCount + " elements from " + $nameToBackup + "..."
  File-Backup $nameToBackup $backupFileName $server $database
 }
 else
 {
  "Skipping " + $backupFileName + " in layer " + $layer
 }
}
"Completed!"

The two other utility methods are simply like this:

Function New-BackUpFolder([string]$destinationFolder)
{
 $dte = get-date
 $dte = $dte.tostring() -replace "[:\s/]", "."
 $backUpPath = "$destinationFolder" + $dte
 $null = New-Item -path $backUpPath -itemType directory
 return $backUpPath
}

Function File-Backup([string]$model, [string]$fileName, [string]$server, [string]$database)
{
 Export-AXModel -Model $model -File $fileName -Server $server -Database $database
}

So in order to wrap things up, all you need is to declare at the top a few variables:
$server = "mydbserver"
$database = "MicrosoftDynamicsAx"
$axBackupFolder = "c:\axModelBackup\"
$modelFilter = "AwesomeApp"
$layerFilter = "ISV"
$incrementBuildBy = 1

And that's a wrap!

Friday, September 7, 2012

Using Powershell to backup your AX 2012 code

One of the repetitive tasks when working with Dynamics AX 2012 is getting out the models out of an environment. Lucky for us this is pretty easy to do using PowerShell. Inspired by the great blog post by Gary Holsopple where he shares a script he made to get the models out, I made this script covering my needs. In my version I iterate over the layers instead, and I prefer to display some feedback while doing so. The export will work each time, since the model-files will get unique names each time. Here's my version:
import-module "C:\Program Files\Microsoft Dynamics AX\60\ManagementUtilities\Microsoft.Dynamics.ManagementUtilities.ps1"

#region Variables
$server = "myserver"
$database = "AX2012_Dev"
$axBackupFolder = "c:\axModelBackup\AX2012_Dev\"


[System.Collections.ArrayList] $layerList = New-Object System.Collections.ArrayList
$layerList = @("USR";"USP";"CUS";"CUP";"VAR";"VAP";)

[System.Xml.XmlDocument] $xml
[System.Xml.XmlNode] $obj
[System.Xml.XmlNode] $property

#endregion

#region Functions
Function New-BackUpFolder($destinationFolder)
{
 $dte = get-date
 $dte = $dte.tostring() -replace "[:\s/]", "."
 $backUpPath = "$destinationFolder" + $dte
 $null = New-Item -path $backUpPath -itemType directory
 return $backUpPath
} 


Function fBackup([string]$model, [string]$fileName, [string]$server, [string]$database)
{
 Export-AXModel -Model $model -File $fileName -Server $server -Database $database
}
#endregion

#region do the work

$backupFilePath = New-BackupFolder($axBackupFolder)
$xml = (Get-AXModel -Server $server -Database $database | convertto-xml )
$nodes = $xml.SelectNodes("Objects/Object")

foreach ($obj in $nodes)
{
 $backupFileName = ""
 $elementCount  = ""
 
# Loop all properties
 foreach ($property in $obj.SelectNodes("Property"))
 {
  if ($property.GetAttribute("Name").Equals( "Name" ))
  {
   $nameToBackup  = $property.InnerText
   $backupFileName = $backupFilePath + "\" + $nameToBackup + ".axmodel"   
  }
  
  if ($property.GetAttribute("Name").Equals( "Layer" ))
  {
   $layer = $property.InnerText         
  }
  
  if ($property.GetAttribute("Name").Equals( "ElementCount" ))
  {
   $elementCount = $property.InnerText         
  }
 }
 
 if ($layerList.contains($layer.ToUpper()) -and $backupFileName -ne "")
 {
  "Exporting " + $elementCount + " elements from " + $nameToBackup + "..."
  fBackup $nameToBackup $backupFileName $server $database
 }
 else
 {
  "Skipping " + $backupFileName + " in layer " + $layer 
 }
}

"Completed!"

#endregion
Further inspired, I made this small script to export the entire modelstore:
import-module "C:\Program Files\Microsoft Dynamics AX\60\ManagementUtilities\Microsoft.Dynamics.ManagementUtilities.ps1"
$server  = "myserver"   # Format: "server\instance"
$db   = "ax2012_dev" 
$folder  = "c:\axModelBackup\"   # Remember trailing slash (\)

#region Do Work 

$dte   = get-date
$dte   = $dte.tostring() -replace "[:\s/]", "."
$file  = $folder + $db + "_" + $dte
Export-AXModelStore -Server $server -Database $db -File $file

#endregion
If you have several AOSes, just copy the files and make one for each AOS where you modify the variables at the top. Fun, fun, fun!