Link
1편/네트워크 연결하기-http://www.wolfpack.pe.kr/303
2편/Bluetooth사용하기-http://www.wolfpack.pe.kr/310
3편/모바일배포일반-http://www.wolfpack.pe.kr/314
4편/PC에서모바일배포-http://www.wolfpack.pe.kr/315

오늘 그냥 필받았다고 치고 원래는 다음주쯤에 해야할 배포 마지막을 밟아 보고자 한다.
지난번에 기본적인 원리까지 진행했는데 이제 구현할 차례이다.

1. PC 설치 프로젝트를 추가하자.
솔루션을 클릭하고 마우스 우클릭, 추가, 새프로젝트 클릭후에 위저드 화면에서 설치프로젝트로

resize_image
2. 설치 프로젝트가 열렸다면 불필요한 폴더 다날리고 "응용 프로그램 폴더" 1개만 남겨 놓은뒤에 TestCAB이라는 폴더를 추가하자.
사용자 삽입 이미지
3. 우측 창을 클릭하여 TESTCAB 프로젝트 출력물을 추가하자.
resize_image
사용자 삽입 이미지
resize_image
4. 응용 프로그램 폴더의 속성중 설치될 폴더가 있다. 너무 기니 알맞게 자르도록 하자.
resize_image

* 현재 상태는 DefaultLocation이 "C:\Program files\FunnyWorld"가 된다. PCSetup프로젝트의 속성에 manufacturer 설정이 FunnyWorld이기 때문이다.
사용자 삽입 이미지
5. 이제 레지스트리를 추가하자.
* PCSetup프로젝트를 클릭하고 마우스 우클릭, 보기, 레지스트리를 차례로 클릭한다.
사용자 삽입 이미지
* PCSetup에 대한 레지스트리를 추가하도록 하자.
resize_image
* "VS2008 Windows mobile 6 개발환경 구축 - 3" 말미에 미리보았던 그 구조이다.
- 우클릭후에 새로만들기로 추가하되 레지스트리에 표현되는 종류는 다음과 같다.
문자열값 - REG_SZ
확장 가능한 문자열 값 - REG_EXPAND_SZ
이진값 - REG_BINARY
DWORD - REG_DWORD
이상 4가지 타잎이 지원된다. 하지만 레지스트리에서 사용하는 것은 총 5가지 타잎으로 "다중문자열값(REG_MULTI_SZ)"가 지원되지 않는것이 좀 흠이랄까?
"VS2008 Windows mobile 6 개발환경 구축 - 3"에서 REG_MULTI_SZ로 보인것은 REG_SZ 타입으로 설정하자.

6. 레지스트리 설정이 완료되고나면 이제 설치후 "CEAppMgr.exe"을 실행시켜 주는 녀석을 만들자.
먼저 솔루션에 콘솔 프로젝트를 추가하였다. 윈도우에서 실행되는 것이라면 다른것도 관계없다. 알아서 취향에 맞게 추가하기만 하자.
resize_image
이제 코딩이다. CEAppMgr.exe가 어디에 있는지 알아야 하니 레지스트리를 뒤져서 실행하도록 짜보자.
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Win32; //레지스트리 관련 필수 추가

namespace runner {     class Program     {         static void Main(string[] args)         {             //레지스트리에 접근하여 값을 가져온다.             string regPath = @"Software\Microsoft\Windows\CurrentVersion\App Paths\CEAppMgr.exe";             RegistryKey rgkey = Registry.LocalMachine.OpenSubKey(regPath, true);             Console.WriteLine(rgkey);             String rtnPath="";             foreach (string Val in rgkey.GetValueNames())                 rtnPath = rgkey.GetValue(Val).ToString();                         //가져온 경로대로 실행한다.             System.Diagnostics.Process ps = new System.Diagnostics.Process();             ps.StartInfo.FileName = @rtnPath;             ps.Start();         }     } }



7. 노가다는 이제 끝나간다. 다시 PC설치용 프로젝트로 이동해서 앞에서 만든 Runner 프로그램을 출력에 추가하고 사용자 작업에 추가해주자.
- runner 프로젝트의 출력을 추가했음
resize_image
- PCSetup프로젝트의 사용자 지정작업 클릭
사용자 삽입 이미지
- 설치 단계에 runner의 기본출력을 지정하였다.
사용자 삽입 이미지

8. 이제 최종 설치한번 해보자.
- 간단하게 솔루션 탐색기에서 PCSetup 프로젝트 선택후 마우스 우클릭하면 설치할 수 있다.
사용자 삽입 이미지
- 설치하고 나서 원하는 대로 추가/제거 윈도우가 나타난다.
resize_image

9. 실재 설치후 테스트
- TESTCAB를 선택하자.
사용자 삽입 이미지
- 응용 프로그램 다운로드 완료라고 뜨고 Windows Mobile Device에서는 열심히 설치중이다.
resize_image
- 설치완료모습
사용자 삽입 이미지


이로써 기본 윈도우즈 모바일 개발환경 구축은 완료되었다.
추가적으로 필요한 부분은 SDK를 구매하는 것을 권한다. 그러나, 일반 범용 어플리케이션은 에뮬레이터로 충분히 나아가 Bluetooth까지 지원하며 PC에서 손쉽게 설치하는 방법까지 공개하였으니 어렵지 않을것이다. 본 윈도우즈 모바일 개발환경 구축 관련 글은 개인 저작물이며 누구나 퍼나를수 있다. 그러나, 허락없이 퍼나르거나 동영상으로 포맷그대로 전환하신 분도 계시다. 쓰지말라고 올리는 것도 아닌데 방명록에 쓰겠다는 멘트만이라도 남겨주면 어떨까?

다음에 또 다른 지식을 나눠보도록 하자.
2009/03/11 15:21 2009/03/11 15:21
Link
1편/네트워크 연결하기-http://www.wolfpack.pe.kr/303
2편/Bluetooth사용하기-http://www.wolfpack.pe.kr/310
3편/모바일배포일반-http://www.wolfpack.pe.kr/314
4편/PC에서모바일배포-http://www.wolfpack.pe.kr/315

이번에는 PC에서 Mobile로 만든 CAB파일을 설치하는 방법에 대해 알아보자.
일단 Windows Mobile 개발이 능숙한 사람을 대상으로하니 자질구래하게 프로그램 소스까지 올리지 않도록 하겠다.

단계는 다음과 같이 한다.
1. Windows Mobile 프로그램 제작
2. Windows Mobile 배포 패키징
3. Regedit로 레지스트리를 건드려 ActiveSync 설치목록에 뜨도록 만들기
4. ActiveSync 설치관리자로 설치하기

1. TestDeploy라는 프로젝트명으로 어플리케이션을 하나 만들었다.

resize_image
2. 이제 CAB으로 싸자
   1) 솔루션에서 새프로젝트를 추가하자.
사용자 삽입 이미지
   2) TESTCAB이라는 이름으로 모바일 설치 프로젝트를 생성
resize_image
   3) "프로그램 폴더" 추가
resize_image
   4) 쓸데없는 폴더는 날리자.
사용자 삽입 이미지
   5) 응용 프로그램 폴더를 클릭하고 추가
사용자 삽입 이미지
사용자 삽입 이미지
   6) 프로그램 폴더에 바로가기를 생성하자.
       - 프로그램 폴더 클릭후에 오른쪽 창에서 마우스 우클릭
사용자 삽입 이미지
      - 응용 프로그램 폴더안의 TestDeploy의 기본 출력(활성)을 선택
resize_image
       - 파일이 생성되면 "Shortcut to TestDeploy의 기본 출력(활성)"이라고 쓰여져 있는데 한글은
         Ansicode로 변환하는데 실패할 수 있으므로 영문으로 바꾸자."Shortcut to TestDeploy"로
         한글만 지웠다.
   7) 이제 설치파일에 기록될 작성자나 뭐 기타 등등을 고쳐주자.
사용자 삽입 이미지
   8) 솔루션 전체를 빌드하자.
사용자 삽입 이미지
   9) ActiveSync의 "탐색" 기능을 이용하여 생성된 CAB 파일을 Windows Mobile에 옮겨 놓자
사용자 삽입 이미지
    10) 옮겨 놓은 모습
사용자 삽입 이미지
   11) 실행하자.
사용자 삽입 이미지
   12) 프로그램 메뉴에 있는지 확인하고 실행하자.
        - 한글이 깨지는 문제는 Widnows Mobile Emulator가 영문버전이기때문임. 한글버전은 문제
           없음.
사용자 삽입 이미지
사용자 삽입 이미지
사용자 삽입 이미지
3. 이제 본격적인 PC를 통한 설치를 하기위해 사전 지식을 쌓아보자.
위에서 일련의 프로그램을 만들고 CAB으로 만들어 배포하는것을 해보았지만 문제는 이게 좀 귀찮다는 것이다. PC에서 Windows Mobile Device를 설치하는 기능이 있음에도 잘 안쓰니까 문제라고나 할까?

- ActiveSync의 프로그램 추가/제거 기능이 바로 그것이다.
사용자 삽입 이미지
- 프로그램 추가/제거를 클릭하면 설치할 수 있는 파일들이 뜬다.
사용자 삽입 이미지
이녀석들은 도대체 어디 있길레 이렇게 뜨는것일까? 시작>실행에서 "Regedit"를 실행하여 살펴보도록 하자.
결론부터 말하자면 여기에 존재한다.
\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows CE Services\AppMgr\Apps

어랏? 많이 보던 녀석들 아닌가?
사용자 삽입 이미지
다시말해 레지스트리에 등록만 해주면 ActiveSync의 기능을 추가/제거 기능을 이용할 수 있을듯 하다.
다음은 "Adobe FlashLite"를 클릭해서 내용을 발취한후 TESTCAB에 맞게 수정한 것이다.
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows CE Services\AppMgr\Apps\TESTCAB] "AppName"="TESTCAB" "Description"="" "IconIndex"=dword:00000000 "InstallDir"="D:\\Work_Source\\TestDeploy\\TESTCAB\\Debug" "ListCabFiles"=hex(7):54,00,45,00,53,00,54,00,43,00,41,00,42,00,2e,00,43,00,41,\   00,42,00,00,00,00,00 "ListCpuTypes"=hex(7):30,00,00,00,00,00 "Provider"="FunnyWorld"


실재 레지스트리를 살펴본 모습은 이러하다.
resize_image

이렇게 레지스트리를 고쳤을때 실재 파일의 위치만 정확하다면 다음과 같이 프로그램 추가/제거 윈도우에서 뜬다.
사용자 삽입 이미지

이제 하나만 더해보자.
TESTCAB를 프로그램 추가/제거에 넣었다고는 하나 저기능을 자동으로 띄우지 못한다면 불편한것은 여전하다. 짧게 다시 결론부터 이야기하자면 저녀석의 명칭은 "CEAppMgr.exe"이다.
(프로그램 추가/제거 윈도우를 활성화 한상태에서 윈도우 작업관리자를 띄워 놓고 이름순으로 정렬한뒤에 프로그램 추가/제거창을 닫으니 사라지는 프로세스가 바로 저 이름이었다.)
어디에 있는줄은 모르겠지만 암튼 CEAppMgr.exe를 실행하면 된다니 이 녀석도 레지스트리에서 찾아보자.


\HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\App Paths\CEAppMgr.exe



위의 경로에 기본값으로 박혀 있다는 것을 확인 가능하다.
* 내경우는 "C:\Program Files\Microsoft ActiveSync\CEAPPMGR.EXE"이었다.

다음에 Windows Setup을 통해 CAB파일을 특정장소에 보관하고 레지스트리를 조작한 후에 CEAppMgr.exe를 실행해보도록 하자.
2009/03/10 15:57 2009/03/10 15:57
Windows mobile 6는 사실 Core가 Mobile 5와 동일하다.
다시말해 기죽지 말자.
아무튼 Smart Phone개발하려면 환경구축이 중요한데 특히 옴니아(Omnia)폰과 같이 고가의 장비를 갖춰서 개발한다는 아닌것 같다.

본 포스팅은 이런 환경을 구축하는데 노력이상의 비용을 지불하지 않는 선에서 환경구축을 완료하는데 그 목적이 있다.

1편 - Emulator에 네트워크 어떻게 연결할까?
2편 - Bluetooth를 Emulation할 수 없을까?
3편 - 만들긴 만들었는데 어떻게 배포하지?

Link
1편/네트워크 연결하기-http://www.wolfpack.pe.kr/303
2편/Bluetooth사용하기-http://www.wolfpack.pe.kr/310
3편/모바일배포일반-http://www.wolfpack.pe.kr/314
4편/PC에서모바일배포-http://www.wolfpack.pe.kr/315

이렇게 3부에 걸쳐 Windows Mobile 6 기반의 어플개발환경구축에대해 주저리주저리 떠들어 보자.

준비물은 Visual studio 2008 Express 이상이면 되고
Omnia같이 해상도가 800*480정도 되는 놈은 미쿡 이미지만 지원하므로 따로 다운로드 받는다.
일단은 Windows mobile 6 SDK부터 다운로드 받자.
http://www.microsoft.com/downloads/det ··· ang%3Den
그리고 480 * 800 개발용 이미지는 여기서 더 받도록 하자.
http://www.microsoft.com/downloads/det ··· ang%3Den

다운로드후 설치는 자동으로 OK.

XP라면 Activesync 4.5를 설치하고 Vista라면 디바이스 센터를 업데이트 한다.
여기서는 Activesync로 진행하겠다.
Activesync를 실행한후 "파일>연결설정"을 클릭한다.
다음과 같은 설정창이 뜨면 "다음 중 한가지 연결 허용"을 체크하고 DMA를 추가해둔다.
사용자 삽입 이미지
나머지는 Visual Studio 2008의 몫이다.
VS2008을 실행한후에 "도구>장치 에뮬레이터 관리자"를 클릭하여 관리자를 실행한다.
사용자 삽입 이미지
관리자 실행후에 해당 이미지를 클릭하고 마우스 우클릭하면 메뉴가 뜨는데 여기서 "연결"을 선택하자.
사용자 삽입 이미지
연결을 클릭하면 자동으로 이미지가 활성화되고 Emulator가 작동하기 시작한다.
사용자 삽입 이미지
에뮬레이터가 실행되면 다시 관리자에서 이미지를 선택하고 마우스 우클릭하여 "크레들에 놓기"를 선택하자.
사용자 삽입 이미지
이제 가상으로 크레들에 놓은것처럼 작동되어 동기화를 시작하게된다.
(동기화 설정은 생략함. 왠만하면 동기화 설정은 모두 언체크하여 하지 않도록 하자.)
사용자 삽입 이미지
마지막으로 연결이 완료되었는지 확인하자.
사용자 삽입 이미지
인터넷이 제대로 작동하는지도 확인하자. 본인의 PC가 인터넷이 연결안되어 있으면 말짱꽝이니 조심해서 체크 바란다.
사용자 삽입 이미지

2009/02/04 13:04 2009/02/04 13:04

C# Windows Forms 프로그래밍을 하면 의외로 Form끼리 데이터 공유가 안되서 애먹는 모습을 종종 보았다.

다음과 같은 폼이 있다고 가정하고

namespace TEST
{
    public partial class FormMain : Form
    {
        public string Value
        { 
            get;set;
        }
        public FormMain()
        {
            InitializeComponent();
            RunChild();
        }
        private void RunChild()
        {
            FormLogin cdf = new FormLogin (this);
            cdf.ShowDialog(); //혹은 cdf.Show();
        } 
     }
}

Value에 대한 GET;SET; 속성을 정의하여 준다.

다른 폼에서는
namespace TEST
{
    public partial class FormLogin : Form
    {
        FormMain MotherFrm;
        public FormLogin(FormMain FatherFrm)
        {
            this.MotherFrm = FatherFrm;
            InitializeComponent();
        }
    }
}

와 같이 정의하여주면 MotherFrm.Value와 같이 사용이 가능하다.

2008/10/15 14:14 2008/10/15 14:14

본격적인 LINQ 실행을 함 해보자.
예고와는 다르게 일단 XML부터 Linq를 통해 한번 제대로 굴려보도록 하자.

1. XML 파싱하기.
먼저 다음과 같이 XML파일 하나 만들어 보자
(파일명은 test.xml로 하자.)

<?xml version="1.0" encoding="utf-8" ?>
<config>
   <id>111.111.111.111</id>
   <user>vic</user>
   <pass>password</pass>
</config>

일반적으로 많이 만들어 사용하는 콘피그 파일이다.
Linq이전에는 이녀석을 비교하려고 XML Document 열어서 열심히 While문으로 Read했었다.
Linq로 이놈을 한번 분석해보면 다음과 같이 매우 짧게 진행할 수 있다.

using System;
using System.Linq;
using System.Xml;
using System.Xml.Linq;

class Test {   static void Main(){    XDocument xe = XDocument.Load(System.Windows.Forms.Application.StartupPath  + "\\test.xml");     var query = from c in xe.Descendants("config")                     select c;

   foreach(var q in query)    {       Console.WriteLine(q);    }    Console.ReadLine();   }  }


실행시켜보면 위의 XML전체가 출력되는 것을 볼수 있을 것이다.
이제 이녀석을 좀더 다듬어 보자.
"select c;"라고 된 부분을 "select c.Element("id");"로 바꿔보자.
    var query = from c in xe.Descendants("config") 
                    select c.Element("id");

실행을 하면 XML의 ID부분만 출력이 될 것이다.
<id>111.111.111.111</id>

어쩐지 제대로 찾아 들어오는 느낌. 이제 아까 바꾼 "select c.Element("id");"를
"select c.Element("id").Value;"로 바꿔보자.
    var query = from c in xe.Descendants("config") 
                    select c.Element("id").Value;

실행하면 결과가 아주 이쁘게 값만 떨어진다.
111.111.111.111

그런데 여기서 만족할 수 없다. 여러개의 값을 가려오려면 어떻게 해야 할 까?
다음과 같이 함 바꿔보자.

    var query = from c in xe.Descendants("config") 
                    select new 
                    {
                        id = c.Element("id").Value,
                       user = c.Element("user").Value
                     }
   //이번에는 foreach문도 바꿔주자
   foreach(var q in query)
   {
      Console.WriteLine(q.id + q.user);
   }   

결과는 직접 함 해보도록하고 이제 다음단계로 SQL문처럼 한번 써보자.
다음과 같이 바꿔보고 실행 함 해보자.
    var query = from c in xe.Descendants("config") 
                where c.Element("user").Value == "vic"
                select c;

어떤게 나오는가? where문이 진짜 먹으니 뿌듯한 느낌!

2. XML생성
이제 한걸음 더 나가서 XML을 생성함 해보자.
사용은 무지 쉽다.
using System;
using System.Linq;
using System.Xml;
using System.Xml.Linq;

class Test {   static void Main(){   XDocument xdoc =       new XDocument(       new XDeclaration("1.0", "UTF-8", "yes"),       new XProcessingInstruction("TEST", "TEST Data"),       new XComment("테스트 XML"),       new XElement("config",           new XElement("id", "1234"),           new XElement("user", "abc")       )            );    xdoc.Save(System.Windows.Forms.Application.StartupPath  + "\\test.xml");   }  }



test,xml을 열어 보면
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<?TEST TEST Data?>
<!--테스트 XML-->
<config>
  <id>1234</id>
  <user>abc</user>
</config>

이렇게 정확하게 들어와 있는 것이 보일것이다.

2008/04/16 13:09 2008/04/16 13:09
가면갈수록 어려워지니 쩝...
뭐 암튼...

test.dll이란 이름의 C++로 만들어진 DLL이 있다고 치자.
그리고 그것의 함수는 다음과 같다고 치자.

int returnInt(int a)
{
    return a;
}


이녀석을 컴파일 하면 test.dll 이란게 생길것이다. 이녀석을 Debug라고하는 컴파일후 생성되는 폴더에 재주껏 넣어 놓고 다음과 같이 코딩해보자.

using System;
using System.Runtime.InteropServices; //여기 선언 중요
class InvokeTest
{
    [DllImport("test.dll")] //만약 함수명이 다르면 EntryPoint="function_name" 지정
    public static extern int returnInt(int a);//외부정의함수이므로 extern과 static필수 

    public static void Main()     {         int i = returnInt(1);         Console.WriteLine(i);     } }

2007/09/03 22:02 2007/09/03 22:02
지난번에 Thread를 왜 쓰레드라고 표기한지에 대해서와 단일 쓰레드의 시작과 종료에 대해 썰을 풀었다.
이번에는 멀티 쓰레드와 동기화를 함해보고 담에는 쓰레드 풀에 대해 썰을 풀어보자.

using System;
using System.Threading; 

//데이터를 주고받아야 하니 Class를 하나 만들고 인터페이스도 만들어 두자.
class work{
  int a; //받을 인자값

  //인터페이스 메소드
  public work(int a){
   this.a = a;
  }
  
  //실제 일할놈
  public void runit(){
   for (int i=0; i<10; i++){
    Console.WriteLine("Thread{0} Running : {1}", a, i);
    Thread.Sleep(100);
   }
  }
}

//메인쓰레드가 있는 클래스
class Test {
  static void Main(){ 
   Console.WriteLine("쓰레드 시작");
   work wk1 = new work(1); //1로 지정
   work wk2 = new work(2); //2로 지정
   ThreadStart td1 = new ThreadStart(wk1.runit); //시작쓰레드 선언하고
   ThreadStart td2 = new ThreadStart(wk2.runit);
   Thread t1 = new Thread(td1); //돌릴준비하고
   Thread t2 = new Thread(td2);
   t1.Start(); //돌리자
   t2.Start();
  }
}

사용자 삽입 이미지
실행후 1번과 2번 쓰레드가 동시에 작동한다.

그런데 1번보다 2번 쓰레드가 중요하다던가 하는 상황에서는 어떻게 하면 될까?
그때는 "ThreadPriority"메소드를 사용하여 우선순위를 지정할 수 있다.

using System;
using System.Threading; 
class work{
  int a;
  public work(int a){
   this.a = a;
  }
  
  public void runit(){
   for (int i=0; i<10; i++){
    Console.WriteLine("Thread{0} Running : {1}", a, i);
    Thread.Sleep(100);
   }
  }
}
class Test {
  static void Main(){ 
   Console.WriteLine("쓰레드 시작");
   work wk1 = new work(1);
   work wk2 = new work(2);
   ThreadStart td1 = new ThreadStart(wk1.runit);
   ThreadStart td2 = new ThreadStart(wk2.runit);
   Thread t1 = new Thread(td1);
   Thread t2 = new Thread(td2);
   t1.Priority = ThreadPriority.Lowest; //이 부분 추가됨. 1번 쓰레드 우선 순위 최하
   t2.Priority = ThreadPriority.Highest; //이 부분 추가됨. 2번 쓰레드 우선 순위 최고
   t1.Start();
   t2.Start();
  }
}

1번 쓰레드에 우선 순위를 최하로 부여하고 2번 쓰레드에는 우선 순위를 올려 보았다.
(설정은 "Highest, AboveNormal, Normal, BelowNormal, Lowest"로 5단계로 설정할 수 있다.)
사용자 삽입 이미지
본 코드가 적용되기전의 결과와는 다르게 2번 쓰레드가 먼저 생성되고 종료된다.
그러나 믿지는 말자. 인텔 계열의 CPU는 0부터 31까지의 값을 가지고 있고 이는 윈도우에서 사용하는 우선 순위나 별반 다르지 않다.

* 작업관리자에서 우선순위를 설정해 보신분들은 금방 알아볼 것이다. 다음의 그림처럼...
사용자 삽입 이미지
암튼 지맘이니까 믿지는 말자. 쓰레드의 위험성은 이처럼 결과를 예측하고 그 예측이 맞을것이라 바라는것 되겠다. 절대 하지말아야 할 주의점 이다.

이렇게 멀티로 작업을 하다보면 공통 변수로 작업해야 할때가 있다. 이때 여러개의 쓰레드가 1개의 값을 건드리다보면 변수의 값이 엉뚱하게 나오기도 한다.

using System;
using System.Threading; 
class work{
  public int a;
  public void runit(){
   int tp = a + 1;
   Console.WriteLine(tp.ToString());
   Thread.Sleep(10);
   a = tp;   
  }
}
class Test {
  static void Main(){ 
   Console.WriteLine("쓰레드 시작");
   work wk = new work();
   Thread[] td = new Thread[5];
   for (int i=0; i<5; i++){
   td[i] = new Thread(new ThreadStart(wk.runit));
   td[i].Start();
   }
   Thread.Sleep(1000);
   Console.WriteLine("최종값:{0}",wk.a);
  }  
}

요녀석을 실행함 해보자.
사용자 삽입 이미지
결과값은 분명 5가 나와야 하지만 그렇지 않고 1로 고정이 되어버렸다.
다음과 같이 lock이란 녀석을 한번 넣어보자.
using System;
using System.Threading; 
class work{
  public int a;
  public void runit(){
   lock(this){ //바로 여기
   int tp = a + 1;
   Console.WriteLine(tp.ToString());
   Thread.Sleep(10);
   a = tp;   
    }
  }
}
class Test {
  static void Main(){ 
   Console.WriteLine("쓰레드 시작");
   work wk = new work();
   Thread[] td = new Thread[5];
   for (int i=0; i<5; i++){
   td[i] = new Thread(new ThreadStart(wk.runit));
   td[i].Start();
   }
   Thread.Sleep(1000);
   Console.WriteLine("최종값:{0}",wk.a);
  }  
}


실행을 하면 다음과 같이 정상값으로 나온다.
사용자 삽입 이미지
lock이란것으로 동시에 호출하는 쓰레드에 대해 작업중이니 기다리라는 명령을 내릴 수 있는것이다. 그러나 기능의 다양성을 원한다면 lock보다는 "Monitor.Enter()"와 "Monitor.Exit()"를 써주기 바란다.

  public void runit(){
   Monitor.Enter(this);
   int tp = a + 1;
   Console.WriteLine(tp.ToString());
   Thread.Sleep(10);
   a = tp;   
    Monitor.Exit(this);
  }
2007/07/18 11:46 2007/07/18 11:46

쓰레드라고 하는것이 한때는 고수들의 전유물이었는데 요즘은 강호고수들이 많아져서인지 아무나 쓰는 기술되었다.
뭐 암튼 대충 쓰레드에 대해 정리하자는 차원에서 써둠을 밝히니 향후에 제대로 안된다고 이런거 하지말자.

1. 쓰레드 사용하기
일단 닷넷의 쓰레드는 굉장히 쓰기쉽다.
다음의 예제를 함해보자.

using System;
using System.Threading;  //쓰레드를 쓰겠다고 선언하자.

class Test {
  static void Main(){ 
   Console.WriteLine("카운트 0부터 49까지 세기!");
   ThreadStart th = new ThreadStart(work); //1.work메소드를 위임하자.
   Thread t = new Thread(th); //2.쓰레드생성하자.
   t.Start(); //3.시작
   Console.WriteLine("끝!");
  }
  public static void work(){
   for (int i = 0; i<50; i++){
    Console.WriteLine("Conut:{0}",i);
   }
  }
}

결과를 보면 짜잔!
사용자 삽입 이미지

* Ultraedit에서 컴파일하고 실행한 결과창임. 이렇게 하고싶으신분들은 본 블로그 잘뒤져보면 나옴.

2. 쓰레드 중지하기
쓰레드를 중지하기위해서는 2가지 방법이 있다.
- Abort()
- Join()
Abort()는 강제종료이므로 어디서 끝날지 아무도 모른다. 신도 모른다.
Join()은 쓰레드가 다 실행될때 까지 기다렸다가 종료시킨다.
다음예제를 보자

using System;
using System.Threading; 

class Test {   static void Main(){    Console.WriteLine("카운트 0부터 1만까지 세기!");    ThreadStart th = new ThreadStart(work);    Thread t = new Thread(th);    t.Start(); //시작    t.Abort(); //강제종료    Console.WriteLine("끝!");   }   public static void work(){    for (int i = 0; i<10000; i++){     Console.WriteLine("Conut:{0}",i);    }   } }


이녀석을 실행해보면 Abort()때문에 이렇게 된다.
사용자 삽입 이미지

코드에서는 1만까지 진행하는것으로 만들어졌지만 강제종료되어 8524에서 종료되었다.
한번 더 해보자.

사용자 삽입 이미지
어쩌구리.. 이번에는 다 돌아 버렸다... ㅡㅡ;; 암튼 이런식으로 예측이 불가능한 코드가 되어버린다. 중간에 종료하는것은 왠만하면 하지말고 Join()을 사용하도록 하자.
위코드에서 다음과 같이 수정한다.
   ...전략...
   t.Start(); //시작
   t.Join(); //이전에 t.Abort()임
   Console.WriteLine("끝!");
   ...후략...

사용자 삽입 이미지
이번에는 다 돈다. (사실은 위의 이미지와 같은 이미지임.. 흐흐흐)

3. 쓰레드의 쉬게하기
이번에는 일하다가 중간에 쉬게 해보자.
using System;
using System.Threading; 

class Test {   static void Main(){    Console.WriteLine("쓰레드 시작");    ThreadStart th = new ThreadStart(work);    Thread t = new Thread(th);    t.Start();    Console.WriteLine(t.ThreadState);    Console.WriteLine("끝!");   }   public static void work(){    Thread.Sleep(100);   } }


사용자 삽입 이미지
쓰레드가 시작되고 Sleep명령으로 인해 Sleep모드로 들어갔다.

명령이 주어질때까지 중지하고 싶다면 Suspend()를 사용하자. Suspended된놈을 다시 살리는 것은 Resume()이 있는데 이건 알아서 한번 만들어 보도록 하자.

결론적으로 .NET의 쓰레드(Thread)는 다음과 같은 상태값을 가진다.
(ThreadState()로 나오는 결과값이 바로 타원형안에 있는 녀석들이다.)

사용자 삽입 이미지
이 표만 잘봐두면 쓰레드 어려운것이 아니다.
일단 생성된 쓰레드는 Unstarted라는 값을 가진다. Start()라는 메소드로 Started라는 상태값을 가지게 되는 것이다. 다시말해 타원안에 있는 것은 상태값, 화살표에 있는 것이 바로 메소드 되겠다.

다음에는 멀티 쓰레드 함 해보자.

* 본 게시물에서 사용한 쓰레드라는 표현은 "Thread"의 한음표현이며 쓰레드는 스레드라고도 표기됩니다. Microsoft공식학습서 Inside C# 2nd Ed.에는 쓰레드라고 표기되어 있어 본 게시물도 쓰레드라고 표현함을 알려드립니다.

2007/07/12 16:20 2007/07/12 16:20
지난번에 쾌속으로 스마트 클라이언트를 만들어 보았다.
(관련글 : http://www.wolfpack.pe.kr/103)

* 다음과 같이 하는 방법도 있고 코딩으로 처리하는 방법도 있다.
(http://www.wolfpack.pe.kr/265 참고)

오늘은 가장중요한 배포이다.
(스마트 클라이언트는 서버에서 다운로드 받은 "dll"이나 "exe"파일이 로컬에서 실행되는 것이라는것만 알고 보도록 하자.)

1. 서버
서버쪽은 MIME타입을 제대로 설정해줘야 익스플로러가 제대로 작동한다.
IIS등록정보에서 "MIME형식"을 클릭해서 활성화 시키자.
(예제는 가상사이트의 등록정보로 실재와 다를수 있다.)
resize_image
"새형식"을 클릭한후 ".dll"파일이면 확장자에 ".dll"을 입력하고 MIME형식에는 "application/octet-stream"이라고 설정하자.
".exe"는 "application/x-msdownload"라고 설정하면 된다.
사용자 삽입 이미지
사용자 삽입 이미지
이것으로 서버쪽은 끄읏!

2. PC설정
PC는 보안설정을 위해 "caspol.exe"라는 넘을 사용한다.
.NET 2.0에서는 "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\"폴더에 있으니 이녀석을 찾아서 DOS창에서 다음과 같이 입력후 실행하면 "yes/no"둘중에 하나를 선택하라고 뜨는데 우리야 뭐 무조건 깔아야 하니 그냥 yes쳐주자.

"caspol.exe -machine -addgroup All_Code -url http://10.250.30.181/* Everything -n SKCC"

resize_image
실행후의 모습인데 참으로 아름답지는 않지만... ㅡㅡ;;
아무튼 제대로 적용됐단다.

이렇게 하면 실행에는 문제가 없을 것이다. 더 추가적으로 "caspol.exe"에 대해 알아보면 이녀석이 사용하는 인자를 분석해보면 다음과 같다.

"-machine"이라고 된부분은 "-en", "-m", "-u"로 대체가능하다.
각각 enterprise, machine, user를 뜻한다. 즉, 대상범위이다.

"-addgroup"이라고 된녀석은 대상 코드를 이야기하고
다음의 구조중 하나에 추가하란 의미이다.
-All_code -+- MyComputer (내컴퓨터에서 실행)
                +- Intranet (인트라넷에서 실행)
                +- Trusted (신뢰할 수 있는 사이트에서 실행)
                +- Internet (인터넷에서 실행)
                +- untrusted (신뢰하지 않는 사이트에서 실행)
"-url"은 "-site","-zone","-url"등으로 대체될 수 있고 다운로드 받는 곳의 조건을 표현하고 있는데 인터넷에서 받을것이니 그냥 "-url"로하자. 요넘 뒤에 있는것이 "http"나 "ftp"로 시작되는 인터넷 표준 주소이다.
주소바로 뒤에 보이는 "Everything"은 다음과 같은 체계로 나뉜다.
-FullTrust
-SkipVerification
-Execution
-Nothing
-Localintranet
-internet
-Everything
다시말해 권한인데 "Everything"은 권한을 다 주는 거다. (PC포맷시켜도 된다. ㅡㅡ;;)
그다음이 FullTrust이며 이렇게 주루루룩 권한이 낮아져서 Nothing이 되면 아무것도 안된다.

그리고 나서 나오는 것이 "-n"인데 이녀석은 이렇게 설정하는 코드 그룹의 이름으로 여기서는 SKCC로 했다. (왜? 그냥~ 사실 나는 SKC&C라는 회사 다닌다.. ㅡㅡa)

이제 SDK가 깔려있다면 있을 제어판>관리도구>.net framework 2.0 Configuration으로 가서 확인해보자.
사용자 삽입 이미지
2007/04/27 18:01 2007/04/27 18:01

스마트 클라이언트가 뭔지 궁금하신분은 다른 사이트에서 찾아보시고 뭐 간단히 말해 닷넷판 ActiveX되겠다.

일단 VS2005있으면 좋겠고 없으면 말고다. ㅡㅡ;;

먼저 새로운 프로젝트를 생성하고 다음과 같이 "Windows 컨트롤 라이브러리"로 설정한뒤 이름을 "Simple"이라고 하자.

resize_image
(잘안보이면 그림을 클릭 함해주면 제대로 보임)
위와 같이 하면 아래와 같이 Simple이라는 폴더가 생성되고 각종 파일이 주루루룩 생긴다.
resize_image
왼쪽에 쪼끄만하게 회색박스가 생길텐데 거기다가 Button컨트롤하나를 올려놓자.
사용자 삽입 이미지
그리고 "button1"을 더블클릭해서 이벤트를 자동생성하고 코딩창에 "MessageBox.show("Hello World!");"를 입력하자.

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

namespace Simple {     public partial class UserControl1 : UserControl     {         public UserControl1()         {             InitializeComponent();         }         //아래 4줄이 새로 추가된 코드임.         private void button1_Click(object sender, EventArgs e)         {             MessageBox.Show("Hello World!");         }         //여기까지임.     } }


이제 "F5"키를 눌러서 디버그 모드에서 테스트 함해보자.
resize_image

아직까지는 문제없이 잘된다.
이제 원래 폴더 밑에 "Simple\bin\Debug"로 가보면 "Simple.dll"이 생성되어 있을것이다.
이놈을 웹루트로 옮기고 아래와 같이 코딩하고 test.htm으로 저장하자.
<object
    id="Simple"
    classid="Simple.dll#Simple.UserColtrol1"
    width="150" height="150">
</object>


id는 알아서 설정해도 될것이다.
그러나 "classid 속성"은 중요하므로 다음과 같은 룰을 따르자.

"classid = [dll명]#[namespace].[class]"

예제에서보면 "Simple.dll"이니 당근 dll명은 "Simple.dll"이다.
namespace는 C#코드에서 "namespace Simple"라고 된 부분이 바로 해당 dll의 namespace이니 요기서 따오면 "Simple"이 되는 것이다.
Class는 "public partial class UserControl1 : UserControl"라고 된부분에서 따오면 된다.
그래서 class부분은 "UserContol1"이 된것이다.
간단한 공식이니 헷갈리지 말고 ^^

이제 웹서버를 통해 실행해보면 다음과 같이 잘 뜬다.
사용자 삽입 이미지
처음 만들어보는 거라 삽질좀 했다. 왜? 그냥 "test.htm"파일을 더블클릭했더니만 절대 실행안된다. 반드시 웹서버에 Request해서 받도록 하자.
2007/04/23 18:25 2007/04/23 18:25