Monday, 29 December 2008

Change the Process Name in Programs executed by Mono under Linux (or other *nix OS)

I try to divide my free time by diving into open source world or trying to port some closed source .NET projects, commissioned by clients, designed to work under Windows to Linux.
I've recently updated a little tool written in C#, upgrading it to a stable state: cptree 1.1. If you don't remember what is for, please (re)read this post. When you execute the program with one or no arguments, it simply list file and folders traversing all the tree from the current (or specified) directory. So a day, working on my Ubuntu Linux pc, I've opened the Process Monitor (the one Windows users call Task Manager), with the will to kill cptree, committed to list a very deep directory. But what a surprise! No cptree or cptree.exe process exists: I was able to find only a process called mono eating a little more of cpu in relation of other processes...

Hence how to set the process name in a .NET application executed by Mono? I causually found the solution inspecting Banshee sources, which I know is a .NET application designed for Linux (forums and blogs are full of compliments about internal architecture of this application - and I can confirm it!). I found the solution in a file called PlatformHacks.cs. Anyway this file contains more than you need, so I suggest you to use my version (it contains just the code needed to accomplish this post intent).

using System;
using System.Text;
using System.Runtime.InteropServices;

namespace CopyDirectoryTree
{
static class PlatformHacks
{
[DllImport("libc")] // Linux
private static extern int prctl(int option, byte[] arg2, IntPtr arg3, IntPtr arg4, IntPtr arg5);

[DllImport("libc")] // BSD
private static extern void setproctitle(byte[] fmt, byte[] str_arg);

public static void SetProcessName(string name)
{
if (Environment.OSVersion.Platform != PlatformID.Unix)
{
return;
}

try
{
if (prctl(15 /* PR_SET_NAME */, Encoding.ASCII.GetBytes(name + "\0"),
IntPtr.Zero, IntPtr.Zero, IntPtr.Zero) != 0)
{

throw new ApplicationException("Error setting process name: " +
Mono.Unix.Native.Stdlib.GetLastError());
}
}

catch (EntryPointNotFoundException)
{

setproctitle(Encoding.ASCII.GetBytes("%s\0"),
Encoding.ASCII.GetBytes(name + "\0"));
}
}

public static void TrySetProcessName(string name)
{
try
{
SetProcessName(name);
}
catch
{
}
}
}
}

The use is straightforward, place the following call as first instruction in the entry point of your program:
PlatformHacks.TrySetProcessName("your-proc-name");

A big post for a little detail? To the readers the last word: feel free to add comments.

Bye and good platform hacking!

No comments:

Post a Comment