C# - Több alkalmazás fordítása egy lépésben

forráskód letöltése
Fejlesztés során általában csak néhány project-tel dolgozunk, azonban adódhat olyan helyzet, amikor egyszerre több alkalmazás futtatható kódjára van szükségünk, de igen időigényes és fárasztó ezeket akár parancssorba begépelve fordítani. Cikkünkben egy olyan alkalmazást készítünk, mely elvégzi ezt nekünk egy lépésben. Ehhez elegendő egy könyvtárba tenni a fordítandó alkalmazások mappáját, és programunk számára ezt az elérési útvonalat megadni.
A .NET keretrendszerben található egy program, mely képes parancssorban megadott utasítások alapján felépíteni a paraméterként kapott .SLN állománnyal rendelkező alkalmazások futtatható kódját. Ennek lehetőségét használjuk ki programunkban.
A program alapértelmezésben a következő helyen található: <%winntroot%>:/Program Files/Microsoft Visual Studio .NET\Common7\IDE\devenv.exe. A program számtalan parancssorban megadható kapcsolóval rendelkezik, melyekkel úgymond testre szabhatjuk a fordítást és a kódgenerálást. Elöljáróban fontos megemlíteni, hogy a következőkben megadott kapcsolók és opciók meghívása a devenv.com alkalmazásnak adja át a paramétereket. Kiterjesztés nélkül kell meghívni a parancssorból, a következő módon:
devenv /kapcsoló [konfiguráció neve] „.SLN állomány elérési útvonala”
A mellékelt alkalmazásban a következő módon hívjuk meg a parancssori fordító eszközt:
devenv /rebuild release ".SLN állomány elérési útvonala"
Az egyes argumentumok a következőket jelentik:
  • /rebuild: újraépíti az alkalmazás futtaható kódját, felülírja az előző fordítás eredményét
  • release: fordítási konfiguráció, értéke debug és release lehet, kötelező megadni.
  • Harmadik paraméter a .SLN kiterjesztésű állomány elérési útvonala, vagyis az a mappa, ahol az állomány megtalálható, és az állomány neve.
Alkalmazásunk a következőképpen épül fel:
A program Form-ján elhelyezett TextBox-ba meg kell adni azt az elérési útvonalat (mappanevet), ahova begyűjtöttük az összes fordítandó alkalmazás könyvtárát. Ez tetszőleges számú almappát tartalmazhat.
A ’Build’ gomb lenyomásával elindul a folyamat, mely lefordítja az alkalmazásokat, a futtatható állományokat, saját komponenst használó alkalmazások esetén, ahol a komponens mappája az alkalmazás mappájában van a .DLL állományokat a .SLN állományok mappájában helyezi el, valamint törli a /bin és /obj mappákat.
A feldolgozáshoz egy rekurzív metódust használunk, mely végignézi a mappákat .SLN állományok után kutatva, találat esetén elvégzi a fordítást, majd a szükséges állomány-lokációs műveleteket.
A Build nevű metódusban helyeztük el a kód oroszlánrészét. Kezdtük a tárolók deklarálásával, melyek a talált könyvárakat és fájlokat tartalmazzák egy-egy DirectoryInfo, illetve FileInfo objektummal jellemezve:
private int Build(string strDirectory)
{
  int res = 0;
  try
  {
    DirectoryInfo CurDir = new  DirectoryInfo(strDirectory);
    DirectoryInfo[] DirArray;
    FileInfo[] FilesArray;
    DirArray = CurDir.GetDirectories();
    FilesArray = CurDir.GetFiles();
    FileInfo[] BinFileArray;
    DirectoryInfo[] SubProjectArray;    
A processzekhez létrehoztunk egy ProcessStartInfo objektumot, hogy ebben összegyűjtve megadjuk az indítási paramétereket:
    ProcessStartInfo psi = new ProcessStartInfo();
A következő szakaszban foreach utasításokkal megyünk végig a kigyűjtött mappákon, majd a Process osztály Start metódusát használjuk fel minden egyes .SLN állomány esetén a parancssori fordító futtatásához. A műveletek processzorigényes volta miatt az egyes feldolgozások megállítják a program főszálát addig, amíg a művelet befejeződik. Ehhez a Process.WaitForExit metódusát használják fel:
    foreach (FileInfo curfileInfo in FilesArray)
    {
      if(curfileInfo.Extension == ".sln")
      {
        psi.FileName = ExistDevenv();  
        psi.Arguments = "/rebuild release " + curfileInfo.FullName;
        Process p = new Process();
        p = Process.Start(psi);
        filesLabel.Text = curfileInfo.FullName;
        filesLabel.Update();
        p.WaitForExit();    
        BinFileArray = GetDirFiles(curfileInfo.DirectoryName + "/bin/Release/");
        for(int i=0;i<BinFileArray.Length;i++)
        {
          if ((BinFileArray[i].Extension == ".dll") || (BinFileArray[i].Extension == ".exe"))
          {
  File.Copy(BinFileArray[i].FullName,curfileInfo.Directory + "/" + BinFileArray[i].Name,true);
          }              
        }  
        Directory.Delete(curfileInfo.DirectoryName + "/bin",true);
        Directory.Delete(curfileInfo.DirectoryName + "/obj",true);    
        SubProjectArray = GetDirDirs(curfileInfo.DirectoryName);
        if (SubProjectArray.Length != 0)
        {
          for(int j=0;j<SubProjectArray.Length;j++)
          {
            Directory.Delete(SubProjectArray[j].FullName + "/bin",true);
            Directory.Delete(SubProjectArray[j].FullName + "/obj",true);
          }
        }            
      }
      filesLabel.Text = "";        
    }
Itt következik a rekurzív függvényhívás a mappákra:
    foreach (DirectoryInfo curdirInfo in DirArray)
    {
      string strDir;
      strDir = curdirInfo.FullName;
      Build(strDir);
    }
  }
  catch
  {
    res = 1;
  }      
  return res;
}
A program a művelet végrehajtása közben folyamatosan jelzi, hogy éppen milyen névvel rendelkező .SLN állomány van feldolgozás alatt.