Montag, 31. März 2014

Kompilierung im AX2012 mit AxBuild.exe


Ab dem  CU7 gibt es für AX2012 R2 ein neues Command Line Utility namens AxBuild.exe, mit dem das Kompilieren parallel über die Kommandozeile ohne den „Bottelneck“ des AX-Clients durchgeführt werden kann.

Mit Hilfe der AxBuild.exe konnten wir den gesamten X++ Source unserer Entwicklung in ca. 30 Min Kompilieren.

Dienstag, 18. März 2014

Fehler „Mixed mode assembly is built against version „v2.0.50727“ of the runtime and cannot be loaded in the 4.0 runtime without additional configuration information." für Visual Studio 2012 WCF Projekte gehosted von Visual Studio 2012 beheben.

Um eine Anbindung eines Archiv System an ein von Entwickeltes AX 2009 Modul zu ermöglich, ohne das eine Direkte Zugriff auf die eigentliche AX Datenbank zu gewähren. Wird von uns ein WCF Dienst eingesetzt der von einem externen Dienstleister konsumiert wird. Innerhalb des WCF Dienstes ist wurde die WCF Host Konfiguration. Um den Folgenden Eintrag erweitert:
 
<startup useLegacyV2RuntimeActivationPolicy="true">
     <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
Somit kann der Eigentliche Dienst ohne Probleme im Mixed assembly mode arbeiten.
Jedoch bin ich beim Testen des Dienstes immer wieder auf diesen Fehler gestoßen, wenn der WCF Dienst vom Visual Studio gehostet wurden.
Nach langen suchen bin ich auf folgende Lösung gestoßen:
 
Hier wurde die eigentliche Konfiguration angepasst, die vom Visual Studio verwendet wird. In der Standard Installation sollte die WcfScvHost.exe.config unter C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE zu finden sein. Hier wurde die WcfScvHost.exe.config um den entsprechenden Eintrag erweitert.
Meine WcfScvHost.exe.config sieht nun wie folgt aus:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
                <startup useLegacyV2RuntimeActivationPolicy="true">
                                <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
                </startup>
                <runtime>
                               <DisableMSIPeek enabled="true"/>
                </runtime>
</configuration>

Montag, 27. Januar 2014

Windows Phone 8 Gestengesteuerte Seitenwechsle

Im ersten Moment war es mir ein Rätzel wie ich einen simplen Seiten Aufruf, für Windows Phone 8 gestengesteuert implementieren sollte. Viel Beispiele und Implementieren Basieren auf dem Silverlight Toolkit für Windows Phone.
Leider ist diese Toolkit für Windows Phone 8 Obsolet, ich habe lange gesucht bis ich auf folgenden Link gestoßen bin.



Wie immer sind die einfachsten Lösungen meist die effektivste, hier wir entsprechend auf das ManipulationCompleted Event des jeweiligen Controls reagiert. Entsprechend der Bewegung Richtung kann man seinen eigenen Seiten Aufruf platzieren.

private void LayoutRoot_ManipulationCompleted(object sender, System.Windows.Input.ManipulationCompletedEventArgs e)
        {
            double dY = e.TotalManipulation.Translation.Y;
            double dX = e.TotalManipulation.Translation.X; 

            if (Math.Abs(dY) > Math.Abs(dX))
            {
                // Vertical
            }
            else
            {
                // Horizontal
                if (dX < 0)
                {
                    NavigationService.Navigate(new Uri("/SecondPage.xaml", UriKind.Relative));
                }
            }
        }

Freitag, 10. Januar 2014

AX2009 Methoden in einen Thread ausführen.

Die ganze Idee der Schaffung eines separaten Thread, um einen Prozess durchzuführen ist eine anerkannte Technik, um mit Multi-Prozesse zu einem bestimmten Zeitpunkt separate Anwendungs-Thread zu schaffen, auf die die Benutzeranwendung zugreift.

Bei Dynamics AX, ist es manchmal nicht so einfach, zu erkennen wo und warum Sie das Themen Multi-Threading verwenden sollten, um einen bestimmten Prozess oder Entwicklungsziel zu erreichen.
In meinem Fall war es, dass ein Prozess des Main Thread. Das weiterarbeitet der Nutzer verzögert, bis der Prozess beendet wurde. Es lag nun nahe diese länger in einen eigenen Thread laufen zu lassen.
Das folgende Beispiel soll zeigen wie man einen Dynamics AX Prozess in einen eigenen Thread ausführen kann. Hierbei war mir eine Rückmeldung der Prozesse nicht wichtig.
Für dieses Beispiel habe ich einen Job erstellt der einen entsprechenden Prozess einer Klasse Kapselt.

static void ThreadJob(Args _args)
{
    Thread              t;
    ExecutePermission   perm;
    container           con;
    ;
    perm = new ExecutePermission();
    perm.assert();
…   // create new thread
    t = new Thread();
    //set parameter values
    con = conins(con,1,’param1’);
    con = conins(con,2,’param2’);
    t.setInputParm(con);
    // run thread
    t.run(classnum(LongProcess), staticMethodstr(LongProcess, ThreadExecute));
}
 

Die Methode “ThreadExecute” der Klasse “LongProcess” beinhält den eigentlichen Source des Prozess.
server static void ThreadExecute(Thread T)
{
    container                 ThParams = T.getInputParm();
    Set                       permissionSet;
    str                       param1;
    int                       param2;
    ;
    permissionSet =  new Set(Types::Class);
    permissionSet.add(new InteropPermission(InteropKind::ClrInterop));
    CodeAccessPermission::assertMultiple(permissionSet);

   //get parameter values
   param1= conpeek(ThParams, 1);
   param2= conpeek(ThParams, 2);
   // run long term process  
   // ………
   

   CodeAccessPermission::revertAssert();

}
  
 
 

 

Mittwoch, 18. Dezember 2013

Drucken eines externen PDF aus AX2009 mit Hilfe des Adobe Readers.

static void printPDF(str _filePath, PrintJobSettings  _printJobSettings = new PrintJobSettings() )
{
    PrintJobSettings    printJobSettings;
    str                          adobeExe;
    str                          adobeParm;
    Set                         permissionSet;
    ;

    permissionSet = new Set(Types::Class);
    permissionSet.add( new InteropPermission(InteropKind::ClrInterop) );
    CodeAccessPermission::assertMultiple( permissionSet );

    if (System.IO.File::Exists(_filePath))
    {
        //get Adobe Reader executable
        adobeExe = WinAPI::findExecutable(_filePath);
      
        adobeParm = strFmt('/n /t "%1" "%2" "%3" "%4"',
                           _filePath,
                           printJobSettings.printerPrinterName(),
                           printJobSettings.printerDriverName(),
                           printJobSettings.printerPortName());

        winAPI::shellExecute(adobeExe,  adobeParm);
    }
    CodeAccessPermission::revertAssert();
}

Adobe Commandline Arguments:
http://www.robvanderwoude.com/commandlineswitches.php#Acrobat

Donnerstag, 7. November 2013

WinApi::CreateDirectoryPath verursacht Fehler bei Verwendung von UNC Pfaden

Bei der Umstellung der Version Kontrolle von relativen Pfaden hin zu UNC Pfaden musste ich feststellen das die Methode WINAPI::CreateDirectoryPath nicht mit UNC Pfaden arbeiten kann. Es wird  folgender Fehlermeldung ausgegeben:

"ClrObject static method invocation error"

Es hat eine Weile gedauert aber dann bin ich auf eine funktionierende Lösung gestoßen.

// Verifyes or creates Path
static client public boolean createDirectoryPath(FilePath _path)
{
         int ptr;
         ;

         _path = strLRTrim(_path);

         if (substr(_path,strlen(_path),1) != '\\') // Adding backslash gives a more simple while-loop!
         {
                 _path += '\\';
         }

         //enables creation of UNC paths, by detecting which folder already exists (backwards).
         ptr = strLen(_path);
         ptr = strfind(_path, '\\', ptr, -ptr);
         while(!WinAPI::folderExists(substr(_path,1,ptr)))
         {
                  ptr = strfind(_path, '\\', ptr -1 , -ptr);
         }

         while (ptr)
         {
                 WinAPI::createDirectory(substr(_path, 1, ptr));

                 if (!WinAPI::folderExists(substr(_path, 1, ptr)))
                {
                        break;
                }

                ptr = strfind(_path, '\\', ptr + 1, strlen(_path));
         }

         return WinAPI::folderExists(_path);
}

Verwendung von Team Foundation Server 2012 als Versionskontrolle für AX 2009

Grundsätzlich kann man für die Installation und Integration die Step by Step Anleitung aus folgenden Blog verwenden http://blog.enhancealm.com.au/2011/03/08/dynamics-ax-development-using-tfs-2010/. Das Vorgehen für TFS2010 ist auf TFS2012 übertragbar.

Problematischer stellte sich die Integration in unserer Multi Developer Umgebung da. Wir verwenden für die Entwicklung von AX2009, Citrix Clients. Über die der jeweilige Entwickler auf den AOS zugreift. AX2009 kennt standardmäßig nur einen Speicherort für das lokale Repository. Um für jeden Entwickler ein lokales Repository zu verwenden musste die AX Klasse SysVersionControlParameters angepasst werden, um eine eigenes Repository mit der Benutzerkennung zu erstellen.

    #SysVersionControl
    SysVersionControlParameters parameter;
    ;
    parameter.selectForUpdate(_forupdate);
    select firstonly parameter
        index Key
        where parameter.Key == 0;

    if(parameter)
    {
        if(parameter.VCSType == SysVersionControlType::SysVersionControlTfs)
        {
            parameter.RepositoryFolder = strFmt("%1_%2",parameter.RepositoryFolder,curUserId());
            new InteropPermission( InteropKind::ClrInterop ).assert();
            if(!WinApi::pathExists(parameter.RepositoryFolder))
            {
               WinApi::createDirectoryPath(parameter.RepositoryFolder);
                info('Nur für Entwickler:\r\nBitte Repository manuell synchronisieren');
            }
        }
    }
.
.
.

Bei der Angabe des Repository für die AX Versions Kontrolle Parameters wird nun nur der Pfad zum Basisordner für alle Entwickler Repository angegeben werden.