TiberoHelper.cs
0.14MB

아는 사람은 알겠지만.

MS-SQL : SqlHelper

Oracle : OracleHelper

주로 이용을 해왔다.

나름 괜찮은 라이브러리라 생각되고 현재까지도 잘 사용하고 있다.

이번에 Tiber로 db가 변경이 되어 Tibero도 Helper가 있다면 참 좋겠다라고 생각했는데

워낙 Tibero 자료가 넉넉치가 않다보니 갑갑하다.

Oracle의 대부분 기능을 Tibero가 흡수(?)라고 해야할지 베꼈다고 해야할지... 암튼 비슷한 구조라 판단이 되어

OracleHelper를 이용하여 Tibero에 맞게 수정을 했다.

결과적으로 문제없이 잘 된다.

---------------------------------------------------------------------------

오라클과는 달리 Oracle Client 설치 후 Oracle.Data.Client.dll 첨부 형태로 되지 않고

Tibero 6 db설치 이후 ODBC로 연결 설정을 추가적으로 해 주어야 한다.

이 부분은 구글링해서 해결했다.

단, 최신정보인 Tibero6 이 아닌 Tibero5버전의 자료가 대부분인데 이 부분은 최신버전에 맞게 설정해 주면 가능할 것 같다.

 

p.s 티맥스는 최신화 가이드 및 기술지원을 잘 배포해 주었으면 한다. <해결하기 위해 답답한 부분이 많아 ㅠ>

 


WRITTEN BY
테네시왈츠
항상 겸손하게 항상 새롭게 항상 진실하게

,

요즘들어 보안에 대한 프로그래밍을 많이 하게 된다.

하래서 한다만 과연 무엇을 위한 보안인지는 모르겠다. 그냥 하는거다.


DB연결자를 구성할때 최소한 서버IP, 사용자정보, 사용자 비밀번호 를 요구한다.

나같은 경우 보통 ini 파일안에 그 정보를 담아두곤 하는데 이 부분에 사용자 비밀번호가 노출돼 보안에 지적될 소지가 있어 암호화 처리하여 ini에 구성한 뒤 복호화 하여 DB Connection을 맺게 구성을 해야 할 것 같다.


그래서 준비해 보았다.



다음과 같은 화면으로 구성해 보았다.


언젠가 쓸 날이 있을거라 본다.


# frmMain.cs

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;


namespace _CS__Generator_Password

{

    public partial class frmMain : Form

    {

        //암호화 복호화 키 8글자 (필히 8자리여야 함)

        WATCrypt m_crypt;


        public frmMain()

        {

            InitializeComponent();

        }


        private void frmMain_Load(object sender, EventArgs e)

        {


        }


        private void btnApply_Click(object sender, EventArgs e)

        {

            if (txtKeyCode.Text.Length != 8)

            {

                MessageBox.Show("Only allows 8-digit");

                return;

            }


            //암호화 복호화 키 8글자 (필히 8자리여야 함)

            m_crypt = new WATCrypt(txtKeyCode.Text);


            txtKeyCode.ReadOnly = true;


        }


        private void btnEncryption_Click(object sender, EventArgs e)

        {

            if (txtKeyCode.ReadOnly == false)

            {

                txtKeyCode.Focus();

                return;

            }


            if (txtEncryption.Text == "")

            {

                txtEncryption.Focus();

                return;

            }


            // 암호화

            txtEncryption_Gene.Text = m_crypt.Encrypt(txtEncryption.Text);

        }


        private void btnDecryption_Click(object sender, EventArgs e)

        {

            if (txtKeyCode.ReadOnly == false)

            {

                return;

            }


            if (txtDecryption.Text == "")

            {

                txtDecryption.Focus();

                return;

            }


            // 복호화

            txtDecryption_Gene.Text = m_crypt.Decrypt(txtDecryption.Text);


        }


    }



}




# WATCrypt.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO;

namespace _CS__Generator_Password
{

    class WATCrypt
    {

        byte[] Skey = new byte[8];

        public WATCrypt(string strKey)
        {
            Skey = ASCIIEncoding.ASCII.GetBytes(strKey);
        }
        
        public string Encrypt(string p_data)
        {

            if (Skey.Length != 8)
            {
                throw (new Exception("Invalid key. Key length must be 8 byte."));
            }


            DESCryptoServiceProvider rc2 = new DESCryptoServiceProvider();

            rc2.Key = Skey;

            rc2.IV = Skey;

            MemoryStream ms = new MemoryStream();

            CryptoStream cryStream = new CryptoStream(ms, rc2.CreateEncryptor(), CryptoStreamMode.Write);

            byte[] data = Encoding.UTF8.GetBytes(p_data.ToCharArray());
            
            cryStream.Write(data, 0, data.Length);

            cryStream.FlushFinalBlock();
            
            return Convert.ToBase64String(ms.ToArray());

        }
        
        public string Decrypt(string p_data)
        {

            DESCryptoServiceProvider rc2 = new DESCryptoServiceProvider();
            
            rc2.Key = Skey;

            rc2.IV = Skey;
            
            MemoryStream ms = new MemoryStream();

            CryptoStream cryStream = new CryptoStream(ms, rc2.CreateDecryptor(), CryptoStreamMode.Write);

            byte[] data = Convert.FromBase64String(p_data);
            
            cryStream.Write(data, 0, data.Length);

            cryStream.FlushFinalBlock();
            
            return Encoding.UTF8.GetString(ms.GetBuffer());

        }

    }
}



WRITTEN BY
테네시왈츠
항상 겸손하게 항상 새롭게 항상 진실하게

,

얼마전 나는 덱스퍼트(http://dexpert.devpia.com/) 라는 개발자 입장에서 자신의 노하우가 담긴 개발 프로그램 및 소스를 유료로 공유할 수 있는 사이트에 이전에 사용하던 프로그램을 등록한 적이 있다. 나혼자만 알기에는 너무 아깝고 실제 처음에 내가 겪은 어려움을 다른 사람도 겪으리라는 판단하에 유용하게 쓰일수 있겠다라는 판단하에 프로그램 및 소스를 등록하였다. 물론 유료로 2만원이라는 적지않은 금액이지만 내가 초반에 PLC 멜섹 통신에서 겪은 어려움을 떠올리면 2만원이라는 금액이 결코 아깝지 않을것이다.


한달정도 흘렀을까? 벌써 2건(?) 판매가 돼어 이를 현금화 하여 돌려받을 수 있을만큼 금액이 되었다. 물론 아주 작은 금액이긴 하지만 내가 만든 프로그램이 다른 사람이 인정하고 사 주었다는것에 대한 뿌듯함이 있다.




'100. John's ideA' 카테고리의 다른 글

생활데이터 라는 어감이 참 와 닿는다  (0) 2016.02.18

WRITTEN BY
테네시왈츠
항상 겸손하게 항상 새롭게 항상 진실하게

,

옮긴 회사가 델파이를 사용하다 보니 이전에 익숙했던 C#을 접할 기회가 거의 없다.

매번 느끼지만 각 프로그래밍언어를 옮기다 보면 변환 함수가 잘 떠오르지가 않아 애를 먹는 경우가 많다.


얼마전 프로그램에서 이번달 마지막 날짜를 구해야 하는 경우있어 델파이로 구현을 해 보다 문득 C#은 어떻게 구현을 할까 의문이 들었다. 그래서 오랫만에 C# 의 감을 느껴보고자 Visul Studio를 키고 동일한 내용의 값을 구현해 보았다.


우선 간단히 로직(?)을 설명하자면 

1. 지정한 날짜 기준에서 다음달 1일의 날짜를 구한다.

2. 다음달 1일 날짜에서 -1 해준다.

- 끝 -


곧바로 이번달 마지막 날짜를 구하는 함수가 C#에서 있는지 모르겠지만 현재로서는 그냥 이렇게 생각을 해 보았다.


1. 지정한 날짜 기준에서 다음달 1일의 날짜를 구한다.

            // "2016-03-01"

            string sFirstDay_of_NextMonth = DateTime.Now.AddMonths(1).ToString("yyyy-MM") + "-01";


2. 다음달 1일 날짜에서 -1 해준다.
            // "2016-02-29"
            string sLastDay_of_ThisMonth  = DateTime.Parse(sFirstDay_of_NextMonth).AddDays(-1).ToString("yyyy-MM-dd");

이런 내용이 되겠다.

자 그럼 응용해서 함수화 한다면 아래와 같이 구현할 수 있을것이다.

        private void Form1_Load(object sender, EventArgs e)
        {
            //// "2016-03-01"
            //string sFirstDay_of_NextMonth = DateTime.Now.AddMonths(1).ToString("yyyy-MM") + "-01";

            //// "2016-02-29"
            //string sLastDay_of_ThisMonth  = DateTime.Parse(sFirstDay_of_NextMonth).AddDays(-1).ToString("yyyy-MM-dd");

           
            string sTestData;
            // "2016-02-29"
            sTestData = GetLastDayOfThisMonth(DateTime.Now);
            // "2017-02-28"
            sTestData = GetLastDayOfThisMonth(DateTime.Parse("2017-02-12"));

        }
        
        /// <summary>
        /// 지정한 달의 마지막 날짜를 구함
        /// </summary>
        /// <param name="dtmDate"></param>
        /// <returns></returns>
        private string GetLastDayOfThisMonth(DateTime dtmDate)
        {
            string sFirstDay_of_NextMonth = dtmDate.AddMonths(1).ToString("yyyy-MM") + "-01";

            return DateTime.Parse(sFirstDay_of_NextMonth).AddDays(-1).ToString("yyyy-MM-dd");            
        }

2월이 들쑥날쑥 하니 예로 적당한 것 같다.

오랫만에 C#을 하니 그냥 마음이 편하다. 왠지 손에 맞는 연장을 든것처럼...
곧 C#으로 개발하는 날이 오겠지?




WRITTEN BY
테네시왈츠
항상 겸손하게 항상 새롭게 항상 진실하게

,

dataGridView 만지작 거리면서 내부적으로 copy & paste가 안되는것을 보고 바로 구글링에 들어갔다.

다행히 착한 소스가 보여 바로 들고왔다.

 

디자인은 대략이렇고 구성돼 있고

 

 

소스는 아래와 같다.

 

 

 

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Windows.Forms;
  9. namespace CopyPasteInGrid
  10. {
  11. public partial class Form1 : Form
  12. {
  13. public Form1()
  14. {
  15. InitializeComponent();
  16. PopulateDataGridView();
  17. }
  18. public void PopulateDataGridView()
  19. {
  20. dataGridView1.ColumnCount = 6;
  21. dataGridView1.Columns[0].Name = "C0";
  22. dataGridView1.Columns[1].Name = "C1";
  23. dataGridView1.Columns[2].Name = "C2";
  24. dataGridView1.Columns[3].Name = "C3";
  25. dataGridView1.Columns[4].Name = "C4";
  26. dataGridView1.Columns[5].Name = "C5";
  27. dataGridView1.Columns[0].HeaderText = "C0";
  28. dataGridView1.Columns[1].HeaderText = "C1";
  29. dataGridView1.Columns[2].HeaderText = "C2";
  30. dataGridView1.Columns[3].HeaderText = "C3";
  31. dataGridView1.Columns[4].HeaderText = "C4";
  32. dataGridView1.Columns[5].HeaderText = "C5";
  33. dataGridView1.Columns[0].Width = 40;
  34. dataGridView1.Columns[1].Width = 40;
  35. dataGridView1.Columns[2].Width = 40;
  36. dataGridView1.Columns[3].Width = 40;
  37. dataGridView1.Columns[4].Width = 40;
  38. dataGridView1.Columns[5].Width = 40;
  39. dataGridView1.Rows.Add(new string[] { "A1", "B1", "C1", "D1", "E1", "F1" });
  40. dataGridView1.Rows.Add(new string[] { "A2", "B2", "C2", "D2", "E2", "F2" });
  41. dataGridView1.Rows.Add(new string[] { "A3", "B3", "C3", "D3", "E3", "F3" });
  42. dataGridView1.Rows.Add(new string[] { "A4", "B4", "C4", "D4", "E4", "F4" });
  43. dataGridView1.Rows.Add(new string[] { "A5", "B5", "C5", "D5", "E5", "F5" });
  44. dataGridView1.Rows.Add(new string[] { "A6", "B6", "C6", "D6", "E6", "F6" });
  45. dataGridView1.Rows.Add(new string[] { "A7", "B7", "C7", "D7", "E7", "F7" });
  46. dataGridView1.AutoResizeColumns();
  47. }
  48. private void dataGridView1_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
  49. {
  50. if (dataGridView1.SelectedCells.Count > 0)
  51. dataGridView1.ContextMenuStrip = contextMenuStrip1;
  52. }
  53. private void cutToolStripMenuItem_Click(object sender, EventArgs e)
  54. {
  55. //Copy to clipboard
  56. CopyToClipboard();
  57. //Clear selected cells
  58. foreach (DataGridViewCell dgvCell in dataGridView1.SelectedCells)
  59. dgvCell.Value = string.Empty;
  60. }
  61. private void copyToolStripMenuItem_Click(object sender, EventArgs e)
  62. {
  63. CopyToClipboard();
  64. }
  65. private void pasteToolStripMenuItem_Click(object sender, EventArgs e)
  66. {
  67. //Perform paste Operation
  68. PasteClipboardValue();
  69. }
  70. private void dataGridView1_KeyDown(object sender, KeyEventArgs e)
  71. {
  72. try
  73. {
  74. if (e.Modifiers == Keys.Control)
  75. {
  76. switch (e.KeyCode)
  77. {
  78. case Keys.C:
  79. CopyToClipboard();
  80. break;
  81. case Keys.V:
  82. PasteClipboardValue();
  83. break;
  84. }
  85. }
  86. }
  87. catch (Exception ex)
  88. {
  89. MessageBox.Show("Copy/paste operation failed. "+ex.Message, "Copy/Paste", MessageBoxButtons.OK, MessageBoxIcon.Warning);
  90. }
  91. }
  92. private void CopyToClipboard()
  93. {
  94. //Copy to clipboard
  95. DataObject dataObj = dataGridView1.GetClipboardContent();
  96. if (dataObj != null)
  97. Clipboard.SetDataObject(dataObj);
  98. }
  99. private void PasteClipboardValue()
  100. {
  101. //Show Error if no cell is selected
  102. if (dataGridView1.SelectedCells.Count == 0)
  103. {
  104. MessageBox.Show("Please select a cell", "Paste", MessageBoxButtons.OK, MessageBoxIcon.Warning);
  105. return;
  106. }
  107. //Get the satring Cell
  108. DataGridViewCell startCell = GetStartCell(dataGridView1);
  109. //Get the clipboard value in a dictionary
  110. Dictionary<int, Dictionary<int, string>> cbValue = ClipBoardValues(Clipboard.GetText());
  111. int iRowIndex = startCell.RowIndex;
  112. foreach (int rowKey in cbValue.Keys)
  113. {
  114. int iColIndex = startCell.ColumnIndex;
  115. foreach (int cellKey in cbValue[rowKey].Keys)
  116. {
  117. //Check if the index is with in the limit
  118. if (iColIndex <= dataGridView1.Columns.Count - 1 && iRowIndex <= dataGridView1.Rows.Count - 1)
  119. {
  120. DataGridViewCell cell = dataGridView1[iColIndex, iRowIndex];
  121. //Copy to selected cells if 'chkPasteToSelectedCells' is checked
  122. if ((chkPasteToSelectedCells.Checked && cell.Selected) ||
  123. (!chkPasteToSelectedCells.Checked))
  124. cell.Value = cbValue[rowKey][cellKey];
  125. }
  126. iColIndex++;
  127. }
  128. iRowIndex++;
  129. }
  130. }
  131. private DataGridViewCell GetStartCell(DataGridView dgView)
  132. {
  133. //get the smallest row,column index
  134. if (dgView.SelectedCells.Count == 0)
  135. return null;
  136. int rowIndex = dgView.Rows.Count - 1;
  137. int colIndex = dgView.Columns.Count - 1;
  138. foreach (DataGridViewCell dgvCell in dgView.SelectedCells)
  139. {
  140. if (dgvCell.RowIndex < rowIndex)
  141. rowIndex = dgvCell.RowIndex;
  142. if (dgvCell.ColumnIndex < colIndex)
  143. colIndex = dgvCell.ColumnIndex;
  144. }
  145. return dgView[colIndex, rowIndex];
  146. }
  147. private Dictionary<int, Dictionary<int, string>> ClipBoardValues(string clipboardValue)
  148. {
  149. Dictionary<int, Dictionary<int, string>> copyValues = new Dictionary<int, Dictionary<int, string>>();
  150. String[] lines = clipboardValue.Split('\n');
  151. for (int i = 0; i <= lines.Length - 1; i++)
  152. {
  153. copyValues[i] = new Dictionary<int, string>();
  154. String[] lineContent = lines[i].Split('\t');
  155. //if an empty cell value copied, then set the dictionay with an empty string
  156. //else Set value to dictionary
  157. if (lineContent.Length == 0)
  158. copyValues[i][0] = string.Empty;
  159. else
  160. {
  161. for (int j = 0; j <= lineContent.Length - 1; j++)
  162. copyValues[i][j] = lineContent[j];
  163. }
  164. }
  165. return copyValues;
  166. }
  167. }
  168. }
  •  

     

     

     

    [출처] http://www.codeproject.com/Articles/208281/Copy-Paste-in-Datagridview-Control?rp=/KB/TipsnTricks/CopyPasteInDatagridview/SourceCode.zip

     

     

    - 솔루션 소스 파일 첨부 -

     

    CopyPasteInGrid.zip

     


    WRITTEN BY
    테네시왈츠
    항상 겸손하게 항상 새롭게 항상 진실하게

    ,

       string GetDefaultPrinter()
       {
           PrinterSettings settings = new PrinterSettings();
           foreach (string printer in PrinterSettings.InstalledPrinters)
           {
               settings.PrinterName = printer;
               if (settings.IsDefaultPrinter)   // 기본 설정 여부
                   return printer;
           }
           return string.Empty;
       }

    WRITTEN BY
    테네시왈츠
    항상 겸손하게 항상 새롭게 항상 진실하게

    ,

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;

    using System.Drawing.Printing;

    namespace _CS__프린트2
    {
        public partial class Form1 : Form
        {
            int PageNo = 0;
            int pageStartRow = 0;
            int endRow = 50;

            public Form1()
            {
                InitializeComponent();
            }

            private void button1_Click(object sender, EventArgs e)
            {

                PageNo = 0;
                pageStartRow = 0;
                PrintDocument doc = new PrintDocument();
                PrintPreviewDialog dlg = new PrintPreviewDialog();
                dlg.Document = doc;
                doc.PrintPage += new PrintPageEventHandler(doc_PrintPage);
                dlg.ShowDialog();

            }


            void doc_PrintPage(object sender, PrintPageEventArgs e)
            {
                int nBotton = e.PageBounds.Bottom - 30;
                Graphics g = e.Graphics;
                Font PF = new Font("굴림", 11);
                int line = 0;
                for (int nRow = pageStartRow; nRow < endRow; nRow++)
                {
                    line++;
                    int y = line * 30;
                    g.DrawString(nRow.ToString(), PF, Brushes.Black, 100, y);
                    if (y > (nBotton - 50))
                    {
                        pageStartRow = nRow + 1;
                        e.HasMorePages = true;
                        DrawFooter(e.Graphics, nBotton);
                        return;
                    }
                    else
                    {
                        e.HasMorePages = false;
                    }
                }
                DrawFooter(e.Graphics, nBotton);
            }

            private void DrawFooter(Graphics g, int nBottom)
            {
                Font PF = new Font("굴림", 20);

                PageNo++;
                string sPageNo = PageNo.ToString() + "Page ";
                g.DrawLine(Pens.Red, 100, nBottom, 700, nBottom);
                g.DrawString(sPageNo, PF, Brushes.Black, 300, nBottom);
            }


        }
    }

    --------------------------------------------------------------------------------------------------

    /////////////////////////////////
    //유용한 함수 추가
    /////////////////////////////////
       
            private void Set_Values(Graphics g, int iType, int _x, int _y, int iWidth, int iHeight, string sValue)
            {
                string sFont01 = "맑은 고딕";
                string sFont02 = "Microsoft Sans Serif";
                string sFontBarcode = "Code39(2:3)";

                sFont01 = "Nsimsun";

                Font m_Font40 = new Font(sFont01, 40);
                Font m_Font20 = new Font(sFont01, 20);
                Font m_Font16 = new Font(sFont01, 16);
                Font m_Font10 = new Font(sFont01, 10);
                Font m_Font08 = new Font(sFont01, 8);
                Font m_Font06 = new Font(sFont01, 6);

                Font m_Font30 = new Font(sFont02, 30);

                Font m_Font_Bar = new Font(sFontBarcode, 24);

                StringFormat sf = new StringFormat();
                sf.Alignment = StringAlignment.Center;
                sf.LineAlignment = StringAlignment.Center;

                // Create pen.
                Pen BlackPen = new Pen(Color.Black, 1);
                Pen WhitePen = new Pen(Color.White, 1);

                Rectangle rect = new Rectangle(_x, _y, iWidth, iHeight);

                if (iType == 0)
                {
                    // MAIN
                    g.FillRectangle(Brushes.Black, rect);
                    g.DrawRectangle(BlackPen, rect);
                    g.DrawString(sValue, m_Font10, Brushes.White, rect, sf);
                }
                else if (iType == 1)
                {
                    g.FillRectangle(Brushes.WhiteSmoke, rect);
                    g.DrawRectangle(BlackPen, rect);
                    g.DrawString(sValue, m_Font06, Brushes.Black, rect, sf);
                }
                else if (iType == 2)
                {
                    g.FillRectangle(Brushes.Black, rect);
                    g.DrawRectangle(WhitePen, rect);
                    g.DrawString(sValue, m_Font06, Brushes.White, rect, sf);
                }
                else if (iType == 3)
                {
                    //g.DrawRectangle(BlackPen, rect);
                    g.DrawString(sValue, m_Font40, Brushes.Black, rect, sf);
                }
                else if (iType == 4)
                {
                    g.DrawRectangle(BlackPen, rect);
                    g.DrawString(sValue, m_Font16, Brushes.Black, rect, sf);
                }
                else if (iType == 5)
                {
                    //g.DrawRectangle(BlackPen, rect);
                    g.DrawString(sValue, m_Font10, Brushes.Black, rect, sf);
                }
                else if (iType == 6)
                {
                    g.DrawRectangle(BlackPen, rect);
                    g.DrawString(sValue, m_Font_Bar, Brushes.Black, rect, sf);
                }
                else if (iType == 99)
                {
                    // 일반 TEXT 입력
                    g.DrawRectangle(BlackPen, rect);
                    g.DrawString(sValue, m_Font06, Brushes.Black, rect, sf);
                }

            }

            private void Set_Image(Graphics g, int _x, int _y, string sPath)
            {
                try
                {
                    // @"C://Test1.jpg"
                    Image tempImage = Image.FromFile(sPath);

                    g.DrawImage(tempImage, _x, _y);
                }
                catch (System.IO.FileNotFoundException ex)
                {
                    if (ex.FileName == null)
                    {
                        //MessageBox.Show("FILE NOT FOUND!!! > " + sPath);
                        txtMsg.Text = "FILE NOT FOUND!!! > " + sPath;
                        TOTxt("PrintProcess" + " > " + txtMsg.Text);
                    }
                }
               
            }

    --------------------------------------------------------------------------------------------------
    -- 샘플 출력 화면(보안상 가림 처리 이해해 주시길...)
    --------------------------------------------------------------------------------------------------




    WRITTEN BY
    테네시왈츠
    항상 겸손하게 항상 새롭게 항상 진실하게

    ,

    90여년전 대.한.독.립.만.세 를 외쳤던 오늘... 빗길을 뚫고 출근길에 올랐다... 기분이... 기분이...
    오늘은 이전 프로젝트때 유용하게 썼던 방법을 블로깅할까 한다.
    제목 그대로 실행중인 프로그램에 대해 알려주는 그런 형태이다.
    C# 윈도우 프로그래밍을 시작하면 항상 아래와 같은 화면으로 시작이 되는데


    여기서 음영처리 된 부분 (Program.cs) 소스를 보자.

    뮤텍스를 이용하여 처리하는 부분이다.
    중복실행에 대한 처리시 알림창을 띄워주고 실행은 안하는 형태를 취했다.

                bool createdNew;
                Mutex dup = new Mutex(true, "WIA_DIO_COM", out createdNew);

                if (createdNew)
                {
                    Application.EnableVisualStyles();
                    Application.SetCompatibleTextRenderingDefault(false);
                    Application.Run(new frmMain());
                    dup.ReleaseMutex();
                }
                else
                {
                    ////중복실행에 대한 처리
                    //System.Media.SystemSounds.Beep.Play();
                    MessageBox.Show("[0] Program Running... System OFF!");
                }
    소스는 이렇게 된다.


    WRITTEN BY
    테네시왈츠
    항상 겸손하게 항상 새롭게 항상 진실하게

    ,