Ana Sayfa | English Blog | Seminer TV | Dil Cookie Sil  Blog'u Mail ile takip et!       
Daron Yöndem - Visual Studio 2005
bir yazılımcının tasarıları...
 Tuesday, September 23, 2008

Başlık olarak “Reflection” yazdıktan sonra ardına sayfalarca açıklama ve örnek konulabilir. Hatta bu konuda ayrı bir kitap bile yazılabilir. Reflection’ın çok farklı kullanımlar var. Özetleyerek hızlı bir şekilde tanımlamak istersek aslında Reflection bize hakkında bilgi sahibi olmadığınız programatik nesnelerle ilgili çalışma zamanında (run-time) bilgi alabilmemize olanak tanıyan bir metottur. Peki böyle bir şeye neden ihtiyacımız olsun? En basit örnek gerçek zamanlı olarak uygulamalara farklı DLL dosyalarının bağlandığı durumları gösterebiliriz. Böyle bir durumda kaynak konumdaki sınıflar veya metotlar ile ilgili herhangi bir bilgi bulunmaz. Söz konusu bu bilgilerin program çalışırken elde edilerek kullanılması gerekir. Gelin ilk olarak Reflection’ın yapısını ve sistemini tanımak adına tek bir uygulama içerisinde nasıl kullanılabileceğimize göz atalım. Örnek uygulamamızda aşağıdaki şekli ile tanımlanmış bir Urun sınıfı kullanacağız.

[VB]

Public Class Urun

 

    Private PAdi As String

    Public Property Adi() As String

        Get

            Return PAdi

        End Get

        Set(ByVal value As String)

            PAdi = value

        End Set

    End Property

 

    Sub New()

 

    End Sub

 

    Sub New(ByVal adi As String)

        Me.Adi = adi

    End Sub

 

    Function Uyari() As String

        Return "Ürünün adı: " & Me.Adi

    End Function

End Class

[C#]

public class Urun

{

 

    private string PAdi;

    public string Adi

    {

        get { return PAdi; }

        set { PAdi = value; }

    }

 

    public Urun()

    {

 

    }

 

    public Urun(string adi)

    {

        this.Adi = adi;

    }

 

    public string Uyari()

    {

        return "Ürünün adı: " + this.Adi;

    }

}

Uygulamamız içerisinde iki adet düğme yer alacak ve kullanacağımız Windows penceresinde global olarak tanımlanmış bir de Object tipinde değişkenimiz bulunacak.

[VB]

Dim BirUrun As Object   

[C#]

object BirUrun;

Uygulama içerisindeki düğmelerden birine basıldığında global BirUrun değişkenimiz yeni bir Urun değişkenine dönüştürülecek.

[VB]

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

    BirUrun = New Urun

End Sub

[C#]

    private void button1_Click_1(object sender, EventArgs e)

    {

        BirUrun = new Urun();

    }

Programımız içerisinde diğer düğmeye basıldığında BirUrun adındaki değişkenimizin Adi özelliğini değiştirerek Uyari adındaki metodunu kullanmak istiyoruz. Fakat Visual Studio içerisinde maalesef ki BirUrun adındaki değişkenle beraber Urun tipine ait Intellisense desteği gelmeyecektir. Aslında bu durumun haklı bir nedeni var. İkinci düğmeye basıldığında BirUrun adındaki değişkenin tipininin Object mi yoksa Urun mü olacağı belli değil. İşte tam da istediğimiz ortamı yaratmış olduk. Kullanacağımız nesnenin tipi belirsiz ve biz ona ait bazı özellikleri kullanmak istiyoruz. Bu durumda ilk olarak ikinci düğmeye basıldığında gerçekten BirUrun değişkeninin tipi Urun mü yoksa değil mi sorusunu kontrol etmemiz lazım.

[VB]

       If TypeOf (BirUrun) Is Urun Then

 

        End If

[C#]

        if ((BirUrun) is Urun)

        {

 

        }

Buraya kadar her şey çok kolay. Bundan sonra eğer IF kontrollerimize olumlu sonuç dönüyorsa ilk olarak gidip nesnenin Adi özelliğini bulmamız ve ona bir değer aktarmamız gerekiyor.

[VB]

BirUrun.GetType.GetProperty("Adi").SetValue(BirUrun, "Daron", Nothing)

[C#]

BirUrun.GetType().GetProperty("Adi").SetValue(BirUrun, "Daron", null);   

Yukarıdaki kod ile elimizdeki nesnenin tipini bilmeden onun Adi adındaki özelliğini (property) yakalayarak değerini Daron olarak değiştiriyoruz. Kodumuzu detaylı olarak adım adım bakacak olursak ilk aşamada nesnenin tipini GetType ile alıyoruz. Sonrasında ise tipini yakaladığımız nesnenin GetProperty ile Adi adındaki özelliğini alarak SetValue ile söz konusu özelliğin değerini değiştiriyoruz. SetValue metodu toplam üç parametre alıyor; bunlardan ilki değer değişikliği yapılacak nesnenin kendisi, ikincisi yeni atanacak olan değer, üçüncüsü ise eğer değiştirilecek olan özellik (property) indeksli ise söz konusu indeks değeri. Bizim örneğimizde indeksli bir özellik olmadığı için bu parametreyi boş geçiyoruz.

Değer atamamızı tamamladığımıza göre bu sefer de sıra geldi BirUrun değişkenimize ait Uyari metodunu çalıştırmaya. Metodumuz bize bir String döndürecek biz de onu doğrudan bir mesaj kutusu ile kullanıcıya göstereceğiz.

[VB]

BirUrun.GetType.InvokeMember("Uyari", Reflection.BindingFlags.InvokeMethod, Nothing, BirUrun, Nothing)

[C#]

BirUrun.GetType().InvokeMember("Uyari", System.Reflection.BindingFlags.InvokeMethod, null, BirUrun, null).ToString();

Reflection kullanarak türü bilinmeyen bir nesnenin bir metodunu çalıştırmak için InvokeMember metodundan faydalanmamız gerekiyor. InvokeMember aslında çok geniş kullanımı olan bir metod, biz şimdilik sadece bir çeşit kullanımına değineceğiz. Örneğimizde InvokeMember bir metod çalıştıracağı için ilk parametresinde çalıştırılacak olan metodun adını ikincisinde BindingFlags.InvokeMethod ile bir Metod çalıştırılacağını belirtiyoruz. Üçüncü parametre bizim şimdilik kullanım alanımız dışında kalan Binding’lerle ilgili, aynı şekilde beşinci parametre de boş bırakılarak geçilecek. Dördüncü parametrede ise hedef nesnemiz olan BirUrun değişkenimizi atayacağız. Böylece metodumuzu da çalıştırmış olduk.

Dinamik DLL Kullanımı

Kabaca Reflection’ın nasıl kullanılabildiğine dair bir örnek yaptıktan sonra artık sıra geldi harici bir DLL dosyasının çalışma anında programımıza ekleyerek içerisindeki yapıları kullanmaya. Bu çeşit bir işlevselliği özellikle gerçek zamanlı DLL derlemesi ile birleştirdiğinizde çok farklı bir dünyaya kapı açmış olacaksınız. Hedef olarak kullanacağımız DLL dosyasını aşağıdaki kodlardan yaratacağız.

[VB]

Public Class Deneme

    Function Metin() As String

        Return "Çalışıyor"

    End Function

End Class

[C#]

    public class Deneme

    {

        string Metin()

        {

            return "Çalışıyor";

        }

Yarattığımız DLL dosyasını uygulamamız ile aynı konuma yerleştirdikten sonra aşağıdaki kod ile DLL’imizi kullanmaya başlayabiliyoruz.

[VB]

Dim BirAssembly As Reflection.Assembly = Reflection.Assembly.LoadFrom("ornek2.dll")

[C#]

System.Reflection.Assembly BirAssembly = System.Reflection.Assembly.LoadFrom("ornek2.dll");

Artık yukarıda tanımladığımız Assembly üzerinden Reflection kullanarak ilerleyebiliriz. İlk olarak Deneme adında sınıfımızdan bir instance almamız gerekecek. Bunun için Deneme tipini bulmamız lazım.

[VB / C#]

BirAssembly.GetModule("Ornek2.dll").GetType("Deneme")

Assembly üzerinden modülümüzü yakalıyor sonra da Deneme adındaki tipinizi buluyoruz. Tabi tipi bulmak yeterli değil, söz konusu tipte bir değişken yaratmamız gerekiyor. Activator sınıfını kullanarak bu tip üzerinden bir instance yaratarak Sinif adında bir değişkene aktaracağız.

[VB]

Dim Sinif = Activator.CreateInstance(BirAssembly.GetModule("Ornek2.dll").GetType("Deneme"))   

[C#]

object Sinif = Activator.CreateInstance(BirAssembly.GetModule("Ornek2.dll").GetType("Deneme"));

Yarattığımız sınıfın maalesef özellikleri otomatik olarak gelmeyecek. O nedenle Metin adındaki metodumuzu da elle bularak çalıştırmak zorundayız.

[VB]

BirAssembly.GetModule("Ornek2.dll").GetType("Deneme").GetMethod("Metin").Invoke(Sinif, Nothing)

[C#]

BirAssembly.GetModule("Ornek2.dll").GetType("Deneme").GetMethod("Metin").Invoke(Sinif, null)

Yine Assembly üzerinden yola çıkarak bu sefer daha da ileri gidiyoruz. Deneme sınıfımızı bulduktan sonra içerisinde Metin adındaki metodumuzu buluyor ve doğrudan Invoke ile söz konusu metodu çalıştırıyoruz. Invoke metodu bizden iki parametre istiyor; bunlardan ilki ana sınıfın kendisi. Bir önceki adımda yakaladığımız sınıfı buraya parametre olarak aktarıyoruz. Diğeri ise bizim kullanmayacağımız Binding parametresi.

Metin metodumuz çalıştırıldığında geriye bir String değişkeni döndürüyor. Bu değişkeni de bir mesaj kutusu ile kullanıcıya göstermek istersek uygulamamızın tam kodunun aşağıdaki şekilde sonlanması gerekiyor.

[VB]

Public Class Form2

 

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim BirAssembly As Reflection.Assembly = Reflection.Assembly.LoadFrom("ornek2.dll")

 

        Dim Sinif = Activator.CreateInstance(BirAssembly.GetModule("Ornek2.dll").GetType("Deneme"))

        MsgBox(BirAssembly.GetModule("Ornek2.dll").GetType("Deneme").GetMethod("Metin").Invoke(Sinif, Nothing))

    End Sub

End Class

[C#]

namespace CSReflection

{

    public partial class Form2 : Form

    {

        public Form2()

        {

            InitializeComponent();

        }

 

        private void button1_Click(object sender, EventArgs e)

        {

            System.Reflection.Assembly BirAssembly = System.Reflection.Assembly.LoadFrom("ornek2.dll");

 

            object Sinif = Activator.CreateInstance(BirAssembly.GetModule("Ornek2.dll").GetType("Deneme"));

            MessageBox.Show(BirAssembly.GetModule("Ornek2.dll").GetType("Deneme").GetMethod("Metin").Invoke(Sinif, null).ToString());

        }

    }

}

Böylece harici bir DLL dosyasını yükleyerek istediğimiz metodu dinamik olarak kullanabildik. Farklı durumlarda isterseniz bir DLL içerisinde tüm metod, sınıf ve özelliklerin listelerini alabilir hatta bunları LINQ sorguları ile tarayabilirsiniz.

[VB]

Dim Metodlar = From Gelenler In BirAssembly.GetModule("Ornek2.dll").GetTypes Where Gelenler.GetMethod("Metin") IsNot Nothing

[C#]

var Metodlar = from Gelenler in BirAssembly.GetModule("Ornek2.dll").GetTypes() where Gelenler.GetMethod("Metin") != null select Gelenler;

Örneğin yukarıdaki LINQ sorgumuz ile harici DLL dosyası içerisinde Metin adında metodu olan tüm sınıfların bir listesini alıyoruz.

Hepinize kolay gelsin.

Tuesday, September 23, 2008 6:51:06 PM (GTB Standard Time, UTC+02:00)  #    Comments [8]   .NET Framework 3.0 | .NET Framework 3.5 | ASP.NET | ASP.NET 3.5 | LINQ | Silverlight 2.0 | Visual Basic 2005 | Visual Basic 2008 | Visual Studio 2005 | Visual Studio 2008 | WCF | WF | WPF  | 
 Sunday, September 21, 2008

Bir uygulama düşünün kendini programlayabilen. Konumuz “Star Trek” veya “Geleceğe Dönüş” değil. Emin olun gerçek dünyadan ve yapılabileceklerden bahsediyorum. Uygulamalarınızın dış sistemlerle ciddi bir bağlantı içerisinde olduğu durumlarda bazen kendi içlerinde dış sistemlere uygun kodlar üreterek kullanmaları gerekebilir. Bunu bazen uygulamaların kendi içlerindeki yapay zeka ile yapabilecekleri gibi bazen ise başka bir dış kaynaktan aldıkları yeni parametrelerden yola çıkarak kendi kodlarında değişiklik yapabilirler. Eğer bunların hiçbiri size gerçekçi gelmiyorsa başka bir seçenek olarak da harici uygulamaların kullanabileceği DLL dosyaları yaratacak bir uygulama yazmak istediğinizde yapmanız gerekenlerden bahsedebiliriz. Aslında her ikisi de aynı kapıya çıkıyor.

Bize dinamik olarak uygulamalar tarafından kullanılabilecek DLL dosyaları yaratacak bir kod lazım. Kullanacağımız nesnelerin çoğunun bulunduğu esas namespace System.CodeDom.Compiler olacak. Bunun haricinde C# veya VB için ayrı ayrı uygun namespace’leri kullanmamız gerek. Eğer VB kodu derleyecekseniz VB sınıflarını C# kodu derleyecekseniz tabi ki C# sınıflarını kullanmalısınız. Çapraz işlem yaparak C# kodunuz ile VB kodundan DLL üretme şansınız da var. Biz örneklerimizde C# ile C#’dan derleme, VB kodu ile de VB’den derleme yapacağız.

[VB]

Dim KodUretici As New Microsoft.VisualBasic.VBCodeProvider

Dim Derleyici As System.CodeDom.Compiler.CodeCompiler = KodUretici.CreateCompiler()

 

Dim Referanslarim As String() = {"System.dll"}

Dim AssemblyAdi As String = "Ornek.dll"

[C#]

Microsoft.CSharp.CSharpCodeProvider KodUretici = new Microsoft.CSharp.CSharpCodeProvider();

System.CodeDom.Compiler.ICodeCompiler Derleyici = KodUretici.CreateCompiler();

 

String[] Referanslarim =  {"System.dll"};

String AssemblyAdi= "Ornek.dll";

Kodumuzun başlangıcında ilk olarak birer CodeProvider nesnesi yaratıyoruz. Elimizdeki hazır kodu derleyecek olan nesneler olarak bu sınıflar VB ve C# için farklılaşıyor. CodeProvider’lar üzerinden birer de derleyici nesnesi aldıktan sonra sıra geliyor derleyeceğimiz kodun referanslarına karar vermeye. Referansları DLL isimleri ile bir String dizisine aktarmanız şart. Windows uygulamalarında en azından System.dll’in web uygulamalarında da System.Web.dll’in referans alınmış olması gerekiyor. Son olarak üreteceğimiz DLL dosyasının adını da başka bir değişkene aktararak yolumuza devam edelim.

[VB]

Dim DerlemeParametreleri As New System.CodeDom.Compiler.CompilerParameters(Referanslarim, AssemblyAdi)

DerlemeParametreleri.GenerateExecutable = True

DerlemeParametreleri.GenerateInMemory = False

[C#]

System.CodeDom.Compiler.CompilerParameters DerlemeParametreleri = new System.CodeDom.Compiler.CompilerParameters(Referanslarim, AssemblyAdi);

DerlemeParametreleri.GenerateExecutable = false;

 DerlemeParametreleri.GenerateInMemory = false;

Derleme işlemini yaparken yapmamız gereken ayarlar var. Bu ayarları derleyicimize bir CompilerParameters nesnesi olarak aktaracağız. DerlemeParametreleri değişkenimizi yaratırken referanslarımızı ve DLL adını aktardıktan sonra özel olarak GenerateExecutable özelliğini false olarak ayarlıyoruz. Böylece derleyicimiz bize tek başına çalışabilir bir dosya yaratmaktansa bir DLL dosyası yaratacak. Bir sonraki adımda da GenerateInMemory özelliğini false yaparak yaratılacak dosyanın uygulamamız ile aynı konuma, diske yazdırılmasını sağlıyoruz. Aksi halde yaratılan Assembly sadece hafızada tutulacak ve diske yazılmayacaktır. Sıra geldi dinamik olarak derlemeyeceğimiz kodu bir değişkene aktarmaya.

[VB]

Dim Kodum As String = <Kod>Public Class Deneme

    Function Metin() As String

        Return "Çalışıyor"

    End Function

End Class</Kod>.Value

[C#]

System.IO.StreamReader Okuyucu = new System.IO.StreamReader("Class1.cs");

string Kodum = Okuyucu.ReadToEnd();

Okuyucu.Close();

Bu noktada VB ile C# arasında farklı işlemler yaptım. VB’de doğrudan yaratacağım kodu uygulamanın içerisine gömerken C#’da derleyeceğim C# kodunu harici bir Class1.cs dosyasından çektim. Siz kendi uygulamalarınızda ister bu kodları farklı dosyalardan çekin ister metin işlemleri ile dinamik kod yaratın. İhtiyaçlarınıza göre uygun çözümü üretmek tamamen size kalmış. Önemli olan tek nokta aslında bu kodlarda hiçbir hatanın olmaması gerektiği, aksi halde derleme işlemi yapılamayacaktır.

[VB]

Dim Sonuc As System.CodeDom.Compiler.CompilerResults = KodUretici.CompileAssemblyFromSource(DerlemeParametreleri, Kodum)

[C#]

System.CodeDom.Compiler.CompilerResults Sonuc = KodUretici.CompileAssemblyFromSource(DerlemeParametreleri, Kodum);

Tüm ayarlarımız tamamlandığında göre doğrudan CodeProvider nesnemizin CompileAssemblyFromSource metodunu kullanarak derleme işlemini başlatabiliriz. Tabi bu esnada daha önce hazırlamış olduğumuz DerlemeParametrelerini de metoda parametre olarak aktarıyoruz. Derleme işlemimizi baştan sona tamamlayan kodumuzu bir bütün olarak inceleyelim.

[VB]

Dim KodUretici As New Microsoft.VisualBasic.VBCodeProvider

Dim Derleyici As System.CodeDom.Compiler.CodeCompiler = KodUretici.CreateCompiler()

 

Dim Referanslarim As String() = {"System.dll"}

Dim AssemblyAdi As String = "Ornek.dll"

 

Dim DerlemeParametreleri As New System.CodeDom.Compiler.CompilerParameters(Referanslarim, AssemblyAdi)

        DerlemeParametreleri.GenerateExecutable = True

        DerlemeParametreleri.GenerateInMemory = False

 

Dim Kodum As String = <Kod>Public Class Deneme

    Function Metin() As String

        Return "Çalışıyor"

    End Function

End Class</Kod>.Value

 

Dim Sonuc As System.CodeDom.Compiler.CompilerResults = KodUretici.CompileAssemblyFromSource(DerlemeParametreleri, Kodum)

[C#]

Microsoft.CSharp.CSharpCodeProvider KodUretici = new Microsoft.CSharp.CSharpCodeProvider();

System.CodeDom.Compiler.ICodeCompiler Derleyici = KodUretici.CreateCompiler();

 

String[] Referanslarim =  {"System.dll"};

String AssemblyAdi= "Ornek.dll";

 

System.CodeDom.Compiler.CompilerParameters DerlemeParametreleri = new System.CodeDom.Compiler.CompilerParameters(Referanslarim, AssemblyAdi);

DerlemeParametreleri.GenerateExecutable = false;

DerlemeParametreleri.GenerateInMemory = false;

 

System.IO.StreamReader Okuyucu = new System.IO.StreamReader("Class1.cs");

string Kodum = Okuyucu.ReadToEnd();

Okuyucu.Close();

 

System.CodeDom.Compiler.CompilerResults Sonuc = KodUretici.CompileAssemblyFromSource(DerlemeParametreleri, Kodum);

Dinamik olarak DLL dosyası derlemek işte bu kadar kolay. Dinamik kod yaratma araçları son dönemde çok popüler. Veritabanına bağlanarak veritabanındaki nesneleri algılayıp uygun “Veri Katmanı” kodunu dinamik olarak oluşturan hazır uygulamalar olduğu gibi bazı durumlarda özel kodlar yazmak da gerekebiliyor. Böyle bir durumda artık siz de uygulamalarınıza farklı kaynaklardaki şartlara uygun kodu dinamik olarak üretebilir ve bir DLL olarak farklı uygulamalara aktarabileceğiniz gibi kendi uygulamalarınızda da kullanabilirsiniz. Yarattığınız DLL dosyasını hemen uygulamanızda kullanmak isterseniz bu sefer dinamik olarak Assembly kullanımını ve Reflection konusuna eğilmenizde fayda var.

Hepinize kolay gelsin.

Sunday, September 21, 2008 7:04:21 PM (GTB Standard Time, UTC+02:00)  #    Comments [3]   .NET Framework 3.0 | .NET Framework 3.5 | ASP.NET | ASP.NET 3.5 | Silverlight 2.0 | Visual Basic 2005 | Visual Basic 2008 | Visual Studio 2005 | Visual Studio 2008 | WCF | WPF  | 
 Friday, September 19, 2008

İster VB olsun ister C#, ister web ister Windows uygulaması olsun yazdığımız tüm kodların derlenerek (Compile) bir EXE veya DLL haline dönüştürüldüğünü biliyoruz. Aslında .NET içerisinde yapılan işlem sizin yazdığınız herhangi bir .NET dilindeki kodun MSIL (Microsoft Intermediate Language)’a çevrilmesidir. İşte tam bu noktada akla gelen ilk soru; acaba bu çeviri işleminin tersini yapmak mümkün mü? Yani elimizdeki DLL veya EXE dosyasından yola çıkarak VB veya C# kodumuzu geri alabilir miyiz? Cevap: Evet.

Şu andan itibaren yapacaklarımız hedef olarak kullanacağınız uygulamanın lisans sözleşmesine göre yeri geldiğinde suç teşkil edebilir. O nedenle sizi özellikle uyarmak istiyorum. Çoğu zaman De-Compile işlemleri yaparkenki amacımız yazdığımız kodun nasıl derleyici tarafında MSIL’e çevrildiğini incelemek veya kaynak kodunu kaybettiğimiz ve bize ait olan bir uygulamanın kodlarına ulaşmak olacaktır. Diğer yandan lisans sözleşmesi ile aykırı düşmediği sürece farklı uygulamaları da De-Compile ederek arka planda farklı işlemlerin nasıl yapıldığını inceleme şansınız da olabilir.

.NET tarafına geçtiğimizde herhangi bir DLL veya EXE’nin aslında MSIL kodları içerdiğinden bahsetmiştik. Tabi ki bu MSIL kodları doğrudan bilgisayarlar tarafından çalıştırılabilir kodlar değiller. O nedenle içerisinde MSIL bulunan bir .NET yapısının çalışabilmesi için hedef makinede .NET Framework’ün yüklü olması gerekiyor. .NET Framework içerisindeki CLR (Common Language Runtime) bizim MSIL kodumuzu makine diline çevirerek çalışmasını sağlayacaktır. Kabaca baktığımızda De-Compile yolunda bizim ilk olarak elimizdeki DLL veya EXE içerisinden MSIL kodunu alarak çıkarmamız gerekecek. Bunun için doğrudan .NET Framework SDK paketi ile beraber gelen MSIL DisAssembler (ILDASM) uygulamasını kullanabiliriz.

IL DASM Kullanımı

Bilgisayarınıza .NET Framework SDK paketini kurduktan sonra doğrudan “Başlat” menüsünden ulaşabileceğiniz ILDASM programını Visual Studio yükleme konumu içerisinde SDK klasörü altında da bulabilirsiniz. Programı açtıktan sonra “File / Open” menüsünden istediğiniz bir .NET DLL veya EXE dosyasını açma şansınız olacaktır.Deneme amaçlı olarak gelin mini bir Windows uygulaması yazalım ve ILDASM ile açarak alacağımız sonucu görelim. Uygulamamız içerisinde birer TextBox, Button ve Label bulunacak. Basit bir şekilde düğmeye basıldığında TextBox içerisindeki değeri Label içerisine aktaracağız.

[VB]

Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Label1.Text = TextBox1.Text

    End Sub

End Class

[C#]

namespace WindowsFormsApplication1

{

    public partial class Form1 : Form

    {

        public Form1()

        {

            InitializeComponent();

        }

 

        private void button1_Click(object sender, EventArgs e)

        {

            label1.Text = textBox1.Text;

        }

    }

}

Yukarıda yazdığımız kodlar ile oluşturduğumuz uygulamayı ILDASM ile açarak sonucu inceleyelim. Uygulamanın ilk açılan penceresinde bizim EXE’ye ait tüm sınıflar ve namespace’ler gözüküyor olacaktır. Eğer herhangi bir nesnenin tanımı veya metodu ile ilgili MSIL kodunu görmek isterseniz doğrudan çift tıklayarak yeni bir pencerede kodların açılmasını sağlayabilirsiniz.

ILDASM içerisinde EXE’mizin MSIL kodları açıkça gözüküyor
ILDASM içerisinde EXE’mizin MSIL kodları açıkça gözüküyor

Hazırladığımız örnek uygulamanın Button_Click durumundaki MSIL kodunu bulduğumuzda aşağıdaki sonuç ile karşılaşıyoruz.

[MSIL]

.method private instance void  Button1_Click(object sender,

                                            class [mscorlib]System.EventArgs e) cil managed

{

  // Code size       23 (0x17)

  .maxstack  8

  IL_0000:  ldarg.0

  IL_0001:  callvirt   instance class [System.Windows.Forms]System.Windows.Forms.Label WindowsApplication1.Form1::get_Label1()

  IL_0006:  ldarg.0

  IL_0007:  callvirt   instance class [System.Windows.Forms]System.Windows.Forms.TextBox WindowsApplication1.Form1::get_TextBox1()

  IL_000c:  callvirt   instance string [System.Windows.Forms]System.Windows.Forms.TextBox::get_Text()

  IL_0011:  callvirt   instance void [System.Windows.Forms]System.Windows.Forms.Label::set_Text(string)

  IL_0016:  ret

} // end of method Form1::Button1_Click

Yukarıdaki MSIL kodu normal şartlarda CLR tarafından makine koduna çevrilerek hedef ortamda çalıştırılıyor. Artık MSIL kodumuzu aldığımıza göre bu kodu VB veya C# koduna çevirmemiz lazım. Tabi bu iş o kadar kolay değil ve tek tek elle yapılabilecek bir iş de değil. O nedenle bu sefer de farklı bir araç kullanacağız.

Reflector iş başında

Lutz Roeder tarafından yazılmış bir program olarak Reflector’ı http://www.red-gate.com/products/reflector/ adresinden bilgisayarınıza indirebilirsiniz. Program aslında bir önceki adımda anlattığım MSIL çözme işlemini de kendi içinde yapabiliyor. Bununla kalmayıp çözdüğü MSIL kodunu istediğiniz .NET diline de çevirebiliyor.

Programı çalıştırdıktan sonra “File / Open” menüsünden istediğiniz bir EXE veya DLL dosyasını seçebilirsiniz. Uygulamanın ana penceresindeki sınıf listesine hemen seçtiğiniz program da gelecektir.

Reflector ile kaynak kodunu görebiliyoruz.
Reflector ile kaynak kodunu görebiliyoruz.

Ufak bir gezinti ile istediğiniz sınıfın veya metodun koduna doğrudan ulaşabilirsiniz. Reflector arayüzündeki “Programlama Dili” seçeneğinde VB, C#, Delphi ve IL seçenekleri bulunuyor. Bir önceki bölümde hazırladığımız uygulamamızı açarak Button.Click durumundaki kodu farklı dillerde Reflector ile alıp inceleyelim.

[VB]

Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs)

    Me.Label1.Text = Me.TextBox1.Text

End Sub

[C#]

private void Button1_Click(object sender, EventArgs e)

{

    this.Label1.Text = this.TextBox1.Text;

}

Yazdığımız kodlar ile Reflector’ın bize verdiği kodlar tam olarak aynı değil. Bu durum zaten çok normal. Çünkü MSIL koduna çeviri esnasında aslında çoğu şey değişiyor. Örneğin tanımladığımız değişkenlerin bize özel olan isimlendirmeleri yok oluyor veya bizim kullandığımız bazı kısa metotlar uzun şekilleri ile yazılabiliyor. Hatta özellikle VB içerisindeki casting kolaylıkları Compile esnasında farklı değişikliklere neden olabiliyor. Bu durumda De-Compile ile aldığımız kod da yazdığımız koddan biraz farklı oluyor. Yine de elimizde çalışır durumda bir kod olduğuna kesin gözü ile bakabiliriz.

Nasıl engelleriz? Obfuscation!

Herhalde çoğunuz “tüm kodlarımız gözler önünde” endişesi içerisindesiniz. Aslında durum gerçekten de öyle. Tabi bu durumun birçok faydası var. Kişisel olarak itiraf etmek gerekirse farklı yazılımları De-Compile ederek çok şey öğrendiğimi söyleyebilirim. Bir defasında da kendi ürettiğimiz bir yazılımı De-Compile etmemiz gerekmişti, gerçekten hayat kurtarmıştı. Peki bunu nasıl engelleyebiliriz? İlk olarak şunu açıkça belirtiyim, herhangi bir .NET uygulamasından MSIL kodunun alınmasını engellemenin hiçbir yolu yok. Yapabileceğimiz tek şey MSIL kodunun okunabilirliliğini azaltmak için işlevsel olarak aynı işi gören fakat daha karışık bir MSIL kodu yaratmak. Bu işlem obfuscation olarak adlandırılıyor.

Obfuscation ile ilgili sektörde çok sayıda ücretli yazılım bulabilirsiniz. Biz bunlardan Xenocode'aait Postbuild 2008 adındaki ticari yazılımı kullanarak obfuscation ile neler yapabildiğimize bakacağız. XenoCode’u ilk açtığımızda karşımıza hemen bir uygulama listesi geliyor. Bu listeye bir önceki adımda kendi hazırladığımız EXE dosyasını ekleyerek uygulamanın üst menüsünden “Protect” tabına geçiyoruz. Burada sadece Windows’da çalışacak EXE dosyalarına uygulanabilecek özel bir koruma yöntemi olan “Surpress ILDASM” seçeneğinin işaretini kaldırmamız gerek. Bu seçenek DLL’lere zaten uygulanamayacaktır. Ekranın sağ tarafında korumak istediğimiz sınıfların ve metodların bir listesini işaretleyebiliyoruz. Tüm ayarları tamamladıktan sonra uygulamanın sağ altındaki “XenoCode Application” düğmesine basıyoruz.

Obfuscation işlemi için yollardayız
Obfuscation işlemi için yollardayız

Obfuscation işlemini tamamladıktan sonra sıra geldi testlerimizi yapmaya. İlk olarak uygulamamızı ILDASM ile açarak bakalım MSIL kodumuz ne hale gelmiş.

[MSIL]

.method private instance void  x44d0c0526a414989(object xe0292b9ed559da7d,

                                                class [mscorlib]System.EventArgs xfbf34718e704c6bc) cil managed

{

  // Code size       23 (0x17)

  .maxstack  8

  IL_0000:  ldarg.0

  IL_0001:  callvirt   instance class [System.Windows.Forms]System.Windows.Forms.Label WindowsApplication1.xaa4f033827d75b4d::get_x029e304eb4c44750()

  IL_0006:  ldarg.0

  IL_0007:  callvirt   instance class [System.Windows.Forms]System.Windows.Forms.TextBox WindowsApplication1.xaa4f033827d75b4d::get_x77691a2cfb8f8048()

  IL_000c:  callvirt   instance string [System.Windows.Forms]System.Windows.Forms.TextBox::get_Text()

  IL_0011:  callvirt   instance void [System.Windows.Forms]System.Windows.Forms.Label::set_Text(string)

  IL_0016:  ret

} // end of method xaa4f033827d75b4d::x44d0c0526a414989

Gördüğünüz gibi aslında çok büyük bir değişiklik yok. Sadece sınıfların ve metodların isimleri değiştirilerek karışık isimler verilmiş. Aynı uygulamayı Reflector ile açtığımızda ise aşağıdaki kodları elde ediyoruz.

[VB]

Private Sub x44d0c0526a414989(ByVal xe0292b9ed559da7d As Object, ByVal xfbf34718e704c6bc As EventArgs)

    Me.x029e304eb4c44750.Text = Me.x77691a2cfb8f8048.Text

End Sub

[C#]

private void x44d0c0526a414989(object xe0292b9ed559da7d, EventArgs xfbf34718e704c6bc)

{

    this.x029e304eb4c44750.Text = this.x77691a2cfb8f8048.Text;

}

Kodlar epey okunurluluğunu kaybetmiş durumda. Bizim örneğimizde sadece tek bir satır kod bulunduğu için neyin ne olduğunu anlamak çok zor olmuyor. Fakat binlerde satırdan oluşan uygulamaların kodlarından anlaşılabilir bir sonuç çıkarmak neredeyse imkânsız olacaktır.

Hepinize kolay gelsin.

Friday, September 19, 2008 6:27:11 PM (GTB Standard Time, UTC+02:00)  #    Comments [11]   .NET Framework 3.0 | .NET Framework 3.5 | ASP.NET | ASP.NET 3.5 | Silverlight 2.0 | Visual Basic 2005 | Visual Basic 2008 | Visual Studio 2005 | Visual Studio 2008  | 
 Monday, January 21, 2008

Web projelerinin dağıtımında kaynak kodların korunması veya en azından alenen ortaya konmaması genelde ticari projelerde istenen bir durumdur. Kendi adıma konuşmam gerekirse ben hem daha kolay kullanım hem de müşteriye uzun vadede kaynak kodu da değiştirerek daha esnek bir yapı ve kolaylık sağlanması adına yazılımların kaynak kodları ile verilmesinden yanayım. Fakat tabi ki durum projenin niteliklerine göre değişecektir.

Özellikle Visual Studio 2003 sonrasında web sitelerinin kod dosyalarının DLL'lere çevrilmesine alışmıştık. Hatta bu durum hoşumuza bile gitmişti. Sonrasında VisualStudio 2005 ile bu durum değişti ve varsayılan ayarlarda VS artık DLL oluşturmamaya başladı. Tabi aspnet_compiler.exe ve aspnet_merge.exe komut satırı araçları kullanılarak bu işlemler Visual Studio 2005 ile de yapılabiliyor fakat komut satırı için artık pek kullanışlı bir araç diyemeyiz.

Bahsettiğim bu araçları arkaplanda otomatik olarak kullanabilecek bir Windows programı gönüllü bir programcı olan ve benim de blogunu takip ettiğim Rick Strahl tarafından hazırlanmış durumda. Aslında bu yeni bir haber değil, yıllardır ben kullanıyordum :) ama yazısı yazmak bugüne nasipmiş. Programı hemen aşağıdaki adresten indirebilirsiniz.

http://www.west-wind.com/files/tools/WestWindAspNetCompilerUI.zip (99 KB)

ASP.NET Compiler Yardımcısı
ASP.NET Compiler Yardımcısı

Programın tüm özelliklerini tek tek anlatmaktansa yukarıdaki fotoğrafta hızlıca açıklamayı tercih ettim. Özellikle üzerinden durmamız gereken noktalardan biri "ASPX files are updateable" seçeneği. Eğer bu seçeneği işaretlerseniz projenizin ASPX dosyalarındaki HTML kodları da DLL dosyalarının içerisine yerleştirilecektir. Böylece ASPX dosyaları içerisinde sadece "This is a marker file generated by the precompilation tool, and should not be deleted!" yazısı yer alacak. ASPX dosyalarının içeriklerini DLL içerisine koysak da fiziksel olarak dosyaların bu uyarı mesajı ile disk üzerinde yer alması gerekiyor, aksi halde IIS 404 File Not Found hatası verecektir.

Bir diğer önemli ayar da "Fixed Names for assemblies" seçeneği. Eğer bu seçeneği işaretlerseniz her bir sınıf, ASPX dosyası için ayrı DLL dosyaları oluşturulacaktır böylece rahatlıkla bir dosyada değişiklik yaptığınızda o dosyaya ait DLL'i sunucuya göndererek projenizi yenileyebilirsiniz.

Eğer kolay dağıtım sizin için çok önemliyse tüm projenizin HTML kodları ile beraber sadece bir DLL olarak hazırlanmasını da sağlayabilirsiniz. Bunun için "Single Assembly" seçeneğini seçerek DLL dosyası için bir isim vermeniz yeterli. Ayrıca bu işlemi projenizdeki her bir klasor için ayrı ayrı düzenlenecek şekilde de ayarlayabilirsiniz. "Merging" bölümündeki özelliklerden faydalanabilmeniz için sisteminizde Visual Studio 2005 için Visual Studio 2005 Web Deployment Projects yüklemesinin yapılmış olması gerekiyor.

Diğer Framework sürümleri?

Yukarıdaki aracı .NET Framework 2.0 için, yani ASP.NET 2.0 için rahatlıkla kullanabilirsiniz. Program içerisinde Framework seçimi yer alsa da maalesef 3.0 veya 3.5 ile çalışmıyor. Bu durumda Merging haricindeki işlemler için doğrudan Visual Studio 2005 veya 2008'i de kullanabiliriz. Build / Publish menüsünde söz konusu ayarlara ulaşabilirsiniz.

Hepinize kolay gelsin.

Monday, January 21, 2008 12:50:10 PM (GTB Standard Time, UTC+02:00)  #    Comments [1]   ASP.NET | Visual Studio 2005 | Visual Studio 2008  | 
 Thursday, December 27, 2007

Bugün sizlere biraz Refactoring'den bahsetmek isriyorum. Refactoring'i kaba bir şekilde tanımlamak gerekirse herhangi bir kodun işlevini değiştirmeden yazılışı değiştirmek ve hedef olarak da kodun okunuşu kolaylaştırmaktır diyebiliriz. Refactoring konusunda sektörde bir çok araç, üçüncü parti uygulamalar satılıyor. Visual Studio içerisinde de C# için hazır bazı ufak tefek Refactoring araçları bulunuyor. Tabi ben bir VB programcısı olarak olayın VB kısmından bahsedeceğim ve sizlere ücretsiz bir Visual Studio eklentisi olan Refactor'u tavsiye edeceğim.

http://msdn2.microsoft.com/en-us/vbasic/bb693327.aspx

Yukarıdaki adresten indirebileceğiniz yazılımın normal sürümü ücretsiz ve hem Visual Studio 2005 hem de 2008 ile uyumlu. Yazılımın daha çok özelliklere sahip bir sürümü de "Refactor Pro" adı altında satılıyor. Biz şimdilik ücretsiz sürümle yetinelim :)

Hemen bir iki örnek ile neler yapabileceğimize bakalım.

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

        Dim ds As New Data.DataSet

 

        Using cnn As New SqlConnection(ConfigurationManager.ConnectionStrings("CNN").ConnectionString)

            Using cmd As New SqlCommand("SELECT * from TABLO", cnn)

                Dim da As New SqlDataAdapter(cmd)

                da.Fill(ds)

            End Using

        End Using

 

        GridView1.DataSource = ds

        GridView1.DataBind()

    End Sub

Yukarıdaki kod herhangi bir asp.net web sayfasının Page.Load durumunda çalışıyor olsun. Gördüğünüz gibi veritabanına bir Select göndererek gelen veriyi GridView'e bağlıyoruz. Eğer Select ile aldığımız veriyi sayfada başka yerlerde de almamız gerekecekse aslında bunu harici bir function olarak yazmamız daha faydalı olacaktır. Hemen aşağıdaki şekilde function içerisine almak istediğim bölümü seçiyorum.

Kodumuzu harici bir function içerisinde alıyoruz.
Kodumuzu harici bir function içerisinde alıyoruz.

"Extract Method" komutu verdiğimizde Refactor bize kodu class yapısı içerisinde nereye yazdırmak istediğimizi soruyor sonrasında da Function'ımızı aşağıdaki gibi otomatik olarak yaratıyor.

Partial Class _Default

    Inherits System.Web.UI.Page

 

    Private Shared Sub Page_LoadExtracted(ByVal ds As Data.DataSet)

        Using cnn As New SqlConnection(ConfigurationManager.ConnectionStrings("CNN").ConnectionString)

            Using cmd As New SqlCommand("SELECT * from TABLO", cnn)

                Dim da As New SqlDataAdapter(cmd)

                da.Fill(ds)

            End Using

        End Using

    End Sub

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

        Dim ds As New Data.DataSet

 

        Page_LoadExtracted(ds)

 

        GridView1.DataSource = ds

        GridView1.DataBind()

    End Sub

End Class

Gördüğünüz gibi artık aynı Function'ı kullanarak sürekli aynı datayı istediğimizde bir DataSet içerisine doldurtabiliyoruz. Fakat burada sizi rahatsız edeceğinden emin olduğum bir şey var; Refactor'un yarattığı function'ın adı çok anlamsız :) Visual Studio içerisinde yaratılan fonksiyonun adını değiştirirseniz Refactor sizin için söz konusu fonksiyonun kullanıldığı yerlerdeki referansları da otomatik olarak değiştirecektir.

Gelelim bir diğer örneğe. Varsayalım ki yeni bir sınıf yapısı oluşturmaya başladınız. Oluşturduğunuz ilk sınıfın bir sürü Private değişkeni var ve bunlara da uygun Property'lerin tanımlanması gerekiyor. Set ve Get leri tek tek her biri için ayarlıyor olmak gerçekten işkenceye dönüşebilir. Gelin aşağıdaki koda bir bakalım.

    Public Class Deneme

        Private Ozellik As Integer

        Private Ozellik2 As Integer

 

        Sub New()

 

        End Sub

 

        Sub New(ByVal Ozellik As Integer, ByVal Ozellik2 As Integer)

            Me.Ozellik = Ozellik

            Me.Ozellik2 = Ozellik2

        End Sub

    End Class

Yukarıdaki sınıfımızda sadece iki adet özellik bulunuyor bunların Property'lerini oluşturmamız gerekiyor. Private değişkenlerin üzerine sağ tuşu ile tıkladıktan sonra "Refactor / Encapsulate Field" komutu veriyorum ve kodun yerleştirileceği yeri de seçtikten sonra Refactor benim için Property kodlarını otomatik olarak yazıyor.

  Public Class Deneme

        Private Ozellik As Integer

        Private Ozellik2 As Integer

 

        Sub New()

 

        End Sub

 

        Sub New(ByVal Ozellik As Integer, ByVal Ozellik2 As Integer)

            Me.Ozellik1 = Ozellik

            Me.Ozellik21 = Ozellik2

        End Sub

        Public Property Ozellik1() As Integer

            Get

                Return Ozellik

            End Get

            Set(ByVal value As Integer)

                Ozellik = value

            End Set

        End Property

        Public Property Ozellik21() As Integer

            Get

                Return Ozellik2

            End Get

            Set(ByVal value As Integer)

                Ozellik2 = value

            End Set

        End Property

    End Class

Refactor tarafından tamamlanan yukarıdaki kodda dikkatinizi çektiyse Sub New kodundaki değerlerin aktarıldığı değişkenlerin isimleri de otomatik olarak Property isimleri ile değiştirilmiş durumda. Bir önceki örnekte olduğu gibi burada da eğer elle Property isimlerini değiştirirseniz Refactor otomatik olarak sınıf içerisinde diğer referansları da değiştiriyor.

Tüm bu işlemleri kod yazarken yapıyor olmak kolaylık sağlayabilir fakat esas mesele elinizde hazır kodları tamamlanmış bir proje varsa gerçekleşiyor. Projeyi inceleyerek sadece Refactoring araçlarını kullanarak daha okunabilir bir kod yaratmaya çalışıyorsunuz, hatta çoğu zaman kodun işleyişini değiştirmeden kodu kısaltabiliyorsunuz bile.

Refactoring'e giriş yapmanızı sağlayacak Refactor eklentisi ne kadar ücretsiz olsa da daha fazla reklamını yapmayacağım :) Refactoring dünyasını keşfetmek artık size kalmış.

Hepinize kolay gelsin.

Thursday, December 27, 2007 4:21:29 PM (GTB Standard Time, UTC+02:00)  #    Comments [2]   ASP.NET | ASP.NET 3.5 | Visual Basic 2005 | Visual Basic 2008 | Visual Studio 2005 | Visual Studio 2008  | 
 Tuesday, October 16, 2007

Yeni hazırladığınız web sitenizi SQL2005 veritabanı üzerine kurguladınız ve lokal olarak kendi makinenizde yarattığınız SQL veritabanına hazırladığınız site ile bazı verilerinizi de girdiniz. Sıra geldi web sitenizi online hale getirmeye, yani hosting sağlayıcınızın sunucularına yüklemeye. Sitenizin dosyalarını FTP üzerinden sunucuya gönderdiniz, son olarak da SQL veritabanınızı hosting sağlayıcınızın verdiği paylaşımlı SQL sunucu üzerindeki veritabanına yüklemeniz gerekiyor. İşte bu noktada sorunlar başlıyor. Eğer bilgisayarınızda Visual Studio 2005 ile beraber gelen SQL Express yüklü ise maalesef SSIS (eski DTS) sisteminizde yüklü olmayacaktır. O nedenle veritabanınızı karşıya atma şansınız yok. Diğer yandan çoğu hosting sağlayıcı kendi yönetim panelleri üzerinden sizin SQL scriptleri yükleyerek işlem yapabileceğiniz ortamlar sağlar. Aslında elinizde tüm veritabanınızı içerisindeki veriler ile birlikte yaratabilecek bir SQL Script bloğu olsu hiç sorun yaşamayacaksınız.

Karşınızda SQL Server Database Publishing Wizard 1.1

Tam olarak yukarıda bahsettiğimiz sorunu giderme amacıyla hazırlanmış olan Database Publishing Wizard ile herhangi bir SQL veritabanından SQL Script'leri yaratabiliyoruz. Bu işlemi yaparken veritabanındaki tüm objeleri yaratacak scriptlerin yanı sıra veritabanındaki veriyi de scriptler şeklinde alabiliyorsunuz. Yazılımı aşağıdaki adresten bilgisayarınıza indirebilirsiniz.

http://www.microsoft.com/downloads/details.aspx?FamilyID=56E5B1C5-BF17-42E0-A410-371A838E570A&displaylang=en

SQL Server Database Publish Wizard ile SQL Script yaratıyoruz.
SQL Server Database Publish Wizard ile SQL Script yaratıyoruz.

Database Publishing Wizard'ı bilgisayarınız Start/Başlat menüsünden çalıştırabileceğiniz gibi isterseniz Visual Studio 2005 içerisinden de kolaylıkla kullanabilirsiniz. Visual Studio 2005 içinde Server Explorer tabında herhangi bir veritabanına sağ tuş ile tıkladığınızda "Publish to provider" komutu ile karşılaşacaksınız, söz konusu komut Database Publishing Wizard'ın açılmasını sağlayacaktır.

Visual Studio 2005 ve Database Publishing Wizard
Visual Studio 2005 ve Database Publishing Wizard

Database Publishing Wizard Visual Studio 2008 ile beraber entegre olarak gelecek. İleriye dönük olarak şu anda desteklenen bir başka Publish metodu daha yer alıyor. Bir web servisi aracılığı ile hosting sağlayıcıya veritabanınızı aktarma şansı tanıyan bu metoddan ben bu yazımda bahsetmedim çünkü bu servisi şu an dünyada bile veren çok az hosting sağlayıcı var. Umarım zamanla bu servis de yaygınlaşır ve onunla ilgili bir yazıyı da bir gün yazmam gerekir :)

Hepinize kolay gelsin...

Tuesday, October 16, 2007 9:48:04 AM (GTB Standard Time, UTC+02:00)  #    Comments [1]   ASP.NET | Visual Studio 2005 | SQL Server 2005  | 
 Tuesday, October 02, 2007

İster internet üzerinden yayınlanan makalelerde olsun ister blog sitenize yollayacağınız bir ipucunda, maalesef sayfanıza HTML kodu veya herhangi bir kod yerleştirmek istediğinizde Visual Studio içerisinden alışık olduğumuz renklendirmeyi almamız pek mümkün olmuyor. Bu durumda çoğu sitede ekran görüntülerinden oluşan resimlerle dolu makaleler görüyoruz. Ben bugüne kadar bu sorunu biraz uğraştırıcı bir yöntemle çözüyordum :)

Bugünden sonra ise CopySourceAsHtml adındaki bir Visual Studio 2005 add-in uygulamasını kullanacağım. Yaptığım testlerde epey başarılı sonuçlar aldım. Uygulama direk Visual Studio içerisindeki renklendirme üzerinden HTML kodu yaratabiliyor. Programı aşağıdaki adresten indirebilirsiniz.

http://www.jtleigh.com/people/colin/software/CopySourceAsHtml/

Tuesday, October 02, 2007 7:43:28 PM (GTB Standard Time, UTC+02:00)  #    Comments [1]   .NET Framework 3.0 | AJAX | ASP.NET | CSS | HTML | JavaScript | Silverlight | Visual Basic 2005 | Visual Studio 2005  | 
 Saturday, September 01, 2007

Visual Studio 2005 içerisinde çalışırken çoğu zaman çalıştığımız dosyaların bulunduğu klasöre ulaşmak ve bazı işlemler yapmak isteriz. Bunun için gidip o klasörü bulmak gerekir. Özellikle bir de projenizi Visual Studio'nun varsayılan konumlarına açmışsanız iş daha da zorlaşır. Visual Studio 2008 ile beraber Solution Explorer'da artık herhangi bir klasöre sağ tıklayıp "Open Folder in Windows Explorer" diyebileceğiz. Peki ya Visual Studio 2005'de? Aşağıdaki linkten gerekli aracı indirip bilgisayarınıza kurduğunuzda Visual Studio 2005 içerisinde Solution Explorer içinde herhangi bir klasöre tıklandığınızda gelen menüde Explore seçeneği yer alacak. Böylece hayatımız biraz daha kolaylaşacak.

ExploreInWindowsSetup.exe (72 KB)

Saturday, September 01, 2007 1:09:14 PM (GTB Standard Time, UTC+02:00)  #    Comments [0]   Visual Studio 2005  | 
Copyright © 2010 Daron Yöndem. Tüm hakları saklıdır.