2007.07.03 17:30
MS Project에서 일정 조정이 끝난 다음 조정된 일정이 들어 있는 파일에서
필요한 항목들을 잘 연동하면 MS Project와 업무솔류션을 연동할 수 있다.

업무솔류션 -> MS Project 연동은 아래 아티클을 참조하시고

  1. 2007/06/26 MS Access를 사용하기 위한 AccessUtil.cs 소스
  2. 2007/06/25 ProcessUtil.cs와
  3. 2007/06/22 MS Project 연동하기 [2/2]
  4. 2007/06/21 MS Project 연동하기 [1/2]


MS Project -> 업무솔류션 연동은 아래 항목들만 잘 연동하면 된다.

TASK_BASE_START
TASK_BASE_FINISH
TASK_EARLY_START
TASK_EARLY_FINISH
TASK_LATE_START
TASK_LATE_FINISH

신고
2007.06.26 17:10

뭐 거창하게 제목을 붙을 것도 없고 공개라 할 것도 없다.
다만 다음에 또 비슷한 작업을 할 때 편하기 위해서 여기다 올려 놓는 것 뿐이니 돌을 던지거나
하지는 말아줬으면 좋겠다.

   public class AccessUtil
    {
        //클래스 맴버
        private System.Data.OleDb.OleDbConnection MdbConnector = new OleDbConnection();            //Access File Opener
        private string DataSource;

        /// <summary>
        /// 생성자
        /// </summary>
        /// <param name="dataSource"></param>
        public AccessUtil(string dataSource)
        {
            DataSource = dataSource;
        }

        /// <summary>
        /// 쿼리를 실행시킨다.
        /// </summary>
        /// <param name="Query">쿼리</param>
        /// <returns>쿼리가 반영된 레코드의 갯수를 린턴한다.</returns>
        public int ExecuteSQL(string Query)
        {
            int nRowCount = 0;

            OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source =" + DataSource); //"c:\\TEMP\\510001.mdb");
            OleDbCommand cmd = new OleDbCommand();
            cmd.Connection = con;
            cmd.CommandText = Query;
            con.Open();
            cmd.ExecuteNonQuery();
            con.Close();

            return nRowCount;
        }

        /// <summary>
        /// 쿼리 결과를 리턴해 준다.
        /// </summary>
        /// <param name="Query">쿼리</param>
        /// <returns>쿼리의 실행결과를 리턴한다.</returns>
        public DataSet FillSQL(string Query)
        {
            DataSet ds = null;

            OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source =" + DataSource); //"c:\\TEMP\\510001.mdb");
            OleDbCommand cmd = new OleDbCommand();
            OleDbDataAdapter ad = new OleDbDataAdapter(cmd);
            cmd.Connection = con;
            cmd.CommandText = Query;

            con.Open();
            ad.Fill(ds);
            con.Close();

            return ds;
        }       
    }

위의 소스에서 소개하고 있는 AccessUtil.cs의 경우 열려고하는 mdb파일의 경로는 생성자로
넘겨주는 방식을 취하고 있다. 이  class에서 제공하고 있는 두 개의 method는

 -ExecuteSQL()
 -FillSQL()

은 모두 인자로 쿼리를 넘길 수 있도록 되어 있으며 Insert, Update, Delete등의 쿼리는
ExecuteSQL을 사용하면 된다. FillSQL은 Select구문을 사용할 수 있게 되어 있다.
예외처리 등은 따로 하지 않았기 때문에 혹시나 참조하실 분은 따로 예외처리를 해주시길
바란다.

-------------------------------------------------------
김영욱 Microsoft
MVP 2006~2007
-------------------------------------------------------
Email: iwinkey@hotmail.com
Blog: winkey.tistory.com
Phone: 016-817-0063
www.winkey.pe.kr
www.vismuri.com
-------------------------------------------------------

신고
2007.06.25 11:41

ProcessUtil.cs와

Tip Tip Tip 2007.06.25 11:41

MS Project 연동하기 Article에서 사용된 ProcessUtil의 전체 소스 입니다.
뭐 별 내용은 없지만 여기에 남겨놓으면 나중에 써먹기 쉬울것 같아서 남겨 놓습니다. ^^
    public class ProcessUtil
    {
        /// <summary>
        /// 생성자
        /// </summary>
        public ProcessUtil()
        {
        }

        /// <summary>
        /// 프로세스를 시작한다.
        /// </summary>
        /// <param name="fileName">파일명</param>
        /// <param name="verb">변수</param>
        /// <param name="args">아규먼트</param>
        public static void StartProcess(string fileName, string verb, string args)
        {
            if (((fileName != null) && (fileName.Length > 0)) &&
                ((verb != null) && (verb.Length > 0)))
            {
                if (File.Exists(fileName))
                {
                    ProcessStartInfo startInfo;
                    startInfo = new ProcessStartInfo(fileName);

                    startInfo.Verb = verb.Trim();
                    startInfo.Arguments = args;

                    Process newProcess = new Process();
                    newProcess.StartInfo = startInfo;

                    try
                    {
                        newProcess.Start();

                        Console.WriteLine(
                            "{0} for file {1} started successfully with verb \"{2}\"!",
                            newProcess.ProcessName, fileName, startInfo.Verb);
                    }
                    catch (System.ComponentModel.Win32Exception e)
                    {
                        Console.WriteLine("  Win32Exception caught!");
                        Console.WriteLine("  Win32 error = {0}",
                            e.Message);
                    }
                    catch (System.InvalidOperationException)
                    {
                        // Catch this exception if the process exits quickly,
                        // and the properties are not accessible.
                        Console.WriteLine("File {0} started with verb {1}",
                            fileName, verb);
                    }
                }
                else
                {
                    Console.WriteLine("File not found:  {0}", fileName);
                }
            }
            else
            {
                Console.WriteLine("Invalid input for file name or verb.");
            }
        }
    }

<리스트1> ProcessUtil의 내용

<리스트1>에서 보는 것과 같이 작성하시면 필요한 프로세스를 시작할 수 있습니다.
위의 ProcessUtil class에서는 StartProcess() Method를 통해서 프로세스를 시작할 수 있는데
이때 필요한 Parameter를 넘겨주시면 됩니다.

-------------------------------------------------------
김영욱 Microsoft
MVP 2006~2007
-------------------------------------------------------
Email: iwinkey@hotmail.com
Blog: winkey.tistory.com
Phone: 016-817-0063
www.winkey.pe.kr
www.vismuri.com
-------------------------------------------------------

신고
.NET Util
2007.06.24 16:52

VS 2008 Multi-Targeting Support

Visual Studio의 다음 버전인 Visual Studo codename "Orcas"의 명칭이
VS 2008로 거의 결정이 되었나 봅니다.

What is Multi-Targeting?

VS 2008에서는 무족건 최신 버전의 Framework을 강요하는 거이 아니라 기존의 2.0이상의 Framework을 선택할 수 있도록 되어 있습니다. 하지만 닷넷 1.0이나 1.1 버전은 지원하지 않습니다.  그 이유는 2.0이상의 버전은 모두 2.0버전과 호환성을 갖는 형태로 추가 개발되었지만 1.0이나 1.1의 경우에는 2.0과 호환성이 없기 때문에 지원을 포기한 것으로 보입니다.

Creating a New Project in VS 2008 that targets .NET 2.0

아래와 같이 새로운 프로젝트를 하나 생성 해보면 우측 상단에서 Framework의 버전을 선택할 수 있도록 되어 있습니다.

만약 2.0을 선택했다면 3.0이나 혹은 3.5에서 지원하는 템플릿들은 모두 제외됩니다.  Silverlight는 3.5버전을 기준으로 했기 때문에 그 이하버전을 선택하면 노출되지 않습니다.

만약 2.0 기반의 웹 프로그램을 선택했다면 아래처럼 웹 2.0기반의 어셈블리들이 추가되어서 나타 납니다.

물론 도구상자에도 2.0에서 사용할 수 있는 컨트롤들이 나타 납니다.

만약 3.0이나 3.5를 선택했다면 해당 버전의 어셈블리가 추가로 선택되어 있습니다.

So why use VS 2008 if you aren't using the new .NET 3.5 features?

VS 2008에서는 아래와 같은 변화가 생겼습니다.

  1. JavaScript intellisense
  2. Much richer JavaScript debugging
  3. Nested ASP.NET master page support at design-time
  4. Rich CSS editing and layout support within the WYSIWYG designer
  5. Split-view designer support for having both source and design views open on a page at the same time
  6. A much faster ASP.NET page designer - with dramatic perf improvements in view-switches between source/design mode
  7. Automated .SQL script generation and hosting deployment support for databases on remote servers

JavaScript intellisense는 Silverlight기반의 작업할 때도 상당히 유용할 것 같습니다. 또 실제로 사용하다 보면 웹에디터 수준으로 향상된 웹 디자인 모드가 인상적입니다.

So how can I upgrade an existing project to .NET 3.5 later?

이미 존재하는 기존의 프로젝트롤 선택해서 업그래이 할 때는 업그레이드 대상의 프로젝트를 선택하시면 됩니다.

물론 버전 업을 선택하고 나면 3.x에서 사용할 수 있는 새로운 참조들이 추가된 것을 볼 수 있습니다.

여기서는  Linq와 관련된 컨트롤도 추가된 것을 볼 수 있습니다.


What about .NET 1.0 and 1.1?

사실 닷넷은 1.x 버전과 2.x 은 너무 많은 차이가 있습니다. 그래서 1.x 버전은 사실상 지원되지 않는 것 가습니다.

What is compatibility like moving from VS 2005 to VS 2008 and .NET Framework 2.0 to 3.5?

2.x 버전을 3.x 버전으로 전환하는 것은 사실 거저먹는 것이나 다름없습니다. 왜냐하면 3.x 버전은 모두 2.0 버전의 업그레이드 버전이긴 하지만 추가 버전이기 때문입니다. ^^

-------------------------------------------------------
김영욱 Microsoft MVP 2006~2007
-------------------------------------------------------
Email:
iwinkey@hotmail.com
Blog: winkey.tistory.com
Phone: 016-817-0063
www.winkey.pe.kr
www.vismuri.com
-------------------------------------------------------

신고
VS2008
2007.06.22 10:40

MS Project와 연동하기 두번째 아티클이다.
첫번째 아티클에서 MS Project에는 많은 테이블들이 있지만 실제로 업무와 연동하기 위한
테이블은 두 개만 잘 활용하면 된다고 했다.

- MSP_PROJECT
- MSP_TASKS

먼저 아래쪽의 코드를 보자

string strTodayFrom = System.DateTime.Now.ToString("yyyy-MM-dd") + " 08:00";
string strTodayTo = System.DateTime.Now.ToString("yyyy-MM-dd") + " 17:00";

//Project 정보를 업데이트 한다.
string strQryUpdate = "update msp_projects " +
                    " set proj_name                = '" + cdhSiteCode.Text + "', " +           //프로젝트 코드
                    "     proj_prop_company        = '회사', " +                                   //프로젝트 소유자  
                    "     proj_info_current_date   = '" + strStartDate + "', " +                 //시작일
                    "     proj_opt_def_finish_time = '" + strFinishDate + "', " +              //종료일
                    "     proj_opt_def_start_time  = '" + strStartDate + "', " +
                    "     proj_info_start_date     = '" + strStartDate + "', " +
                    "     proj_info_finish_date    = '" + strFinishDate + "', " +
                    "     proj_last_saved          = '" + strStartDate + "', " +
                    "     proj_creation_date       = '" + System.DateTime.Now.ToString("yyyy-MM-dd") + "', " +
                    "     proj_ext_edited          = true, " +
                    "     proj_ext_edited_date     = true, " +
                    "     proj_ext_edited_text     = true, " +
                    "     proj_ext_edited_num      = true, " +
                    "     proj_prop_title          = '" + cdhSiteCode.Text + "' ";              //프로젝트 코드

LEC.Win.PL.COCM.AccessUtil oAu = new LEC.Win.PL.COCM.AccessUtil("C:\\temp\\" + cdhSiteCode.Text + ".mdb");
oAu.ExecuteSQL(strQryUpdate);
<리스트1> 프로젝트 정보를 입력한다.

<리스트1>에서 처럼 필요한 프로젝트 정보를 먼저 입력해야 한다.
MSP_PROJECTS에서 해당 프로젝트의 정보를 입력하고 나서 해당 프로젝트의 하나 하나의
업무에 관한 정보(Activity)는 MSP_TASKS에 입력하면 된다.
<리스트1>의 코드에서 보면

LEC.Win.PL.COCM.AccessUtil oAu = new LEC.Win.PL.COCM.AccessUtil("C:\\temp\\" + cdhSiteCode.Text + ".mdb");
oAu.ExecuteSQL(strQryUpdate);
이런 두줄이 있는데 이부분은 MS Access를 다루기 위해서 본인이 만든 공통 클래스이다.
(이 부분도 원하신다면 주저않고 공개하겠다. ^^)

여기 까지 끝나고 나면 이제 본격적으로 업무에 관련된 Activity정보를 입력할 차례이다.

//Task 정보를 입력한다.
int nCnt = 0;
string strWbs = null;
string strTaskName = null;
string strGlvl = null;

string strSummuryYN = null;
string strTaskType = null;

if (dsPrgs.Tables[0].Rows.Count > 0)
{
      foreach (DataRow drRow in dsPrgs.Tables[0].Rows)
      {
          nCnt++;

          if (drRow[0].ToString() != null) strWbs = drRow["마스타WBS코드"].ToString();
          if (drRow[1].ToString() != null) strTaskName = drRow["액티비티명칭"].ToString();
          if (drRow[2].ToString() != null) strGlvl = drRow["액티비티레벨"].ToString();

          if (drRow["최하위레벨여부"] != null)
         {
               if (drRow["최하위레벨여부"].ToString().Equals("Y"))
              {
                    strSummuryYN = "0";
                    strTaskType = "1";
              }
              else
              {
                    strSummuryYN = "1";
                    strTaskType = "0";
               }
         }

         strQryUpdate =
               "insert into msp_tasks " +
                  " (proj_id, " +
                  "  task_id, " +
                  "  task_uid," +
                  "  task_dur," +
                  "  task_dur_fmt," +
                  "  task_base_dur_fmt, " +
                  "  task_early_start," +
                  "  task_early_finish," +
                  "  task_late_start," +
                  "  task_late_finish, " +
                  "  task_start_date, " +
                  "  task_finish_date," +
                  "  task_priority," +
                  "  task_type," +
                  "  task_creation_date, " +
                  "  task_wbs," +
                  "  task_is_summary," +
                  "  task_outline_level," +
                  "  EXT_EDIT_REF_DATA," +
                  "  task_name) " +
               "values " +
                  "(1," +
                  nCnt.ToString() + "," +
                  nCnt.ToString() + "," +
                  4800 + "," +
                  " 53," +
                  " 53," +
                  " '" + strTodayFrom + "'," +
                  " '" + strTodayTo + "'," +
                  " '" + strTodayFrom + "'," +
                  " '" + strTodayTo + "', " +
                  " '" + strTodayFrom + "'," +
                  " '" + strTodayTo + "'," +
                  " 500," +
                  " " + strTaskType + "," +
                  " '" + strTodayFrom + "'," +
                  " '" + strWbs + "'," +
                  " " + strSummuryYN + "," +
                  "  " + strGlvl + "," +  
                  "  1," +
                  " '" + strTaskName.Replace("'", "''") + "' )"; // string에 '이 들어있는 경우 odbc에러나므로 ''로 변경

            oAu.ExecuteSQL(strQryUpdate);
     } // end of foreach
}
<리스트2> MSP_TASKS에 데이터를 입력하는 소스

MSP_TASKS에 데이터를 입력하기 위해서는 <리스트2>의 소스를 참고하면 된다.
먼저 하나씩 잘 살펴보면

if (drRow[0].ToString() != null) strWbs = drRow["마스타WBS코드"].ToString();
if (drRow[1].ToString() != null) strTaskName = drRow["액티비티명칭"].ToString();
if (drRow[2].ToString() != null) strGlvl = drRow["액티비티레벨"].ToString();

위의 부분은 strWbs, strTaskName, strGlvl 변수를 셋팅하는데
Activity에 사용할 고유한 WBS코드와 액티비티명칭 그리고 레벨을 설정하기 위한 부분이다.

액티비티를 설정할 때 또 중요한 부분이 해당 액티비티가 최하위 레벨인가를 설정해야
하는 부분이 있는데

          if (drRow["최하위레벨여부"] != null)
         {
               if (drRow["최하위레벨여부"].ToString().Equals("Y"))
              {
                    strSummuryYN = "0";
                    strTaskType = "1";
              }
              else
              {
                    strSummuryYN = "1";
                    strTaskType = "0";
               }
         }

위의 부분 처럼 최하위 여부를 strSummuryYN, strTaskType에 각각 설정해야 한다.
그 외 나머지 부분은 모두 MDB파일에 던지기 위한 쿼리를 설정하는 부분이기 때문에
설명을 생략한다.

사실 어느 컬럼들을 사용할 것인지만 잘 설정되어 있으면 생각보다 아주 간단한 작업이다.

이렇게 설정된 MDB파일을 이제 MS Project와 연계해서 실행시키기만 하면 작업은 완료된다.
생성된 MDB파일을 MS Project에 넘겨주면서 실행시키는 방법은

string strMsProject = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + "\\Microsoft Office\\OFFICE11\\WINPROJ.EXE";
if (System.IO.File.Exists(strMsProject))
      LEC.Win.PL.COCM.ProcessUtil.StartProcess(strMsProject, " ", "C:\\TEMP\\" + projectCode + ".mdb");
else
      LEC.Framework.Win.MsgBox.ShowMsg("MS Project가 설치되지 않았습니다.");
<리스트3> MS Project를 실행시키기

<리스트3>에서 Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) 이부분은 환경 정보를 가지고 있는 Environment 객체에서 시스템에서 사용하고 있는 폴더에 관한 정보를 가져오는 방법으로 이 방법을 잘 이용하면 MyDocument와 같이 미리 설정된 폴더들의 정보를 가져올 수 있다.
여기서는 ProgramFiles 폴더의 정보를 가져온다.
시스템의 ProgramFiles 폴더에 MS Project가 있는지 확인해보고 없으면 경고창을 띄워주고 존재하면

LEC.Win.PL.COCM.ProcessUtil.StartProcess(strMsProject, " ", "C:\\TEMP\\" + projectCode + ".mdb"); 를 통해서 MS Project파일을 실행시킨다.
물론 LEC.Win.PL.COCM.ProcessUtil 객체도 본인이 공통으로 따로 만들어 놓은것이다.
(음 다음 아티클에서 공개해버리겠다. ^^)

두 개의 공통 모듈로 인해서 설명의 다소 부족한 상태가 되어 버렸지만
전반적인 모습은 충분히 이해할 수 있었으리라 생각된다.
다음 아티클에서 두 개의 공통 모듈(사실 안을 들여다 보면 별거 없지만...)을
모두 공개해 버리겠다. ^^

-------------------------------------------------------
김영욱 Microsoft
MVP 2006~2007
-------------------------------------------------------
Email:
iwinkey@hotmail.com
Blog: winkey.tistory.com
Phone: 016-817-0063
www.winkey.pe.kr
www.vismuri.com
-------------------------------------------------------

신고
2007.06.21 14:51

사용자 삽입 이미지

<그림1> Microsoft Office Project


MS Project는 Microsoft에서 만든 일정관리 도구이다.
완전 전문적인 도구는 아니지만 실제 업무를 진행하기에는 충분한 기능이 제공된다.
따라서 MS Project와 기존의 시스템을 연동하거나 하는 일이 발생된다.
일정관리뿐 아니라 인원이나 장비와 같은 자원관리도 함께 지원하기 때문에
MS Project의 파일구조는 다소 복잡하고 상당히 많은 테이블과 컬럼들로 구성되어
있어서 핸들링 하기에 다소 난해해 보인다.

사용자 삽입 이미지
<그림2> MS Project의 실행모습


사용자 삽입 이미지

<그림3> MS Project에서 다른 이름으로 저장하기


하지만 실제로 일정만 연동하는 경우에는 그렇게 어렵지 않다. MS Project 파일을 직접핸들링 하는 것은 매우 어렵다. 그래서 좀 쉽게 가기 위해서는 다른이름으로 저장을 선택해서 MS Project 파일을 Microsoft Access 파일인 *.mdb 파일로 저장한 다음 다루는 방법이 좋다.

사용자 삽입 이미지
<그림4> Microsoft Office Access 2007

저장된 mdb파일을 열어보면 다소 많은 테이블 갯수에 일단 깜짝 놀라게 된다. 많은 테이블 중에서 일정을 연동하기 위해서는 두개의 테이블만 다루면 되니까 일단 걱정은 잠시 보류해도 좋다.

- MSP_PROJECTS
- MSP_TASKS

위의 두개의 테이블에 필요한 자료를 써 넣고 다시 MS Project에 열게 되면
변경된 내용을 확인 할 수 있다.
사용자 삽입 이미지
<그림5> 일정 연동에 필요한 테이블

-------------------------------------------------------
김영욱 Microsoft
MVP 2006~2007
-------------------------------------------------------
Email:
iwinkey@hotmail.com
Blog: winkey.tistory.com
Phone: 016-817-0063
www.winkey.pe.kr
www.vismuri.com
-------------------------------------------------------
신고
2007.06.20 15:17

사용자 삽입 이미지
모 건설사의 프로젝트를 하다가 보니 mdb파일을 사용자의 PC에 생성하는 부분이 필요하게 되었다.
MS Project와 상호 연동하는 부분인데 mdb파일을 통해서 일정을 상호 핸들링하는 모듈 개발이
있었다. (MS Project와 연동하는 부분도 조만간 올리도록 하겠다. .. ^^)

MS Project에서 사용하는 형식으로 mdb파일을 생성하면
생각보다 꽤많은 테이블이 들어 있고 각각의 테이블에는 엄청난 갯수의 컬럼들이 설정되어 있다.


이렇게 엄청난 수의 테이블과 컬럼을 매번 코드로 생성하는
것이 좋은 방법은 아닌 것 같아서 기본 구조를 미리 생성해서
닷넷 어셈블리의 리소스로 첨부하고 필요할 때 리소스에서
해당 파일을 생성해 내는 편이 프로그램도 간단해지고
성능에도 오히려 도움이 될 것이라는 생각이 들었다.

리소스에 첨부될 수 있는 파일의 종류는
제한이 없다. 필요하다면 어떤 파일이라도 첨부할 수 있다.
이를 잘 활요하면 엑셀이나 워드도 포함시킬 수 있기
때문에 다양한 활용이 가능하다.









1.아래 그림에서 처럼 리소스를 추가 시키려고 하는 프로젝트에서 찾기쉽게 적당한 폴더를 만들고
폴더에서 오른쪽 마우스 버튼을 클릭해서 추가->기존 항목 추가 를 선택해서 추가할 파일을
선택한다.

사용자 삽입 이미지
 
위의 과정을 거치면서 파일을 프로젝트에 추가했지만 아직 어셈블리 안에 함께 포함되지는
않는데 추가시킨 파일의 속성에서 빌드 작업을 포함 리소스로 수정해 두어야한다.
여기까지 하면 프로젝트에 포함된 파일은 빌드작업시에 어셈블리내의 리소스로 함께 포함되어서
배포되게 된다.
사용자 삽입 이미지

이제 포함된 리소스를 가지고 원래 파일로 복원하는 방법을 설명하자면
리소스로 포함된 파일의 바이너리 형태의 스트림을 가지고 와서 로컬에 직접 써주기만 하면 파일로
복원이 가능하다.

//리소스에 포함된 내용을 가져와서 로컬에 파일로 복원시키는 코드
using (BinaryReader reader = new BinaryReader(System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("LEC.Win.PL.CPNetworkPlan.Resources.Sample_Project.mdb")))
{
      using (BinaryWriter writer = new BinaryWriter(new FileStream("C:\\temp\\" + cdhSiteCode.Text + ".mdb", FileMode.Create)))
      {
            int count = (int)reader.BaseStream.Length;

            byte[] butter = reader.ReadBytes(count);

            writer.Write(butter);
         }
    }

위의 소스 중에서 특히 아래부분을 주의해야 한다.
GetManifestResourceStream("LEC.Win.PL.CPNetworkPlan.Resources.Sample_Project.mdb")
스트림으로 가져올 리소스의 namespace를 정확하게 기술해 주지 않으면
절대로!!! 동작하지 않는다. ^^


-------------------------------------------------------
김영욱 Microsoft
MVP 2006~2007
-------------------------------------------------------
Email:
iwinkey@hotmail.com
Blog: winkey.tistory.com
Phone: 016-817-0063
www.winkey.pe.kr
www.vismuri.com
-------------------------------------------------------

신고


티스토리 툴바