https://www.buraksenyurt.com/Burak Selim Şenyurt - Visual Studio2018-12-25T19:08:00+00:00Matematik Mühendisi Bir Bilgisayar Programcısının NotlarıBurak Selim SenyurtBlogEngine.Net Syndication Generatorhttps://www.buraksenyurt.com/opml.axdBurak Selim SenyurtMatematik Mühendisi Bir Bilgisayar Programcısının Notlarıtr-TRBurak Selim Şenyurt0.0000000.000000https://www.buraksenyurt.com/post/Nedir-Bu-MSBuildNedir Bu MSBuild?2013-08-01T07:47:00+00:00bsenyurt<p><span style="color: #ff0000;"><a href="https://www.buraksenyurt.com/pics/msbuild_9.jpg"><img style="background-image: none; float: right; padding-top: 0px; padding-left: 0px; margin: 4px 0px; display: inline; padding-right: 0px; border-width: 0px;" title="msbuild_9" src="/pics/msbuild_9_thumb.jpg" alt="msbuild_9" width="204" height="204" align="right" border="0" /></a>[Orjinal Yazım Tarihi – 25/02/2013]</span></p>
<p>Merhaba Arkadaşlar,</p>
<p>Yıllar öncesinde bir kaç seneliğine de olsa saygın bir eğitim kurumunda eğitmen olarak görev alma şansını yakalamıştım. Özellikle <strong>C#</strong>’ ın öğretilmeye çalışıldığı başlangıç niteliğindeki seanslarda dilin temel özelliklerini anlatırken, tüm dış çevre ile olan bağlantıyı kesip, sadece anahtar kelime(keyword), ifade ve materyale odaklanmaya çalışırdık. Bu sebepten genellikle ilk örneklerimiz ve <strong>Hello World </strong>uygulamamız, <strong>Notepad </strong>gibi bir program ve komut satırındaki<strong> csc<em>(C# Compiler)</em></strong> ile inşa edilirdi.</p>
<p>O zamanlar bu bizim için yeterli görünüyordu ama tabi <strong>.Net Framework 2.0</strong> ile birlikte hayatımıza yeni bir inşa süreci de girdi. Aslında bu günkü konumuzda da, <strong>Notepad<em>(tam olarak Notepad 2)</em></strong> ve komut satırı aracını kullanarak ilerlemeye çalışıyor olacağız. Amacımız <strong>MSBuild</strong> platformunu çok kısaca tanımaya ve anlamaya çalışmak.</p>
<p><strong>Microsoft Build Engine</strong> aslında başlı başına bir platformdur. Kısaca <strong>MSBuild</strong> olarak anılmaktadır ve bir uygulamanın inşa edilmesi noktasında devreye giren <strong>XML<em>(eXtensible Markup Language)</em></strong> tabanlı bir <strong>Script</strong> bütününü esas alır. Kısacası uygulamanın inşa edilmesi sırasındaki aşamalar <strong>XML</strong> tabanlı bir akış olarak ifade edilebilmektedir. <strong>MSBuild</strong> platformunun en önemli özelliği ise, inşa sürecinde <strong>Visual Studio</strong> gibi bir araca ihtiyaç duymuyor oluşudur.</p>
<p>Evet <strong>Visual Studio</strong>’ nun kendisi, <strong>Build </strong>işlemlerinde bu platformu kullanmaktadır doğru ama, tam tersi durum geçerli değildir. Yani istersek <strong>MSBuild</strong> aracını kullanarak, bir uygulamanın veya uygulama ortamının üretilmesi sırasındaki aşamaları, basit bir <strong>Notepad</strong> aracı ile tasarlayabilir ve <strong>MSBuild.exe</strong>’ den yararlanarak hayata geçirebiliriz<em>(Ancak bu gün şanslısınız çünkü <strong>Notepad2 </strong>isimli ürünü kullanacağız. <a href="http://sourceforge.net/projects/notepad2/">Sourceforge adresinden indirebilirsiniz</a> <img class="wlEmoticon wlEmoticon-smile" style="border-style: none;" src="/pics/wlEmoticon-smile_91.png" alt="Smile" /> )</em></p>
<p>Bu fikir tabi ki otomatize edilmiş <strong>Build</strong> işlemlerinin de icra edilebileceği anlamına gelmektedir. Ki <strong>Team Foundation Server</strong> ürünü de <strong>MSBuild</strong>’ un etkin bir şekilde kullanılmasına olanak tanımaktadır. Özellikle <strong>Team Foundation Build </strong>olarak anılan platform içerisinde <strong>Build Server</strong>’ un kurulduğu ortam <strong>MSBuild Script</strong>’ lerini kullanarak üretim işlemlerini gerçekleştirmektedir. Söz gelimizi <strong>TFS </strong>tarafında eğer <strong>Continous Integration </strong>gibi bir strateji tercih edilmişse, kodlamacıların <strong>Check-In</strong> işlemleri sonrası <strong>Team Foundation Build</strong> devreye girecek ve <strong>MSBuild script</strong>’ leri otomatik olarak çalıştırılarak inşa işlemleri icra edilecektir. <em>(<strong>Team Foundation Build</strong> ayrıca incelenmesi gereken bir konu olduğundan bu yazımızda detaylandırılmamıştır)</em> </p>
<p><strong>Visual Studio</strong> ortamında geliştirdiğimiz projeleri göz önüne aldığımızda, oluşturulan proje dosyaları içerisinde, <strong>MSBuild</strong>’ un kullanacağı <strong>ayarlar<em>(Settings) </em></strong>ve bazı koşul bağlı işlevsellikler konuşlandırılmaktadır. Tabi geliştirici olarak bu kısımlar ile pek fazla uğraşmayız ve nihayetinde <strong>Visual Studio</strong> bizim için bu akışları otomatik olarak inşa eder. Ancak <strong>Release Manager</strong> gibi pozisyonlar özellikle bu proje dosya içeriklerini değerlendirerek genişletmeler yapabilir ve <strong>MSBuild</strong> sürecini farklılaştırabilirler.</p>
<blockquote>
<p>Visual Studio ile geliştirilen proje dosyaları C# tarafı için csproj, Visual Basic tarafı için vbproj, Managed C++ tarafı içinse vcxproj uzantılı olanlardır.</p>
</blockquote>
<h1>Hangi Durumlarda MSBuild</h1>
<p>Peki <strong>MSBuild</strong> ağırlık olarak hangi hallerde ele alınır.</p>
<ul>
<li>En bilinen sebep elimizde <strong>Visual Studio</strong> olmayan bir ortamda inşa etme işlemlerinde değerlendirilebiliyor olmasıdır.</li>
<li><strong>Compiler</strong> devreye girmeden önce bazı dosyaların <strong>Process</strong> edilmesi gereken durumlarda ele alınabilir.<em>(Pre-Processing Steps)</em> </li>
<li>Benzer şekilde <strong>Process</strong> sonrası yapılması istenen işlemler içinde kullanılabilir<em>(Post-Processing Steps)</em></li>
<li><strong>Build</strong> işlemi sonucu çıktıların farklı bir klasöre taşınması sağlanabilir. <em>(Ki bu klasör pek çok projenin ortaktaşa kullandığı bir assembly için paylaşımdaki bir makine bile olabilir)</em></li>
<li>Çıktıların sıkıştırılması istendiği bir durumda ele alınabilir.</li>
<li>İnşa işleminin birden fazla <strong>Process’</strong> e bölünerek daha hızlı tamamlanması istendiği durumlarda değerlendirilebilir. <em>(Özellikle Enterprise çözümlerde, n sayıda Branch’ in ve dolayısıyla çıktının söz konusu olabileceği senaryolarda, uzun sürebilecek Build işlemleri için kritik bir özelliktir)</em></li>
<li><strong>MSBuild 64bitlik </strong>bir sistem için inşa işlemini icra edebilir.</li>
<li><strong>Build</strong> işleminin herhangibir noktasında harici bir aracın kullanılması istendiği hallerde göz önüne alınabilir.</li>
</ul>
<p>ve benzeri pek çok durumda <strong>MSBuild</strong>’ u açık bir şekilde özelleştirerek kullanabiliriz.</p>
<h1>Proje Dosyasının İçine Bakalım</h1>
<p>Hızlı bir şekilde uygulama geliştirme işine giren pek çok yazılımcı çoğunlukla <strong>MSBuild </strong>gibi programların ürettiği çıktıları göz ardı etmektedir. Nasıl olsa binlerce dolar verilerek satın alınan <strong>Visual Studio </strong>bizim yerimize pek güzel bu işi halletmektedir. Ancak gerçek hayatta öyle vakalar ve senaryolara vuku bulmaktadır ki, bunların üstesinden gelebilmek için özelleştirmelere gidilmesi şart olmaktadır. Bu özelleştirme konsepti <strong>MSBuild </strong>tarafı için de geçerlidir. Bu sebepten proje dosyalarının içeriğinin az da olsa bilinmesi en azından şema yapısının anlaşılması yararlıdır. Tipik olarak bir <strong>Console </strong>uygulaması dahi açsak, üretilen proje dosyası içerisinde<em>(ki örneğimiz <strong>csproj </strong>uzantılı olandır)</em> aşağıdakine benzer bir içerik oluştuğu görülecektir.</p>
<pre class="brush:xml;auto-links:false;toolbar:false" contenteditable="false"><?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{21E86FBF-5A78-4175-8522-A6FC854BB637}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>ConsoleApplication33</RootNamespace>
<AssemblyName>ConsoleApplication33</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project></pre>
<p>Bu <strong>XML</strong> içeriğinin şema yapısına bakıldığında aşağıdaki grafikte görülen iskeletin söz konusu olduğu görülecektir.</p>
<p><a href="https://www.buraksenyurt.com/pics/msbuild_2.png"><img style="margin: 4px 0px; display: inline;" title="msbuild_2" src="/pics/msbuild_2_thumb.png" alt="msbuild_2" width="331" height="595" /></a></p>
<p>Aslında içerik okunduğunda, <strong>Visual Studio</strong> <strong>Proje</strong> <strong>Özelliklerinden</strong> de ayarladığımız pek çok öğenin buraya yazıldığı görülebilir. Örneğin <strong>PropertyGroup</strong> elementlerinde <strong>Debug</strong>, <strong>Debug-Any CPU</strong> ve <strong>Release-Any CPU</strong> için bazı atamalar söz konusudur.</p>
<p><strong>Debug</strong> ile alakalı <strong>PropertyGroup</strong>’ a bakıldığında uygulamanın vereceği çıktının <strong>exe</strong> olacağı,<strong> .Net</strong> <strong>Framework 4.5</strong> platformunu hedef aldığı, <strong>Assembly</strong> adının <strong>ConsoleApplication33</strong> olduğu ve buna bağlı olarak da <strong>Root</strong> <strong>Namespace’</strong> in yine <strong>ConsoleApplication33</strong> şeklinde set edildiği görülebilir. <strong>Condition</strong> niteliklerinde belirtilen kısımlar, <strong>MSBuild</strong> uygulamasına bazı kriterlere göre nasıl çıktı üretmesi gerektiğini de söylemektedir. Örneğin uygulama <strong>Release</strong> modda inşa edildiğinde, çıktının<strong> bin\Release</strong> klasörüne doğru yapılması gerektiği yine bir <strong>PropertyGroup</strong> içerisinde ifade edilmiştir.</p>
<blockquote>
<p>Condition niteliklerinde kullanılan $ notasyonu mutlaka dikkatinizi çekmiştir. Aslında burada $[PropertyName] şeklinde bir kullanım söz konusudur. Burada inanılmaz geniş bir esneklik vardır.</p>
<p>Örneğin $(registery:Hive\SomeKey\SomeSubKey@Value) gibi bir ifade ile Registery’ deki bir değeri okuyabilir ve Build içerisinde kullanabiliriz. Ya da $([System.DateTime]::Now.ToString("yyyy.MM.dd")) gibi bir kullanım ile o anki zamanı istediğimiz formatta elde edebiliriz vb…</p>
<p>[PropertyName] yerine gelecek MSBuild özelliklerinin neler olabileceğini <a href="http://msdn.microsoft.com/en-us/library/ms171458.aspx">MSDN adresinden</a> öğrenebilirsiniz.</p>
</blockquote>
<p><strong>ItemGroup</strong> elementleri içerisine bakıldığında, uygulamanın referans ettiği diğer <strong>Assembly’</strong> ların adları, <strong>Compile</strong> işlemi sırasında derlemeye tabi olacak <strong>C#</strong> dosyaları gibi bilgiler yer almaktadır. <strong>Visual Studio’</strong> nun ürettiği <strong>XML</strong> içeriğine bakıldığında, son kısımda yorum satırları içerisine dahil edilmiş <strong>Target</strong> isimli bir element daha olduğu görülmektedir. Bu elementi kullanarak <strong>MSBuild</strong> için bazı <strong>Task’</strong> lar tanımlanabilir ve inşa işlemi sırasında devreye girmeleri sağlanabilir.</p>
<p><strong>Task</strong> olarak yapılan tanımlamalar paylaşılabilir ve farklı geliştirme <strong>Build’</strong> larında da kullanılabilir. Bu yüzden bir yazılım evinin <strong>Build</strong> işlemlerinde standart olarak gerçekleştirdiği bazı yürütmeler, <strong>Task</strong> olarak tanımlanıp ilgili <strong>Build</strong> paketlerine gömülebilir. Ayrıca <strong>Task’</strong> lar <strong>Reusable</strong> özelliği taşımaktadır. <em>(<strong>Target</strong> elementleri genellikle yazıldıkları sırada çalışmaktadır. Yani belirli bir sırada icra edilmesi istenen <strong>Task’</strong> lar var ise, <strong>Target</strong> elementinin buna uygun olacak şekilde kullanılması gerekir)</em></p>
<blockquote>
<p>Schema yapısı bu kadar basit değildir. Kullanılabilecek tüm elementler için <a href="http://msdn.microsoft.com/en-us/library/5dy88c2e.aspx">MSDN üzerindeki şu adrese gitmenizi</a> öneririm.</p>
</blockquote>
<h1>Klavye Başına</h1>
<p>Yazımızın bu bölümünde basit bir örnek geliştirmeye çalışıyor olacağız. Amacımız temel seviyede <strong>MSBuild</strong> aracını kullanmak ve konsepti anlamaya çalışmak olacaktır. İlk olarak basit bir <strong>C#</strong> koduna ihtiyacımız var. Bu amaçla örneğin <strong>C:\Samples\HowToMSBuild\</strong> isimli klasör altında, aşağıdaki içeriğe sahip bir <strong>C#</strong> dosyası oluşturduğumuzu düşünelim.</p>
<p><a href="https://www.buraksenyurt.com/pics/msbuild_3.png"><img style="margin: 4px 0px; display: inline;" title="msbuild_3" src="/pics/msbuild_3_thumb.png" alt="msbuild_3" width="596" height="451" /></a></p>
<p>Bu adımdan sonra yine <strong>Notepad2</strong> aracını kullanarak aşağıdaki içeriğe sahip bir <strong>csproj</strong> dosyası üreterek devam edelim.</p>
<pre class="brush:xml;auto-links:false;toolbar:false" contenteditable="false"><Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Compile Include="MSBuildHowTo.cs" />
</ItemGroup>
<Target Name="Build">
<Csc Sources="@(Compile)"/>
</Target>
</Project></pre>
<p><strong>Project</strong> içerisinde bir adet <strong>ItemGroup</strong> ve <strong>Target</strong> elementi yer almaktadır. <strong>ItemGroup</strong> içerisinde yer alan <strong>Compile</strong> elementi, <strong>Include</strong> <strong>niteliğinde<em>(attribute)</em></strong>, derleme işlemine tabi olacak dosyayı belirtmektedir. <strong>Target</strong> altındaki <strong>Csc</strong> elementinin <strong>Sources</strong> niteliğinde ise <strong>Compile</strong> isimli bir komut yer almaktadır. Dolayısıyla bu <strong>Task</strong>, <strong>MSBuild</strong> aracına, <strong>Compile</strong> elementine dahil edilen dosyanın derlenmesi gerektiğini söylemektedir.</p>
<p>Bu içeriği <strong>Builder.csproj</strong> adı ile kaydettikten sonra ise sıradaki operasyon, <strong>MSBuild</strong> komut satırı aracını kullanarak inşa işlemini yürüttürmektir. Bunun için <strong>MSBuild’</strong> u aşağıdaki gibi kullanabiliriz.</p>
<p><strong>msbuild Builder.csproj /t: Build /verbosity: detailed</strong></p>
<p><a href="https://www.buraksenyurt.com/pics/msbuild_5.png"><img style="margin: 4px 0px; display: inline;" title="msbuild_5" src="/pics/msbuild_5_thumb.png" alt="msbuild_5" width="642" height="698" /></a></p>
<p>Görüldüğü gibi çalışma sonrasında <strong>MSBuildHowTo</strong> isimli bir <strong>exe</strong> dosyası oluşmuştur. Söz konusu <strong>exe</strong> dosyasını doğrudan çalıştırdığımızda ise, <strong>pre-precessor</strong> direktifi dışında kalan kod parçasının yürütüldüğü gözlemlenecektir.</p>
<blockquote>
<p>MSBuild özellikle kurulu olan .Net Framework versiyonuna bağlı olaraktan Microsoft.Net\Framework\vX.X.XXXXX altında yer almaktadır. Örneğin ben kendi sistemimde aşağıdaki klasörde yer alan sürümü kullandım.</p>
<p><a href="https://www.buraksenyurt.com/pics/msbuild_4.png"><img style="margin: 4px 0px; display: inline;" title="msbuild_4" src="/pics/msbuild_4_thumb.png" alt="msbuild_4" width="374" height="171" /></a></p>
<p>Bunu sistem’ de Path olarak belirtebiliriz ama dilerseniz doğrudan Visual Studio Command Prompt’ tan da yararlanabiliriz.</p>
</blockquote>
<h1>CSPROJ İçeriğini Genişletelim</h1>
<p>Şimdi <strong>csproj</strong> dosyasının içeriğini biraz daha genişletelim ve aşağıdaki hale getirelim.</p>
<pre class="brush:xml;auto-links:false;toolbar:false" contenteditable="false"><Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<AssemblyName>MSBuildHowTo</AssemblyName>
<OutputPath>Bin\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Include="MSBuildHowTo.cs" />
</ItemGroup>
<Target Name="Build">
<MakeDir Directories="$(OutputPath)" Condition="!Exists('$(OutputPath)')" />
<Csc Sources="@(Compile)" OutputAssembly="$(OutputPath)$(AssemblyName).exe" />
</Target>
</Project></pre>
<p>Bu sefer <strong>PropertyGroup</strong> içerisinde <strong>assembly</strong> adını<em><strong>(AssemblyName elementi)</strong></em> ve <strong>build</strong> işlemi sonrası ortaya çıkacak olan çıktının konuşlandırılacağı klasörü de belirttik<em><strong>(OutputPath)</strong></em>. Diğer yandan bu örneğimizde yer alan en önemli kısım <strong>Build </strong>isimli <strong>Target</strong> elementinin içeriğidir. Dikkat edilecek olursa ilk sırada <strong>MakeDir</strong> isimli element yer almaktadır. Burada <strong>$(OutputPath) </strong>ile çıktının yapılacağı klasör işaretlenirken aslında <strong>PropertyGroup>OutputPath </strong>elementinin içeriği ifade edilmektedir. Önemli olan kısım ise <strong>Condition</strong> niteliğinde yazılan değerdir. <strong>!Exists(‘$(OutputPath)’)</strong> ifadesi ile şu söylenmektedir. <strong>“OutputPath yoksa…”</strong>. Buna göre eğer <strong>Condition</strong> sağlanırsa, <strong>MakeDir</strong> <strong>OutputPath</strong>’ in oluşturulması gerektiğini belirtecektir.</p>
<p><strong>Csc</strong> elementinde ise derleme işlemi için kullanılacak olan kaynak <strong>Sources</strong> elementi ile ifade edilirken, aslında <strong>ItemGroup</strong> içerisindeki <strong>Compile</strong> elementinde yer alan <strong>Include</strong> niteliğinin değeri işaret edilmektedir. <strong>OutputAssembly</strong> niteliğine atanan değer ise, <strong>OutputhPath</strong> özelliğinin belirttiği klasörün altına <strong>AssemblyName’</strong> in işaret ettiği isimle bir <strong>exe</strong> üretilmesi gerektiğini belirtmektedir. Buna göre komut satırından yapılan <strong>MSBuild</strong> çağrısı sonucu aşağıdaki gibi olacaktır.</p>
<p><strong>msbuild Builder.csproj /t: Build /verbosity: detailed</strong></p>
<p><a href="https://www.buraksenyurt.com/pics/msbuild_6.png"><img style="margin: 4px 0px; display: inline;" title="msbuild_6" src="/pics/msbuild_6_thumb.png" alt="msbuild_6" width="639" height="782" /></a></p>
<p>Oldukça zevkli öyle değil mi? <img class="wlEmoticon wlEmoticon-smile" style="border-style: none;" src="/pics/wlEmoticon-smile_91.png" alt="Smile" /></p>
<h1>Target Belirtmek</h1>
<p>Öyleyse gelin olayı biraz daha genişleterek devam edelim.</p>
<pre class="brush:xml;auto-links:false;toolbar:false" contenteditable="false"><Project DefaultTargets="Build" xmlns=" http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<AssemblyName>MSBuildHowTo</AssemblyName>
<OutputPath>Bin\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Include="MSBuildHowTo.cs" />
</ItemGroup>
<Target Name="Build">
<MakeDir Directories="$(OutputPath)" Condition="!Exists('$(OutputPath)')" />
<Csc Sources="@(Compile)" OutputAssembly="$(OutputPath)$(AssemblyName).exe" />
</Target>
<Target Name="Clean" >
<Delete Files="$(OutputPath)$(AssemblyName).exe" />
</Target>
<Target Name="Rebuild" DependsOnTargets="Clean;Build" />
</Project></pre>
<p>Bu seferki çalışmada <strong>3 adet</strong> <strong>Target</strong> elementi söz konusudur. Ancak her birinin <strong>Name</strong> niteliğinin değerleri farklıdır. Buna göre, <strong>Build, Clean</strong> ve <strong>Rebuild</strong> isimli <strong>Target’</strong> lar olduğunu ve aslında bunların <strong>3 ayrı Task</strong>’ ı ifade ettiğini düşünebiliriz. Yani <strong>MSBuild</strong> aracını kullanırken <strong>/t: [TargetNameValue]</strong> şeklinde bir yaklaşım ile, istediğimiz <strong>Target’</strong> ın yürütülmesini sağlayabiliriz. Söz gelimi;</p>
<p><strong>msbuild Builder.csproj /t: Clean /verbosity: detailed</strong></p>
<p>şeklinde yapılan çağrı sonucunda, proje dosyasındaki <strong>Target</strong> elementlerinden <strong>Clean</strong> isimli olanı çalıştırılacaktır. Bu elementte ise <strong>Delete</strong> isimli bir alt element yer almakta olup <strong>Files</strong> niteliğinde belirtilen kritere göre, <strong>Bin</strong> klasöre altında <strong>assembly</strong> adı ile duran <strong>exe</strong> dosyasının silinmesi gerektiği ifade edilmektedir.</p>
<p><a href="https://www.buraksenyurt.com/pics/msbuild_7.png"><img style="margin: 4px 0px; display: inline;" title="msbuild_7" src="/pics/msbuild_7_thumb.png" alt="msbuild_7" width="638" height="547" /></a></p>
<p>Eğer <strong>Rebuild</strong> takısını kullanırsak bu durumda <strong>Target->Name</strong> niteliği <strong>Rebuild</strong> olan bölüm devreye girecektir. Bu vakada dikkat edilmesi gereken ise <strong>DependsOnTargets</strong> niteliği içerisinde yazılan <strong>Clean;Build</strong> ifadesidir. Yani şunu ifade etmiş oluruz;</p>
<blockquote>
<p><strong>Ey MSBuild!…Önce Clean isimli Target, sonrasında ise Build isimli Target içeriğini icra et</strong></p>
</blockquote>
<p>ki bu durumda <strong>Bin</strong> klasörü içeriği silinecek ve tekrardan bir derleme işlemi yapılarak, orada ilgili <strong>exe</strong> çıktısının üretilmesi sağlanacaktır.</p>
<p><strong>msbuild Builder.csproj /t: Rebuild /verbosity: detailed</strong></p>
<p><a href="https://www.buraksenyurt.com/pics/msbuild_8.png"><img style="margin: 4px 0px; display: inline;" title="msbuild_8" src="/pics/msbuild_8_thumb.png" alt="msbuild_8" width="638" height="785" /></a></p>
<p>Örnekler daha da çoğaltılabilir. Yapılabilecek pek çok şey var <img class="wlEmoticon wlEmoticon-winkingsmile" style="border-style: none;" src="/pics/wlEmoticon-winkingsmile_189.png" alt="Winking smile" /> Bunun için mutlaka <strong>MSDN</strong> orjinli bir kaynağa başvurmanızı veya yazımızın sonunda belirttiğimiz tarzdaki bir kitabı tedarik etmenizi öneririm. Ancak temel mantığı ifade edebildiğimizi varsayıyorum. Bundan sonrasında <strong>Condition’</strong> lara ve kullanılabilecek <strong>element/attribute</strong> tiplerine bakılması yeterli olur düşüncesindeyim.</p>
<h1>.Net Framework 4.5 ile Gelen Yenilikler</h1>
<p><strong>MSBuild</strong> ürününe <strong>Framework 4.5</strong> sürümü ile birlikte bazı geliştirmeler ve yeni özellikler de katılmıştır. Henüz inceleme fırsatı bulamadığım bu özellikleri aşağıdaki maddeler ile özetleyebiliriz.</p>
<ul>
<li><strong>ARM<em>(Advanced RISC Machine)</em></strong> desteği gelmiştir. Yani <strong>Build</strong> çıktıları <strong>ARM</strong> işlemcilerini hedef alacak şekilde üretilebilir.</li>
<li>Bir <strong>Task</strong><em> (Target elementi ile belirtilen bir görev diyelim)</em> süreç dışı<em><strong>(Out of Process)</strong></em> modda çalışmaya zorlanabilir.</li>
<li>Yeni bazı <strong>XML</strong> <strong>element</strong> ve <strong>nitelikleri<em>(Attributes)</em></strong> gelmiştir.</li>
<li>Klasik bir cümle olacak ama, <strong>Performans<em>(Performance)</em></strong> ve <strong>Ölçeklendirme<em>(Scabilitiy)</em></strong> noktasında iyileştirmeler vardır <img class="wlEmoticon wlEmoticon-smile" style="border-style: none;" src="/pics/wlEmoticon-smile_91.png" alt="Smile" /></li>
</ul>
<blockquote>
<p>MSBuild’ un etkili kullanımı üzerine geliştirilmiş bazı araçlar da vardır. Görsel arabirimleri olan bu araçlar yardımıyla MSBuild akışlarını daha kolay yönetebiliriz. Attrice firmasının bu alanda ön plana çıkan <a href="http://www.attrice.info/msbuild/index.htm">Microsoft Build Sidekick</a> isimli ürünü gibi.</p>
</blockquote>
<h1>Öneri Kitap</h1>
<p><a href="https://www.buraksenyurt.com/pics/msbuild_1.jpg"><img style="float: left; margin: 4px 0px; display: inline;" title="msbuild_1" src="/pics/msbuild_1_thumb.jpg" alt="msbuild_1" width="129" height="160" align="left" /></a><strong>Microsoft</strong>’ un <strong>Visual Studio</strong> ailesi ve geliştirme platformu oldukça geniş bir alana yayılmakta olup, pek çok notkasında uzmanlık gerektiren yapılar içermektedir. Bu sebepten söz konusu yapılara yönelik pek çok yayın da<em>(kitap, official site, blog vb) </em>mevcuttur.</p>
<p>Örneğin <strong>MSBuild</strong> tarafında daha önceden yayınlanmış olan <strong>Inside The Microsoft Build Engine</strong> isimli kitabın <strong>Nisan </strong>ayı içerisinde yayınlanan yeni bir tamamlayıcı baskısı mevcuttur. Yaklaşık olarak 120 sayfalık bir kitap olmasına rağmen odaklandığı konu özünde <strong>MSBuild </strong>ürünüdür. Kitaba <a href="http://www.amazon.com/Supplement-Inside-Microsoft%C2%AE-Build-Engine/dp/0735678162/ref=sr_1_1?s=books&ie=UTF8&qid=1361775657&sr=1-1&keywords=msbuild">Amazon üzerinden bu adres yardımıyla</a> erişebilirsiniz.</p>
<p>Böylece geldik bir yazımızın daha sonuna. Bu yazımızda kısada olsa, <strong>MSBuild</strong> platformunu ve <strong>XML</strong> tarafındaki <strong>betikleri<em>(Scripts)</em></strong> anlamaya çalıştık. Ağırlıklı olarak bir inşa sürecine müdahale edebildiğimizi, bunun için platformun sunduğu bazı standart element ve niteliklerin olduğunu gördük. Devamı sizde artık <img class="wlEmoticon wlEmoticon-smile" style="border-style: none;" src="/pics/wlEmoticon-smile_91.png" alt="Smile" /> Bir başka yazımızda görüşünceye dek hepinize mutlu günler dilerim.</p>
<p><span style="color: #ff0000;">[Orjinal Yazım Tarihi – 25/02/2013]</span></p>
<p><a href="http://blogs.msdn.com/b/visualstudio/archive/2013/07/24/msbuild-is-now-part-of-visual-studio.aspx" target="_blank"><span style="color: #ff0000;">[Güncel bilgi –> MS Build is now part of Visual Studio!]</span></a></p>2013-08-01T07:47:00+00:00microsoft build enginebuildcompilexmlproject filecommand promptvisual studioplatformteam foundation buildbuild serverbuild servicec#c# projectproject propertiesbsenyurtMicrosoft Build Engine aslında başlı başına bir platformdur. Kısaca MSBuild olarak anılmaktadır ve bir uygulamanın inşa edilmesi noktasında devreye giren XML(eXtensible Markup Language) tabanlı bir Script bütününü esas alır. Kısacası uygulamanın inşa edilmesi sırasındaki aşamalar XML tabanlı bir akış olarak ifade edilebilmektedir. MSBuild platformunun en önemli özelliği ise, inşa sürecinde Visual Studio gibi bir araca ihtiyaç duymuyor oluşudur...https://www.buraksenyurt.com/pingback.axdhttps://www.buraksenyurt.com/post.aspx?id=5e3559b5-233e-4292-a01a-fdf89d0ecdb65https://www.buraksenyurt.com/trackback.axd?id=5e3559b5-233e-4292-a01a-fdf89d0ecdb6https://www.buraksenyurt.com/post/Nedir-Bu-MSBuild#commenthttps://www.buraksenyurt.com/syndication.axd?post=5e3559b5-233e-4292-a01a-fdf89d0ecdb6https://www.buraksenyurt.com/post/Text-Template-and-VSIX-Project-TemplateText Template ve VSIX Project Template Kullanımı2012-07-17T08:04:00+00:00bsenyurt<p><span style="color: #ff0000;">[Aşağıdaki örnek Visual Studio 2012 RC sürümü üzerinde ele alınmıştır]</span></p>
<p><a href="https://www.buraksenyurt.com/pics/deadline.jpg"><img style="margin: 4px 0px; display: inline; float: right;" title="deadline" src="/pics/deadline_thumb.jpg" alt="deadline" width="300" height="223" align="right" /></a>Merhaba Arkadaşlar,</p>
<p>Çoğu zaman geliştiricilerin karşısına zaman kısıtı olan projelerde, sıklıkla tekrar eden çözümsel ihtiyaçlar çıkar. Örneğin, ürünün içerisinde n sayıda ekran kullanıldığını ve bunların aslında belirli bir noktaya kadar bir kaç parametre ile değişen ama standart kod içeriklerine sahip olduğunu düşünün. Hatta bu tip ekranları bir kaç proje için aynı şekilde ürettiğinizi.</p>
<p>Yazılımcılar bu gibi durumlarda yükü azaltmak ve özellikle Deadline sürelerini eritmek adına, parçaları otomatik olarak üreten kodlar ile çözümleme yoluna gitmeye gayret ederler. Bir başka deyişle <strong>otomatik kod üreticilerini(Auto Code Generator)</strong> yazmak için çaba gösterirler. Bu oldukça etkili ve önemli bir yaklaşımdır. Tekrarlı işleri azaltmakla kalmaz, aynı zamanda yeniden yapılması gereken üretimlerde veya toplu güncellemelerde işleri merkezi bir noktadan kolaylaştırır.</p>
<p>Ancak yazılımcıların bu gibi ihtiyaçlarda yine de yaptıkları bazı temel hatalar vardır. Söz gelimi dosya üretme ve devreye alma işlemlerini yapmak için herşeyi sıfırdan yazma yoluna gidebilirler. Oysaki kullanılan geliştirme ortamlarının bu gibi noktalarda ürettikleri bazı kolaylaştırıcı çözüm yolları da bulunmaktadır. Söz gelimi <strong>Visual Studio</strong> tarafından bakıldığında, <strong>Text Template</strong>' ler kod dosyalarının otomatik üretiminde kullanılabilir. Hatta <strong>Visual Studio SDK</strong> ile birlikte gelen <strong>VSIX</strong> <strong>Project Template</strong>' ler ile bu gibi üretimlerin birer <strong>Extension</strong> olarak şablonlaştırılması da mümkündür.</p>
<p>İşte bu yazımızda bu tip bir ihtiyacı göz önüne alarak <strong>Text Template</strong> ve bununla ilişkili <strong>VSIX Project Template</strong> üretimi işinin içerisinde yer almaya çalışıyor olacağız. <strong>Text Template</strong> ve <strong>VSIX</strong> <strong>Project Template</strong> öğeleri ile ilişkili teknik detayları <strong><a href="http://msdn.microsoft.com/en-us/library/dd885119" target="_blank">MSDN</a></strong>’ de bulabilirsiniz. Biz bu yazımızda çok daha basit bebek adımları ile ilerleyerek çözüme ulaşmaya çalışacak ve adımlarımız arasında, aslında neleri yapıp neleri elde ettiğimizi göreceğiz.</p>
<p>İşe ilk olarak <strong>Class Library</strong> projesi oluşturup, <strong>Text Template</strong> tipinden bir öğeyi içeri dahil ederek başlayabiliriz.</p>
<p><a href="https://www.buraksenyurt.com/pics/tutorialtt1.png"><img style="margin: 4px 0px; display: inline;" title="tutorialtt1" src="/pics/tutorialtt1_thumb.png" alt="tutorialtt1" width="524" height="411" /></a></p>
<p>Öğemize <strong>DbClassTemplate</strong> ismini verebiliriz. <strong>TT(Text Template)</strong> uzantılı olan bu dosya aslında metinsel içerik ile <strong>C#/Vb.Net</strong> tabanlı kod parçalarını bir arada ele alıp üretimi gerçekleştirmek üzere kullanılmaktadır. <strong>Visual Studio</strong> ile entegre çalışmakta olup yaptığımız her <strong>Save</strong> işlemi sonrası bir üretim gerçekleşmektedir. Söz konusu dosyanın içeriğini ise aşağıdaki gibi oluşturduğumuzu düşünelim.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false"><#@ template debug="True" hostspecific="True" language="C#" #>
<#@ output extension=".cs" #>
<#@ Assembly Name="System.Data" #>
<#@ Import Namespace="System.Data.SqlClient" #>
<#@ Import Namespace="System.Data" #>
<#@ Import Namespace="System.Text" #>
// Özet :Bu dosya içerisinde seçilen veritabanı içerisindeki tablolara eş düşen birer sınıf söz konusudur
// Yazan :Unknown Developer
// Yazım tarihi :Uzay Tarihi 2012
<#
var connectionString = "data source=.;database=Chinook;integrated security=SSPI;MultipleActiveResultSets=True";
var builder = new StringBuilder();
var dbName = "Chinook";
using (SqlConnection connection = new SqlConnection(connectionString))
{
var commandTables = new SqlCommand("select object_id,name from sys.tables where type='U' order by name",connection);
var commandColumns = new SqlCommand("select C.name, (select top 1 name from sys.types T where T.system_type_id=C.system_type_id) as TypeName from sys.columns C where object_id=@ObjectId order by C.name",connection);
commandColumns.Parameters.Add("@ObjectId", SqlDbType.Int);
connection.Open();
SqlDataReader readerTables = commandTables.ExecuteReader();
while (readerTables.Read())
{
builder.AppendLine(string.Format("\tpublic class {0}", readerTables["name"].ToString()));
builder.AppendLine("\t{");
commandColumns.Parameters["@ObjectId"].Value = Convert.ToInt32(readerTables["object_id"]);
SqlDataReader readerColumns = commandColumns.ExecuteReader();
while (readerColumns.Read())
{
// Bu kısımda daha etkili bir tip dönüşüm fonksiyonelliği kullanılmalıdır.
string dbType=readerColumns["TypeName"].ToString();
string dotNetType = "object";
if (dbType.Contains("varchar") || dbType.Contains("text")) dotNetType = "string";
if (dbType.Contains("int") || dbType == "number" || dbType=="numeric") dotNetType = "int";
if (dbType == "decimal" ||dbType == "money") dotNetType = "decimal";
if (dbType.Contains("date") || dbType.Contains("Date")) dotNetType = "DateTime";
if (dbType.Contains("binary")) dotNetType = "byte[]";
builder.AppendLine(string.Format("\t\tpublic {0} {1}{{get;set;}}", dotNetType, readerColumns["name"].ToString()));
}
readerColumns.Close();
builder.AppendLine("\t}");
}
readerTables.Close();
}
#>
using System;
using System.Linq;
namespace <#= dbName #>
{
<#= builder.ToString() #>
}</pre>
<p>Şimdi bu kod parçasında ne yaptığımıza bir bakalım.</p>
<p><strong><#@ </strong>ile başlayıp biten kısımlarda, üretimi yapılacak olan çıktıya ve TT dosyası içeriğine ait bir takım bilgiler vermekteyiz. Örneğimizde çıktının <strong>cs</strong> uzantılı bir <strong>CSharp</strong> dosyası olacağı belirtiliyor. Bunun dışında <strong>System.Data Assembly'</strong> ının çıktının bulunacağı yerde var olması gerektiği ifade ediliyor. Ayrıca kod içerisinde kullanılacak olan<strong> isim alanları(Namespaces)</strong> da belirtiliyor.</p>
<p><strong><#</strong> ile başlayıp biten kısımların haricinde kalan bölümler, tipik olarak çıktı dosyası içerisine yazılan metinsel bilgiler olarak da düşünülebilirler. Her ne zaman bir kod parçasını çalıştırmak istersek, <strong><#</strong> ile başlayan blokları ele almamız gerekmektedir.</p>
<p>Örneğimizde yer alan ilk bloğun yaptığı iş, veritabanına bağlanıp <strong>Chinook</strong> tablolarını ve bu tablolara ait kolonların karşılığı olan <strong>class</strong> ve <strong>property</strong> içeriklerini üretmektir. Bu amaçla içeride <strong>StringBuilder</strong> tipinden yararlanıldığı görülmektedir. Yanlız şu kod parçasına dikkat etmeliyiz <img class="wlEmoticon wlEmoticon-sarcasticsmile" style="border-style: none;" src="/pics/wlEmoticon-sarcasticsmile_5.png" alt="Sarcastic smile" /></p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
using System.Linq;
namespace <#= dbName #>
{
<#= builder.ToString() #>
}</pre>
<p>Burada <strong><#=builder.ToString()#></strong> yazan kısmın yerine, yukarıdaki kod parçasının içerisinde kullanılan <strong>builder</strong> isimli <strong>StringBuilder</strong> değişkeninin çıktısı yerleştiriliyor olacaktır. Hatta <strong>dbName</strong> değişkeni de <strong>namespace</strong> adı olarak alınmaktadır. Geri kalan kısımlar sabit metinsel bilgilerdir.</p>
<p>Dosyamızı bu haliyle kayıt ettiğimizde, <strong>Visual Studio IDE</strong>' si otomatik olarak içeriği çalıştıracak ve bir <strong>C#</strong> kod dosyasını üreterek içeriğini aşağıdaki şekilde görülen hale getirecektir.</p>
<p><a href="https://www.buraksenyurt.com/pics/tutorialtt2.png"><img style="margin: 4px 0px; display: inline;" title="tutorialtt2" src="/pics/tutorialtt2_thumb.png" alt="tutorialtt2" width="301" height="673" /></a></p>
<p>Dikkat edileceği üzere <strong>Chinook </strong>veritabanında yer alan tablolara karşılık gelen sınıf dosyaları üretilmiş olup, <strong>Column’</strong> ların veri tiplerine göre de uygun <strong>Property’</strong> ler ilgili tipler içerisine dahil edilmiştir. Artık elimizde <strong>cs</strong> tabanlı otomatik olarak üretilmiş bir içerik mevcuttur. Bu haliyle de içeriği herhangibir <strong>.Net</strong> projesine ekleyip kullanabilme şansına sahibiz.</p>
<p>Şu anda yapmak istediğimiz ise söz konusu<strong> Text Template</strong> içeriğini ve üretimini bir <strong>Extension</strong> haline getirmektir. Bu sayede bu TT öğesini herhangibir projeye ekleyebilir ve gerekli otomatik üretimleri yaptırtabiliriz. Tabi bu yapının parametrik olarak çalışması çok daha önemlidir. Nitekim geliştiriciler üretimini yapacakları veritabanına ait Connection String bilgisini isterlerse seçebilmelidir. Şimdi yazımızın ikinci kısmını ele almaya başlayabiliriz <img class="wlEmoticon wlEmoticon-winkingsmile" style="border-style: none;" src="/pics/wlEmoticon-winkingsmile_99.png" alt="Winking smile" /></p>
<p>Bu amaçla ilk olarak <strong>File</strong> menüsünden <strong>Export Template</strong> seçeneğini işaretleyip <strong>DbClassGenerator’</strong> ü sıkıştırılmış bir paket haline getirmemiz gerekmektedir. Söz konusu paketin üretimi sırasında <strong>Visual Studio</strong> bir <strong>Wizard</strong> yardımıyla bizden bir kaç adımı tamamlamamızı isteyecektir. Söz konusu adımları aşağıdaki sırayla icra edebiliriz.</p>
<p>Adım 1de Item Template seçimi yapılabilir. Nitekim TT’ mizi bir proje öğesi olarak kullandırtmak istiyoruz.</p>
<p><a href="https://www.buraksenyurt.com/pics/tutorialtt3.png"><img style="display: inline;" title="tutorialtt3" src="/pics/tutorialtt3_thumb.png" alt="tutorialtt3" width="517" height="537" /></a></p>
<p>Adım 2 de paket içerisine almak istediğimiz <strong>Text Tempalte</strong> dosyalarını seçebiliriz.</p>
<p><a href="https://www.buraksenyurt.com/pics/tutorialtt4.png"><img style="margin: 4px 0px; display: inline;" title="tutorialtt4" src="/pics/tutorialtt4_thumb.png" alt="tutorialtt4" width="244" height="234" /></a></p>
<p>3ncü adımda, <strong>Text Template’</strong> in çalışması sonrası ortaya çıkacak ürünün dahil olduğu projenin referans etmesi gereken <strong>Assembly’</strong> lar var ise bunu belirtebiliriz. Örneğimizde temel olan <strong>System</strong> ve <strong>System.Data assembly’</strong> ları seçilmiştir.</p>
<p><a href="https://www.buraksenyurt.com/pics/tutorialtt5.png"><img style="display: inline;" title="tutorialtt5" src="/pics/tutorialtt5_thumb.png" alt="tutorialtt5" width="355" height="301" /></a></p>
<p>4ncü adımda <strong>Template</strong> ile ilişkili isim ve açıklama bilgilerini verip dilersek bir de <strong>Icon</strong> belirleyerek öğemizin görünümünü göz alıcı bir hale getirebiliriz.</p>
<p><a href="https://www.buraksenyurt.com/pics/tutorialtt6.png"><img style="display: inline;" title="tutorialtt6" src="/pics/tutorialtt6_thumb.png" alt="tutorialtt6" width="581" height="464" /></a></p>
<p>Bu işlemleri tamamladığımızda ise aşağıdaki ekran görüntüsünde yer alan sıkıştırılmış dosyanın üretildiğini görmüş olacağız.</p>
<p><a href="https://www.buraksenyurt.com/pics/tutorialtt7.png"><img style="margin: 4px 0px; display: inline;" title="tutorialtt7" src="/pics/tutorialtt7_thumb.png" alt="tutorialtt7" width="543" height="405" /></a></p>
<p>Üretilen dosya adresi bizim için önemlidir nitekim <strong>VSIX Project Template’</strong> de bunu kullanıyor olacağız. Çünkü VSIX projesi ilgili dosyayı alıp kendi içerisine entegre ediyor olacak. Öyleyse Visual C# – Extensibility sekmesinden bir VSIX Project öğesi seçerek ilerlemeye devam edelim.</p>
<blockquote>
<p>Buradaki VSIX Project öğesinin kullanılabilir olması için Visual Studio 2012 SDK’ nın yüklü olması gerektiğini unutmayalım. Aynı durum Visual Studio 2010 sürümü için de geçerlidir.</p>
</blockquote>
<p><a href="https://www.buraksenyurt.com/pics/tutorialtt8.png"><img style="margin: 4px 0px; display: inline;" title="tutorialtt8" src="/pics/tutorialtt8_thumb.png" alt="tutorialtt8" width="640" height="360" /></a></p>
<p>Bu işlem sonrasında <strong>Visual Studio IDE</strong>’ si karşımıza detaylı bir özellik penceresi çıkartacaktır. Bu özellikler temel olarak <strong>vsixmanifest</strong> uzantılı dosya içerisinde bulunmaktadır. <strong>Designer</strong> tarafında ki en önemli kısımlardan birisi de <strong>Assets</strong> bölümüdür. Burada daha önceden <strong>Zip</strong> çıktısı haline getirdiğimiz <strong>Template</strong> içeriğinin işaretlenmesi esasına dayalı bazı seçimler yapmamız gerekmektedir. Örneğimizde bu kısmı aşağıdaki gibi doldurmamız yeterli olacaktır.</p>
<p><a href="https://www.buraksenyurt.com/pics/tutorialtt10.png"><img style="margin: 4px 0px; display: inline;" title="tutorialtt10" src="/pics/tutorialtt10_thumb.png" alt="tutorialtt10" width="640" height="388" /></a></p>
<p><strong>Type</strong> kısmında <strong>ItemTemplate</strong> seçildiği görülmektedir <em>(Template’ i hangi tipte Export ettiğimizi hatırlayın <img class="wlEmoticon wlEmoticon-winkingsmile" style="border-style: none;" src="/pics/wlEmoticon-winkingsmile_99.png" alt="Winking smile" /> ) </em>Kaynak olarak <strong>File on filesystem</strong> seçeneği işaretlenmiştir. <strong>Path</strong> bölümünde zip uzantılı dosyanın lokasyonunun verilmesi yeterli olacaktır. İlgili adres bilgisi verildikten sonra <strong>Asset</strong> kısmına tekrardan girilirse yol bilgisinin artık projedeki <strong>ItemTemplates</strong> klasörünü işaret ettiği gözlemlenebilir. Bunun sebebi ilk adımda seçilen adreste yer alan içeriğin <strong>VSIX</strong> projesine kopyalanmış olmasıdır.</p>
<p><a href="https://www.buraksenyurt.com/pics/tutorialtt11.png"><img style="margin: 4px 0px; display: inline;" title="tutorialtt11" src="/pics/tutorialtt11_thumb.png" alt="tutorialtt11" width="240" height="223" /></a></p>
<p><strong>Manifest</strong> bilgilerini düzenlediğimiz kısımda set ettiğimiz özellikler çok doğal olarak arka plana <strong>XML</strong> tabanlı olarak yazılmaktadır. Sonuç itibariyle <strong>vsixmanifest</strong> dosyasının içeriği de aşağıdaki gibi olabilir.</p>
<pre class="brush:xml;auto-links:false;toolbar:false" contenteditable="false"><?xml version="1.0" encoding="utf-8"?>
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011" xmlns:d="http://schemas.microsoft.com/developer/vsx-schema-design/2011">
<Metadata>
<Identity Id="25970a0b-c664-4112-8739-3e2bbc1fea61" Version="1.0" Language="en-US" Publisher="BurakSenyurt" />
<DisplayName>Db POCO Generator</DisplayName>
<Description>Veritabanı tabloları için otomatik olarak POCO tip üretimi gerçekleştirmek üzere tanımlanmış bir Extension dır.</Description>
</Metadata>
<Installation>
<InstallationTarget Id="Microsoft.VisualStudio.Pro" Version="11.0" />
</Installation>
<Dependencies>
<Dependency Id="Microsoft.Framework.NDP" DisplayName="Microsoft .NET Framework" d:Source="Manual" Version="4.5" />
</Dependencies>
<Assets>
<Asset Type="Microsoft.VisualStudio.ItemTemplate" d:Source="File" Path="ItemTemplates" d:TargetPath="ItemTemplates\Db Class Generator.zip" />
</Assets>
</PackageManifest></pre>
<p>Biz örneğimizde çok basit olarak <strong>Display Name, Description, Id, Version</strong> gibi kısımlara müdahale ettik. Ancak daha ileri seviyede müdahalelerde de bulunabiliriz. Söz gelimi Framework hedef versiyonlarını değiştirebilir ki örnemğizde bu bağımlılık 4.5 sürümüne göre yapılmıştır.</p>
<p>Yaptığımız çalışma sonucu projeyi <strong>build</strong> edersek eğer aşağıdaki gibi <strong>vsix</strong> uzantılı <strong>Extension</strong> <strong>Installer</strong> dosyasının yer aldığı bir sonuca ulaşmış oluruz.</p>
<p><a href="https://www.buraksenyurt.com/pics/tutorialtt12.png"><img style="margin: 4px 0px; display: inline;" title="tutorialtt12" src="/pics/tutorialtt12_thumb.png" alt="tutorialtt12" width="574" height="76" /></a></p>
<p>Bir başka deyişle söz konusu <strong>installer</strong> dosyasını çalıştırıp <strong>template’</strong> imizin <strong>Visual Studio</strong> ortamına entegre edilmesini sağlayabiliriz. Lakin halen eksik olan bir kaç şey bulunmaktadır. Projemizde kullandığımız <strong>Text Template</strong> içerisinde yer alan<strong> Connection String</strong> ve <strong>DbName</strong> gibi bilgiler <strong>hard coded</strong> olarak tutulmaktadır. Oysaki bağlantı bilgisini dışarıdan verebilmiş olsaydık çok daha generic bir proje öğemiz olurdu. Şimdi bu parametreleri dışarıdan nasıl alabileceğimize bir bakalım <img class="wlEmoticon wlEmoticon-winkingsmile" style="border-style: none;" src="/pics/wlEmoticon-winkingsmile_99.png" alt="Winking smile" /></p>
<p>İlk olarak <strong>DbClassGenerator.Design</strong> isimli bir <strong>Windows</strong> uygulaması oluşturalım ve söz konusu projeye aşağıdaki referansları ekleyelim. Bu proje öğeyi eklediğimiz sırada devreye girecek bir arabirimi geliştiricinin karşısına çıkartmak için kullanılacaktır.</p>
<blockquote>
<p>Projenin VSIX dosyasının install edilmesi sırasında devreye girebilmesi için, output olarak C:\Program Files\Microsoft Visual Studio 11.0\Common7\IDE\ adresine çıktı vermesi gerekmektedir. Bu nedenle projenin özelliklerinden Build->Output kısmında ilgili lokasyon bildirilmelidir.</p>
<p>Ayrıca projenin output tipinin Class Library olarak set edilmesi gerekmektedir.</p>
</blockquote>
<p><a href="https://www.buraksenyurt.com/pics/tutorialtt13.png"><img style="margin: 4px 0px; display: inline;" title="tutorialtt13" src="/pics/tutorialtt13_thumb.png" alt="tutorialtt13" width="346" height="236" /></a></p>
<p><strong>EnvDTE</strong> ve <strong>Microsoft.VisualStudio.TemplateWizardInterface assembly’</strong> larının referans edilmesinin ardından, aşağıdaki basit <strong>Windows Forms</strong> tasarımını ve kod içeriğini geliştirerek ilerleyebilir.</p>
<blockquote>
<p>Örneğimizde çok basit bir arabirim söz konusudur. Ancak burada daha kompleks bir Connection String designer’ ı da söz konusu olabilir. Bu tamamen tasarlanan Template’ in kullanacağı parametrelerinin nasıl ve ne şekilde set edileceğine bağlı olarak değişir.</p>
<p>Yine örnekte hata yönetimi çok fazla dikkate alınmamıştır. Zero Data testleri yapılmamıştır. Bu gibi hususları kendi geliştireceğiniz örnek içerisinde dikkatli bir şekilde ele almalısınız.</p>
</blockquote>
<p><a href="https://www.buraksenyurt.com/pics/tutorialtt17.png"><img style="margin: 4px 0px; display: inline;" title="tutorialtt17" src="/pics/tutorialtt17_thumb.png" alt="tutorialtt17" width="465" height="217" /></a></p>
<p> </p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
using System.Windows.Forms;
namespace DbGenerator.Design
{
public partial class Form1
: Form
{
public string ConnectionString { get; set; }
public string NamespaceName { get; set; }
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void btnSet_Click(object sender, EventArgs e)
{
if (!String.IsNullOrEmpty(txtConnectionString.Text))
ConnectionString = txtConnectionString.Text;
if (!string.IsNullOrEmpty(txtDbName.Text))
NamespaceName = txtDbName.Text;
DialogResult = System.Windows.Forms.DialogResult.OK;
}
}
}</pre>
<p>Dikkat edileceği üzere bu basit formdan <strong>TT</strong> içerisindeki parametrelere set edeceğimiz değişken değerlerini almaktayız. Tabi işin önemli kısmı bu pencerenin, öğe <strong>Visual Studio </strong>projesine eklenirken karşımıza çıkmasını sağlamaktır. Bunun için <strong>IWizard</strong> <strong>arayüzünü(interface)</strong> implemente edecek bir sınıfı projemize dahil etmemiz gerekiyor. <strong>GeneratorDesigner</strong> olarak adlandırabileceğimiz sınıfın kod içeriğini ise aşağıdaki gibi geliştirdiğimizi düşünelim.</p>
<p> </p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System.Collections.Generic;
using System.Windows.Forms;
using EnvDTE;
using Microsoft.VisualStudio.TemplateWizard;
namespace DbGenerator.Design
{
public class GeneratorDesigner
:IWizard
{
private bool CanAddProjectItem;
public void RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, WizardRunKind runKind, object[] customParams)
{
Form1 frm = new Form1();
if (frm.ShowDialog() == DialogResult.OK)
{
replacementsDictionary.Add("$connectionString$", frm.ConnectionString);
replacementsDictionary.Add("$dbnameString$", frm.NamespaceName);
}
else
{
// Default bir değer kısımlarına geçerli bir takım bilgiler yazmakta yarar olabilir. Nitekim geçerli bir ConnectionString bilgisi olmaması halinde uygulama hata verecek ve cs dosyaları başarılı bir şekilde üretilmeyecektir.
replacementsDictionary.Add("$connectionString$", "default bir değer");
replacementsDictionary.Add("$dbnameString$", "Default bir değer");
}
CanAddProjectItem = true;
}
public bool ShouldAddProjectItem(string filePath)
{
return CanAddProjectItem;
}
public void BeforeOpeningFile(ProjectItem projectItem)
{
}
public void ProjectFinishedGenerating(Project project)
{
}
public void ProjectItemFinishedGenerating(ProjectItem projectItem)
{
}
public void RunFinished()
{
}
}
}</pre>
<p>IWizard türevli bu sınıf içerisinde basit bir Application Life Cycle söz konusudur aslında. Biz ilk girişte bazı parametrelerin set edilmesi için araya girerek müdahale de bulunuyoruz. Bu nedenle dikkat edileceği üzere RunStarted metodunda, <strong>$ </strong>sembolleri arasında tanımlanmış olan bazı parametrelerin değiştirilmesi işlemi söz konusudur. Bunun için tasarladığımız Windows Form’ una ait bir örnek oluşturulmuş, ardından form içerisine girilen metinsel bilgiler alınarak koleksiyona dahil edilmiştir. Tabi çok doğal şu anda kafamızda bir soru oluşması muhtemeldir. Acaba bu değişkenler nerede tanımlanmalıdır <img class="wlEmoticon wlEmoticon-thinkingsmile" style="border-style: none;" src="/pics/wlEmoticon-thinkingsmile_2.png" alt="Thinking smile" /></p>
<blockquote>
<p>Application Life Cylce içerisindeki metodlara bakıldığında Loglama işlemlerinin de yapılabileceği uygun noktalar olduğu görülmektedir.</p>
</blockquote>
<p>Tahmin edeceğiniz üzere <strong>Text Template</strong> içeriğini kullanan kısım <strong>VSIX</strong> projemizdir. Bu proje <strong>ItemTemplates</strong> klasörüne <strong>zip</strong> olarak ilgili <strong>Template</strong> içeriğini ve dosyalarını indirmiştir. Parametreleri sisteme entegre etmek için bu zip içeriğindeki bazı dosyaları değiştirmemiz şarttır<em>(Ya da en baştan TT’ yi bunu düşünerek tasarlamak gerekmektedir)</em>. İlk olarak <strong>vstemplate</strong> uzantılı dosya içeriğinde aşağıdaki değişiklikleri yapalım.</p>
<pre class="brush:xml;auto-links:false;toolbar:false" contenteditable="false"><VSTemplate Version="3.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="Item">
<TemplateData>
<DefaultName>Db Class Generator.tt</DefaultName>
<Name>Db Class Generator</Name>
<Description>Veritabanı için otomatik POCO Sınıf üretimlerini gerçekleştirir.</Description>
<ProjectType>CSharp</ProjectType>
<SortOrder>10</SortOrder>
<Icon>__TemplateIcon.ico</Icon>
</TemplateData>
<TemplateContent>
<References>
<Reference>
<Assembly>System</Assembly>
</Reference>
<Reference>
<Assembly>System.Data</Assembly>
</Reference>
</References>
<ProjectItem SubType="" TargetFileName="$fileinputname$.tt" ReplaceParameters="true">DbClassTemplate.tt</ProjectItem>
<!--<ProjectItem SubType="Code" TargetFileName="$fileinputname$.cs" ReplaceParameters="true">DbClassTemplate.cs</ProjectItem>-->
</TemplateContent>
<WizardExtension>
<Assembly>DbClassGenerator.Design</Assembly>
<FullClassName>DbClassGenerator.Design.GeneratorDesigner</FullClassName>
</WizardExtension>
</VSTemplate></pre>
<p>3 önemli değişiklik vardır.</p>
<ul>
<li><strong>cs</strong> dosyasının üretimine ait bildirimde bulunan <strong>ProjectItem</strong> elementi kaldırılmıştır.<em>(Örnekte yorum satırı yaptık)</em></li>
<li>İkinci olarak <strong>tt</strong> için kullanılan <strong>ProjectItem</strong> elementindeki <strong>ReplaceParameters</strong> değeri <strong>true</strong> yapılmıştır. Nitekim <strong>$</strong> işaretleri arasına aldığımız parametrelerin değiş tokuş edileceğinin belirtilmesi gerekmektedir.</li>
<li>3ncü ve en önemli değişiklik ise <strong>WizardExtension</strong> bloğunun eklenmiş olmasıdır. Bu blok tahmin edileceği üzere<strong> $</strong> işareti ile belirlenmiş parametrelerin alınması için gerekli arabirimin devreye alınması sırasında rol oynamakta olup, hangi <strong>IWizard</strong> türevli tipin değerlendirileceğini belirtmektedir.</li>
</ul>
<p>Tabi <strong>tt</strong> uzantılı dosyamızda da bazı değişikliklerin yapılması şarttır. Yani <strong>$</strong> işaretli parametrelerin eklenmesi gerekmektedir.</p>
<pre class="brush:xml;auto-links:false;toolbar:false" contenteditable="false"><#
var connectionString = "$connectionString$";
var builder = new StringBuilder();
var dbName = "$dbnameString$";</pre>
<p>Bu son işlemlerden sonra <strong>VSIX</strong> Projesini bir kere daha derlememiz gerekir. <em>(Hatta daha önceden install etmişsek uninstall edip son bir build yapıp tekrardan install etmemiz gerekmektedir) </em>Tüm bu işlemlerin arından <strong>VSIX</strong> dosyasını çalıştırıp template’ in yüklenmesini sağlayabiliriz. Eğer işler yolunda giderse aşağıdaki iki pencereyi görmemiz şu an mutlu olmamız için yeterli olacaktır <img class="wlEmoticon wlEmoticon-openmouthedsmile" style="border-style: none;" src="/pics/wlEmoticon-openmouthedsmile_28.png" alt="Open-mouthed smile" /></p>
<p><a href="https://www.buraksenyurt.com/pics/tutorialtt14.png"><img style="display: inline;" title="tutorialtt14" src="/pics/tutorialtt14_thumb.png" alt="tutorialtt14" width="460" height="338" /></a></p>
<p><a href="https://www.buraksenyurt.com/pics/tutorialtt15.png"><img style="background-image: none; margin: 4px 0px; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="tutorialtt15" src="/pics/tutorialtt15_thumb.png" alt="tutorialtt15" width="464" height="342" border="0" /></a></p>
<p>Şimdi her hangibir proje açalım ve daha sonra<strong> Add New Item</strong> ile ilerleyelim. Listenin en başında gurur kaynağımız olan öğeyi<em>(Db Class Generator)</em> görebiliriz.</p>
<p><a href="https://www.buraksenyurt.com/pics/tutorialtt16.png"><img style="margin: 4px 0px; display: inline;" title="tutorialtt16" src="/pics/tutorialtt16_thumb.png" alt="tutorialtt16" width="640" height="442" /></a></p>
<p>Öğeyi seçtikten sonra ise karşımıza tasarladığımız <strong>Windows Forms</strong> penceresi çıkacaktır. Eğer doğru <strong>Connection String</strong> bilgisini girersek<em>(bu örnekte <strong>MultipleActiveResultSets</strong> değeri için true vermeyi unutmayın)</em> <strong>cs</strong> içeriğinin otomatik olarak üretildiğine şahit olabilirsiniz <img class="wlEmoticon wlEmoticon-smile" style="border-style: none;" src="/pics/wlEmoticon-smile_40.png" alt="Smile" /> </p>
<p>Görüldüğü üzere bir TT projesi VSIX ile bir arada değerlendirildiğinde Visual Studio tarafına Extension yazılması söz konusudur. Biraz uzun ve yorucu bir makale olduğu kadar uygulama sırasında da oldukça dikkat ve titizlik isteyen bir çalışma söz konusudur. Umarım istediğiniz sonuçları sizlerde elde edersiniz. Bir sonraki makalemizde görüşünceye dek hepinize mutlu günler dilerim.</p>
<blockquote>
<p>Size tavsiyem otomatik Windows Forms veya ASP.Net Web Pages ya da MVC öğeleri üretecek bir TT üzerinde çalışmanızdır. Ayrıca bu örnekteki Windows Forms’ u hatalara neden olmayacak ve developer’ ın hayatını daha da kolaylaştıracak şekilde geliştirmeyi ciddi anlamda düşünmelisiniz.</p>
</blockquote>
<p><span style="color: #ff0000;">[Aşağıdaki örnek Visual Studio 2012 RC sürümü üzerinde ele alınmıştır]</span></p>
<p><a href="https://www.buraksenyurt.com/pics/2012%2f7%2fDbClassGenerator.zip">DbClassGenerator.zip (105,75 kb)</a></p>2012-07-17T08:04:00+00:00text templatevisual studio sdkvsix project templatevisual studio 2012bsenyurtAncak yazılımcıların bu gibi ihtiyaçlarda yine de yaptıkları bazı temel hatalar vardır. Söz gelimi dosya üretme ve devreye alma işlemlerini yapmak için herşeyi sıfırdan yazma yoluna gidebilirler. Oysaki kullanılan geliştirme ortamlarının bu gibi noktalarda ürettikleri bazı kolaylaştırıcı çözüm yolları da bulunmaktadır. Söz gelimi Visual Studio tarafından bakıldığında, Text Template' ler kod dosyalarının otomatik üretiminde kullanılabilir. Hatta Visual Studio SDK ile birlikte gelen VSIX Project Template' ler ile bu gibi üretimlerin birer Extension olarak şablonlaştırılması da mümkündür.https://www.buraksenyurt.com/pingback.axdhttps://www.buraksenyurt.com/post.aspx?id=4b48e341-8040-49dd-b4ae-be72ffdb56c82https://www.buraksenyurt.com/trackback.axd?id=4b48e341-8040-49dd-b4ae-be72ffdb56c8https://www.buraksenyurt.com/post/Text-Template-and-VSIX-Project-Template#commenthttps://www.buraksenyurt.com/syndication.axd?post=4b48e341-8040-49dd-b4ae-be72ffdb56c8https://www.buraksenyurt.com/post/VSTS-2008-icin-Custom-Check-In-Policy-GelistirmekVSTS 2008 için Custom Check-In Policy Geliştirmek2009-08-07T12:56:00+00:00bsenyurt<p><img style="float: right;" src="/pics/2009%2f8%2fblg58_Giris.jpg" alt="" />Merhaba Arkadaşlar,</p>
<p>Bir süredir <strong>Team Foundation</strong> <strong>Server</strong> üzerinde ve doğal olarak <strong>Visual Studio Team System 2008</strong> geliştirme ortamında çalışmaktayım. Tabi uzun yıllar <strong>Visual Source Safe</strong> ile vakit geçirmenin sonucunda, <strong>TFS</strong> ile birlikte gelen pek çok nimetin farkına çok geç varabiliyoruz. Herşeyden önce TFS'in, <strong>MSF(Microsoft Solution Framework) </strong>ve <strong>CMMI(Capability Maturity Model Integration)</strong> gibi yazılım geliştirme süreç modellerinin uygulanabildiği profesyonel bir çevre sağladığını bilmemiz gerekiyor.</p>
<p>İşin içerisine <strong>Reporting Services'</strong> ile etkili raporlama, <strong>SharePoint</strong> ile tutarlı, ölçeklenebilir döküman yönetimi gibi pek çok yararlı üründe giriyor. Tabiki bu tip sistemlerin uygulanması her zaman kolay değildir. Her şeyden önce bir öğrenme süreci için geliştirme ekibinin ciddi zaman ayrılması şarttır. Öyleki, model içerisinde <strong>çevik(Agile)</strong> süreçlerin uygulanabilirliği söz konusudur ki bunlarda başlı başlına birer konsepttir.</p>
<p>Biz bu yazımızda <strong>Visual Studio Team System 2008</strong> ile çalışırken, özel <strong>Check-In ilkelerinin(Custom Check-In Policy)</strong> nasıl geliştirilebileceğini basit bir örnek üzerinden ele almaya çalışacağız. Genellikle yazılım projelerinde görev alan geliştiricilerin, en alt kademeden en üst kademeye doğru çıktıkça<strong>(Junior -> Architect)</strong> çok daha az sayıda<strong> Check-In</strong> yaptıkları görülebilir<img title="Wink" src="/editors/tiny_mce3/plugins/emotions/img/smiley-wink.gif" alt="Wink" border="0" /> Bu aslında iyi yazılım geliştirme süreçlerinde bir kural olarak değerlendirilmesi gereken durumlardandır. Söz gelimi bir projenin mesai sonunda eğer derlenemiyorsa Check-In' lenmemesi<em>(ki bunu VSTS üzerinden vereceğiniz hazır bir Policy ile kolayca garantileyebilirsiniz),</em> gün içinde belkide 1 en fazla 2 Check-In yapılmasına izin verilmesi, özellikle versiyon takibi açısından da son derece önemlidir. Peki <strong>VSTS</strong> tarafından bizlere sunulan hazır <strong>Check-In</strong> ilkeleri<strong>(Builds, Code Analysis, Testing Policy, Work Items)</strong> dışında kendi özel politikalarımızı nasıl geliştirebilir ve projeye uygulayabiliriz?</p>
<p>Aslında burada amaç, <strong>VSTS'</strong> in dış ortama sunulan bazı arayüzlerini kullanarak kendisine yeni davranışlar ekleyebilmektir. Yani bir <strong>Plug-In</strong> modeli ile karşı karşıya olduğumuzu düşünebiliriz. Dilerseniz bu fikirden yola çıkalım. İşe ilk olarak basit bir <strong>Class Library</strong> geliştirerek başlamamız gerekiyor. Söz konusu sınıf kütüphanesine, <strong>Microsoft.TeamFoundation.Version.Client</strong> isimli referansın eklenmesi gerekmektedir. Bu referans varsayılan kuruluma göre <strong>C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssemblies</strong> klasörü altında bulunmaktadır. Refernasların eklenmesinin arından, <strong>PolicyBase</strong> isimli tipten türetilen bir sınıfın geliştirilmesi ve bunun içerisinde gerekli üyelerin <strong>ezilmesi(Override)</strong> gerekmektedir.</p>
<p>Örneğimizde, <strong>TFS</strong> üzerindeki bir projeye eklenen dosyaların oluşturulduktan sonra, ne kadar süre sonra<strong> Check-In' </strong>lenebileceklerine dair bir ilke tanımlamaya çalışıyor olacağız. Eğer oluşturulma zamanı, gün değerinden küçük ise<strong> Check-In</strong> işlemi yapılırken <strong>uyarı(Warning)</strong> mesajı verilmesini sağlayacağız. Bununla birlikte istenirse <strong>Check-In</strong> için gerekli gün sayısını belirleyebileceğimiz basit bir iletişim penceremizde olacak. Böylece istenirse gün bazındaki Timeout süresi <strong>Edit</strong> seçeneği ile değiştirilebilir olacak. Bu tabiki tamamen sembolik bir örnek. <em>(Bazı kaynaklarda Check-In lenecek dosyalar içerisinde yasaklı kelimelerin bulunmasının önüne geçilmesi veya kod standartlarından çok özel olan bazılarına uyulmadığı durumlarının ele alınması için geliştirilen ilkeler yer almaktadır. Sizde projeninizin ihtiyacı olan ilkeleri modelleyebilirsiniz.)</em></p>
<p>Örneğimizde yer alan Timeout isimli sınıfa ait kod yapısı aşağıda görüldüğü gibidir.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
using System.Collections.Generic;
using Microsoft.TeamFoundation.VersionControl.Client;
using System.Windows.Forms;
namespace TimeoutPolicy
{
[Serializable] // Serileştirilebilir olma şartı
public class Timeout
: PolicyBase // Custom policy yazmak için PolicyBase tipinden türetme yapmak gerekmektedir
{
// Minimum Check-In süresi
public int TimeoutDay { get; set; }
public Timeout()
{
TimeoutDay=1;
}
public override string Description
{
get { return "Bir Check-In işlemi yapılması için, dosyanın ilk oluşturulmasından sonra geçmesi gereken minimum gün süresi kontrolünü yapar"; }
}
// Policy içerisinde yer alan gün değeri istenirse editlenebilir
public override bool Edit(IPolicyEditArgs policyEditArgs)
{
// Gün değerini almak için InputDayForm açılır
// InputDayForm sınıfının yapıcı metoduna o anki Timeout sınıfının referansı gönderilir. Böylece form içerisinde this referansına ait gün değeri set edilebilir.
InputDayForm inputForm = new InputDayForm(this);
inputForm.ShowDialog();
return true;
}
// Policy kontrolünün yapıldığı yerdir. Geriye var ise hata bildirimlerini döndürür
public override PolicyFailure[] Evaluate()
{
List<PolicyFailure> failures = new List<PolicyFailure>();
// Şu an beklemede olan tüm PendingChange referansları dolaşılır
foreach (var item in PendingCheckin.PendingChanges.AllPendingChanges)
{
// Eğer değişiklik örneğin bir dosya ile ilgiliyse
if(item.ItemType== ItemType.File)
{
// Dosyanın oluşturulma tarihi ile güncel tarih arasındaki farka bakılır
TimeSpan distance = DateTime.Now - item.CreationDate;
// Fark var ise
if (distance.TotalDays < TimeoutDay)
{
failures.Add(
new PolicyFailure(String.Format("{0} tarihli {1} için Check-In süresi dolmamış. Lütfen {2} gün bekleyiniz",item.CreationDate,item.FileName,TimeoutDay), this)
); // Bir PolicyFailure nesnesi örneklenir ve mesaj bilgisi yazdırırılır.
}
}
}
if (failures.Count > 0)
return failures.ToArray();
else
return null;
}
public override string Type
{
get { return "Chech-In Timeout(Day)"; }
}
public override string TypeDescription
{
get { return "Gün bazlı Check-In süresi"; }
}
}
}</pre>
<p><strong>Timeout</strong> sınıfı <strong>serileştirilebilir(Serializable)</strong> olarak tanımlanmalıdır. Ayrıca <strong>PolicyBase</strong> tipinden türemelidir. Türeme sonucu <strong>ezilmesi(Override)</strong> gereken bazı üyeler olduğu görülmektedir. Bunlardan belkide en önemlisi <strong>Evaluate</strong> isimli metoddur. Bu metod içerisinde, senaryoda yer alan ilkenin uygulanması ve ilkenin aşılması halinde geriye <strong>PolicyFailure</strong> tipinden uyarı mesajlarının bir dizi şeklinde döndürülmesi sağlanmaktadır. Bizim örneğimizde dikkat edileceği üzere beklemede olan tüm <strong>Check-In'</strong> ler içerisinde tipi <strong>File</strong> olanlar ele alınmakta ve <strong>CreationDate</strong> özelliklerinin değerlerine bakılmaktadır. Eğer bu değer <strong>Timeout</strong> sınıfının kendi özelliği olan <strong>TimeoutDay</strong> değerinden küçük ise <strong>PolicyFailure</strong> oluşturulmaktadır. Ezilen diğer bir metodda <strong>Edit</strong> fonskiyonudur. Bu fonksiyon ile ilkenin düzenlenebilip düzenlemeyeceğine karar verilebilir. Biz örneğimizde, <strong>TimeoutDay</strong> özelliğinin değerinin değiştirilebileceği basit bir <strong>Windows Form</strong> kullanıyoruz. InputDayForm isimli bu Windows Form' un görüntüsü ve kod içeriği ise şu şekildedir;</p>
<p><img src="/pics/2009%2f8%2fblg58_WinForm.gif" alt="" /></p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
using System.Windows.Forms;
namespace TimeoutPolicy
{
public partial class InputDayForm : Form
{
private Timeout _timeOut;
public int Day
{
get { return Convert.ToInt16(nupDay.Value); }
}
public InputDayForm(Timeout timeOut)
{
InitializeComponent();
_timeOut = timeOut;
nupDay.Value = _timeOut.TimeoutDay;
btnClose.DialogResult = DialogResult.OK;
}
private void btnClose_Click(object sender, EventArgs e)
{
_timeOut.TimeoutDay = (Int16)nupDay.Value;
}
}
}</pre>
<p>Formumuz oluşturulurken, Timeout referansını almaktadır. Böylece Form üzerindeki NumericUpDown kontrolünde yapılan değişimlere göre, Timeout içerisindeki TimeoutDay değeri dinamik olarak değiştirilebilir.</p>
<p>İşlemlerimiz bununla bitmiyor tabiki. Geliştirdiğimiz sınıf kütüphanesinin, <strong>VSTS 2008</strong> arabiriminde <strong>Team Exlporer</strong> üzerinden kullanılabilmesi için <strong>Registry'</strong> de ufak bir ekleme yapmamız gerekmektedir <img title="Undecided" src="/editors/tiny_mce3/plugins/emotions/img/smiley-undecided.gif" alt="Undecided" border="0" /> Aynen aşağıdaki ekran görüntüsünde olduğu gibi.</p>
<p><img src="/pics/2009%2f8%2fblg58_RegEditContent.gif" alt="" /></p>
<p>Bu ekleme işlemi sırasında dikkat edilmesi gereken noktalardan birisi <strong>Value</strong> adının <strong>assembly</strong> adı ile aynı olmasıdır. <strong>Value Data</strong> kısmında ise dikat edileceği üzere geliştirdiğimiz sınıf kütüphanesinin fiziki adresi bulunmaktadır. Peki şimdi elimize ne geçti. <img title="Cool" src="/editors/tiny_mce3/plugins/emotions/img/smiley-cool.gif" alt="Cool" border="0" /> <strong>VSTS 2008</strong> üzerinde <strong>Source Settings</strong> kısmını açıp(aşağıdaki ekran görüntüsünde olduğu gibi),</p>
<p><img src="/pics/2009%2f8%2fblg58_SourceControlSettings.gif" alt="" /></p>
<p>yeni bir <strong>Check-In Policy</strong> eklemek istediğimizde aşağıdaki durum ile karşılaşırız.</p>
<p><img src="/pics/2009%2f8%2fblg58_AddCheckInPolicy.gif" alt="" /></p>
<p>Görüldüğü gibi az önce geliştirdiğimiz <strong>Custom Check-In Policy</strong> tipi burada yer almaktadır. <strong>Policy'</strong> yi ekledikten sonra dilersek <strong>Edit</strong> düğmesinide kullanabilir ve <strong>TimeoutDay</strong> özelliğinin değerini değiştirebiliriz.</p>
<p><img src="/pics/2009%2f8%2fblg58_SourceControl.gif" alt="" /></p>
<p>Süper. Artık durumu test edebiliriz. Ben <strong>TFS</strong> üzerindeki örnek bir projede bu ayarları yaptıktan ve yeni eklediğim bazı dosyaları <strong>Check-In'</strong> lemek istedikten sonra aşağıdaki ekran görüntüsünde yer alan uyarılar ile karşılaştım.</p>
<p><img src="/pics/2009%2f8%2fblg58_CheckInPolicyWarnings.gif" alt="" /></p>
<p><strong>TimeoutDay</strong> özelliğini 7 gün olarak set ettikten sonra başıma neler gelmiş neler ? <img title="Sealed" src="/editors/tiny_mce3/plugins/emotions/img/smiley-sealed.gif" alt="Sealed" border="0" /> Elbette buradaki ilkeleri ezip geçebiliyoruz bildiğiniz üzere ama izleri kalıyor... Bu örnek ilkeyi uygulanızı önermem. Ancak sanıyorumki artık kendi özel Check-In ilkelerinizi nasıl geliştirebileceğinizi gördünüz. Böylece geldik bir yazımızın daha sonuna. Tekraradan görüşünceye dek hepinize mutlu günler dilerim.</p>
<p><a href="https://www.buraksenyurt.com/pics/2009%2f8%2fTimeoutPolicy.rar">TimeoutPolicy.rar (30,07 kb)</a></p>2009-08-07T12:56:00+00:00vsts 2008bsenyurtBir süredir Team Foundation Server üzerinde ve doğal olarak Visual Studio Team System 2008 geliştirme ortamında çalışmaktayım. Tabi uzun yıllar Visual Source Safe ile vakit geçirmenin sonucunda, TFS ile birlikte gelen pek çok nimetin farkına çok geç varabiliyoruz.https://www.buraksenyurt.com/pingback.axdhttps://www.buraksenyurt.com/post.aspx?id=60ab26a3-bc8b-4de9-bc91-571890a344ba1https://www.buraksenyurt.com/trackback.axd?id=60ab26a3-bc8b-4de9-bc91-571890a344bahttps://www.buraksenyurt.com/post/VSTS-2008-icin-Custom-Check-In-Policy-Gelistirmek#commenthttps://www.buraksenyurt.com/syndication.axd?post=60ab26a3-bc8b-4de9-bc91-571890a344ba