Apr 24, 2008

Redirecting standard error output in cmd.exe

Hi. Suppose you have the following C++ program (in a Windows box):
#include "stdafx.h"
#include "string.h"


void write(char *str, FILE *target)
{
fwrite(str, strlen(str), 1, target);
}

void _tmain(int argc, _TCHAR* argv[])
{
write("Test:stderr\r\n", stderr);
write("Test:stdout\r\n", stdout);
}
and you want to redirect its output to a file. We could try something like in Windows console:
test.exe > myfile.txt

Unfortunately the naive approach don't work because there are data being outputted to stderr and we are redirecting only the standard output (stdout). In order to redirect stderr we can use the following syntax:
command handler# > target

let's try a sample:
test.exe 1>myfile.txt

This will redirect stdout (handle 1) to myfile.txt To redirect stderr (handle 2) we can use:
test.exe 2>myfile.txt

Ok. Now we can try:
test.exe > myfile.txt 2>myfile.txt

but, again, this doesn't work; instead we get an error message:
D:\temp\cpp\Test\Debug>Test > myfile.txt 2>myfile.txt
The process cannot access the file because it is being used by another process.
Ok, there's one last trick we can try (duplicate stderr to stdout):
test.exe > myfile.txt 2>&1

Great! Now it works as expected! Last, but not least,
you can find more information here. Hope this can be useful :) Adriano

Apr 22, 2008

Db4o news!

Hi, Db4o just announced a new release! Check it out here and let us know what you think about these new (IMO) cool features! Adriano

Apr 9, 2008

A Linq playground for you and your objects

In this post we'll implement a very basic Linq Console application that supports "ad hoc" queries allowing users to enter Linq queries and run them against a db4o database. Our main goal is to show how such mechanism can be implemented on top of Linq/Db4o.

That said, let's play with the application for a while and them dig a little bit in its code.

How to use it ?

First, download the code here and compile it (any version of Visual Studio 2008 can be used).

Now populate a db4o database (with data) and copy the an assembly containing the types stored in that database to the LinqConsole.exe folder.


You will need to copy your model assembly to
LinqConsole executable directory, otherwise it
will not be able to find it.


Start the application and, once presented the prompt (
>), enter commands (prefixed with ":") or a query (finished with ";"). The very first command you may want to try is :help to see a list of valid commands (type :help and press ):
Basically, we want to run a (Linq) query against a db4o database, so we need to specify:
  • the database file to query (through database command)

  • the assembly containing the types stored in the database; we call this assembly, model assembly because usually, it will hold your business objects (the model in MVC pattern). Unfortunately, this assembly must be in the same directory as the application, otherwise the application will not be it able to find it (technically one can configure the application using Linq.Console.exe.config file to allow assemblies to be stored in alternative directories).
With these parameters defined you can type Linq queries as you would do pragmatically, for instance:

from Type t in database select t;

and press to see the results:


As the application tries to run the query only when it finds a semicolon ";" it's also possible to enter a query in multiple lines. You can see a short demo of the application in bellow.








Before leaving this topic, I'd like to call your attention that in order to Linq for db4o to work you need to specify a type in the query (that's the entry point for our custom "Linq Provider"), otherwise, you will get an error like the one bellow:


Note that in this case I've omitted Person type in the query, i.e, I've typed:

from p in database select p;

instead of:

from Person p in database select p;


How it works ?

The basic idea behind this application is pretty simple: Given a model assembly (specified through
load command), a db4o database (specified through database command) and a Linq query, find all types and namespaces defined in such assembly them emit code to run the query against the database.

In
CompileQuery() method we emit a new type (TheQuery) using the specified values (database, namespace and query). This type implements IInteractiveQuery interface, so, after instantiating it we call its Run() method to execute the query.

In order to dynamically compile this type (
TheQuery) we use classes defined in System.CodeDom.Compiler and Microsoft.CSharp namespaces; any compilation errors will be rendered in red on yellow background text.

Improvements

Well, I must admit: in its current state, this program has some limitations (but most of them are there to allow you to play with it ;)

From the top of my head, I can came up with a list (of coarse, not an exhaustive one) of possible improvements:
  • Support model assemblies in other directories
    Currently in order to use a model assembly, users are required to copy it to the application folder.


  • Check if the types stored in the database can be found in the model assembly.

  • Better error handling in general

  • Warn users about invalid commands Currently nothing happens for invalid commands (no message).

  • List types inside an assembly A new command (for instance, types) could be added to allow users to list the types contained in an assembly.

  • Add support to query Db4o in server mode.

  • Auto-completion This probably would require major changes in the input handling, but it would be nice to add auto-completion to list types, assemblies, databases, etc. in the commands.

  • You name it! The sky is the limit :)
Final Words!

I really expect that you enjoyed this application; if you have questions/suggestions please, fell free to drop me a line :)

Thoughts?

Adriano