Nedavno sam na jednom projektu imao zathjev da se aplikacija može pokrenuti u sučelju u kojem korisnik interaktivno može postavljati parametre procesiranja, te da se ta ista aplikacija može pokrenuti u komandnoj liniji gdje se svi parametri procesiranja postavljaju kao komandno-linijski argumenti.
Iako na prvu problem ne zvuči komplicirano ugrađena podrška za takav scenarij ne postoji u .NET Frameworku. Ukoliko za projekt Windows aplikacije Output type promijenimo u Console Application...
...rezultat neće biti ono što bi se svakome svidjelo:
Srećom Win32 API ima metode kojima se to može riještiti.
private const uint ATTACH_PARENT_PROCESS = 0x0ffffffff;
[DllImport("kernel32.dll")]
public static extern bool AllocConsole();
public static bool AttachConsole()
{
return AttachConsole(ATTACH_PARENT_PROCESS);
}
[DllImport("kernel32.dll")]
public static extern bool AttachConsole(uint dwProcessId);
[DllImport("kernel32.dll")]
public static extern bool FreeConsole();
Korištenjem navedenih P/Invoke metoda možemo otvoriti samo konzolu ili samo Windows aplikaciju kao u slijedećem kodu:
static void Main(string[] args)
{
if (args.Length > 0 && args[0].Equals("/cmd"))
{
if (!AttachConsole())
{
AllocConsole();
}
// do Console.* work...
FreeConsole();
}
else
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
AttachConsole će se pokušati spojiti na postojeću konzolu (ako je aplikacija pokrenuta iz komandne linije), a ako ne uspije (AttachConsole vrati false) pozvat ćemo AllocConsole što će kreirati novu konzolu i u njoj izvršiti aplikaciju. FreeConsole na kraju pozivamo kako bismo oslobodili lock na trenutnu konzolu.