Luc

Csőhalmadár!

Visual Studio 2010 project wizard

Ha sokszor kell ugyanazon modulokból, de nem mindig ugyanazokat alkalmazni a munkáink során, akkor meggyorsíthatja a fejlesztést, ha a project létrehozásakor nem nekünk kell hozzáadogatni a modulokat és esetleg refaktorálni, hanem ezt egy varázsló segítségével oldjuk meg. Példaképp hozzunk létre egy konzol alkalmazást és írjunk bele egy sort, mondjuk ezt: Console.WriteLine("$probaszoveg$"); A $probaszoveg$ lesz az a blokk, amit majd a konkrét project létrehozásakor szeretnénk lecserélni a megfelelő szövegre. Ugyanekkor szeretnénk, ha két osztálydefiníció közül egy bekerülne a projectbe.
 Ebből készítsünk project template-et a file menü Export template menüpontjával. Itt válasszuk a project template lehetőséget és jelöljük ki a konzol projectet. Ezután adhatunk a template-nek nevet, leírást, ikont. Hagyjuk bekapcsolva az importálást VS-be. A template helyét láthatjuk a wizard utolsó lépésében. Ezzel megvan a példánkban létrehozandó majd testreszabandó projectünk template-je.
 Hagyjuk most hűlni a template-t és kezdjünk bele a varázslóba. Hozzunk létre - akár a fenti konzol projectünk solution-jén belül - egy Class Library projectet. Maradjon a neve a felettébb fantáziadús ClassLibrary1. Adjuk hozzá a projecthez következő referenciákat:
1.Microsoft.VisualStudio.TemplateWizardInterface
2.EnvDTE
3.System.Windows.Forms

Adjunk a projecthez egy Windows Form elemet. Ezen helyezzünk el egy TextBox-ot és pár ComboBox-ot - ez utóbbiban legyen valahány elem - valamint egy Button-t. A vezérlők értékeit tegyük elérhetővé publikus property-ken keresztül.
private void button1_Click(object sender, EventArgs e)
{
   Probaszoveg = tbSzoveg.Text;
   Osztalynev = cbClass.SelectedItem.ToString();
   Proptipus = cbPropType.SelectedItem.ToString();
   Propnev = cbPropName.SelectedItem.ToString();

   this.Dispose();

}

public string Probaszoveg { get; private set; }
public string Osztalynev { get; private set; }
public string Proptipus { get; private set; }
public string Propnev { get; private set; }
A ClassLibrary1.cs-be húzzuk be a szükséges névtereket, azaz:
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using EnvDTE;
using Microsoft.VisualStudio.TemplateWizard;
Hozzunk létre egy osztályt az IWizard interface alapján.
public class WizardClass1 : IWizard
{
   public void BeforeOpeningFile(ProjectItem projectItem)
   { }

   public void ProjectFinishedGenerating(Project project)
   { }

   public void RunFinished()
   { }

   public void RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, WizardRunKind runKind, object[] customParams)
   { }

   public bool ShouldAddProjectItem(string filePath)
   {
      return true;
   }

   public void ProjectItemFinishedGenerating(ProjectItem projectItem)
   { }

}
A ShouldAddProjectItem és a ProjectItemFinishedGenerating metódusok csak item template-ekhez kellenek, de mivel az IWizard interface jajjgat ha nem impelemtáljuk őket, hát itt vannak.

A fenti WizardClass1-en belül hozzunk létre a varázslónk egy példányát és a property-ket, amikben a varázslónk segítségével lekérdezett értékeket tároljuk.
public class WizardClass1 : IWizard
{
    private WizardForm1 newForm;

    public String Osztalynev { get; private set; }
    public string Proptipus { get; private set; }
    public string Propnev { get; private set; }
}
A RunStarted metódus akkor fut le, ha már a project template alapján létrejött a projectünk. Persze az még nem a végleges formában van, mert szeretnénk ha a varázslónk összegyűjtötte adatok szerint nézne ki. Ehhez meg kell jelenítenünk a varázslót és beolvasni a kiválasztott értékeket, azaz írjuk a RunStarted metódusba az alábbiakat.
newForm = new WizardForm1();
newForm.ShowDialog();

Osztalynev = newForm.Osztalynev;
Proptipus = newForm.Proptipus;
Propnev = newForm.Propnev;

replacementsDictionary.Add("$probaszoveg$", newForm.Probaszoveg);
Ezután a $$ jelek közé rakott szövegek lecserélődnek a kívánt tartalomra. Ezzel kész is van a template alapján létrehozott project, de mi még tovább szeretnénk menni és mást is hozzáadni az új projecthez. A ProjectFinishedGenerating metódusban ez fusson:
string dir = Path.GetDirectoryName(project.FullName);
string code =
    "using System;\r\nusing System.Collections.Generic;\r\nusing System.Text;\r\n\r\n" +
    "namespace WizardGenerated\r\n{\r\n\tpublic class " +
    Osztalynev +
    "\r\n\t{\r\n\tpublic " +
    Proptipus + " " + Propnev+ ";\r\n\t}\r\n}";
StreamWriter sw = new StreamWriter(dir + "\\" + Osztalynev + ".cs");
sw.Write(code);
sw.Close();
project.ProjectItems.AddFromFile(dir + "\\" + Osztalynev + ".cs");
Ezzel tulajdonképpen el is készült némileg egyszerűre sikeredett varázslónk. Természetesen a fentieket érdemes ellenőrzésekkel, tyr-catch blokkokkal és MessageBox-okkal jól telerakni, de az olvashatóság miatt ezeket kihagytam.

Következő dolgunk, a Visual Studio tudomására hozni, hogy használja is az alkotásunkat.

Ehhez a gacutil.exe és az sn.exe programokat kell futtatnunk, amik általában a "c:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\NETFX 4.0 Tools\x64\" könyvtárban találhatók. De ha nem szeretnénk folyton parancsorba írogatni és erre pazarolni az értékes időt, akkor a wizard projectünkön jobb gomb, properties és a Build Events fülön a Post-build event command line-hoz írjuk be az alábbiakat:
"c:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\NETFX 4.0 Tools\x64\gacutil.exe" -u "$(ProjectName)"
"c:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\NETFX 4.0 Tools\x64\gacutil.exe" -i "$(TargetPath)"
"c:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\NETFX 4.0 Tools\x64\sn.exe" -T "$(TargetPath)"
Érdemes egyébként nem csak simán bemásolni a fentieket, hanem meggyőződni róla, hogy tényleg ott van-e az említett két segédprogram. Figyelmetekbe ajánlom az Edit Post-build gombot, találhattok benne még makrókat. A fenti sorok hatására bekerül a GAC-ba a varázslónk dll-je. Feltéve, ha adminisztrátorként futtatuk a Visual Studio-t. Ha van valami rendszergazdai vénával megáldott ember, aki meg tudja mondani, hol és milyen jogosultságot kell adni az usernek, hogy ne csak rendszergazdaként tudja hatásosan futtatni a fentieket, az ne habozzon, ossza meg velem. Az utolsó sor visszaadja a PublicKeyToken-t, amit mindjárt fel is használunk. Ezt az Output konzolon (Ctrl+W, O) nézhetjük meg.

Már csak a fent létrehozott project template-t kell szerkeszteni. Keressük meg és csomagoljuk ki a .vstemplate kiterjesztésű állományt. Ehhez kell hozzáírnunk a </TemplateContent> tag után az alábbi kódblokkot. (Nem tudom miért utána kell, mindenhol így írták, én meg lusta voltam máshogy kipróbálni.)
<WizardExtension>
   <Assembly>ClassLibrary1, Version=1.0.0.0, Culture=Neutral, PublicKeyToken=***************</Assembly>
   <FullClassName>ClassLibrary1.WizardClass1</FullClassName>
</WizardExtension>
A beírandó PublicKeyToken-t az előbb tudtuk meg az sn.exe jóvoltából. Dobjuk be a .vstemplate állományt a template ZIP-be. Innentől, ha a varázslón bármit változtatni szeretnénk, csak újra kell buildelni és már használható is. Kicsit bonyolultabb a dolog, ha a project templaten szeretnénk változtatni, de az sem vészes. Az apróbbakat akár a template-ben is elintézhetjük kézzel, de ha komolyabb változtatásokat kell végezni, akkor célszerű újragenerálni a template-t, az viszont törli a fenti <WizadExtension> tag-et, így azt újra hozzá kell adnunk.

Ha mindent jól csináltunk és én sem felejtettem el leírni semmit sem, akkor a build után használható lesz az új project template + a varázslónk. Fontos, hogy a gacutil.exe lefutása után csak akkor tudjuk használni az új wizardot, ha új Visual Studio-t indítottunk.

Megjegyzés Hozzáfűzése

Loading