Friday, August 8, 2014

An interesting exercise with Powershell for implementing continuous integration with Epicor E4SE

I have been working with Epicor E4SE for a couple of years now, our systems are heavily customized and we also have an in-house development team working on development and support. As the application grows, we are building more sites and also ongoing tasks of deployment becoming quite a bit overhead, it is this point that I started to looking into ways to automate all these tasks and achieve continuous integration.
Another thing that worth mentioning, I used Jira in a previous job and found it is really handy thus introduced and implemented Jira and also its fisheye subversion integration, this helps us to manage the development team's work in a much efficient way. This does provide a foundation for us to go a step further to work towards continuous integration and work in a much more agile way. Initially I was looking into develop the build script using C# however it is not easy for us to modify the code as it goes and it is also not as easy to integrate with other scripts for system configuration which are usually written in different scripting language, the final language I chose is powershell due to its rich feature and ongoing populality, the functionalities includes the following:
> automatically check out latest version of source from subversion
> build the source using the checkout source, including components assemblies, interface assemblies, proxies interfaces and javascript web service proxies, forms, reports (aspx), a lot of these are achieved via calling Epicor.Tools
> automatically create application folders and copy application files over.
> create web application and application pool, configure web application and application pool automatically, these include E4SE web app, SecurityManager and Firesentry.

Monday, August 4, 2014

asp.net IIS won't serve default document (default.aspx) with error 404

in my case, here is the fix:
<system.webServer>
<handlers>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
</handlers>
</system.webServer>

Wednesday, July 30, 2014

Automated Build CSharp code using CodeDomProvider and .csproj file

Here is the code snippet from the code I used for automated compilation of CSharp code....
 string _projectName = Path.GetFileNameWithoutExtension(projectFilePath);  
 XmlDocument _project = new XmlDocument();  
 _project.Load(projectFilePath);  
 XmlNamespaceManager ns = new XmlNamespaceManager(_project.NameTable);  
 ns.AddNamespace("msbld", "http://schemas.microsoft.com/developer/msbuild/2003");  
 XmlNode _settings = _project.SelectSingleNode("//msbld:Project/msbld:PropertyGroup/msbld:AssemblyName", ns);  
 string _asmName = _settings.InnerText;  
 XmlNodeList _files = _project.SelectNodes("//msbld:Project/msbld:ItemGroup/msbld:Compile", ns);  
 ArrayList _sourceNames = new ArrayList();  
 // Add compilable files  
 foreach (XmlNode _file in _files)  
 {  
   string _codeFilename = _file.Attributes["Include"].Value.ToLower();  
  if ( _codeFilename != "assemblyinfo.cs"      && !_codeFilename.EndsWith("vsa.cs") )       
      {  
                          // Read the source code  
           int _idx = _sourceNames.Add(_file.Attributes["Include"].Value);  
      }  
 }  
 XmlNodeList _reference = _project.SelectNodes("//msbld:Project/msbld:ItemGroup/msbld:Reference", ns);  
  foreach (XmlNode _asmRef in _reference)  
 {  
         // Try to use the AssemblyName attribute if it exists  
         string _refAsmName;  
         if (_asmRef.Attributes["AssemblyName"] != null)  
           _refAsmName = _asmRef.Attributes["AssemblyName"].Value;  
         else if (_asmRef.Attributes["Name"] != null)  
           _refAsmName = _asmRef.Attributes["Name"].Value;  
         else  
         {  
           _refAsmName = _asmRef.Attributes["Include"].Value;  
           if (_refAsmName.IndexOf(",") > 0)  
             _refAsmName = _refAsmName.Substring(0, _refAsmName.IndexOf(","));  
         }  
        cp.ReferencedAssemblies.Add(_refAsmName + ".dll");  
  }  
       cp.GenerateExecutable = false;   // result is a .DLL  
       cp.IncludeDebugInformation = true;  
       String[] _sourcefiles = (String[])_sourceNames.ToArray(typeof(string));  
       CompilerResults cr = provider.CompileAssemblyFromFile(cp, _sourcefiles);  
       if (cr.Errors.Count > 0) //if (_compErrs.Length > 0)  
                {  
                     bool _error = false;  
         foreach (CompilerError _err in cr.Errors)  
                     {                           
                          // Error or warning?  
                          if (!_err.IsWarning)//( _err.ErrorLevel != Microsoft.CSharp.ErrorLevel.Warning )  
                               _error = true;  
                          if(_error)                           
                               swrLog.WriteLine("CompileAndDeploy:CompileComponentAssemblies: Error compiling " + _projectName + ".\nPlease rectify then redeloy.");  
                          else  
                               swrLog.WriteLine("CompileAndDeploy:CompileComponentAssemblies: Warning compiling " + _projectName + ".\nPlease rectify then redeloy.");  
                          swrLog.WriteLine( _err.ErrorText);  
                     }  
                     if (_error)  
                     {  
                          swrLog.WriteLine("Compile errors occurred. Rectify first.");  
                          throw new Exception ("Compile errors occurred. Rectify first." );  
                     }  
                }  
method 2: msbuild

                           //string projectFileName = @"C:\Temp\E4SE\src\SMEC\Epicor.SMEC.IInterfaces.csproj";
                            BuildManager manager = BuildManager.DefaultBuildManager;

                            ProjectInstance projectInstance = new ProjectInstance(path);
                            var result = manager.Build(new BuildParameters()
                            {
                                DetailedSummary = true
                            },
                                new BuildRequestData(projectInstance, new string[] { "Build" }));
                            var buildResult = result.ResultsByTarget["Build"];
                            var buildResultItems = buildResult.Items;
                            mswrLog.WriteLine("Building: " + path + " Result: " + buildResult.ResultCode);

Thursday, May 15, 2014

Web Application and WCF hosted together and enabling AD FS 2.0 claim based signon

while trying to enable ADFS based single sign-on for both the web application and wcf, I got the wcf service working however when trying to access web app, I got the following error message: ID4036: The key needed to decrypt the encrypted security token could not be resolved from the following security key identifier Apparently we need to add the certificate for encryption of wcf sign-on, however this causes issue for the web application, tried various suggestion and no luck. At the end, I created another RP policy and separate the two and all work fine!

Tuesday, May 13, 2014

How to run Epicor E4SE ICE 1.4 and ICE1.5 side by side

Recently I upgraded our E4SE V8.11 from ICE 1.4 to ICE1.5, after upgrade, I noticed that another sites which hasn't been rebuilt stopped working. Since we don't want to upgrade the other site, I need to figure out a way to make ICE1.4 and 1.4 run side by side. At the end, the solution is actually surprisingly simple, use the bindingRedirect settings in web.config, we only need to either install ICE 1.4 assemblies in GAC or simply copy to the 'bin' folder. ....................