Thursday, July 21, 2016

Bulk Importing XPOs


Recently, we had a consultant do a large set of fixes to our system.  As part of the agreement, he was supposed to implement best practice fixes across the system.  Given the number of places this needed to be touched, it was a bad idea.  However, the decision was not in my hands.

Once the changes were migrated to our Test environment, we started our regression tests.  Everything went well until we got to printing customer invoices.  No matter what we tried, we couldn’t get that piece to work.  As a result, management decided to rollback everything.  The problem was that in the intervening time a large number of other changes had been promoted to build.  As a result, we needed to restore our model store to the state the consultant’s changes had been checked into TFS.  Then each change after the consultant’s needed to be integrated into the original code base.  It was painful, but I finished it in a couple of weeks.

Now I had a collection of XPOs that needed to be turned into a new model store.  As a baseline, I simply restored a backup model store from production and then disconnected build from TFS.  In order to import the corrected XPOs, I decided to build a tool to help automate the imports.  After the imports, I attached build to a new TFS project and exported the model store.

The tool itself was a little unique.  Given that this just a quick and dirty exercise, I decided to write it as a windows form.  The final form was quite simple:


In order to perform the operation, the user needed to select the root directory where all the XPOs are located.  Once selected, all XPO files in the selected directory and its subdirectories are found and listed in the textbox.

private void btnRootDirectory_Click(object sender, EventArgs e)

{

FolderBrowserDialog fbd = new FolderBrowserDialog();

lstXPOs.DataSource = null;

 

fbd.RootFolder = Environment.SpecialFolder.MyComputer;

if(fbd.ShowDialog() == DialogResult.OK)

{

txtRootDirectory.Text = fbd.SelectedPath;

lstXPOs.DataSource = Directory.GetFiles(txtRootDirectory.Text,"*.xpo", SearchOption.AllDirectories);

}

}

 


 

Next, the user needs to select an output directory.  This just calls a FolderBrowserDialog.

private void btnFindOutputDirectory_Click(object sender, EventArgs e)

{

FolderBrowserDialog fbd = new FolderBrowserDialog();

 

fbd.RootFolder = Environment.SpecialFolder.MyComputer;

if (fbd.ShowDialog() == DialogResult.OK)

{

txtOutputDirectory.Text = fbd.SelectedPath;

}

}

 

 

The output of the process button will be an xml file detailing which files to import and a directive to import without compiling and a bat file to begin the importing process. 

private void bntProcess_Click(object sender, EventArgs e)

{

if (lstXPOs.DataSource != null && !string.IsNullOrWhiteSpace(txtRootDirectory.Text))

{

string[] files = (string[])lstXPOs.DataSource;

string fileToWrite = txtOutputDirectory.Text + @"\aximport.xml";

string batchToWrite = txtOutputDirectory.Text + @"\aximport.bat";

string logFile = txtOutputDirectory.Text + @"\aximport.log";

if (File.Exists(fileToWrite))

{

File.Delete(fileToWrite);

              }

using (StreamWriter sw = new StreamWriter(fileToWrite))

{

sw.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>");

sw.WriteLine("<AxaptaAutoRun exitWhenDone=\"true\" version=\"6.2\" logFile=\"" + logFile + "\" >");

foreach (string fileName in files)

{

string command = "<XpoImport file=\"" + fileName + "\" />";

sw.WriteLine(command);

}

sw.WriteLine("<CompileApplication crossReference=\"false\" />");

sw.WriteLine("</AxaptaAutoRun>");

sw.Close();

}

 

if (File.Exists(batchToWrite))

{

File.Delete(batchToWrite);

}

using (StreamWriter sw = new StreamWriter(batchToWrite))

{

sw.WriteLine("ax32.exe -StartupCmd=AutoRun_" + fileToWrite);

sw.Close();

}

}

}

 

The entire point of the exercise is to generate a command line bat file that will open the Ax client and automatically start importing the designated files.

The bat file contains a single line:

ax32.exe -StartupCmd=AutoRun_C:\AxImportTest\aximport.xml

The import file, is an xml file that contains an autorun instruction and an attribute to designate where the log file should be placed.

<?xml version="1.0" encoding="utf-8"?>

<AxaptaAutoRun exitWhenDone="true" version="6.2" logFile="C:\AxImportTest\aximport.log" >

<XpoImport file="C:\AxImportTest\Parts Canada Model\Classes\MaintainCustomCharges.xpo" />

<XpoImport file="C:\AxImportTest\Parts Canada Model\Classes\SalesPickingListJournalCreate.xpo" />


</AxaptaAutoRun>

 

Running the batch file will then import the listed XPO files.