'c#'에 해당되는 글 27건

  1. 2008.04.10 EventLog
  2. 2008.04.08 쓰레드에 의한 파일 전송 1
  3. 2008.04.02 네트워크 드라이브
  4. 2008.04.01 USB 및 하드웨어 인식
  5. 2008.04.01 XML Serialize
  6. 2008.04.01 폴더/ 디렉토리 탐색기/브라부져 FolderBrowser
  7. 2008.03.07 Shallow Vs Deep Copy 깊은 복사
  8. 2008.03.07 컨트롤에 컨트롤 넣기 DataTemplate, FrameworkElementFactory 1
  9. 2008.03.06 CreateDirectory 사용권한
  10. 2008.03.05 클래스의 XML 문서화.

EventLog

Program/C# 2008. 4. 10. 11:46
프로그램의 런타임시에 어찌 돌아가는지 혹은 문제는 없는지 보통 Log 파일을 기록합니다.
무식하게 텍스트 파일에 때려 넣었었는데 아래와 같은게 있네요..
사용법은 간단합니다. 자세한 사항에 대해서는 귀찮아서 조사 안해봤네요...
MSDN 긁어왔습니다 -0-;

──────────────────────────────────────────────────

간단한 사용법

string 타입의 Source 와 LogName 이 필요합니다.

// Source 를 생성합니다.
if (!System.Diagnostics.EventLog.SourceExists("Source"))
                    System.Diagnostics.EventLog.CreateEventSource("LogName", ""Source");

// 이벤트를 기록합니다.
System.Diagnostics.EventLog.WriteEntry(LogFileName, Msg);
WriteEntry 함수는 여러 가지로 오버라이드되어 있군요.. 입맛에 맞게 사용하시면 될 것 같습니다.

──────────────────────────────────────────────────

비스타 기준  [제어판] [관리도구] [이벤트뷰어]
왼쪽 트리에 보시면 LogName 라고 확인 하실수 있을 겁니다.
사용자 삽입 이미지


──────────────────────────────────────────────────

EventLog 클래스

스레드로부터 안전한 방식

이 형식의 모든 public static(Visual Basic에서는 Shared) 멤버는 스레드로부터 안전합니다. 하지만 인스턴스 멤버는 스레드로부터 안전하지 않습니다.

설명

EventLog를 사용하면 중요한 소프트웨어 또는 하드웨어 이벤트 정보가 기록되어 있는 Windows 2000 이벤트 로그에 액세스하거나 사용자 지정할 수 있습니다. 예를 들어, EventLog를 사용하여 기존 로그를 읽고, 로그에 엔트리를 쓰고, 이벤트 소스를 만들거나 제거하고, 로그를 삭제하고, 로그 엔트리에 응답할 수 있습니다. 또한 이벤트 소스를 만들 때 새로운 로그를 만들 수도 있습니다.

CreateEventSource를 호출할 때 지정한 로그가 컴퓨터에 없으면 사용자 지정 로그가 새로 만들어지고 응용 프로그램이 해당 로그의 소스로 등록됩니다. 따라서 EventLog 클래스를 사용하면 적절한 액세스 권한이 있는 이벤트 로그에서 엔트리를 쓰거나 읽을 수 있습니다.

참고   보안 로그는 읽기 전용입니다.

이벤트 로그에 쓸 경우 Source 이벤트를 지정하거나 만들어야 합니다. Source 는 이벤트 로그에 응용 프로그램을 유효한 엔트리 소스로 등록합니다. Source를 사용하면 한 번에 하나의 로그에만 쓸 수 있습니다. Source 에는 여러 가지 문자열을 사용할 수 있지만 시스템에 있는 다른 소스와는 다른 이름을 사용해야 합니다. 대개 소스에는 응용 프로그램 이름 또는 다른 특정 문자열이 사용됩니다. 중복된 Source 값을 만들려고 하면 예외가 throw됩니다. 그러나 하나의 이벤트 로그에 여러 개의 소스를 연결할 수 있습니다.

로그를 읽으려면 EventLogLog 이름 및 MachineName (서버 컴퓨터 이름)을 지정합니다. 소스는 로그에 기록하는 경우에만 필요하기 때문에 Source를 지정할 필요가 없습니다. Entries 멤버는 자동으로 엔트리의 이벤트 로그 목록으로 채워집니다.

참고    Log/ MachineName 쌍을 지정하여 로그에 연결하는 경우 MachineName을 지정할 필요가 없습니다. MachineName을 지정하지 않으면 기본적으로 로컬 컴퓨터(".")가 지정됩니다.

이벤트 로그에 쓸 때 message 매개 변수와 함께 보낼 정보 형식을 지정할 수 있습니다. 메시지를 보내는 것 외에 메시지가 오류, 경고 또는 정보 엔트리 형식인지 여부를 나타내는 EventLogEntryType을 보낼 수 있습니다. 또한 응용 프로그램 정의 eventIdcategory 매개 변수를 지정하여 이벤트 뷰어의 형식 및 범주 열에 표시할 수 있습니다. 그리고 지정한 이벤트에 추가 정보를 연결하는 경우 이벤트 엔트리에 이진 데이터를 첨부할 수도 있습니다.

EventLog 클래스는 개별 이벤트 로그 및 해당 엔트리에 대한 액세스 뿐만 아니라 모든 이벤트 로그 컬렉션에 대한 액세스도 제공합니다. EventLog의 정적(Visual Basic에서는 Shared) 멤버를 사용하여 로그를 삭제하고, 로그 목록을 가져오고, 소스를 만들거나 삭제하고, 컴퓨터에 특정 소스가 이미 포함되어 있는지 여부를 확인할 수 있습니다.

Windows 2000에는 응용 프로그램, 시스템 및 보안의 3가지 기본 로그가 있습니다. 다른 응용 프로그램이나 Active Directory와 같은 서비스가 설치되어 있으면 이벤트 로그가 더 있을 수 있습니다. EventLog를 사용하여 서버의 이벤트 뷰어를 통해 볼 수 있는 사용자 지정 이벤트 로그를 만들 수 있습니다.

이벤트 로그에 쓰는 경우 디스크 공간, 프로세서 시간 및 기타 시스템 리소스가 사용됩니다. 따라서 필수 정보만 기록해야 합니다. 또한 성능에 좋지 않은 영향을 주지 않도록 기본 코드 경로 대신 오류 경로에 이벤트 로그 호출을 배치하는 것이 좋습니다.

EventLog 인스턴스의 초기 속성 값 목록을 보려면 EventLog 생성자를 참조하십시오.

:

쓰레드에 의한 파일 전송

Program/SilverLite | WPF 2008. 4. 8. 09:48

쓰레드에 의한 파일 전송

환경 : VS2008, WPF 프로젝트


내용 : 쓰레드를 사용하여 내트워크 내의 원격지에 파일을 전송한다.
파일 전송 상황에 대한 ProgressBar를 갱신한다.


파일 전송
우선 알아야 할것은 파일의 전송량의 정보를 어떻게 알 것인가 이다.
FileStream 클래스를 이용해 보자

사용자 삽입 이미지

여기서 Info는 개인적으로 정의한 구조체로 복사 원본 파일명과 대상 경로를 가지고 있다.
두개의 파일 스트림을 정의하고, 버퍼를 생성한다.
버퍼의 단위만큼 파일을 기록하고 이 정보를 통해 현재 진행 상황을 알 수 있을 것이다.

사용자 삽입 이미지

좀 더 꼼꼼한 개발자라면 Try Catch Finally를 통해 오류 상황에 대한 처리를 잊지 않을 것이다.
사용자 삽입 이미지


왜 쓰레드를 사용하였는가?
용량이 큰 파일을 전송해보았다면, 해당 응용프로그램은 정지 상태가 된다.
이 시점에서 UI의 변경이나 다른 작업을 시도한다면, 응용프로그램은 응답없음 상태가 될 것이다.
이후에 설명하겠지만 Progressbar에 작업 상황을 표현 하는 것 또한 쉽지 않을 것이다.

쓰레드를 사용하기 위해서 우선, 쓰레드에 대한 이해가 필요하다.
쓰레드를 사용함으로서 생기는 문제점들에 대해서 고려되어야 할 것이다.

다음 글은 네이버 블로그 muduri07님의 포스트에 이해 대한 자료가 잘 정리되어 있다
http://blog.naver.com/muduri07?Redirect=Log&logNo=130006369226
다른 주의 사항들과 비롯하여 쓰레드는 최소단위의 오퍼레이션이어야 한다는 것을
명심하기 바랍니다.

쓰레드에 대한 이해가 되었다면 다음으로 WPF 에서의 쓰레드에 대한 이해가 필요하다.
MSDN "발송자를 사용하여 응답 성능이 뛰어난 응용 프로그램 작성" 이라는 포스트이다.
http://msdn2.microsoft.com/ko-kr/magazine/cc163328.aspx

내용을 요약하자면, UI들은  DispatcherObject 를 상속받아 Dispatcher(발송자)를 보유하고 있다.
이러한 발송자들은 메세지 처리 및 기타의 작업들을 진행하는 역할을 한다.
이러한 역할이 VerifyAccess, CheckAccess 다.
DispatcherObject 를 상속받은 개체는 UI쓰레드가 아닌 곳에서 호출될때 에러를 발생한다.
발송자의 Invoke, BeginInvoke 매서드를 통해서 이 상황을 해결한다.
또한 BackgroundWorker를 이용할 수 있다.

한마디로 UI 개체들은 자신이 속한 쓰레드가 아닌 다른 쓰레드 에서 호출할때 에러가 발생하고, 이 문제를 해결하기 위한 방법에 대한 포스트 이다.

실제 적으로 쓰레드를 생성하는 것은 간단하다.
이 둘의 네임스페이스가 필요 할 것이다.

using System.Windows.Threading;
using System.Threading;

Thread trd = new Thread(new ThreadStart(FileCopyThread));
trd.Start();

Thread 클래스는 생성자 파라미터로 ThreadStart 라는 대리자(delegate)를 요한다.
쓰레드의 사용에서 대리자는 실과 바늘과 같은 관계로서 쓰레드의 진입 시점이 되는 매서드를 제공한다.
대라자는 과거 C의 경우의 매서드 포인터와 같은 개념으로 이해하고 있다.
매서드를 지칭하고 있는 대리자는 대리자의 사용으로 매서드를 호출한다.

위 코드는 ThreadStart라는 대리자를 통해 FileCopyThread 라는 매서드를 호출 하고 있고,
ThreadStart 는 프레임 워크에서 제공되는 대리자 이다.

FileCopyThread 매서드는 앞부분에서 설명한 파일의 복사 작업을 진행하게 될 것이다.

지금까지 내용을 살펴 보면 쓰레드를 생성하였고, 이러한 쓰레드를 통해 파일 전송을 진행한다.
다음으로 보아야 할 것은 파일 전송 상황에 대한 ProgressBar의 갱신이다.

ProgressBar의 갱신 또한 스레드로 처리되어야 한다.
파일의 전송과 ProgressBar의 갱신이 같은 스레드내에 존재한다면..
파일이 전송되는 도중에는 Progressbar를 갱신하지 못할 것이기 때문이다.
하지만 이 문제에 대한 해결은 앞부분에 설명하였다.
사용자 삽입 이미지

FilecopyThread 매서드에 대해 살펴보자
Dispatcher.Invoke(DispatcherPriority.Normal, _pgsSetting, (int)(SourceFile.Length / BUFFER));
Invoke 매서드는 우선순위, 대리자, 대라자에 전달된 파라미터 들을 인자로 가진다.
이 매서드는 _pgsSetting 라는 대리자를 호출하여 int 값을 파라미터로 전달 하고 있다.

_pgsSeetting 라는 대리자를 정의 하는 부분이다.

delegate void DG_SetProgress(int max);
private void SetProgress(int max)
{
progressFile.Value = 0;
progressFile.Minimum = 0;
progressFile.Maximum = max;
}

_pgsSetting = new DG_SetProgress(SetProgress);

SetProgress 매서드는 progressFile 이라는 프로그레스바를 호출하고있다.
아래는 프로그래스바의 상태를 갱신하는 부분이다.
DG_RefreshProgress _pgsRefresh;
private void RefreshProgress()
        {
            progressFile.Value += 1;
            progressTotal.Value += 1;
        }

이렇게 Invoke 매서드를 통해 새로운 스레드에서 프로그래스의 값을 변경한다.

지금가지의 내용을 요약한다면 메인 윈도우에는 프로그레스 바가 놓여있다.
파일을 전송 명령이 시작되면 스레드를 통해 파일의 전송이 진행된다.
이 스레드는 파일 전송도중 진행상황을 메인 윈도우의 프로그레스 바에 표현 하는데,
Dispatcher.Invoke 매서드를 통해 새로운 스레드로서 동작하게 된다.

'Program > SilverLite | WPF' 카테고리의 다른 글

Resource Dictionary  (0) 2008.04.01
폴더/ 디렉토리 탐색기/브라부져 FolderBrowser  (0) 2008.04.01
SilverLite  (0) 2008.01.16
:

네트워크 드라이브

Program/C# 2008. 4. 2. 20:10
네트워크 드라이브의 목록 정보를 가져오고, 설정하는 방법입니다.

유경상님의 닷넷 블로그로 설명이 잘되어 있네요

네트워크 드라이브 설정
http://www.simpleisbest.net/archive/2005/06/07/157.aspx

네트워크 드라이브 목록
http://www.simpleisbest.net/archive/2005/08/26/211.aspx

'Program > C#' 카테고리의 다른 글

EventLog  (0) 2008.04.10
USB 및 하드웨어 인식  (0) 2008.04.01
XML Serialize  (0) 2008.04.01
:

USB 및 하드웨어 인식

Program/C# 2008. 4. 1. 18:35

환경 : VS2008, WPF, C#

컴퓨터가 하드웨어를 인식했을때 이에 대한 이벤트를 처리하는 부분입니다.
C# 에서 API를 사용해서 구현하는 방법에 대해 알아보겠습니다.

알아야 할 것은 두가지 입니다.
하드웨어가 인식되었을대 어떠한 메세지가 오느냐?
이 메세지에 포함된 값을 어떻게 확인하느냐?

답을 먼저 말한다면
하드웨어를 인식했을 경우 WM_DEVICECHANGE 라는 메세지가 날라옵니다.
USB 의 인식 및 제거를 확인하기 위해서 아래와 같은 상수 값들이 필요합니다.

            UInt32 WM_DEVICECHANGE    = 0x0219;
            UInt32 DBT_DEVTUP_VOLUME = 0x02;
            UInt32 DBT_DEVICEARRIVAL = 0x8000;
            UInt32 DBT_DEVICEREMOVECOMPLETE = 0x8004;

UInt32는 닷넷에서 메세지 상수값에 대응하는 타입입니다.
각 값들에 대해서는 MSDN 및 구글을 검색하시면 쉽게 아실 수 있습니다.
만약 USB 가 아닌 다른 장치를 인식해야 한다면.. 그에 해당하는 상수값들을 사용하면 될 것입니다.

첫번째, 우선 메세지 프로시져를 만들어야 합니다.

protected override void WndProc(ref Message m)

닷넷에서는 WndProc 를 오버라이드 함으로서 메세지를 가로챌 수 있습니다.


두번째, 장치가 인식되었는지를 확인해야 합니다.

if (m.Msg == WM_DEVICECHANGE)

장치의 변화는 확인하였군요...


셋째, 어떠한 장치인지를 확인해야 합니다.
   int devType = Marshal.ReadInt32(m.LParam, 4);
   (devType == DBT_DEVTUP_VOLUME)

Marshal(마샬) 클래스는 언메니지드 코드에 접근할 수 있고,
기타 포인터및 C 스타일의 자료형들을 사용할 수 있도록 지원하는 클래스다라고..
알고 있습니다. 정확히 알아보진 않았고 대략 그런 용도로 사용하고 있느니까요..
이에 대해선 좀더 자세히 알아 보시길 바랍니다.
어쨌건 마샬 클래스를 통해서 LParam 값을 읽어 장치의 타입을 검색하는 군요..

넷째, 그렇다면 장치의 인식인지, 제거 인지를 판단해야 합니다.
if (m.WParam.ToInt32() == DBT_DEVICEARRIVAL)
if (m.WParam.ToInt32() == DBT_DEVICEREMOVECOMPLETE)

추가로, 볼륨 장치 일경우 드라이브의 형태로 잡힐텐데요. 드라이브명까지 알아본다면

DEV_BROADCAST_VOLUME 라는 구조체를 정의합니다.
LParam 에서 볼륨 정보를 가지고 있는 놈이지요.

[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
        public struct DEV_BROADCAST_VOLUME
        {
            public int dbcv_size;
            public int dbcv_devicetype;
            public int dbcv_reserved;
            public int dbcv_unitmask;
        }

TJ.TJUtil.DEV_BROADCAST_VOLUME vol;
vol = (DEV_BROADCAST_VOLUME)Marshal.PtrToStructure(m.LParam, typeof(DEV_BROADCAST_VOLUME));

vol.dbcv_unimask 값으로 드라이브 명을 얻을 수가 있는데요...
값을 바로 주진 않는군요... 아래 함수를 정의 해 봅니다.
public static char DriveMaskToLetter(int mask)
        {
            char letter;
            string drives = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
            int cnt = 0;
            int pom = mask / 2;
            while (pom != 0)
            {
                pom = pom / 2;
                cnt++;
            }

            if (cnt < drives.Length)
                letter = drives[cnt];
            else
                letter = '?';

            return letter;
        }

vol.dbcv_unimask 값을 파라미터로 받아서 드라이브 명의 문자를 리턴 합니다.


'Program > C#' 카테고리의 다른 글

네트워크 드라이브  (0) 2008.04.02
XML Serialize  (0) 2008.04.01
Shallow Vs Deep Copy 깊은 복사  (0) 2008.03.07
:

XML Serialize

Program/C# 2008. 4. 1. 12:00
환경 : VS2008, WPF 프로젝트

Xml Selralize 를 사용하는데 있어서 좋은 정보를 제공하는 곳입니다.
http://www.ensimple.net/enSimple/show.aspx?cnum=68&b_id=study_csharp&page=1

http://www.topxml.com/xmlserializer/serialize_class.asp

Serialize 를 사전에서 찾아보면 "번호순으로 나열하다" 라는 군요..
데이터를 스트림의 형식으로 표현하여 읽고 쓰기를 한다는 의미 같습니다.

제가 Serialize 를 사용하게 된 계기는 XML 문서를 메모리 상에 클래스로 구조화 하기 위해서 였습니다.
그러기 위해선 우선 해당 XML 문서의 형식에 맞는 클래스가 존재 하여야 할 것입니다.

MSDN을 에서 XSD를 검색해보면 ..
XML 문서의 스키마를 생성하고 이를 클래스 화 하는 방법에 대해서 아실 수 있을 겁니다.
이렇게 생성된 클래스를 사용하는데 있어서 주의 할 점은..
기본값의 사용입니다. XML 무서의 특정 노드에 값이 없을경우 클래스는 기본 값 설정을 하여야 할 것입니다.
또한 노드 컬렉션에 값이 없을경우 이런 경우 클래스의 컬렉션은 null 값 조차 가지지 않습니다.
해당 컬렉션의 유효성을 판단하기 위해 null 비교 하였다면 바로 에러가 날 것입니다.
스키마 혹은 클래스를 조작하여 이런 경우에 대비 할수가 있습니다만,
이번 포스트의 범위가 아니므로 넘어가도록 하겠습니다.

XML 문서의 구조가 비교적 간단 하다하면 위와 다르게 직접 클래스를 생성하셔도 될것입니다.
XML 시리얼 라이져는 프로퍼티 및 public 영역에 대해 XML 문서와의 매칭을 하게 됩니다.

[XmlAttribute()]
public string book {get; set;}

이런식으로 선언하게 되면 book 이라는 에트리 뷰트가 생성되게 되는 거죠...
주목할 점은 [] 부분 입니다.
사실 대괄호 안의 값을 변경함으로서 우리는 좀 더 테크니컬할 클래스를 생성 할 수가 있습니다.
이에 대한 설명은 상단의 두번째 링크된 페이지를 참조 하시면 될 것입니다.

클래스의 이름은 노드가 되고 클래스 내에 설정된 에트리 뷰트 및 노드들은 클래스 노드의 자식노드가 됩니다.
만약 클래스가 컬렉션을 포함하고 있다 해도 같은 원리가 되는 것이지요..
사용자 삽입 이미지


읽어드리는.. 디시리얼 라이즈 하는 부분입니다.
Page 라는 클래스는 제가 정의한 클래스 입니다.
이 클래스 타입에 맞는 시리얼라이져를 생성한후,
읽어드릴 XML 문서의 경로에 해당하는 XmlTextReader 를 생성합니다.
그리고 디시리얼라이즈.. 간다하죠..

그렇다면 쓰기.. 시리얼라이즈 하는 부분에 대해서 알아볼까요..
사용자 삽입 이미지


기본 디시리얼라이즈에 역순입니다.
XmlSerializerNamespaces 라는 것은 시리얼라이즈시에 루트 노드의 네임스페이스를 셋팅하는 부분입니다.
저부분을 삭제하고 실행 해보면 기본 네임스페이스(?? 기억이..)가 들어가는 것을 보실 수 있습니다.

잦은 시리얼라이즈의 사용은 프로그램에 부하가 된다고 합니다만.. 전 아직 잘 모르겠군요..
잦은 이라는 정도가 어느 선까지를 말하는지...

이제 시리얼라이즈의 대상이 되는 클래스를 만드는 부분과 DOM 에 대한 이해만 충분하다면
XML 문서를 조작하는데 있어서는 무리 없을 것 같습니다.

이는 다음 기회에 ~
:

폴더/ 디렉토리 탐색기/브라부져 FolderBrowser

Program/SilverLite | WPF 2008. 4. 1. 10:05

환경 : VS2008, WPF 어플리케이션

폴더 블라우져에 대해서 알아보도록 하겠습니다.
WPF 파일 다이얼로그를 사용하기 위해서는 Microsoft.Win32 네임스페이스를 참조하여야 합니다.
FolderBroswer 는 System.Windows.Forms 네임스페이스에 존재합니다.
생성해 볼까요..?

System.Windows.Forms.FolderBrowserDialog Fdlg = new System.Windows.Forms.FolderBrowserDialog();

이렇게 폴더 브라우져가 생성되었습니다.
보통 제가 사용하기에 열기/저장 다이얼로그를 사용하는 경우 필터와 루트 폴더 정도 셋팅해서 사용하는데..
폴더 브라우져는 필터 속성이 없으므로 루트 폴더 지정에 대해서 알아보겠습니다.

Fdlg.RootFolder = Environment.SpecialFolder.MyPictures;

스페셜 폴더에 보면 몇가지 종료의 폴더 정보를 가져 오실 수 있습니다.
인텔리젼스가 지원된다면 아래와 같은 목록을 보실수 있습니다.

사용자 삽입 이미지
이 목록에 원하는 경로가 있다면 성공입니다.
하지만, 꼭 입맛에 맞을듯 말듯한 경우가 있죠.. ? ㅎㅎ 그래서 알아봤습니다.

    public class TJFolderBrowser
    {
        public static void SetRootFolder(System.Windows.Forms.FolderBrowserDialog fbd, CsIdl csidl)
        {
            Type t = fbd.GetType();
            FieldInfo fi = t.GetField("rootFolder", BindingFlags.Instance | BindingFlags.NonPublic);
            fi.SetValue(fbd, (System.Environment.SpecialFolder)csidl);
        }


        [Flags()]
        public enum CsIdl
        {
            Desktop = 0x0000, // Desktop
            Internet = 0x0001, // Internet Explorer (icon on desktop)
            Programs = 0x0002, // Start Menu\Programs
            Controls = 0x0003, // My Computer\Control Panel
            Printers = 0x0004, // My Computer\Printers
            Personal = 0x0005, // My Documents
            Favorites = 0x0006, // user name\Favorites
            Startup = 0x0007, // Start Menu\Programs\Startup
            Recent = 0x0008, // user name\Recent
            SendTo = 0x0009, // user name\SendTo
            BitBucket = 0x000a, // desktop\Recycle Bin
            StartMenu = 0x000b, // user name\Start Menu
            MyDocuments = 0x000c, // logical "My Documents" desktop icon
            MyMusic = 0x000d, // "My Music" folder
            MyVideo = 0x000e, // "My Videos" folder
            DesktopDirectory = 0x0010, // user name\Desktop
            Drives = 0x0011, // My Computer
            Network = 0x0012, // Network Neighborhood (My Network Places)
            Nethood = 0x0013, // user name\nethood
            Fonts = 0x0014, // windows\fonts
            Templates = 0x0015,
            CommonStartMenu = 0x0016, // All Users\Start Menu
            CommonPrograms = 0x0017, // All Users\Start Menu\Programs
            CommonStartup = 0x0018, // All Users\Startup
            CommonDesktopDirectory = 0x0019, // All Users\Desktop
            AppData = 0x001a, // user name\Application Data
            PrintHood = 0x001b, // user name\PrintHood
            LocalAppData = 0x001c, // user name\Local Settings\Applicaiton Data (non roaming)
            AltStartup = 0x001d, // non localized startup
            CommonAltStartup = 0x001e, // non localized common startup
            CommonFavorites = 0x001f,
            InternetCache = 0x0020,
            Cookies = 0x0021,
            History = 0x0022,
            CommonAppdata = 0x0023, // All Users\Application Data
            Windows = 0x0024, // GetWindowsDirectory()
            System = 0x0025, // GetSystemDirectory()
            ProgramFiles = 0x0026, // C:\Program Files
            MyPictures = 0x0027, // C:\Program Files\My Pictures
            Profile = 0x0028, // USERPROFILE
            SystemX86 = 0x0029, // x86 system directory on RISC
            ProgramFilesX86 = 0x002a, // x86 C:\Program Files on RISC
            ProgramFilesCommon = 0x002b, // C:\Program Files\Common
            ProgramFilesCommonx86 = 0x002c, // x86 Program Files\Common on RISC
            CommonTemplates = 0x002d, // All Users\Templates
            CommonDocuments = 0x002e, // All Users\Documents
            CommonAdminTools = 0x002f, // All Users\Start Menu\Programs\Administrative Tools
            AdminTools = 0x0030, // user name\Start Menu\Programs\Administrative Tools
            Connections = 0x0031, // Network and Dial-up Connections
            CommonMusic = 0x0035, // All Users\My Music
            CommonPictures = 0x0036, // All Users\My Pictures
            CommonVideo = 0x0037, // All Users\My Video
            Resources = 0x0038, // Resource Direcotry
            ResourcesLocalized = 0x0039, // Localized Resource Direcotry
            CommonOemLinks = 0x003a, // Links to All Users OEM specific apps
            CdBurnArea = 0x003b, // USERPROFILE\Local Settings\Application Data\Microsoft\CD Burning
            ComputersNearMe = 0x003d, // Computers Near Me (computered from Workgroup membership)
            FlagCreate = 0x8000, // combine with CSIDL_ value to force folder creation in SHGetFolderPath()
            FlagDontVerify = 0x4000, // combine with CSIDL_ value to return an unverified folder path
            FlagNoAlias = 0x1000, // combine with CSIDL_ value to insure non-alias versions of the pidl
            FlagPerUserInit = 0x0800, // combine with CSIDL_ value to indicate per-user init (eg. upgrade)
            FlagMask = 0xFF00, // mask for all possible flag values
        }
    }

TJFolderBrowser 는 클래스는 임의로 제가 생성한 것으로..
CsIdl 열겨형에 존재하는 값들로 루트 폴더를 셋팅해주는 클래스 입니다.
열거형 중에 Network 라는 값을 사용하기 위해 위 클래스를 사용하였는데요.

SetRootFolder 함수는 파라미터로 폴드브라우져와 열거형 값을 원하는 군요.. 그리고 Static 으로 선언되어있구요
사용하는 부분을 볼까요..

TJFolderBrowser.SetRootFolder(Fdlg, TJFolderBrowser.CsIdl.Network);

간단하군요 ^^

'Program > SilverLite | WPF' 카테고리의 다른 글

Resource Dictionary  (0) 2008.04.01
SilverLite  (0) 2008.01.16
RIA ?  (0) 2008.01.16
:

Shallow Vs Deep Copy 깊은 복사

Program/C# 2008. 3. 7. 15:25

C# 은 기본 적으로 얕은 복사를 기반으로 합니다.
C/C++ 의 포인터 개념처럼...
처음 C# 을 하게 되면서 의식하지 않고 놓쳤던 부분이네요..

엄밀히 말하면 구조체는 깊은 복사, 클래스는 얕은 복사를 기본으로 하죠..
C# 에서 타입은 클래스로 되어 있습니다.
그렇다면 모든 타입의 인스턴스에 대한 복사는 얕은 복사인가..
그렇지 않습니다.
실제적으로  int  를 예로 들면 깊은 복사가 행해 집니다.
이는 내부적으로 깊은 복사의 처리를 대행 하기 때문입니다.

그렇다면 우선 깊은 복사가 진행되는 타입과 얕은 복사가 진행되는 타입에 대해서 먼저 숙지 해야 할 것입니다.
MSDN ㄱㄱ 잠깐 보면 대충 감이 잡히실 겁니다.

그럼 깊은 복사를 하는 방법을 알아보도록하죠..
깊은 복사를 하는 함수를 따로 빼도 되고 IClonable 인터페이스를 상속받은후
Clone() 함수를 구현 해줘도 됩니다..

방법 1 :  MemberwiseClone()함수를 이용

ICloneable 함수를 상속 받았다 가정하면..
object Clone()
{
       return this.MemberwiseClone();
}

간단하죠? 이렇게 쉽게 끝날리가 없습니다. ㅎㅎ
MSDN 에 MemberwiseClone 함수를 검색해 보면 Shallow Copy 라고 명시하고 있습니다.
요놈은 확실히 얕은 복사 입니다.
정확히 말하면 복사하려는 클래스가 가진 필드중..
값을 가지는 필드에 대해서는 깊은 복사를 참조를 가진 필드에 대해서는 얕은 복사를..
수행하게 됩니다.
간단히 예제를 만들어서 요놈으로 깊은 복사를 시도 해보신분들은 착각하기 딱 좋죠..

방법 2 : 메모리 시리얼라이징

            MemoryStream mem = new MemoryStream();
            BinaryFormatter bf = new BinaryFormatter();

            bf.Serialize(mem, obj);
            mem.Position = 0;

            object result = bf.Deserialize(mem);
            mem.Close();

이렇게 한 후 result 를 리턴 해주게 되면.. 메모리 상의 깊은 복사가 됩니다.
시리얼라이즈를 자주 사용하게 되면 시스템이 느려진다 던데..
그것 까진 잘 모르겠군요...

방법 3 : 이건 생각만 해본 바 인데...
MemberwiseClone() 를 참조 필드마다 모두 적용시킨다면..?
참조 필드가 많고 다층이라면 빡시겠군요...

'Program > C#' 카테고리의 다른 글

XML Serialize  (0) 2008.04.01
컨트롤에 컨트롤 넣기 DataTemplate, FrameworkElementFactory  (1) 2008.03.07
CreateDirectory 사용권한  (0) 2008.03.06
:

컨트롤에 컨트롤 넣기 DataTemplate, FrameworkElementFactory

Program/C# 2008. 3. 7. 12:30

리스트 뷰 칼럼에 체크 박스를 넣는 방법에 대해서 알아 보겠습니다.
자료를 찾아보면 이를 Xaml 코드로 수행하는 방법에 대해서는 쉽게 보실 수 있을 겁니다.
전 코드로 이러한 작업을 하는 방법에 대해 알아보죠..

우선 수행순서를 알아보면..(일부순서는 바뀌어도 됩니다.)
1. 컬럼의 생성
            col = new GridViewColumn();
            col.Header = "사용";


2. 데이터 템플릿 생성
            DataTemplate dt = new DataTemplate();

3. 컬럼에 데이터 템플릿 연결
            col.CellTemplate = dt;

4. 팩토리 생성
            FrameworkElementFactory Factory = new FrameworkElementFactory(typeof(CheckBox));

5. 데이터 템플릿에 연결
            dt.VisualTree = Factory;

6. 원하는 프로프티(값)을 팩토리에 바인딩
            Bind = new Binding("isuse");
            Bind.Converter = new IsUseChkConvert();
            Factory.SetBinding(CheckBox.IsCheckedProperty, Bind);
            Factory.AddHandler(CheckBox.LoadedEvent, new RoutedEventHandle(Check_Load));

프로퍼티에 값을 기록 하는 것 이외에 런타임 이벤트 또한 생성 할 수가 있습니다.
이런 식으로 해당 컨트롤에 대한 이벤트를 추가 하여도 되고
로드 이벤트만 걸어주고 로드 이벤트 핸들러 내에서 런타임 이벤트를 생성해도 됩니다.
아무래도 이 방법이 좀더 친숙하겠죠 ^^;

제가 설명한 예제는 리스트 뷰의 컬럼에 체크 박스를 넣는 내용입니다.
여기서 주목할 것은
DataTemplate, FrameworkElementFactory 클래스 입니다.
http://msdn2.microsoft.com/ko-kr/library/system.windows.frameworkelementfactory.aspx
위 링크의 내용을 보면 Xaml 이 아닌 코드로의 사용은 비추천 한다고 나오네요.
하지만 테크니컬한 조작을 하지 않는다면 큰 무리는 없어보입니다.
http://msdn2.microsoft.com/ko-kr/library/system.windows.datatemplate.aspx
위 링크는 데이터 템플릿에 대한 글입니다.
내용을 읽어 보시면 System.Windows..::.FrameworkTemplate 클래스를 상속받는군요..
팩토리는 프렘웍 템플릿을 상속받은 템플릿에는 적용이 가능하다..??

'Program > C#' 카테고리의 다른 글

Shallow Vs Deep Copy 깊은 복사  (0) 2008.03.07
CreateDirectory 사용권한  (0) 2008.03.06
클래스의 XML 문서화.  (0) 2008.03.05
:

CreateDirectory 사용권한

Program/C# 2008. 3. 6. 17:18
public FileSystemAccessRule (
	IdentityReference identity,
	FileSystemRights fileSystemRights,
	InheritanceFlags inheritanceFlags,
	PropagationFlags propagationFlags,
	AccessControlType type
)
 
또는
public FileSystemAccessRule (
	string identity,
	FileSystemRights fileSystemRights,
	InheritanceFlags inheritanceFlags,
	PropagationFlags propagationFlags,
	AccessControlType type
)
account는 사용자 식별타입입니다.
Domain 사용자라면 Domain\사용자ID
아니라면 컴퓨터명\사용자ID
등으로 사용할 수도 있습니다.
:

클래스의 XML 문서화.

Program/C# 2008. 3. 5. 10:17
XMLSerializer 를 이용하여 클래스를 XML 문서화 할 수 있다.
클래스는 직접 만들어 질 수도 있고, Xsd.exe 를 통해서 생성될 수 있다.

    XmlRootAttribute xRoot = new XmlRootAttribute();
    xRoot.ElementName = "CustomRoot";
    xRoot.Namespace = "http://www.cpandl.com";
    xRoot.IsNullable = true;
     
    XmlSerializer serializer = new XmlSerializer(typeof(OrderedItem),xRoot);
     
    OrderedItem i = new OrderedItem();
     
    TextWriter writer = new StreamWriter(filename);
    
    serializer.Serialize(writer, i);
    writer.Close();

XmlSerializer 생성자들을 살펴 보면 다양한 형태의 저장이 가능하다.
위 에제에서 xRoot를 사용한 이유는 저장될때 노드의 네임이 클래스의 네임을 그대로 인용하는데, 전 노드의 이름을 따로 주어야 했기 때문이다.

Korea MSDN 링크
http://msdn.microsoft.com/library/kor/default.asp?url=/library/KOR/cpref/html/frlrfSystemXmlSerializationXmlSerializerClassTopic.asp

'Program > C#' 카테고리의 다른 글

CreateDirectory 사용권한  (0) 2008.03.06
차일드 컨트롤들의 열거...  (0) 2008.02.29
전역 변수, Properties  (0) 2008.02.29
: