Tuesday, December 4, 2007

C# and .Net on Linux

Compile and run C# command line and GUI applications on Linux

Shekhar Govindarajan

In the past issues of PCQuest we have talked much about MS .Net and C# programming language. .Net and its programming languages (C#, VB .Net, VC++ .Net, Visual J#, Python .Net, Perl .Net, COBOL .Net, etc) are available for only the Windows platform�Win 9x, ME, NT, 2000, XP, Win CE (for portables), etc. But a project named Mono has been introduced now. This is an effort to port .Net and its languages. As of now only C# has been ported to non-Windows platforms.

Libraries, compiler/interpreter and a runtime environment are the three essentials to write and run a program on a platform (OS + hardware architecture). Libraries make the writing of large programs easy by providing commonly-used routines in the form of classes and methods (functions). The .Net framework also has a number of libraries called class libraries. The compiler and the runtime are needed to convert a program into an executable and to run this executable respectively.

Mono packages the port of .Net library classes, a C# compiler and the .Net runtime�CLR (Common Language Runtime).

A graphical Image browser applications in C# running on LinuxMono claims to run on Linux, Solaris, FreeBSD and MS Windows. And besides the Intel x86 processors (486, Pentiums), it is said to support Sparc, PowerPC and StrongArm processors too.

Without getting into more theory, let�s see how Mono works on Linux. We�ll install Mono on PCQLinux 7.1, compile some C# programs and execute them. We are assuming that you are familiar with the .Net framework and the basics of C#.

Installation
Mount this month�s PCQuest CD and change to the directory system/cdrom/unltdos/linux/mono. Install all the RPMs found in this directory as

rpm -ivh *.rpm

Among other RPMs required by Mono, the Mono RPM named mono-0.12_baselabs-20020709.i386.rpm gets installed. The basic .Net assemblies like System.Data.dll, System.dll, System.Drawing.dll, System.Web.dll and System.Xml.dll are copied to the directory /usr/lib.

Now, type in the following program in a Linux text editor and save the file as HelloMono.cs.


class HelloMono
{
public static void Main(string[ ] args)
{ System.Console.WriteLine(�Hello Mono�);
}
}

Compile the program as

mcs HelloMono.cs

Mcs is the Mono C# command-line compiler. It has many command-line options like the csc compiler of MS .Net SDK. The above command will produce an executable named HelloMono. exe. Note that this executable is not a Linux executable but a .Net executable, technically called the IL (Intermediate Language) code. To run this executable, issue the following.

mono HelloMono.exe

You will see �Hello Mono� displayed on the Linux console. For more on mcs and Mono, refer to their man pages, which can be brought up by issuing:

man mcs
man mono

GUI on Mono
Mono does not support Windows Forms for GUI widgets. However, GTK# (a C# binding of GTK+graphical library) can be used for coding GUI components in C#. You�ll find all the requisites for installing GTK# on the CD. Let�s first install it and then execute some sample GTK# programs.

Change to the directory system/cdrom/unltdos/linux/gtksharp/dep on the CD and install the RPMs as

rpm -Uvh *.rpm --nodeps

Copy the file named gtk-sharp-0.2.1.tar.gz found in the directory system/cdrom/unltdoss/ linux/gtksharp to /opt directory. Extract the archive as

tar �zxvf gtk-sharp-0.2.1.tar.gz

This will produce a directory named gtk-sharp-0.2.1 within /opt. Change to this directory and issue

./configure --prefix=/usr
make
make install

Monkey Business
Money wise with Mono: .Net development can take place on a low-cost non-Windows platform like Linux. The deployment platform can be either Linux or Windows, with the OS cost (per user, per system licenses) in Windows concerning only the end user and not the developer.

Consider the scenario of a client-server .Net application. A user will interact only with the client (which should hopefully be a pleasant-looking GUI application) and expect a familiar platform like Windows. It will not matter to him if the server part is on Windows or Linux. So, the server part can be deployed on a Linux server using Mono, saving on the cost of setting up a dedicated Windows server.

Easy migration: If Mono comes out well, Windows developers, too, can develop for Linux and other non-Windows platforms. It won�t be a surprise if later a free or low-cost .Net IDE (Integrated Development Environment) like Visual Studio .Net makes a debut for Linux.

Linux developers, who should already have a grip of C/C++, can learn C# with similar syntax and constructs as in C/C++. Or, they can wait for a Mono C++ compiler that would give them an easier migration path.

The success of all this depends upon how well Mono is developed and how close and compatible it is with the implementation of the .Net framework on Windows. Other key factors will be its performance and the look-and-feel of its GUI components.

If you�re wondering what the title Monkey Business means, here�s the mystery unraveled�Mono means monkey in Spanish.

All the assemblies related to GTK# (gtk-sharp.dll, atk-sharp.dll, gdk-sharp.dll, glib-sharp.dll and pango-sharp.dll) are copied to the directory /usr/lib. You will need to refer to them using the �r option (see below) when you compile a C# program that uses GTK# for GUI. Reboot the machine once before proceeding further.

You�ll find some GTK# sample programs (HelloWorld.cs, Menu. cs, ButtonApp.cs) in the directory /opt/gtk-sharp-0.2.1/sample. You can compile them as

mcs -r gtk-sharp -r glib-sharp HelloWorld.cs

mcs -r gtk-sharp -r glib-sharp -r System.Drawing Menu.cs

mcs -r gtk-sharp -r glib-sharp -r System.Drawing ButtonApp.cs

Note how we are referring to the various assemblies using the �r option. Next, start X Window using the startx command and from within a terminal window, change (cd) to the directory /opt/gtk-sharp-0.2.1/sample and issue the following commands to execute the respective programs.

mono HelloWorld.exe
mono Menu.exe
mono ButtonApp.exe

Since Mono is an ongoing project and not all the .Net class libraries have been ported, you may find some quirks with it. Nevertheless, it�s usable to a great extent. You can check out the port status of class libraries at www.go-mono.com/class-status.html. For more on Mono, go to www.go-mono.com. For more on GTK#, see http://gtk-sharp. sourceforge.

Net/.

Shekhar Govindarajan

Running .Net applications on Linux with Mono

Imagine the fate of your company rests on your completing your new Linux project on time. You have a crack team of first-class developers, but they're all .Net programmers. What are you going to do? Admit that Windows is better that Linux? Cry? Resign? No, you're going to install Mono and save the world!

Mono is an open source project (sponsored by Novell ) that allows you to run .Net applications on Linux (as well as Unix, Mac OS X, Solaris and even Windows). To obtain it, go to the Mono download page and find the version you need for your distro.


Once you've installed Mono, get one of your .Net programmers to create and compile a simple Microsoft Visual Studio C# console application. Just something easy, such as:


using System; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Console.WriteLine("Hello World"); } } }




If you don't have your own tame .Net programmer, you're going to need a Windows machine with Microsoft Visual Studio installed. (Stop making faces like that!) Download the free Microsoft Visual C# Express Edition .

Transfer the compiled application from the Windows machine by using FTP or Samba, then log on to your Linux box and run the application:


$ ConsoleApplication1.exe Hello World


Surely it can't be as simple as that? Amazingly, it is. If you don't believe that it's Mono that's allowing you to do this, try transferring the application to a Linux box that hasn't got Mono installed. You'll get a result something like:


$ ConsoleApplication1.exe

-bash: ./ConsoleApplication1.exe: cannot execute binary file






You may need to run chmod +x on the file to get it to run. Also, I found that on Debian at this stage I got an error: The assembly mscorlib.dll was not found or could not be loaded. It should have been installed in the '/usr/lib/mono/2.0/mscorlib.dll' directory. I cured that by executing:


$ cd /usr/lib/mono $ sudo ln -s 1.0 2.0

The application name ends in .exe because it has been compiled as a Windows application. Once you've got it on Linux you can of course call it whatever you want:


$ mv ConsoleApplication1.exe HelloWorld $ HelloWorld Hello World

You've just seen just how easy is to use a Microsoft Visual Studio application on Linux. However, you're also probably thinking that you have absolutely no intention of using Windows at all; your .Net programmers are just going to have to have to learn to program in something that runs solely on Linux. That's a good idea -- if you've got the time for them to learn something new. If not, don't despair. Mono comes with its own .Net compiler, mcs. To us it, paste the code for the 'Hello World' application above into a file, compile it (using mcs), then run the new application from the command line.


$ mcs -out:HelloWorld.exe Program.cs $ HelloWorld.exe Hello World

If you've still got that Windows machine fired up, you may find it interesting to transfer the newly compiled application to it and running your app in Windows. You'll find that you've created something on Linux that will also run on Windows.


Of course, by the time you've explained all this to your .Net programmers they'll be up in arms. "How can you expect us to program without a pretty GUI?" they'll cry.


"With Monodevelop ," you'll say, referring to Mono's integrated development environment (IDE). With Monodevelop your developers can happily work with Glade#, Gnome#, and GTK#, all within a .Net-type environment. Check the software's download page for your distro's version and any dependencies.






When you install Glade, make sure that you obtain Glade2 and not Glade1. On Debian sudo apt-get install glade will grab Glade1, which will not work with Monodevelop. The correct installation command is sudo apt-get install glade-2 .

The developers should leave you in peace for a while, but they'll be back. "Where's the GUI designer?" they'll ask. This is where you introduce them to building interfaces with Glade . When you start a new Monodevelop Glade# application, use a file called gui.glade . You can edit this with Glade and then do the programming in Monodevelop. If your developers have any further questions, point them in the direction of the Mono GTK# Beginner's Guide .


With your .Net programmers happily producing applications for Linux, you can turn your attention to ASP .Net for building Web applications. You're going to need a Web server, which can be either Apache (with mod_mono installed) or Mono's own Web server, XSP. Have a look at the Mono Handbook page for Web sites and Web services to find out how to set up the XSP server. On Debian, for example, its just a matter of installing the software:


sudo apt-get install mono-xsp

Then running it:


$ cd mono $ xsp xsp Listening on port: 8080 Listening on address: 0.0.0.0 Root directory: /home/bainm/mono Hit Return to stop the server.

XSP will run in the directory where you start it, will use this as its home directory, and will use port 8080 by default. If you don't want to have to change into that directory every time you start the server, you can use its --root option. To change the port, use the --port option:


$ xsp --root ~/mono --port 8081

When you've got your server up and running, go to Mono's Web Services page , where you'll find some good examples of the types of services that you can start running. However, if you're desperate to see the server in action, go to the directory you're running XSP from and cat the following into index.aspx:


<%@ Page Language="C#" %> <html><body> <%     Response.Output.Write("Hello World!"); %> </body> </html>

Now open up a Web browser and type in the URL of your host (plus the port number) -- e.g. http://hector:8080 . Granted, this isn't the most exciting example in the world, but it proves that you can run ASP .Net on Linux. A quick search on Google will give you a host of other examples that you can use.


With Mono, Monodevelop, and XSP in place, you can throw away Microsoft Visual Studio and you can throw away Windows, and you don't have to throw away the valued experience of your .Net programmers.

Mono 1.0 Brings Linux .Net-Style Development

By Jason Brooks

Novell Inc.'s Mono 1.0 is an open-source implementation of Microsoft Corp.'s .Net development platform that provides companies with the opportunity to pursue the latest Microsoft development technologies while leaving open the door to cross-platform support.

While the .Net Framework targets only Windows, Mono 1.0 supports Linux and Unix platforms, as well as systems running Windows and Mac OS X.

Mono comprises a compiler for the C# programming language, a run-time engine for Microsoft's Common Language Infrastructure and a group of .Net-compatible class libraries that are required for running .Net applications with Mono. These libraries include open-source versions of Microsoft's ADO.Net data access and ASP.Net Web application development technologies.

There have been rumors that Microsoft may open-source the Common Language Runtime component of .Net. Click here to read more.

Using the mod_mono Apache Web server module that ships with Mono 1.0, sites can serve ASP.Net pages with Apache on Linux (the module doesn't support Apache on Windows). This means that companies can make development and production platform choices separately.

Perhaps more important than Mono 1.0's ability to bring certain Windows applications to Linux is that it brings the .Net development model to Linux. A variety of class libraries for developing native Linux applications are included along with Mono's .Net compatibility libraries.

In eWEEK Labs' tests, for example, we were able to quickly create a simple Web browser in C#, with a GUI based on the Gtk framework and rendering handled by Mozilla's Gecko engine.

Although Mono 1.0 is intended to provide full compatibility with pure .Net Version 1.1 applications, .Net applications that make use of native Windows APIs will require porting work to be brought over to Linux.

Applications that use Microsoft's WinForms rich user interface classes, which depend on native Windows system calls, can run with Mono using a library based on Wine that ships along with Mono.

Mono 1.0 ships with MonoDevelop, a port of the open-source .Net IDE (integrated development environment) SharpDevelop to Gtk#. MonoDevelop doesn't handle GUI creation—for that, we used the Gtk interface tool Glade.

Mono also includes a documentation browser. We were impressed with the breadth of Mono's documentation, which includes lots of sample projects.

Mono's compiler supports C#, and a Mono compiler for Microsoft's Visual Basic .Net, called MBas, is under development.

Mono ships with IKVM, a Mono-based Java virtual machine, plus implementations of Java class libraries based on work from the open-source project Classpath. IKVM enables sites to run Java applications with Mono and use Java libraries in .Net applications.

Mono 1.0 is available for free download in source code form at www.mono-project.com/downloads.

Mono's run-time engine supports the x86, x86-64, PowerPC, SPARC, S390, StrongARM and HPPA processor architectures on Linux, Windows, HP-UX, Solaris, Mac OS and BSD operating systems. Mono also ships with a native optimizing compiler in both ahead-of-time and just-in-time compilation modes for the x86, SPARC, S390 and PowerPC architectures.

Precompiled, ready-to-install packages are also available through this site for Red Hat Linux 9, Fedora Core 1 and 2, SuSE Linux Enterprise Server 8, SuSE Linux 9.0 and 9.1, Slackware 10, Windows 2000 and above, and Mac OS X Panther.

Senior Analyst Jason Brooks can be reached at jason_brooks@ziffdavis.com.

horizontal rule

Monday, December 3, 2007

PHP Webservices and C# / .NET SOAP Clients

Code Zulu Bind Maker is a project I started working on about 3 years ago. Its a stupid little app that configures game settings for Counter-Strike. When I wrote it, version 1.6 was in beta, and everybody played version 1.5 (which was ever so different). Anyway I run a website that supports the app, and of course, its written in PHP / MySql (my poison of choice on the web).

The reason for the boring and seemingly pointless background is that ever since I wrote the app, I always wanted to integrate the website and application, but never really thought of a "good" way to do it. A couple days ago, I had some spare time and sat down to see how easy it would be to create some PHP webservices that I could easily consume in C#. I had been considering expanding the community aspect of the bind maker website into the application so that they'd work seamlessly together. I also wanted to add a common place that gaming communities could spend their time (which I had previously planned for just the website, but was thinking of the possibilities of bringing that into the app as well), and a PHP webservice combined with a C# windows app seemed like the best option.

C# webservices (server side) are about as easy-as-it-gets to write. C#'s SOAP client is completely transparent (or I should say completely generated so you code just like you would use any other objects) and is completely brainless to use. Since I'd never done webservice work in PHP, I started asking Mr. Google how it worked, and what would you now but that I stumbled across the NuSOAP library for php. It sure beat the heck out of writing all my WSDL files by hand, wrapping and unwrapping stupidly simple SOAP messages, and hacking everything very poorly.

My first PHP webservice iteration was a simple "hello " web method. It used a simple type (xsd:string) as its parameter and returned a simple type (again another xsd:string) as its return value and looked like this:
 /**
* ProcessSimpleType method
* @param string $who name of the person we'll say hello to
* @return string $helloText the hello string
*/

function ProcessSimpleType($who) {
return "Hello $who";
}
NuSoap was great. It took care of all the nitty-gritty work that I had previously done myself. All it took was about 8 lines of code to set up the SOAP server and register the method and my types.
require_once("lib/nusoap/nusoap.php");
$namespace = "http://sanity-free.org/services";
// create a new soap server
$server = new soap_server();
// configure our WSDL
$server->configureWSDL("SimpleService");
// set our namespace
$server->wsdl->schemaTargetNamespace = $namespace;
// register our WebMethod
$server->register(
// method name:
'ProcessSimpleType',
// parameter list:
array('name'=>'xsd:string'),
// return value(s):
array('return'=>'xsd:string'),
// namespace:
$namespace,
// soapaction: (use default)
false,
// style: rpc or document
'rpc',
// use: encoded or literal
'encoded',
// description: documentation for the method
'A simple Hello World web method');

// Get our posted data if the service is being consumed
// otherwise leave this data blank.

$POST_DATA = isset($GLOBALS['HTTP_RAW_POST_DATA'])
? $GLOBALS['HTTP_RAW_POST_DATA'] : '';

// pass our posted data (or nothing) to the soap service
$server->service($POST_DATA);
exit();
That was it. From visual studio I was then able to consume the webservice by adding a web reference




With the reference added, I put a button on my form, and added the following button click event handler:
private void button1_Click(object sender, EventArgs e) {
SimpleService svc = new SimpleService();
string s = svc.ProcessSimpleType("steve");
MessageBox.Show(s);
}
Ran my application, pressed the button (which in turn called the webservice), and voilĂ  I get a message box telling me Hello:



That's great! Completely useless, but great!

Now to get a little more complicated... I had planned on using complex data types that would be consumed by both PHP and .NET clients (A PHP SOAP client for the website, and .NET client for the windows application). It may sound stupid to have a PHP client when most likely I'd have access to the method directly, but the server that is going to host the webservices is actually different than the "web presence" server I host my website on. Anyway, the test complex types I came up needed to look like simple structs (in C#) which would also be used in an array, and they looked something like this:
public struct MySoapObject {
public string Author;
public string Name;
public string Description;
public string Text;
public int VoteTotal;
public int VoteCount;
}

MySoapObject[] soapObjects = new MySoapObject[10];
so I added the definitions in PHP using NuSOAP like this:
$server->wsdl->addComplexType(
'MySoapObject',
'complexType',
'struct',
'all',
'',
array(
'Author' => array('name'=>'Author','type'=>'xsd:string'),
'Name' => array('name'=>'Name','type'=>'xsd:string'),
'Description' => array('name'=>'Description','type'=>'xsd:string'),
'Text' => array('name'=>'Text','type'=>'xsd:string'),
'VoteTotal' => array('name'=>'VoteTotal','type'=>'xsd:int'),
'VoteCount' => array('name'=>'VoteCount','type'=>'xsd:int')
)
);

$server->wsdl->addComplexType(
'MySoapObjectArray',
'complexType',
'array',
'',
'SOAP-ENC:Array',
array(),
array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'tns:MySoapObject[]')),
'tns:MySoapObject'
);
I defined the method in PHP that would take in an array of MySoapObjects, process them, and then return one MySoapObject that it had "processed".

That method looked like this:
function ProcessMySoapObject($mySoapObjects) {
$mso = $mySoapObjects[3];
$mso['Name'] = "|||";
return $mso;
}
The SOAP server registration:
$server->register(
'ProcessMySoapObject',
array('soapObjects'=>'tns:MySoapObjectArray'),
array('return'=>'tns:MySoapObject'),
$ns,
false,
'rpc',
false,
'Processes an array of MySoapObjects and returns one of them');


And I did exactly the same as I did before--and added the web reference in visual studio to my project. This time not only did Visual Studio add the Service class and web method, it added the 2 data types I had defined in PHP on my SOAP server (actually, it just built the MySoapObject, and the array was left out because arrays are an implied data type).



I changed my button click event in my windows form and added the following code:
private void button1_Click(object sender, EventArgs e) {
Services s = new Services();
MySoapObject[] ms = new MySoapObject[10];
for(int i = 0; i < ms.Length; i++) {
ms[i] = new MySoapObject();
ms[i].Author = "Steve";
ms[i].Description = "The One that should be returned";
ms[i].Name = i.ToString();
ms[i].Text = "something something something " + i.ToString();
ms[i].VoteCount = i * 2;
ms[i].VoteTotal = (int)Math.Pow(ms[i].VoteCount, 2);
}
MySoapObject retn = s.ProcessMySoapObject(ms);
string output = "";
output += retn.Author + "\t\t\r\n";
output += retn.Description + "\t\t\r\n";
output += retn.Name + "\t\t\r\n";
output += retn.Text + "\t\t\r\n";
output += retn.VoteCount.ToString() + "\t\t\r\n";
output += retn.VoteTotal.ToString() + "\t\t\r\n";
MessageBox.Show(output);
}
Compiled, ran and clicked.


Simple, Easy, Can't believe I never tried it before now!

This opened up a whole new world of opportunities in cross-platform distributed computing that I'd never exposed myself to before... what a wonderful thing!

About Me

Ordinary People that spend much time in the box
Powered By Blogger