- Hikaru {Aka} Yuuki のブログ - http://www.hikaruyuuki.com -
Buat WinForms Application Beserta Versi Console-nya
Posted By Adikara Putra (Hikaru Yuuki) On 6日 6月 2011年 @ 11:39 In Pemrograman | No Comments
Beberapa waktu lalu saya ingin membuat aplikasi desktop namun yang juga dapat berjalan di console. Jadi, ketika memanggil file executable aplikasi tersebut tanpa argumen maka akan menjalankan versi GUI dari aplikasi tersebut, namun bila memanggil file executable aplikasi tersebut dengan argumen maka akan menjalankan versi Console dari aplikasi tersebut (atau versi GUI namun dengan form yang berbeda dengan form utama, tergantung dari argumen dan parameter yang diberikan).
Setelah Googling, melalui .NET C# hal ini dapat dilakukan dengan beberapa trik, antara lain:
void Mainprogram lakukan seleksi kondisi bila argumen diberikan maka menjalankan versi Console, bila tidak diberikan maka menjalankan versi GUI menggunakan
FreeConsole(); Application.Run(new Form1());
FreeConsole digunakan untuk mem-free-kan console yang dibuat otomatis karena kita pilih Console Application. Namun, sayangnya melalui cara ini, maka ketika kita menjalankan program maka akan terlihat di layar window Console dibuat dan hilang dan digantikan oleh Form1. Sehingga program kita terlihat kurang “elegan”. (dicuplik dari web milik Ben [2])
AttachConsole untuk “menempelkan” Console pada program yang sejak awal dibuat sebagai WinForms Application. Walau mengkoding lebih banyak namun setidaknya ini jauh lebih elegan dibanding cara pertama yang menampilkan sekilas window console sebelum versi GUI ditampilkan. (dicuplik dari web milik Timm [3])
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Microsoft.Win32.SafeHandles;
using System.Diagnostics;
namespace ConsoleTest
{
static class Program
{
[DllImport("kernel32.dll")]
static extern bool AttachConsole(UInt32 dwProcessId);
[DllImport("kernel32.dll")]
private static extern bool GetFileInformationByHandle(SafeFileHandle hFile, out BY_HANDLE_FILE_INFORMATION lpFileInformation);
[DllImport("kernel32.dll")]
private static extern SafeFileHandle GetStdHandle(UInt32 nStdHandle);
[DllImport("kernel32.dll")]
private static extern bool SetStdHandle(UInt32 nStdHandle, SafeFileHandle hHandle);
[DllImport("kernel32.dll")]
private static extern bool DuplicateHandle(IntPtr hSourceProcessHandle, SafeFileHandle hSourceHandle, IntPtr hTargetProcessHandle,
out SafeFileHandle lpTargetHandle, UInt32 dwDesiredAccess, Boolean bInheritHandle, UInt32 dwOptions);
private const UInt32 ATTACH_PARENT_PROCESS = 0xFFFFFFFF;
private const UInt32 STD_OUTPUT_HANDLE = 0xFFFFFFF5;
private const UInt32 STD_ERROR_HANDLE = 0xFFFFFFF4;
private const UInt32 DUPLICATE_SAME_ACCESS = 2;
struct BY_HANDLE_FILE_INFORMATION
{
public UInt32 FileAttributes;
public System.Runtime.InteropServices.ComTypes.FILETIME CreationTime;
public System.Runtime.InteropServices.ComTypes.FILETIME LastAccessTime;
public System.Runtime.InteropServices.ComTypes.FILETIME LastWriteTime;
public UInt32 VolumeSerialNumber;
public UInt32 FileSizeHigh;
public UInt32 FileSizeLow;
public UInt32 NumberOfLinks;
public UInt32 FileIndexHigh;
public UInt32 FileIndexLow;
}
static void InitConsoleHandles()
{
SafeFileHandle hStdOut, hStdErr, hStdOutDup, hStdErrDup;
BY_HANDLE_FILE_INFORMATION bhfi;
hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
hStdErr = GetStdHandle(STD_ERROR_HANDLE);
// Get current process handle
IntPtr hProcess = Process.GetCurrentProcess().Handle;
// Duplicate Stdout handle to save initial value
DuplicateHandle(hProcess, hStdOut, hProcess, out hStdOutDup,
0, true, DUPLICATE_SAME_ACCESS);
// Duplicate Stderr handle to save initial value
DuplicateHandle(hProcess, hStdErr, hProcess, out hStdErrDup,
0, true, DUPLICATE_SAME_ACCESS);
// Attach to console window – this may modify the standard handles
AttachConsole(ATTACH_PARENT_PROCESS);
// Adjust the standard handles
if (GetFileInformationByHandle(GetStdHandle(STD_OUTPUT_HANDLE), out bhfi))
{
SetStdHandle(STD_OUTPUT_HANDLE, hStdOutDup);
}
else
{
SetStdHandle(STD_OUTPUT_HANDLE, hStdOut);
}
if (GetFileInformationByHandle(GetStdHandle(STD_ERROR_HANDLE), out bhfi))
{
SetStdHandle(STD_ERROR_HANDLE, hStdErrDup);
}
else
{
SetStdHandle(STD_ERROR_HANDLE, hStdErr);
}
}
///
/// The main entry point for the application.
///
[STAThread]
static void Main(string[] args)
{
bool NoGui = false;
string name = "";
int number = 0;
for (int i = 0; i != args.Length; ++i)
{
switch (args[i])
{
case "/NoGui": NoGui = true; break;
case "/name": name = args[++i]; break;
case "/number": number = int.Parse(args[++i]); break;
default: Console.WriteLine("Invalid args!"); return;
}
}
if (!NoGui)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
else
{
// initialize console handles
InitConsoleHandles();
// to demonstrate where the console output is going
int argCount = args == null ? 0 : args.Length;
Console.WriteLine("nnn************Console Application Starting!!!*************");
Console.WriteLine("You specified {0} arguments:", argCount);
Console.Error.WriteLine("This is the error channel");
for (int i = 0; i < argCount; i++)
{
Console.WriteLine(" {0}", args[i]);
}
Console.WriteLine("*************Console Application Ended!***********");
System.Windows.Forms.SendKeys.SendWait("{ENTER}");
}
}
}
}
Misal bila file executable nya adalah ConsoleTest.exe,
Untuk memanggil versi GUI maka langsung saja panggil
ConsoleTest.exe
Untuk versi Console-nya maka panggil
ConsoleTest.exe /NoGui /name testing /number 123
void Main
Article printed from Hikaru {Aka} Yuuki のブログ: http://www.hikaruyuuki.com
URL to article: http://www.hikaruyuuki.com/blog/buat-winforms-application-jadi-satu-dengan-versi-console-nya.html
URLs in this post:
[1] Your Ad Here: http://www.adbrite.com/mb/commerce/purchase_form.php?opid=1784967&afsid=1
[2] (dicuplik dari web milik Ben: http://benincampus.blogspot.com/2011/03/re-console-output-from-winforms.html
[3] dicuplik dari web milik Timm: http://www.csharp411.com/console-output-from-winforms-application/
[4] Your Ad Here: http://www.adbrite.com/mb/commerce/purchase_form.php?opid=1957137&afsid=1
[5] .NET WinForms vs Delphi (1): http://www.hikaruyuuki.com/blog/net-windows-forms-vs-delphi-1.html
[6] Spiderman versi Jepang, pernah nonton?: http://www.hikaruyuuki.com/blog/spiderman-versi-jepang-pernah-nonton.html
[7] Lagu buat yang lagi patah hati: http://www.hikaruyuuki.com/blog/lagu-buat-yang-lagi-patah-hati.html
[8] Buat dan Perjuangkan “Monster Media” Verbatim Buatanmu: http://www.hikaruyuuki.com/blog/buat-dan-perjuangkan-monster-media-buatanmu.html
[9] Membuat Tampilan Button Seperti Office 2010 dengan C#: http://www.hikaruyuuki.com/blog/membuat-tampilan-button-seperti-office-2010-dengan-c-sharp.html
Click here to print.
Copyright © 2011 Hikaru {Aka} Yuuki のブログ. All rights reserved.