HyperLink
Bejelentkezés
E-mail: 
Jelszó: 





Skip Navigation Links
 

Futtatható program generálása programból


Példaprogram letöltése

6124 bájt

Visual Studio.NET-es alkalmazásaink készítésekor arra is van lehetőségünk, hogy programunk futása alatt létrehozzunk egy új programot, melyet EXE állományba mentve futtatható alkalmazást kapunk. Ezt felhasználva generáltathatunk olyan alkalmazásokat, melyek az adott géphez, felhasználóhoz kötött információkat, kódokat tartalmaznak a létrehozott EXE-ben, mely ezután már megváltoztathatatlan, de felhasználható sok más esetben is ez a lehetőség, mivel a generált alkalmazás bármilyen kódot tartalmazhat.

Mellékelt példában olyan EXE-ket hozunk létre, melyek a konzolalkalmazás csoportjába esnek. Indításukkor egyetlen kódot, egy GUID számot írnak a standard kimenetre. Ez a GUID szám a generáló alkalmazásban kerül létrehozásra, így egyedi és jellemző lesz arra a számítógépre, melyen programunk fut.
A Form-ra egyetlen gombot helyezünk, melynek lenyomásakor fogjuk az EXE-t létrehozni. Az EXE neve egy szám. Először 1.EXE, majd a 2.EXE és így tovább. Ezt a folyamatos számozást úgy érjük el, hogy ellenőrizzük, hogy az adott EXE létezik-e már.
  Private Sub button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles button1.Click
    Dim i As Integer = 1
    While File.Exists(GetFileName(i))
      i += 1
    End While
Ha találunk egy olyan EXE-t, mely még nem létezik, akkor ennek nevét tároljuk a filename változóban.
    Dim filename As String = GetFileName(i)
Nézzük, miként is megy egy EXE létrehozása. Először is kell egy AssemblyName osztály példánya. Ezzel tudjuk egyedileg azonosítani az újonnan létrehozandó assembly-t. A Name property-be egy tetszőleges nevet adunk.
    Dim am As New AssemblyName()
    am.Name = "TestAssembly"
Az assembly létrehozásához egy AssemblyBuilder osztály felhasználása válik szükségessé, melyet úgy hozhatunk létre, hogy az AppDomain osztály CurrenctDomain property-jéből kiolvasott osztály DefineDynamicAssembly függvényét hívjuk. Ezzel létrehozhatunk egy új dinamikus alkalmazásmodult. Első paraméterébe a már létrehozott AssemblyName osztálynak a példánya jön, míg másodikként a hozzáférési módot adhatjuk meg. Save mód esetén a generált alkalmazást menthetjük EXE-be, míg Run mód esetén csak futtathatjuk azt. A harmadik paraméterben megadhatunk egy alkönyvtárat, ahová az EXE-t majd menteni szeretnénk.
    Dim ad As AppDomain = AppDomain.CurrentDomain
    Dim ab As AssemblyBuilder = ad.DefineDynamicAssembly(am, AssemblyBuilderAccess.Save, Application.StartupPath) 
Ezt követően definiálnunk kell egy új modult a már létrehozott assembly részére. Ehhez a DefineDynamicModule függvény nyújt segítséget. Első paraméterként a modul nevét, míg másodikként az EXE állomány nevét kell megadnunk.
    Dim mb As ModuleBuilder = ab.DefineDynamicModule("TestModule", filename)
Következő lépésként egy típusfordítót kell létrehoznunk. Ennek segítségével tudunk majd függvényt létrehozni a modulon belül. A típusfordítót a TypeBuilder osztály képviseli, melyet a már meglévő modul DefineType függvényének hívásával hozhatunk létre. Ezt követően a DefineMethod segítségével létrehozhatunk egy függvényt. Mivel minden modulban szükséges egy olyan függvény, mely alapértelmezettként lesz meghívva az alkalmazás indításakor, így ezt nevezzük EntryMethod-nak, melyet publikusra és statikusra választunk. Ennek a függvénynek nem lesz sem paramétere, sem visszatérési értéke. Ha ilyen függvényt szeretnénk készíteni, akkor a DefineMethod harmadik paraméterében kellene megadnunk a függvényünk visszatérési értékét, míg a negyedikben egy olyan tömböt, melyben felsoroljuk a paramétereinek típusait. A harmadik és negyedik paraméter egyaránt Type típusban várja ezeket az információkat.
    Dim tb As TypeBuilder = mb.DefineType("TestType", TypeAttributes.Public)
    Dim metb As MethodBuilder = tb.DefineMethod("EntryMethod", MethodAttributes.Public Or MethodAttributes.Static, Nothing, Nothing)     
Attól, hogy a függvényünk neve EntryMethod, még nem lesz alapértelmezett. Hogy azzá váljon, meg kell hívnunk a SetEntryPoint függvényt, melynek paraméterként megadjuk az imént létrehozott függvényünket.
    ab.SetEntryPoint(metb)
Ezt követően tetszőleges kódot generálhatunk a függvényünkhöz. A kód generálásánál természetesen nem használhatunk fel C#, vagy egyéb forráskódot, hiszen itt most egy közvetlenül készítendő futtatható állományról van szó. A Visual Studio.NET által generált alkalmazások azonban nem gépi kódot, hanem egy belső kódot tartalmaznak, melyet Microsoft Intermediate Language-nek (MSIL) neveznek. Ilyen kódokat írhatunk a függvényünkbe. Ehhez segítséget nyújt számunkra az ILGenerator osztály, mely képes Microsoft Intermediate Language kódok létrehozására.
Az ILGenerator osztály EmitWriteLine függvény például olyan kódot generál, mely megfelel a Console.WriteLine utasításának. Paraméterként is azt a sztringet kell átadnunk, melyet a WriteLine-nak adnánk és hatása is azzal megegyező lesz. Mivel most egy új GUID szám kiírása a cél, így ennek megfelelően itt ezt adjuk meg paraméterként.
    Dim il As ILGenerator = metb.GetILGenerator()
    il.EmitWriteLine(Guid.NewGuid().ToString())
Példánk egyszerűsége miatt a létrehozott EntryMethod függvénynek más feladata nincs, így már csak be kell fejeznünk a függvényünk futását egy return utasítással. Az ehhez szükséges Intermediate Language kódot az Emit függvény hívásával írhatjuk be. Paraméterként a Ret kódot kell megadni, mely a return utasítással egyenlő.
    il.Emit(OpCodes.Ret)
Végső lépésként a fentiekben megfogalmazott típust legeneráltatjuk és elmentjük egy EXE állományba, mely ezt követően máris futtatható.
    tb.CreateType()
    ab.Save(filename)
  End Sub 'button1_Click
Kicsit térjünk még vissza az Emit függvényre. Ennek paramétereként az OpCodes felsorolt típus elemei közül választhatunk egy-egy utasítást, mely megfelel az Intermediate Language azonos nevű utasításainak. Sok esetben ezek az utasítások paraméter nélküliek, mint a Ret is, van azonban olyan eset, ahol paramétert is vár az utasítás. Ekkor az Emit függvény azon változatát kell használnunk, mely második paraméterrel is rendelkezik és itt megadható az adott parancshoz tartozó paraméter értéke is.

Felhasználási feltételek
A Software Online szoftverfejlesztői magazin mindegyik cikke, minden megjelent képe, és egyéb publikált anyaga szerzői jog védelme alatt áll! Bármilyen formában történő másodlagos terjesztésük, közzétételük vagy felhasználásuk kizárólag a kiadó előzetes írásbeli engedélyével történhet!

Copyright © 1999-2012 Animare Software Kft. Minden jog fenntartva!
| Készült: Animare Stúdió | Adatvédelem | Kapcsolat |