분류 전체보기 (328)
.NET (111)
OOP (10)
Event (0)
웹서비스 (1)
ASP.NET (40)
C# (37)
JavaScript (10)
ADO.net (1)
XML.net (1)
Exchang server 2010 (3)
WPF (0)
HTML/CSS (6)
S/W tip (35)
etc (63)
DB (34)
HOT item~! (48)
Disign pettens (4)
UX (6)
나의 S/W (2)
개발관련 이슈 (16)
Diary (1)
웹플러스 (1)
calendar
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
tags
archive
link
ColorSwitch 00 01 02
▣  .NET/C# - 해당되는 글 37건

▣  LINQ - .NET/C# - 2010. 2. 19. 10:25

▣  화상키보드 관련 - .NET/C# - 2010. 2. 11. 18:30

안녕하세요?

 

C# 을 즐겨이 사용하는 전진우라고합니다 ^^

 

Win32 API를 C#에서 Import 해서 사용하는 방법이 있습니다.

 

포커싱된 윈도우에 키를 입력하는 함수는 keybd_event 가 있습니다.

 

제가 간단하게 코드를 한번 적어 볼께요..

 

  1. using System.Runtime.InteropServices;
  2. using System.Windows.Forms;
  3.  
  4. namespace YourNamespaceHere
  5. {
  6.   class Program
  7.   {
  8.     [DllImport("user32.dll")]
  9.     static extern uint keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
  10.  
  11.     static void Main(string[] args)
  12.     {
  13.       keybd_event((byte)Keys.A, 0, 0, 0); // 'A' key down
  14.       keybd_event((byte)Keys.A, 0, 0x02, 0); // 'A' key up (  0x02 = KEYEVENTF_KEYUP )
  15.     }
  16.   }
  17. }

이정도로 가능하겠습니다.

 

keydb_event 함수 원형은 아래와 같습니다 (MSDN 참고)

 

keybd_event

The keybd_event function synthesizes a keystroke. The system can use such a synthesized keystroke to generate a WM_KEYUP or WM_KEYDOWN message. The keyboard driver's interrupt handler calls the keybd_event function.

Windows NT: This function has been superseded. Use SendInput instead.

VOID keybd_event(  BYTE bVk,           // virtual-key code  BYTE bScan,         // hardware scan code  DWORD dwFlags,      // flags specifying various function options  DWORD dwExtraInfo   // additional data associated with keystroke);

 

bVk 파라메터에 Keys클래스를 이용해서 키 값을 적어주시면 포커스 된 윈도우에 메시지가 가게 됩니다.

 

bScan 파라메터는 0으로 두시면됩니다.

 

dwFlags 파라메터는 0x02 키 업, 0x00 키 다운 입니다.

 

dwExtraInfo 파라메터는 Shift, Ctrl, Alt키등을 함께 누르게도 할 수 있습니다.

 

아래는 가상키 와 bVk 파라메터에 넣어주시면 되는 값들을 나열했습니다.

 

가상키이름  bVK헥사값 bVK 파라메터  
VK_LBUTTON 1 1 마우스 왼쪽 버튼
VK_RBUTTON 2 2 마우스 오른쪽 버튼
VK_CANCEL 3 3 Ctrl + C
VK_MBUTTON 4 4 마우스 가운데 버튼
VK_BACK 8 8 Backspace
VK_TAB 9 9 Tab
VK_CLEAR 0C 12 CLEAR
VK_RETURN 0D 13 Enter
VK_SHIFT 10 16 Shift
VK_CONTROL 11 17 Ctrl(좌측)
VK_MENU 12 18 Alt(좌측)
VK_PAUSE 13 19 Pause Break
VK_CAPITAL 14 20 Caps Lock
VK_HANGUL 15 21 한/영 키
VK_HANJA 19 25 한자 키
VK_ESCAPE 1B 27 ESC
VK_SPACE 20 32 Spacebar
VK_PRIOR 21 33 Page Up
VK_NEXT 22 34 Page Down
VK_END 23 35 End
VK_HOME 24 36 Home
VK_LEFT 25 37 Left Arrow(←)
VK_UP 26 38 Up Arrow(↑)
VK_RIGHT 27 39 Right Arrow(→)
VK_DOWN 28 40 Down Arrow(↓)
VK_SELECT 29 41 Select
VK_EXECUTE 2B 43 EXECUTE
VK_SNAPSHOT 2C 44 PrtScr
VK_INSERT 2D 45 Insert
VK_DELETE 2E 46 Delete
VK_HELP 2F 47 Help
VK_0 30 48 0 키
VK_1 31 49 1 키
VK_2 32 50 2 키
VK_3 33 51 3 키
VK_4 34 52 4 키
VK_5 35 53 5 키
VK_6 36 54 6 키
VK_7 37 55 7 키
VK_8 38 56 8 키
VK_9 39 57 9 키
VK_A 41 65 A 키
VK_B 42 66 B 키
VK_C 43 67 C 키
VK_D 44 68 D 키
VK_E 45 69 E 키
VK_F 46 70 F 키
VK_G 47 71 G 키
VK_H 48 72 H 키
VK_I 49 73 I 키
VK_J 4A 74 J 키
VK_K 4B 75 K 키
VK_L 4C 76 L 키
VK_M 4D 77 M 키
VK_N 4E 78 N 키
VK_O 4F 79 O 키
VK_P 50 80 P 키
VK_Q 51 81 Q 키
VK_R 52 82 R
VK_S 53 83 S 키
VK_T 54 84 T 키
VK_U 55 85 U 키
VK_V 56 86 V 키
VK_W 57 87 W 키
VK_X 58 88 X 키
VK_Y 59 89 Y 키
VK_Z 5A 90 Z 키
VK_LWIN 5B 91 윈도우키(좌측)
VK_RWIN 5C 92 윈도우키(우측)
VK_APPS 5D 93 App Menu 키
VK_NUMPAD0 60 96 숫자키패드 0
VK_NUMPAD1 61 97 숫자키패드 1
VK_NUMPAD2 62 98 숫자키패드 2
VK_NUMPAD3 63 99 숫자키패드 3
VK_NUMPAD4 64 100 숫자키패드 4
VK_NUMPAD5 65 101 숫자키패드 5
VK_NUMPAD6 66 102 숫자키패드 6
VK_NUMPAD7 67 103 숫자키패드 7
VK_NUMPAD8 68 104 숫자키패드 8
VK_NUMPAD9 69 105 숫자키패드 9
VK_MULTIPLY 6A 106 숫자키패드 *
VK_NUMADD 6B 107 숫자키패드 +
VK_SEPARATOR 6C 108  SEPARATOR
VK_SUBTRACT 6D 109 숫자키패드 -
VK_DECIMAL 6E 110 숫자키패드 .
VK_DEVIDE 6F 111 숫자키패드 /
VK_F1 70 112 F1 키
VK_F2 71 113 F2 키
VK_F3 72 114 F3 키
VK_F4 73 115 F4 키
VK_F5 74 116 F5 키
VK_F6 75 117 F6 키
VK_F7 76 118 F7 키
VK_F8 77 119 F8 키
VK_F9 78 120 F9 키
VK_F10 79 121 F10 키
VK_F11 7A 122 F11 키
VK_F12 7B 123 F12 키
VK_F13 7C 124 F13 키
VK_F14 7D 125 F14 키
VK_F15 7E 126 F15 키
VK_F16 7F 127 F16 키
VK_F17 80 128 F17 키
VK_F18 81 129 F18 키
VK_F19 82 130 F19 키
VK_F20 83 131 F20 키
VK_F21 84 132 F21 키
VK_F22 85 133 F22 키
VK_F23 86 134 F23 키
VK_F24 87 135 F24 키
VK_NUMLOCK 90 144 Num Lock 키
VK_SCROLL 91 145 Scroll Lock 키

 

꼭 성공하시고,

 

즐거운 프로그래밍 하셔요 ^^



▣  COM등록 - .NET/C# - 2010. 1. 20. 15:03

▣  c# pannel 참고 - .NET/C# - 2009. 12. 23. 14:11

 

드디어 몇개월동안 고민했던 c# 더블버퍼링 문제 해결!

더블버퍼링 하는 법은 진작부터 알고 있었는데, panel에도 적용시켜줘야 한다는걸 몰랐다.

우리나라 싸이트에는 역시 해답이 없는데

구글에서 c# panel doublebuffering이라고 쳐서 해결

다음은 쓴 소스


public class DoubleBufferPanel : Panel
{
   public DoubleBufferPanel()
   {
     // Set the value of the double-buffering style bits to true.
     this.SetStyle(ControlStyles.DoubleBuffer |
       ControlStyles.UserPaint |
       ControlStyles.AllPaintingInWmPaint,
       true);

     this.UpdateStyles();
   }
}

이렇게 해준 후에 form1.designer.cs에 가서 panel 부분을 찾아준후 이렇게 바꿔주면 끝
panel1 = new System.Windows.Forms.Panel(); 을

panel1 = new DoubleBufferPanel();

아 기쁘다 내일은 얼른 세부구현 만들어서 넘겨야지!

해결하고 났더니 코딩하고 싶은 마음이 굴뚝같이 생김 ㅋㅋ

[출처] C# 더블버퍼링|작성자 별한아름




출처 : http://cafe.naver.com/winform.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=103


 

주     제 BindingNavigator  

 
 작 성 자 : 박종명 (mkex)   


 작 성 일 : 2008년 02월 13일(수)  

  
 수 정 일 : 2008년 02월 13일(수) 

 

이번 포스트에서는 비동기 작업을 지원하는 BackgroundWorker 컴포넌트에 대해 알아 보겠습니다.

 

참고로 구성요소로 번역되는 컴포넌트는 컨트롤과는 달리 UI 를 가지고 있지 않습니다.

아래처럼 Visual Studio 의 도구상자를 통해 폼에 이 컴포넌트를 올리면 폼에 특별한 UI 는 나타나지 않은 채

하위 컴포넌트 목록 창에만 표시됩니다.

 

뭐.. 중요한 내용은 아니었구요..

 

비동기 작업이란 수행 시간이 오래 걸리는 작업을 백그라운드 상에서 별도로 처리한게 하는 방법입니다.

즉 메인 쓰레드와 분리된 쓰레드에서 작업을 수행하도록 하여 응용프로그램의 블럭을 방지하고 지연을

최소화하는 프로그래밍 방식입니다.

 

MSDN에서는 수행시간이 오래 걸리는 작업을 다음처럼 예시하고 있습니다.

  • 이미지 다운로드

  • 웹 서비스 호출

  • 파일 다운로드 및 업로드(피어-투-피어 응용 프로그램에 대한 다운로드 및 업로드 포함)

  • 복잡한 로컬 계산

  • 데이터베이스 트랜잭션

  • 로컬 디스크 액세스(메모리 액세스에 비해 상대적으로 속도가 느림)

     

    그리고 MSDN의 설명 한 마디를 보시죠..

    "BackgroundWorker 구성 요소를 사용하면 응용 프로그램의 주 UI 스레드와 다른 스레드에서 시간이 많이 소모되는

    작업을 백그라운드"에서 비동기적으로 실행할 수 있습니다"

     

    BackgroundWorker 컴포넌트는 닷넷 2.0 부터 새로이 추가된 컴포넌트 입니다.

    물론 이전 버전에서도 사용할 수 있었지만 닷넷 프레임워크에 포함된 형태는 아니었었습니다.

     

    BackgroundWorker 를 사용하기 전에는 이러한 비동기 작업을 처리하기 위해서 수동으로 작업자 쓰레드(Worker Thread)를

    직접 생성해서 주 쓰레드(Main Thread) 와 분리하여 작업을 처리하는 코드를 직접 작성했어야 했으며,

    작업 진행상황이나 작업 취소와 같은 일련의 작업을 개발자가 직접 해 주어야 했습니다.

    쓰레드에 관해서는 다음의 사이트의 글들을 참고 하시기 바랍니다.

     

    Process & Thread 개요

    Mulit Thread Programming

    ThreadState (Thread 상태)

    공급자/소비자 문제로 알아보는 동기화 문제

    [동기화] Monitor 클래스

    [동기화] Interlocked 클래스 와 lock 문

    [동기화] Mutex 클래스

    [동기화] Event

     

    이렇듯 멀티 쓰레드 프로그래밍을 작성할 때는 다양한 이슈가 있습니다.

    쓰레드 자체에 대한 자세한 내용은 위의 링크 및 기타 다른 자료로 학습을 하시면 되겠습니다.

    이번 글에서는 BackgroundWorker 컴포넌트의 사용방법에 대해서 다루겠습니다.

     

    * BackgroundWorker 의 이벤트

    이 컴포넌트를 사용하여 비동기 작업을 하고하 할 경우 알아야 이벤트에 대해서 알아 보겠습니다.

    BackgroundWorker 컴포넌트에는 3개의 이벤트가 있습니다.

     

    1) DoWork

        백그라운드 작업의 실제 실행을 처리하는 이벤트 입니다.

        단 이 이벤트는 자동으로 발생하지 않고 BackgroundWorker 의 RunWorkerAsync 메서드가 호출될 때 발생하게 됩니다.

        즉 개발자가 비동기 작업을 위해 RunWorkerAsync 메서드를 호출하면 자동으로 DoWork 이벤트가 발생하게 됩니다.

        RunWorkerAsync -> DoWork

     

    2) ProgressChanged

        백그라운드 작업의 진행률을 처리하기 위한 이벤트 입니다.

        이 이벤트 역시 개발자가 수종으로 발생 시켜줘야 하는데,

        BckgroundWorker 의 ReportProgress 메서드를 명시적으로 호출하여 이벤트를 발생시킬 수 있습니다.

        또한 연관된 속성으로는 WorkerReportProgress 로써 이 속성이 참(true) 로 설정되어 있어야 됩니다.

        ReportProgress -> ProgressChanged

     

    3) RunWorkerCompleted

        백그라운드 작업의 완료, 중도 취소, 예외가 생겼을 때 발생하는 이벤트 입니다.

        연관된 속성으로는 WorkerSupportsCancellation 로써 이 속성이 참(true) 로 설정되어 있어야 합니다.

        이 이벤트의 매개변수인 RunWorkerCompletedEventArgs 객체를 통해 작업이 중도에 취소되었는지, 예외가 발생했는지

        를 알 수 있습니다.

     

    이상 3가지 이벤트를 사용하여 손 쉽게 백그라운드 작업을 구현하실 수 있게 됩니다.

       

     

    * Demo

    일단 다음과 같이 오래 걸리는 작업을 수행하는 메서드(DelayMethod)를 작성하도록 합니다.

    현재 이 글에서는 이 작업이 무엇을 하는지가 중요한게 아니라 오래 걸리는 작업이 중요한 포인터이기 때문에

    실제로 오래걸릴만한 작업이 아닌 의도적으로 중간에 Sleep 를 걸어 두도록 하겠습니다.

     

    다음의 코드가 작업이 오래 걸리는 역할을 하는 메서드 정의입니다.

    매개변수로 최대값을 받아서 순차적으로 더해 갑니다. 그리고 최종 더한 값을 반환하도록 합니다.

    메서드의 지연처리를 위해 중간에 Thread.Sleep 으로 수행을 잠시 멈춥니다.

    (실제로 이런 코드는 있을 수는 없겠죠.. 하지만 테스트를 위해 아래처럼 작성하도록 합니다)

     private Int64 DelayMethod(int maxNumber)
     {
          Int64 result = 0;
          for (int i = 1; i <= maxNumber; i++)
          {
              result += i;
              System.Threading.Thread.Sleep(100);

          }

          return result;
     }

     

     

    1. 비동기로 처리 하지 않을 경우

    위 메서드를 백그라운드에서 처리하지 않고 동기방식으로 처리하도록 해 보겠습니다.

    폼에 버턴을 하나 두고 버턴을 클릭하면 위 메서드가 수행되고 끝나면 결과값을 Label 에 기록하는 간단한 샘플입니다.

    버턴이 클릭 되었을 때 다음처럼 메서드를 호출합니다.

     

    Int64 result =  DelayMethod(100);
    this.lblResult.Text = result.ToString();

     

    최대값을 100 을 주었고 중간중간에 100밀리 세컨드 만큼 수행을 멈추므로 이 작업은 시간이 조금 걸리는 작업이 됩니다.

    직접 실행을 해 보면 버턴을 클릭하고 난 후 부터 작업이 완료될 때 까지 폼이 멈춰버리고 다른 어떠한 작업도 할 수 없게 됩니다.

    또한 이 폼을 다시 보이게 하려면 다음처럼 하얀색 빈 바탕 화면처럼 나오게 됩니다.

     

    = 원래 폼 모양 =

       

     

    = 수행 도중 창을 내렸다가 다시 올렸을 경우의 모양 =

     

    시간이 오래 걸리는 작업을 동기로 구현한다면 이러한 문제가 발생합니다.

    즉 UI 쓰레드에서 직접 메서드를 수행하기 때문에 다른 곳에서는 제어권을 받을 수 가 없게 되는 것입니다.

     

     

    2. BackgroundWorker 를 이용해 비동기로 처리하기.

     

    이제 위 메서드를 비 동기로 처리 해 보겠습니다.

    우선 폼의 모양을 아래처럼 조금 다듬습니다.

     

    최대값을 사용자로 부터 입력 받기 위한 NumericUpDown 컨트롤과 작업의 시작,취소 버턴

    그리고 작업 진행률을 보기 위한 ProgressBar , 결과값 출력을 위한 Lable 컨트롤을 적절히 배치 하였습니다.

    이 샘플은 msdn 의 BackgroundWorker 샘플 중 피보나치 수열을 계산하는 샘플을 조금 변형한 것입니다.

     

     

    ① 비 동기 작업의 진행률과 취소를 지원하기 위해 두개의 속성을 설정합니다.

        (이 코드에서는 Form_Load 이벤트에서 작성합니다. 디자인 타임에 속성 창을 통해서 하셔도 됩니다)

       

     //최대값 저장을 위한 멤버 변수

     int maxNumber = 10; 

     

     //폼 로드 이벤트

     private void Form1_Load(object sender, EventArgs e)
     {
          //작업 진행률을 보고할 수 있도록 설정한다.
          this.backgroundWorker1.WorkerReportsProgress = true;
          //작업을 취소할 수 있도록 설정한다.
          this.backgroundWorker1.WorkerSupportsCancellation = true;
     }

     

    ② 다음으로 '작업 시작' 버턴을 클릭했을 때 다음 처럼 비동기 작업을 시작하도록 합니다.

     private void startAsyncButton_Click(object sender, EventArgs e)
     {

          //시작된 이후에 필요하지 않은 컨트롤은 사용 불가 처리 한다.

          this.numericUpDown1.Enabled = false;
          this.lblResult.Text = String.Empty;                                  
          this.startAsyncButton.Enabled = false;           
          this.cancelAsyncButton.Enabled = true;

     

          // 최대값 얻기
          int maxNumber = (int) numericUpDown1.Value;

     

          // 진행률 퍼센트 계산을 위한 변수 초기화
          highestPercentageReached = 0;

     

          //백그라운드 작업을 시작한다.이 메서드 호출은 DoWork 이벤트를 발생시킨다

          //이때 매개변수로 최대값을 넘겨 준다
          backgroundWorker1.RunWorkerAsync(maxNumber);
     }

     

     

    ③ 이제 본격적으로 BackgroundWorker 컴포넌트의 이벤트를 작성합니다.

     

    = DoWork 이벤트 =

     private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
     {           
          BackgroundWorker worker = sender as BackgroundWorker;
               
          //실제로 백그라운드에서 돌아갈 메서드를 호출한다 

          //이때 앞서 RunWorkerAsync 메서드 호출 시 전달한 매개변수를 e.Argument 로 다시 넘긴다.

          //그리고 비동기 작업의 결과 값을 EventArgument 의 Result 에 저장한다.
          e.Result = this.DelayMethod((int)e.Argument, worker, e);

     }

     

    = ProgressChanged 이벤트 =

     //BackgroundWorker 의 ReportProgress가 호출될때 발생한다. 비동기 작업 진행률을 보고 받는다
     private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
     {

          //ProgressBar 에 진행률을 표시한다
          this.progressBar1.Value = e.ProgressPercentage;
     }

     

    = RunWorkerCompleted 이벤트 =

     //백그라운드 작업이 완료되거나 취소되거나 예외를 발생시켰을 때 발생합니다
     private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
     {            
          //작업에 오류가 발생하면 메세지를 띄운다
           if (e.Error != null)
          {
              MessageBox.Show(e.Error.Message);
          }
          //작업이 취소되었으면 취소되었다는 메세지를 보여준다
          else if (e.Cancelled)
          {                
              lblResult.Text = "작업이 취소되었습니다";
          }
          //작업이 완료되면 결과값을 보여준다
          else
          {
              //결과값 출력
              lblResult.Text = e.Result.ToString();
          }
               
          //기타 컨트롤 사용가능케 설정
          this.numericUpDown1.Enabled = true;            
          startAsyncButton.Enabled = true;           
          cancelAsyncButton.Enabled = false;
     }

     

    ④ 취소 버턴 클릭 이벤트를 작성합니다

     private void cancelAsyncButton_Click(object sender, EventArgs e)
     {
          //비동기 작업을 취소를 요청한다.

          //이 메서드 호출로 BackgroundWorker 의 CancellationPending 속성이 true로 설정한다
          this.backgroundWorker1.CancelAsync();

          //취소 버턴 비활성화
          cancelAsyncButton.Enabled = false;
     }

     

    ⑤ 비동기로 수행될 메서드

    실제 시간이 오래 걸리는 작업을 하는 메서드 정의 입니다.

    기존 비지니스 처리 이외에 BackgroundWorker 의 작업 취소 감지 및 진행률 보고 로직이 포함되어야 합니다

     private Int64 DelayMethod(int maxNumber, BackgroundWorker worker, DoWorkEventArgs e)
     {
          Int64 result = 0;


          for (int i = 1; i <= maxNumber; i++)
          {
              //백그라운드 작업을 취소 했는지 검사한다.
             if (worker.CancellationPending)
             {
                  e.Cancel = true;
             }
             else
             {
                  result += i;

     

                  //진행률을 % 로 계산한다.
                  int percentComplete = (int) ((float)i / (float)maxNumber * 100);

                  if (percentComplete > highestPercentageReached)
                  {
                      highestPercentageReached = percentComplete;

     

                      //ProgressChanged 이벤트를 발생시킨다
                      //작업의 완료률을 0~100 숫자로 보고한다
                      worker.ReportProgress(percentComplete);
                   }

     

                  //지연을 위해 잠시 멈춘다
                  Thread.Sleep(100);
             }
        }       

          //수행을 마치면 결과 값을 반환한다
          return result;            
     }

     

    이제 코드 작성이 완료 되었습니다.

    첨부파일에 이 글에 사용된 샘플 프로젝트가 등록되어 있으니 다운받으셔서 직접 실행 시켜 보시기 바랍니다.

    아래 그림은 프로젝트를 실행완료한 화면 입니다.

     

    이상 닷넷 2.0 에 새로 추가된 BackgroundWorker 컴포넌트에 대해 간략히 살펴 보았습니다.

     


  • ▣  COM INTEROP - .NET/C# - 2009. 10. 13. 16:09

    http://blog.naver.com/horsepia/90004035909

    COM Interop Part 2: C# Server Tutorial

    COM Interop allows COM developers to access managed code as easily as they access other COM objects. This tutorial demonstrates using a C# server with a C++ COM client. It also explains the following activities:

    • How to create the C# server
    • How to create the COM client

    The tutorial also briefly demonstrates the marshaling that is automatically applied between managed and unmanaged components.

    COM Interop Part 1: C# Client Tutorial shows the fundamentals of using C# to interoperate with COM objects and is a prerequisite for this tutorial. For an overview of both tutorials, see COM Interop Tutorials.

    Sample Files

    See COM Interop Part 2 Sample to download and build the sample files discussed in this tutorial.

    Further Reading

    Tutorial

    This tutorial demonstrates the following activities to create the C# server:

    • How to use the Guid attribute on interfaces and classes to expose them as COM objects and how to generate a globally unique identifier (GUID) for the Guid attribute.
    • How to use RegAsm to register a .NET Framework program for use by COM clients and create a type library (.tlb file) from a .NET Framework program.

    The tutorial also demonstrates the following activities to create the COM client:

    • How to export managed servers and how to use them to create COM objects.
    • How to import the .tlb file, generated by RegAsm, into the COM client and how to use CoCreateInstance to create an instance of a .NET Framework coclass.
      Note   To create a GUID for interfaces and coclasses that you export to COM clients, use the tool Guidgen.exe, shipped as part of Visual Studio. Guidgen allows you to choose the format in which the GUID is expressed so you don't have to retype it. For more information on Guidgen, see the Knowledge Base article Q168318 "XADM: Guidgen.exe Available Only for Intel Platforms." KB articles are available in the MSDN Library and on the Web at http://support.microsoft.com.

    Example

    This example consists of two files:

    • A C# file, CSharpServer.cs, that creates the CSharpServer.dll file. The .dll is used to create the file CSharpServer.tlb.
    • A C++ file, COMClient.cpp, that creates the executable client, COMClient.exe.

    File 1: CSharpServer.cs

    // CSharpServer.cs
    // compile with: /target:library
    // post-build command: regasm CSharpServer.dll /tlb:CSharpServer.tlb
    
    using System;
    using System.Runtime.InteropServices;
    namespace CSharpServer
    {
       // Since the .NET Framework interface and coclass have to behave as 
       // COM objects, we have to give them guids.
       [Guid("DBE0E8C4-1C61-41f3-B6A4-4E2F353D3D05")]
       public interface IManagedInterface
       {
          int PrintHi(string name);
       }
    
       [Guid("C6659361-1625-4746-931C-36014B146679")]
       public class InterfaceImplementation : IManagedInterface
       {
          public int PrintHi(string name)
          {
             Console.WriteLine("Hello, {0}!", name);
             return 33;
          }
       }
    }

    File 2: COMClient.cpp

    // COMClient.cpp
    // Build with "cl COMClient.cpp"
    // arguments: friend
    
    #include <windows.h>
    #include <stdio.h>
    
    #pragma warning (disable: 4278)
    
    // To use managed-code servers like the C# server, 
    // we have to import the common language runtime:
    #import <mscorlib.tlb> raw_interfaces_only
    
    // For simplicity, we ignore the server namespace and use named guids:
    #if defined (USINGPROJECTSYSTEM)
    #import "..\RegisterCSharpServerAndExportTLB\CSharpServer.tlb" no_namespace named_guids
    #else  // Compiling from the command line, all files in the same directory
    #import "CSharpServer.tlb" no_namespace named_guids
    #endif
    int main(int argc, char* argv[])
    {
       IManagedInterface *cpi = NULL;
       int retval = 1;
    
       // Initialize COM and create an instance of the InterfaceImplementation class:
       CoInitialize(NULL);
       HRESULT hr = CoCreateInstance(CLSID_InterfaceImplementation,
                   NULL, CLSCTX_INPROC_SERVER,
                   IID_IManagedInterface, reinterpret_cast<void**>(&cpi));
    
       if (FAILED(hr))
       {
          printf("Couldn't create the instance!... 0x%x\n", hr);
       }
       else
       {
          if (argc > 1)
          {
             printf("Calling function.\n");
             fflush(stdout);
             // The variable cpi now holds an interface pointer 
             // to the managed interface.
             // If you are on an OS that uses ASCII characters at the 
             // command prompt, notice that the ASCII characters are 
             // automatically marshaled to Unicode for the C# code.
             if (cpi->PrintHi(argv[1]) == 33)
                retval = 0;
             printf("Returned from function.\n");
          }
          else
             printf ("Usage:  COMClient <name>\n");
          cpi->Release();
          cpi = NULL;
       }
    
       // Be a good citizen and clean up COM:
       CoUninitialize();
       return retval;
    }

    Output

    The executable client can be invoked with the command line: COMClient <name>, where <name> is any string you want to use, for example, COMClient friend.

    Calling function.
    Hello, friend!
    Returned from function.

    In the sample IDE project, set the Command Line Arguments property in the project's Property Pages to the desired string (for example, "friend").

    top
    :

    ▣  c#배포 및 설치 - .NET/C# - 2009. 8. 17. 14:13
    안녕하세요? 맨날맑음 입니다.

    .NET 으로 프로젝트를 만들고, 배포를 하는 방법은 Click Once같은 방법도 있지만 이번에는 Windows Installer 배포에 대해 알아보겠습니다. 기존에 .Net으로 프로젝트 개발만 해보았지, 배포는 신경을 쓰지 않아 잘 모르다가, 이번에 VS2008에서 기본으로 제공되는 배포 프로젝트의 사용법을 알아 보았습니다.
    아래 링크를 따라가면 배포프로젝트에 관한 MSDN 도움말을 보실 수 있습니다.
    http://msdn.microsoft.com/ko-kr/library/206sadcd(VS.80).aspx

    우선 배포할 프로그램을 준비합니다. 저는 간단한 윈폼 프로젝트로 하겠습니다.

    VS2008에서 새 프로젝트를 추가 하고, 기타 프로젝트 형식 -> 설치 및 배포 -> 설치프로젝트를 선택합니다.

    다음과 같이 배포 프로젝트가 생성됩니다.

    솔루션 탐색기와 속성 창을 보면 아래와 같이 프로젝트와, 여러 속성이 보이게 됩니다.
    이제 이 속성들의 의미를 하나하나 알아보겠습니다.
    ▷AddRemoveProgramIcon : 제어판 -> 프로그램 추가/제거에 표시될 아이콘을 등록합니다.
    ▷Author : 프로젝트 작성자의 이름을 등록합니다.
    ▷Desciption : 설치 관리자에 관한 설명을 등록합니다.
    ▷DetectNewerInstalledVersion : 프로그램 설치시 버전 비교를 통해 새 버전인지 확인 해 줍니다. 이미 설치 되있을 경우 설치 되어있다고 알려주기도 합니다.
    ▷Keyword : 설치 관리자를 검색하는데 사용 할 키워드를 지정합니다.
    ▷Localization : 로케일을 적용한다고 하는데, 글로벌 프로그램이 아니라면 신경 안써도 될 듯 합니다.
    ▷Manufacturer : 제조업체의 이름을 지정합니다
    ▷MunufacturerUrl : 제조업체의 홈페이지 링크를 지정.
    ▷PostBuildEvent : 배포프로젝트를 빌드한 후에 실행 할 명령줄을 지정합니다.
    ▷PreBuildEvent : 배포프로젝트를 빌드하기 전에 실행 할 명령줄을 지정합니다.
    ▷ProductCode : 응용프로그램의 고유 식별자(GUID)를 지정합니다.
    ▷ProductName : 프로그램의 공개 이름을 지정합니다.
    ▷RemovePrevionsVersions : 설치시 이전버전을 삭제 할지를 지정합니다.
    ▷RunPostBuildEvent : PostBuildEvent 속성에서 지정된 명령줄을 실행할 시기를 결정합니다.
    ▷SearchPath : 개발 컴퓨터의 어셈블리, 파일 또는 병합 모듈을 검색하는 데 사용되는 경로를 지정합니다.
    Subject : 프로그램을 설명하는 추가정보를 지정합니다.
    ▷SupportPhone : 전화번호를 지정합니다.
    ▷SupportUrl : 마찬가지로 추가 설명을 하는 웹사이트 주소
    TargetPlatform : 프로그램이 실행될 플랫폼을 지정.
    ▷Title : 설치 관리자의 제목을 지정합니다.
    ▷UpgradeCode : 프로그램 버전이 여러가지 일때 고유식별자를 지정합니다.
    ▷Virsion : 버전을 지정합니다.




    속성 참 많네요.. 정작 중요한건 ProductName, Title, Author, MAnufacturer 정도 입니다.

    이제 파일시스템 탭으로 이동하여 대상 컴퓨터의 파일 시스템 -> 응용 프로그램 폴더를 선택한 후 속성창을 확인합니다.

    DefalutLocation이라는 속성에 [ProgramFilesFolder][Manufacturer]\[ProductName] 라고 되어 있습니다. 인스톨시 프로그램이 설치될 폴더 인데요. 이 설정으로 하게 되면 프로그램파일 폴더 밑에 제조회사명 밑에 프로그램 이름 폴더 안에 깔리게 되겠습니다. 맘에 드는 폴더로 변경 하시면 됩니다.

    이제 파일을 추가 해 보겠습니다. 응용 프로그램 폴더에서 마우스 오른쪽 버튼을 누르면 파일이나 폴더등을 추가 할 수 있습니다. 미리 만들어 놓은 샘플 어플리케이션을 추가 하겠습니다.


    이렇게 하면 앞서 지정된 설치 폴더에 MainApp.exe가 설치 됩니다. 명색이 인스톨 프로그램인데 이것만 지정하면 안되겠죠? 위에 사용자 바탕화면사용자 프로그램 메뉴가 보입니다.
    말 그래로 사용자 바탕화면은 바탕화면에 설치 될 파일을 지정 할 수 있고, 사용자 프로그램 메뉴는 [시작]->[프로그램]의 폴더나 파일을 지정 할 수 있습니다.
    바탕화면과 프로그램 메뉴에 MainApp.exe의 바로가기를 넣어주면 클라이언트가 아주 편리 할 것 같습니다.
    MainApp.exe를 마우스 오른쪽 버튼으로 클릭하여 바로가기를 만듭니다. 저는 두개를 만들어 이름을 원하는데로 변경한 후 하나는 사용자 바탕화면으로 끌어다 놓았고, 사용자 프로그램 메뉴에는 [새폴더]를 하나 추가 하여, 그 안에 넣었습니다. 그리고 아이콘 파일(.ico)도 하나 추가하여 바로가기의 속성중 Icon에 연결 시켜 줍니다. 그럼 바로가기가 우리가 지정한 아이콘으로 생성 됩니다.

    이제 언인스톨 기능을 하는 바로가기도 지원해 주어야 좀 더 있어보일 것입니다.
    바탕화면에서 텍스트문서(txt)를 하나 추가해서 확장자를 bat로 바꾸어 줍니다. 편집기로 파일을 열어 Msiexec /x {ProductCode} 를 추가 해 줍니다. 여기서 ProductCode는 위에 프로젝트 속성중에 있던 코드 입니다. 지금 예제 대로 하면 Msiexec /x {A1715BBB-A953-4F01-B788-168542ED2BC3} 이 되겠네요.

    현재 배포하는 샘플 프로그램이 매우 간단하여 파일이 하나이지만, 대부분의 응용은 여러 DLL을 포함하고 있을것입니다. 그리고 각 파일마다 설치하고 싶은 경로가 다를 수 있는데, 파일시스템 탭의 대상 컴퓨터의 파일 시스템을 오른쪽 버튼으로 누르면 특수폴더 추가에서 원하는 폴더를 추가 할 수 있습니다.

    이제 이 파일을 응용프로그램 폴더에 포함 시켜주고, 마찬가지 방법으로 바로 가기를 만들어서 원하는 곳에 추가 시켜 줍니다. 프로젝트를 다시 빌드 하고 테스트 해보겠습니다. 프로젝트 폴더의 Relese 폴더에 들어가니 파일이 두개 보입니다.(Relese모드로 빌드 했을 경우, Debug 모드 일경우 Debug 폴더에 생성)
    Setup.exe를 더블 클릭하니 설치가 잘 됩니다.
    설치시 생긴 바로가기 아이콘으로 Uninstall도 잘되는지 확인해 보겠습니다.
    정상적으로 잘 되는걸 볼 수 있습니다. 쓰다 보니 스크롤의 압박이군요;
    만약 설치 대상컴퓨터(클라이언트)에 .Net Framwork가 없을때 자동으로 설치되게 하는 것 까지 쓰려고 했는데,
    다음편으로 넘겨야 할 것 같습니다. 다음편에는 이같은 기능을 해주는 Boot Strapper에 관해 포스팅 하겠습니다.
    top
    :

    ▣  Console Output 을 텍스트 파일로 남겨보자 - .NET/C# - 2009. 6. 26. 19:21

    Console.WriteLine() 은 콘솔창에 데이터를 출력하기 위해 많이 사용한다.

    이렇게 출력되는 데이터를 텍스트 파일로 남기고 싶다면 아래와 같이 한다.


    실행프로그램 이름이 "test.exe" 이고, 로그파일의 이름이 "log.txt" 라면

    아래 그림과 같이 하면 된다.



    그럼 프로그램이 실행되면서 "log.txt" 파일에 기록이 시작된다.

    프로그램 종료 후 로그파일을 확인해 보자.

    top
    :

    ▣  c# 시작 - .NET/C# - 2009. 6. 2. 16:27

    자료출처 : http://msdn.microsoft.com/ko-kr/library/ms186214.aspx


    ==> 책에 있을 법한 이야기들이다. 이렇게까지 하는 이유야 중요하니까? 천천히 읽어보자!


    Visual C# 시작
    C# 언어(C# 작업 절차)

    이 항목에서는 일반적으로 사용되는 C# 언어 작업에 대한 도움말의 링크를 제공합니다. 도움말에서 설명하는 일반적인 작업의 다른 범주를 보려면 C# 작업 절차를 참조하십시오.

    Visual C#의 새로운 기능

    쿼리 식, 컬렉션 이니셜라이저, 람다 식, 익명 형식, 자동으로 구현된 속성, 부분 메서드(Partial Method) 등의 새로운 언어 기능에 대한 정보가 들어 있습니다. Visual C# IDE의 새로운 기능에 대한 정보도 제공합니다.

    C# 시작 키트 사용

    Visual C# 시작 키트를 로드하고 빌드하는 방법에 대해 설명합니다.

    C# 언어 사양

    최신 버전의 사양(Microsoft Word 형식)에 대한 링크를 제공합니다.

    Main()과 명령줄 인수(C# 프로그래밍 가이드)

    개체를 만들고 다른 메서드를 호출할 수 있는 프로그램의 진입점인 Main 메서드에 대해 설명합니다. C# 프로그램에는 진입점이 하나만 있을 수 있습니다.

    방법: foreach를 사용하여 명령줄 인수 액세스(C# 프로그래밍 가이드)

    명령줄 매개 변수에 액세스하는 방법을 보여 주는 코드 예제를 제공합니다.

    방법: 명령줄 인수 표시(C# 프로그래밍 가이드)

    args 문자열 배열을 통해 명령줄 인수를 표시하는 방법에 대해 설명합니다.

    Main() 반환 값(C# 프로그래밍 가이드)

    Main 메서드의 가능한 반환 값에 대해 설명합니다.

    방법: 생성자를 호출하지 않고 개체 초기화(C# 프로그래밍 가이드)

    개체 이니셜라이저 사용 방법을 보여 줍니다.

    base(C# 참조)

    파생 클래스의 인스턴스를 만들 때 호출되는 기본 클래스 생성자를 지정하는 방법에 대해 설명합니다.

    방법: 메서드에 대한 구조체 전달과 클래스 참조 전달 간의 차이점 이해(C# 프로그래밍 가이드)

    구조체를 메서드로 전달할 때는 구조체의 복사본이 전달되지만 클래스 인스턴스를 전달할 때는 참조가 전달된다는 사실을 보여 주는 코드 예제를 제공합니다.

    인스턴스 생성자(C# 프로그래밍 가이드)

    클래스 생성자 및 상속에 대해 설명합니다.

    방법: 복사 생성자 작성(C# 프로그래밍 가이드)

    클래스의 생성자에서 다른 개체를 인수로 사용하는 방법을 보여 주는 코드 예제를 제공합니다.

    방법: 구조체 간의 사용자 정의 변환 구현(C# 프로그래밍 가이드)

    두 개의 구조체를 정의하고 두 구조체 간의 변환을 보여 주는 코드 예제를 제공합니다.

    Boxing 변환(C# 프로그래밍 가이드)

    값 형식과 boxed 개체에 서로 다른 값을 저장하는 방법을 보여 주는 예제를 제공합니다.

    Unboxing 변환(C# 프로그래밍 가이드)

    잘못 boxing된 경우 오류 메시지를 표시하는 방법을 보여 주는 코드 예제를 제공합니다.

    개체 형식 배열(C# 프로그래밍 가이드)

    배열의 차수를 표시하는 코드 예제를 제공합니다.

    가변 배열(C# 프로그래밍 가이드)

    배열을 요소로 사용하는 배열을 만드는 코드 예제를 제공합니다.

    배열을 매개 변수로 전달(C# 프로그래밍 가이드)

    문자열 배열을 초기화하여 배열의 요소를 출력하는 PrintArray 메서드에 매개 변수로 전달하는 코드 예제를 제공합니다.

    ref 및 out을 사용하여 배열 전달(C# 프로그래밍 가이드)

    메서드에 배열을 전달하는 데 사용된 outref 간의 차이점을 보여 주는 코드 예제를 제공합니다.

    방법: 쿼리 식에서 암시적으로 형식화된 지역 변수 및 배열 사용(C# 프로그래밍 가이드)

    배열과 지역 변수에 대한 암시적 형식 지정을 사용하는 방법을 설명합니다.

    방법: 자동으로 구현된 속성을 사용하여 간단한 클래스 구현(C# 프로그래밍 가이드)

    속성 집합을 캡슐화하는 작은 클래스를 만드는 방법을 설명합니다.

    방법: 읽기/쓰기 속성 선언 및 사용(C# 프로그래밍 가이드)

    읽기/쓰기 속성을 선언하고 사용하는 방법을 보여 주는 예제를 제공합니다.

    방법: 추상 속성 정의(C# 프로그래밍 가이드)

    추상 속성을 정의하는 방법을 보여 주는 코드 예제를 제공합니다.

    값 형식 매개 변수 전달(C# 프로그래밍 가이드)

    다양한 방법으로 값 형식을 전달하는 방법을 보여 주는 코드 예제를 제공합니다.

    참조 형식 매개 변수 전달(C# 프로그래밍 가이드)

    다양한 방법으로 참조 형식을 전달하는 방법을 보여 주는 코드 예제를 제공합니다.

    방법: 사용자 지정 확장 메서드 구현 및 호출(C# 프로그래밍 가이드)

    다른 형식의 인스턴스 메서드인 것처럼 호출되는 정적 메서드를 만드는 방법을 설명합니다.

    방법: 이벤트 구독 및 구독 취소(C# 프로그래밍 가이드)

    폼, 단추, 목록 상자 등을 포함하여 다른 클래스에서 게시한 이벤트를 구독하는 방법을 보여 줍니다.

    방법: .NET Framework 지침을 따르는 이벤트 게시(C# 프로그래밍 가이드)

    EventHandlerEventHandler<(Of <(TEventArgs>)>)을 기반으로 이벤트를 만드는 방법을 보여 줍니다.

    방법: 인터페이스 이벤트 구현(C# 프로그래밍 가이드)

    인터페이스에 선언된 이벤트를 구현하는 방법을 보여 줍니다.

    방법: 사전을 사용하여 이벤트 인스턴스 저장(C# 프로그래밍 가이드)

    해시 테이블을 사용하여 이벤트 인스턴스를 저장하는 방법에 대해 설명합니다.

    방법: 파생 클래스에서 기본 클래스 이벤트 발생(C# 프로그래밍 가이드)

    보호된 가상 메서드의 기본 클래스 이벤트를 파생된 클래스에서 호출할 수 있도록 래핑하는 방법을 보여 줍니다.

    방법: 인터페이스 멤버를 명시적으로 구현(C# 프로그래밍 가이드)

    인터페이스를 명시적으로 구현하는 클래스를 선언하는 방법과 인터페이스 인스턴스를 통해 멤버에 액세스하는 방법을 보여 줍니다.

    방법: 상속을 사용하여 인터페이스 멤버를 명시적으로 구현(C# 프로그래밍 가이드)

    상자의 크기를 미터와 인치 단위로 표시하는 예제를 제공합니다.

    .NET Framework의 제네릭

    System.Collections.Generic 네임스페이스에 있는 새로운 제네릭 컬렉션 집합의 기능과 용도에 대해 설명합니다.

    제네릭 코드의 default 키워드(C# 프로그래밍 가이드)

    형식 매개 변수에 default 키워드를 사용하는 방법을 보여 주는 코드 예제를 제공합니다.

    제네릭 메서드(C# 프로그래밍 가이드)

    제네릭 메서드를 선언하는 구문에 대해 소개합니다. 응용 프로그램에서 제네릭 메서드를 사용하는 방법을 보여 주는 예제도 제공합니다.

    형식 매개 변수에 대한 제약 조건(C# 프로그래밍 가이드)

    제네릭 클래스를 인스턴스화하는 데 사용한 형식의 메서드 및 속성에 액세스할 수 있도록 형식 매개 변수를 제한하는 방법을 보여 줍니다.

    제네릭 대리자(C# 프로그래밍 가이드)

    제네릭 대리자를 선언하는 구문을 제공합니다. 코드 예제를 비롯하여 제네릭 대리자를 인스턴스화하고 사용하는 데 필요한 몇 가지 중요한 정보도 포함되어 있습니다.

    방법: 네임스페이스 별칭 한정자 사용(C# 프로그래밍 가이드)

    이름이 동일한 다른 엔터티에 의해 멤버가 숨겨질 수 있는 경우에 전역 네임스페이스의 멤버에 액세스하는 기능에 대해 설명합니다.

    방법: 제네릭 목록에 대한 반복기 블록 만들기(C# 프로그래밍 가이드)

    정수 배열을 사용하여 SampleCollection 목록을 만드는 예제를 제공합니다. for 루프는 컬렉션을 반복하며 각 항목의 값을 생성합니다. 그런 다음 foreach 루프를 사용하여 컬렉션의 항목을 표시합니다.

    방법: 제네릭 목록에 대한 반복기 블록 만들기(C# 프로그래밍 가이드)

    제네릭 클래스 Stack<T>에서 제네릭 인터페이스 IEnumerator<T>를 구현하는 예제를 제공합니다. T 형식의 배열이 선언되고 Push 메서드를 통해 값이 할당됩니다. GetEnumerator 메서드에서는 yield return 문을 사용하여 배열의 값을 반환합니다.

    익명 함수(C# 프로그래밍 가이드)

    람다 식과 익명 메서드를 사용하여 대리자 형식을 만드는 방법에 대해 설명합니다.

    방법: 대리자 조합(멀티캐스트 대리자)(C# 프로그래밍 가이드)

    멀티캐스트 대리자를 구성하는 방법을 보여 주는 예제를 제공합니다.

    방법: 대리자 선언, 인스턴스화 및 사용(C# 프로그래밍 가이드)

    대리자를 선언, 인스턴스화 및 사용하는 방법을 보여 주는 예제를 제공합니다.

    방법: 연산자 오버로딩을 사용하여 복소수 클래스 만들기(C# 프로그래밍 가이드)

    연산자 오버로드를 사용하여 복소수 덧셈을 정의하는 복소수 클래스 Complex를 만드는 방법을 보여 줍니다.

    방법: 플랫폼 호출을 사용하여 웨이브 파일 재생(C# 프로그래밍 가이드)

    플랫폼 호출 서비스를 사용하여 Windows 플랫폼에서 웨이브 사운드 파일을 재생하는 방법을 보여 줍니다.

    방법: 포인터를 사용하여 바이트 배열 복사(C# 프로그래밍 가이드)

    포인터를 사용하여 배열 간에 바이트를 복사하는 방법을 보여 줍니다.

    방법: Windows ReadFile 함수 사용(C# 프로그래밍 가이드)

    Windows ReadFile 함수를 호출하는 방법을 보여 줍니다. 읽기 버퍼에 대한 매개 변수로 포인터가 필요하기 때문에 이 함수에서는 안전하지 않은 컨텍스트를 사용해야 합니다.

    스레드 및 스레딩 사용

    관리되는 스레드를 만들고 관리하는 방법과 의도하지 않은 결과를 방지하는 방법에 대해 설명하는 항목의 목록을 제공합니다.

    방법: 스레드 만들기 및 종료(C# 프로그래밍 가이드)

    스레드를 만들고 시작하는 방법과 동일한 프로세스에서 동시에 실행되는 두 스레드 간의 상호 작용을 보여 주는 예제를 제공합니다.

    방법: 생산자와 소비자 스레드 동기화(C# 프로그래밍 가이드)

    C# lock 키워드와 Monitor 개체의 Pulse 메서드를 사용하여 동기화를 수행하는 방법을 보여 주는 예제를 제공합니다.

    방법: 스레드 풀 사용(C# 프로그래밍 가이드)

    스레드 풀을 사용하는 방법을 보여 주는 예제를 제공합니다.

    방법: 정규식을 사용하여 문자열 검색(C# 프로그래밍 가이드)

    Regex 클래스를 사용하여 문자열을 검색하는 방법에 대해 설명합니다. 이러한 검색은 매우 간단한 것에서부터 정규식을 사용하는 것에 이르기까지 매우 다양할 수 있습니다.

    방법: 여러 문자열 조인(C# 프로그래밍 가이드)

    여러 문자열을 조인하는 방법을 보여 주는 코드 예제를 제공합니다.

    방법: 문자열 처리 메서드를 사용하여 문자열 검색(C# 프로그래밍 가이드)

    String 메서드를 사용하여 문자열을 검색하는 방법을 보여 주는 코드 예제를 제공합니다.

    방법: Split 메서드를 사용하여 문자열 구문 분석(C# 프로그래밍 가이드)

    Split 메서드를 사용하여 문자열을 구문 분석하는 방법을 보여 주는 코드 예제를 제공합니다.

    방법: 문자열 내용 수정(C# 프로그래밍 가이드)

    문자열의 내용을 배열로 추출하고 배열의 일부 요소를 수정하는 코드 예제를 제공합니다.

    방법: 특성을 사용하여 C/C++ 공용 구조체 만들기(C# 프로그래밍 가이드)

    Serializable 특성을 사용하여 클래스에 특정 특성을 적용하는 예제를 제공합니다.

    방법: C# DLL 만들기 및 사용(C# 프로그래밍 가이드)

    예제 시나리오를 사용하여 DLL을 빌드하고 사용하는 방법을 보여 줍니다.

    방법: 파일이 어셈블리인지 확인(C# 프로그래밍 가이드)

    DLL이 어셈블리인지 여부를 테스트하는 예제를 제공합니다.

    방법: 어셈블리 로드 및 언로드(C# 프로그래밍 가이드)

    런타임에 특정 어셈블리를 현재 응용 프로그램 도메인에 로드하는 방법에 대해 설명합니다.

    방법: 다른 응용 프로그램과 어셈블리 공유(C# 프로그래밍 가이드)

    어셈블리를 다른 응용 프로그램과 공유하는 방법에 대해 설명합니다.

    다른 응용 프로그램 도메인의 코드 실행(C# 프로그래밍 가이드)

    다른 응용 프로그램 도메인으로 로드한 어셈블리를 실행하는 방법을 보여 줍니다.

    방법: 응용 프로그램 도메인 만들기 및 사용(C# 프로그래밍 가이드)

    연산자 오버로드를 사용하여 3중값 논리 형식을 구현하는 방법을 보여 줍니다.

    Visual C# 샘플

    Hello World 샘플에서 제네릭 샘플(C#)에 이르는 다양한 샘플 파일을 열거나 복사할 수 있는 링크를 제공합니다.

    top
    :

    ▣  stack - .NET/C# - 2009. 5. 25. 20:19

    Stack 데이타 추상

    윤 상배

    dreamyun@yahoo.co.kr



    1절. 소개

    이 문서는 Stack 데이타 추상에 대해서 다룬다. 매우 간단하고 직관적인 내용임으로 부담없이 읽기 바란다.


    2절. Stack

    Stack 의 자료저장 형태는 배열과 동일하다. 다만 자료를 빼내오는 순서에 따라서 Stack 인지가 구분되어진다.


    2.1절. Stack 데이타 추상

    Stack 는 "더미" 란 뜻을 가진다. 책더미, 신문더미 등에 사용하는 바로 그 더미 이다. 책더미를 예로 들어보자 책더미를 쌓았다고 했을때, 이 책더미에서 책을 가져오는 가장 정상적인 방법은 제일 위에 있는 책을 가져오는 방식이다.

    다시 말하자면 가장 먼저 들어간 책은 가장 나중에 꺼낼수 있을 것이다. 이런식으로 자료가 가장 밑에 쌓이고(입력), 자료를 가져올때(출력)는 가장 위(최근)의 자료를 가져오는 자료구조를 Stack 라고 한다. 이러한 Stack 의 특징때문에 흔히 "FILO (First-In-Last-Out)" 혹은 "LIFO (Last-In-First-Out)" 라고 한다. 선입후출, 후입선출 형 자료구조이다.

    그림 1. Stack 자료구조

    그림 1 은 Stack 자료구조의 모습이다. A 가 가장 먼저 입력된 값이고 E 가 가장 마지막으로 입력된 값이다. 값을 가져올때는 가장 최근에 입력된 데이타인 E 를 가져오게 이다. 만약에 F 라는 새로운 자료를 입력한다면, 가장 윗부분에 쌓이게 될것이다.

    Stack 데이타 추상은 자료의 입출력이 LIFO가 되도록 구현하면 된다.


    2.1.1절. Stack 구현을 위해 기술되어야할 행동

    행동 대신 메서드라고 해도 관계는 없다. Stack 는 LIFO 자료입출력을 위해서 보통 4가지의 메서드가 기술된다. 즉 Push 와 Pop, Empty, Size 이다. 그리고 이외에 stack 사이즈관리 등을 위한 capacity와 같은 몇가지 메서드를 부가적으로 구현할수도 있을것이다. "필수" 라고 되어있는 것은 stack 의 필수 행동들이고 "유용" 이라고 되어 있는것은 구현되면 도움이 되는 행동들이다.

    표 1. Stack 기본 행동

    Push stack 의 가장 (top)에 데이타를 저장한다. 필수
    Pop stack 의 가장위에 있는 데이타를 가져온다. 가져온 데이타는 stack 에서 삭제한다. 필수
    Empty stack 가 비어있는지 확인한다. 필수
    Size 스택에 들어있는 원소갯수를 돌려준다. 유용
    Capacity 스택의 크기 - 담을수 있는 원소갯수 - 를 구한다. 유용

    2.1.2절. 구현 및 테스트

    2.1.2.1절. Stack Class

    위의 "Stack 기본 행동" 을 모두 구현할수 있도록 클래스를 제작한다. Stack 데이타 추상을 위해서 클래스를 사용하는 이유는 ADT 의 구현이 용이하기 때문이다. 그리고 이번에는 좀더 "일반적인" Stack 데이타 추상을 위해서 Template class 를 이용하도록 하겠다.

    stack.h

    #include <string>
    #include <iostream>
    
    using namespace std;
    
    template <typename T>
    class stack
    {
        private:
            T *container;    // 저장소 
            int member_num;  // 스택에 저장된 원소의 갯수
            int stack_size;  // 스택의 용량크기
            int ele_sizeof;  // 타입 T 의 sizeof
    
        public:
            // 생성자 
            // 디폴트 인자로 스택의 용량크기를 받아들인다.  
            // 용량크기 만큼 메모리 할당하고
            // 몇가지 값을 초기화 한다.  
            stack(int asize=12)
            {
                stack_size = asize;
                member_num = 0;
                ele_sizeof = sizeof(T);
                container = (T *)malloc(ele_sizeof * stack_size);
            }
    
            // 소멸자
            // 스택을 free 한다. 
            ~stack()
            {
                free(container);
            }
    
            // 데이타를 스택에 입력한다.  
            // 만약 스택사이즈가 꽉차있다면 
            // realloc 를 호출해서 스택사이즈를 
            // (현재 스택사이즈 * 2) 만큼 늘려준다.
            void push_back(T data)
            {
                if (member_num == (stack_size - 1))
                {
                    stack_size *= 2;
                    container = (T *)realloc(container, ele_sizeof * stack_size);
                }
                *(container + member_num) = data;
                member_num++;
            }
    
            // 스택에서 데이타를 꺼낸다.  
            T pop_back()
            {
                member_num --;
                return *(container+member_num);
            }
    
            // 데이타가 비어있는지 확인한다. 
            bool empty()
            {
                return member_num == 0;
            }
    
            // 스택에 저장된 데이타의 갯수 
            int size()
            {
                return member_num;
            }
    
            // 스택의 용량
            int capacity()
            {
                return stack_size;
            }
    };
    					
    쏘쓰는 간단함으로 설명하지 않겠다.

    다음은 템플릿 클래스로 구현한 stack 자료추상의 구현이 잘되었는지 확인하기 위해서 만든 main() 함수를 포함한 테스트용 코드이다.

    stack_test.cc

    #include "stack.h"
    #include <iostream>
    using namespace std;
    int main()
    {
        stack<int> mystack(2);
        int i, size;
    
        cout << "Capacity " << mystack.capacity()<< endl;
        mystack.push_back(1);
        mystack.push_back(2);
        mystack.push_back(3);
        mystack.push_back(4);
        cout << "Capacity " << mystack.capacity()<< endl;
    
        cout << "size : " << mystack.size() << endl;
    
        size = mystack.size();
        for (i  = 0; i < size; i++)
        {
            cout << mystack.pop_back() << endl;
        }
    
        if (mystack.empty())
        {
            cout << "stack is empty" << endl;
        }
    }
    					
    위의 코드는 쓸만하게 작동하지만 string, vector 과 같은 자료형은 값으로 사용할수 없도록되어있다. 이들은 malloc() 함수를 이용해서 메모리 할당이 가능하지 않기 때문이다. 이럴경우 malloc 대신 new 를 사용하면 될것인데, 이것은 각자 코딩해보기 바란다.

    top
    :


    articles
    recent replies
    recent trackbacks
    notice
    Admin : New post