FTP in .Net

Doing FTP in .Net is not as hard as you may imagine. There is a very simple way and a bit advanced way. Simple way is using System.Net.WebClient class    and its UploadFile method. Advanced way includes using System.Net.FtpWebRequest and System.Net.FtpWebResponse classes. Using them you can do ordinary FTP operations like ListDirectory, UploadFile, DeleteFile, etc. For an example see following code. More information is available from here.

public void DeleteFile(string remotePath)
    FtpWebRequest request = (FtpWebRequest)WebRequest.Create(remotePath);
    request.Credentials = new NetworkCredential("user name", "password");
    request.Method = WebRequestMethods.Ftp.DeleteFile;

    FtpWebResponse response = (FtpWebResponse)request.GetResponse();


‫تبدیل به استرینگ در C#‎

اگر شما هم تا حالا برای ساخت یک استرینگ از استرینگ و عدد در C#‎ از روشی مثل string str = “old” + (2+2).ToString()‎ استفاده می‌کردید، یعنی خودتان زحمت ToString()‎ را می‌کشیدید، دیگر این زحمت را نکشید. چون قانون String Concatenation در C#‎، شرح داده شده در بخش ۷.۸.۴ مشخصات زبانی C#‎، طوری است که اگر بخواهید یک عدد یا هر نوع داده‌ای دیگری مثل DateTime یا کلاس‌های ساخت دست خودتان را به یک استرینگ اضافه کنید، آن عدد یا نوع داده‌ای غیر استرینگ خود به خود به استرینگ تبدیل می‌شود، یعنی .ToString()‎ آن به طور خودکار فراخوانی می‌شود.

این موضوع را وسط یک رفتار عجیب C#‎ پیدا کردم. یک سری کد از قبل داشتم که در آنها یک رشته به یک متغیر از نوع استرینگ می‌چسبید. نوع آن متغیر را بعد از مدتی به یک کلاس ساخت خودم تبدیل کردم و انتظار داشتم کامپایلر C#‎ به آن خط گیر بدهد که نداد. به همین خاطر یک سوال در Stack Overflow پرسیدم و علت را فهمیدم.

How to add parameter to Build process parameters?

If you have added some new Activity or CodeActivity to your build process template but you don’t want to edit template process each time you want modify properties of Activity or CodeActivity, you must add that parameter to “Build process parameters” list of your desired build definition. By doing this, there is no need to modify template process and check-in back it each time.

Jason has described this and has showed how you can do it by editing XAML file directly. But if you are searching for an easier way, follow these steps:

1. Open build process template.
2. Open Arguments tab at the bottom-left corner of the screen.
3. Add your parameters as “In” arguments.
4. Pass value of these arguments to properties of desired build/workflow activities.
5. Save and check-in template process.
6. Open up Build Definition that uses this template process.
7. Go to Process tab and navigate to Misc section. You will see your added arguments there, that are added as “Build process parameters”.
8. Fill your values there to be used by TFS Build.

Custom workflow activity’s problem with Visual Studio designer

After reading Jim Lamb’s guide for creating a custom workflow activity for TFS Build 2010, I created a project to create my own custom workflow activity too, by following Jim’s guides line by line. At the end, despite my correct custom activity, when I tried to use that in a typical template process by dragging it onto the workflow I just saw a deny symbol and couldn’t put my activity on that workflow.

After so many verifications of my custom activity and so many googling, I decided to add my activity by editing XAML file directly in notepad. Unfortunately when loaded the workflow in the Visual Studio again, a red label with message “Activity could not be loaded because of errors in the XAML.” was showing instead of my activity. So googled again and found Ewald Hofman’s solution. Based on his guides I installed my assembly in GAC and the red error message label disappeared. I was having still 2 more problems. First, Jim’s sample code was working with no problem, but my activity needed registration in GAC. Second, despite of disappearing red label, I was still unable to drag my activity to workflows, I was forced to edit XAML file directly.

After a whole challenging day, I realized that Jim’s sample assembly exists in C:Program Files (x86)Microsoft Visual Studio 10.0Common7IDEPrivateAssemblies previously! I don’t know how Jim’s ActivityPack has gone to that location but I know when I copied my custom activity’s assembly to that location, my 2 problem solved too. So I could use Visual Studio designer to drag my custom workflow activity into any workflow or template process I want.

log4net: logging NHibernate and my own domain

I was used to use entlib for logging. But as I’m in favour of open source and because I am using NHibernate and Castle ActiveRecord in my applications, decided to use log4net instead. So found a good article about it, and enabled it for my application. But the problem was a very huge log file was producing because of verbose logs from NHibernate.

I’ve been heard that log4net uses hierarchical loggers but did not have a good understanding of it. I was thinking that using hierarchical loggers I can omit NHibernate’s logs and instead show my application’s logs. My bad assumption about hierarchical loggers was that they should be defined in app.config/web.config as nested. Obviously this assumption was wrong. Hierarchical logger in log4net means that you define a root and define all loggers inside it directly. Hierarchy then is understood of “name” attribute of “logger” node. This just acts a C# namespaces. For example you can have “NHibernate” and “NHibernate.SQL”. The second one is a child of the first.

Following guides in this, this, this, this and this link helped me to build my own config that works greatly in my application:



value="%d [%t] %-5p %c [%x] - %m%n" />

value="%d [%t] %-5p %c [%x] - %m%n" />

Customizing build process in TFS 2010

If you ever has need to customize build process in Team Foundation Build 2010, you may noticed that there is several ways to do it while each way is suitable for a specific range of requirements:

1. Running external tools like batch files or ftp.exe or MSBuild Community Tasks via InvokeProcess or via MSBuild Activity.

2. Invoke .Net classes and methods like System.IO.File.Delete() via InvokeMethod.

3. Creating your own custom workflow activity for TFS Build 2010.

For our specific need that is synchronizing a remote server via FTP, none of first 2 ways is suitable. In first way, running external programs, this is very hard to synchronize a whole remote directory and its sub-directories just via ftp.exe and a bunch of batch file commands like FOR. In addition, this may impose dependency to external tools in the server.

In the second way, running .Net classes and methods, we have to create our own ftp utility or use third party tools like ftp.exe or MSBuild Community Tasks. In addition this causes using intensive usage of TF Build activities that’s not easy to copy to new Team Foundation builds in new projects.

Third and last way, creating your own activity is harder to implement but has many advantages over other ways including:

1. High flexibility because this is entirely written by yourself.

2. Maintaining is easier because all of your work is kept in a single Visual Studio project.

3. It is easier to deploy it in new team builds because it is simply just one single workflow activity.

4. It is easier to configure. You configure it via its arguments and variables. No need to modify template process itself.

Confusing problem with log4net

I’m using log4net for logging in my ASP.NET application. This web site is based on .Net framework 3.5 and is installed on IIS 7.5 and Windows Server 2008 R2 in a 64 bit machine. Logging was working greatly when I was running application from Visual Studio 2010’s internal web server, but was not working at all when run from IIS.

First thing that I thought about was permission. So I grant full access to network service with the folder containing application: “c:inetpubwwwrootmyapp”. But this didn’t work and no log file generated. As I’m new to Windows Server 2008, I tried to grant full permission to all users that I knew: IUSR, local service, aspnet, IIS_IUSRS, Everyone, etc. But still nothing was working. A question in SO caused me to think this is because of trust level, so I set my application’s trust level to full. But still nothing was working. Another question in serverfault.com caused me to think the problem root is that Windows Server 2008 is using a new user for IIS. So I tried to use icacls to add ApplicationPoolIdentity to permission list. After it, I tried to change Identity of DefaultAppPool to Network Service. But none of this two solutions solved my problem.

Some people have been recommending to enabling internal logging of log4net to detect original problem. And yes, this showed me what was the problem:

log4net: XmlConfigurator: config file [C:inetpubwwwrootlog4net.config] not found. Configuration unchanged.

After some investigations, root cause was detected. It was due to incorrect use of Server.MapPath. I was forgotten to add a tilde mark in beginning of log4net.config’s path. When I used Server.MapPath as follow, all headaches have suddenly disappeared and my log file appeared and get working as I was desiring:

XmlConfigurator.Configure(new FileInfo(Server.MapPath("~/log4net.config")));

A wrong path has been causing log4net to search c:inetpubwwwroot for log4net.config not my application’s path at c:inetpubwwwrootmyapp. All this nightmare was because of my own mistake not Windows, IIS or .Net!

نرم‌افزارهای آزاد و متن‌باز

دوستی می‌خواست چیزهایی راجع به نرم‌افزارهای آزاد، متن‌باز، تفاوت‌ها و دیگر مسائل بداند. این متن جوابی است به ایشان.

متن‌باز بودن نرم‌افزار به چه معنی است؟ تا آنجا که من می‌دانم هر نرم‌افزاری می‌تواند متن‌باز هم باشد. مثلاً یک نرم‌افزار پولی یا مجانی یا آزاد یا غیر آزاد می‌تواند متن‌باز هم باشد یا نباشد. دلیل این که همراه بیشتر نرم‌افزارهای پولی سورس آنها هم ارائه نمی‌شود آن است که سورس برنامه‌ها بسیار گرانقیمت‌تر از خود نرم‌افزارها هستند. مثلا ویندوز ایکس‌پی فرضاً ۱۰۰ دلار است ولی سورس کد آن ۱۰ میلیون دلار است.

اما نرم‌افزار آزاد به نرم‌افزاری گفته می‌شود که کاربر آن می‌تواند هر طور که دلش خواست آن را تغییر داده و حتی مجدداً منتشر کند. دقت کنید که در کشورهای غربی قوانین سخت‌گیرانه‌ای در رعایت اجازه‌نامه‌ی نرم‌افزار وجود دارد. مثلاً اگر در اجازه‌نامه‌ی ویندوز ایکس‌پی نوشته شده باشد که شما اجازه ندارید با آن آهنگ گوش کنید یعنی واقعاً اجازه‌ی انجام این کار ندارید و انجام آن به معنی جرم است. تا آنجا که من می‌دانم آزاد بودن یک نرم‌افزار به معنی متن‌باز بودن آن نیست. یعنی نرم‌افزار می‌تواند آزاد باشد ولی سورس آن در دسترس نباشد.

آزاد بودن نرم‌افزار اصلاً ربطی به پول ندارد. یعنی نرم‌افزار می‌تواند آزاد باشد ولی پولی هم باشد. مثلاً شرکت موزیلا می‌تواند فایرفاکس را در حین این که نرم‌افزاری آزادی هم هست، آن را به فروش هم برساند. حتی شرکت‌هایی غیر از موزیلا، مثلاً مایکروسافت یا شهرداری تهران هم می‌توانند فایرفاکس را بفروشند بدون که کار خلاف قانونی انجام داده باشند.

اما در مورد تغییرات قضیه یک کم فرق می‌کند. اگر شما یا هر کس دیگری در چیزی مثل فایرفاکس یا وردپرس یا جوملا یا هر چیز دیگری تغییری دادید و خواستید آن را دوباره منتشر کنید باید طبق اجازه‌نامه‌ی آن رفتار کنید. مثلاً اگر اجازه‌نامه‌ی آن GPL است باید نسخه تغییر یافته‌ی آن مجدداً تحت اجازه‌نامه‌ی GPL بوده و سورس تغییر یافته‌ی آن به طور عمومی در دسترس باشد. بیشتر اجازه‌نامه‌ها شما را مجبور می‌کنند علاوه بر این که نسخه‌ی تغییر و سورس آن منتشر کنید، شما را مجبور می‌کنند نسخه‌ی مجوز قبلی، پدیدآورندگان، تغییر دهندگان قبلی و… را همراه با تغییرات جدید ارائه دهید. این به این معنی است که اگر وردپرس تحت یکی از این جور اجازه‌نامه‌ها مثل GPL باشد و شما آن را تغییر داده و مجدداً منتشر کردید، علاوه بر این باید سورس تغییر یافته را در دسترس عموم قرار داده و ضمناً اجازه ندارید مشخصات پدیدآورندگان قبلی را پاک کرده یا تغییر دهید.

در مورد کامپوننت‌ها و کتابخانه‌های نرم‌افزار یک سری قواعد خاصی هست که از یک اجازه‌نامه به اجازه‌نامه‌ی دیگر تفاوت می‌کند. مثلاً اگر آن کامپوننت تحت اجازه‌نامه‌ی GPL بود آن وقت نرم‌افزاری که از آن کتابخانه استفاده می‌کند هم باید تحت اجازه‌نامه‌ی GPL بوده و سورس آن به رایگان در دسترس عموم قرار بگیرد. این داستان در مورد کامپوننت‌هایی که تحت اجازه‌ی LGPL باشند صادق نیست. یعنی می‌توانید از چنین کامپوننت‌هایی در نرم‌افزارتان استفاده و مجوز آن را همچنان به صورت تجاری نگه دارید. به طور کلی در مورد هر کامپوننتی باید به متن اجازه‌نامه‌ی آن مراجعه کنید.

روش رایج پول در آوردن از نرم‌افزارهای آزاد، پشتیبانی فنی و خدمات مشاوره است. مثلاً نرم‌افزار OTRS خودش آزاد، متن‌باز و مجانی است و هر کسی هر کار که دلش خواست می‌تواند با آن بکند. اما شرکت حامی آن خدمات hosting آن را به صورت پولی ارائه می‌کند، خدمات نصب و مشاوره و خدمات پشتیبانی آن را هم به صورت پولی ارائه می‌کند و پول خوبی از این راه به دست می‌آورد. البته راه‌های زیادی برای پول درآوردن از نرم‌افزارهای آزاد هست که بستگی به شرایط دارد.

فراموش نشود که هیچ کدام از این قوانین در داخل ایران اهمیتی ندارد و فقط اگر خواستید کارتان را به طور جدی در خارج از کشور هم استفاده کرده یا منتشر کنید باید آنها را دانسته و رعایت کنید.

جهت اطلاع بیشتر:
‫کپی‌لفت (Copyleft) چیست؟ 

‫چرا FOSS (و Open Source) برای ما خوب است؟‫حرکت به سمت FOSS
‫برنامه‌های من برای مهاجرت به FOSS 

ضمناً فکر می‌کنم سایت‌ها و انجمن‌های فارسی‌زبان زیادی باشند که روی این موضوعات کار می‌کنند.

Unlocking TFS Version Control items

We have a Visual Studio solution that uses some external assemblies coming from third parties. This solution resides in TFS 2010 version control. We have configured Team Foundation Build to do automatic builds of the solution. As you know you should put any external assemblies in TFS Version Control to do a proper build without any build breaks. So we did same. Whenever we want to update the assembly with a new one, we first check-out the item, copy newer assembly to local folder and then check-in it again.

An assembliy (.dll file) in TFS can not be checked-out by multiple users because it’s a binary file and can’t merged or compared. Just like files of type gif. We had a situation recently that a user checked-out one assembly without checking-in it again or undoing his change. As he went to vacation, that assembly remained locked in TFS version control and no one could check-out that assembly again. Me as TFS administrator was forced to unlock it. So googled for the solution and found Martin Woodward’s work-around:

tf lock $/MyProject/MyPath/MyFile.cs /lock:none /workspacename:WorkSpaceName /server:my_server

Unfortunately this was not working for me because I got error:
Tf10152: the item xxx must remain locked because its file type prevents multiple check-outs.

I was very hopeless but another link showed me how to use “undo” to solve my problem. This time it worked nicely:

tf undo /workspace; /server:  item

For those unfamiliar with “tf”, it is powerful command-line tool for TFS that can be run from a “Visual Studio Command Prompt” window.

Each TPC needs a separate Build Controller

If you are going to start using TFS 2010 please be aware that each TPC (Team Project Collection) needs a separate Build Controller.

For those who are intended to use TFS 2010 as their ALM engine, TFS 2010 can contain several TPCs. Each TPC can contain several Team Projects. Each Team Project is a regular space in TFS that contains Work Item Management, Source Control and Build automation. Build automation in each Team Project contains several Build Definitions that build project with several conditions. Each Build Definition is assigned to a Build Controller. A Build Controller is a build server that builds project using conditions defined in Build Definitions.

In other hands while defining a new Build Definition you must specify its Build Controller. Unfortunately with TFS 2010 you can not use Build Controller defined for say TPC number one for say TPC number two. Each TPC must have its own Build Controller.

Considering that a Build Controller is really a server, assigning a server to each TPC defined in TFS is not very applicable in most companies and teams. There is an article in MSDN blogs that shows a way to use a single Build Controller in several TPCs. As the article itself emphasis, this hack is not recommended for operational installations. Some people like us have been forced to use a single TPC for all Team projects. This work-around has many disadvantages like interfere of Team Projects, security issues, etc, but at least have solved the problem of need to several servers as Build Controllers.

See also:
My question in StackOverflow
Related content in TFS forum
Related content in GeeksWithBlogs
Jim Lamb’s hack for the problem