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!