Posted
Filed under C#

// ------------------------------------------------------------------------------

// DataGridView의 Cell 속성을 ComboBox로 했을경우의 몇가지 팁.

// (C#에 입문한지 얼마 안되서 최적의 방법인지 어쩐지는 모르겠습니다)

// ------------------------------------------------------------------------------


int nYourRow = 1;

int nYourCell = 2;

int nSelectedIndex = 0;

String strCurrentValue = "";

int nCurrentSelectedIndex = 0;


DataGridViewComboBoxCell dgvCb = (DataGridViewComboBoxCell)dataGridView.Rows[nYourRow].Cells[nYourCell];


// ComboBox를 원하는 값으로 지정할 경우

dgvCb.Value = dgvCb.Items[nSelectedIndex].ToString();


// ComboBox의 선택된 값을 가져올 경우

strCurrentValue = (String)dgvCb.Value; // (String)생략 가능


// ComboBox의 선택된 Index 가져올 경우

nCurrentSelectedIndex = dgvCb.Items.IndexOf(dgvCb.Value);



/*

* 정말 오랫만에 데브피에 로긴을 하네요..

* "아마 Rows.Selected() 인가가 있을겁니다. 확인해 보세요 ^^; "

* 이건 행이 선택되어졌는가를 반환합니다.

*/


2009/07/17 20:41 2009/07/17 20:41
Posted
Filed under C#

Internet Explorer 에서의 닷넷 Smart Client 개발

   강좌 최초 작성일 : 2004년 02월 15일
   강좌 최종 수정일 : 2005년 03월 10일

   작성자 : kevin(정 성태)
   편집자 : Taeyo(김 태영)

   강좌 제목 : Smart Client 의 개요

강좌 전 필자의 잡담>

그 전에 태오의 잡담 : 이 강좌는 2004년 2월부터 4월까지 월간마소에 연재되었던 스마트 클라이언트에 대한 컬럼이구요. 닷넥엑스퍼트의 기술 컨설턴트이신 정성태님이 제공해주셨습니다. 스마트 클라이언트에 대한 자료를 구하기 힘든 상황에서 이렇게 선뜻 좋은 자료를 공개해주신 성태님께 다시 한번 감사드립니다.

참고로, 성태님의 개인 사이트는 바로 www.sysnet.pe.kr입니다.
강좌보고 감동을 먹어서 한마디 격려를 해 주고 싶거나, 강좌에 대해 질문은 요기로!!!


요즘 들어서, Smart Client 라는 용어를 심심치 않게 들어 보았을 것이다. 모바일 분야에 계신 분들은 하나의 "기기" 라고 알고 계실 텐데, 필자의 이번 강좌에서는 "기기" 를 다루는 것이 아니고, Microsoft 가 선보인 ".NET Framework" 의 부분으로 나온 "Smart Client" 소프트웨어 개발을 다루려고 한다. 사실, 닷넷에서도 Smart Client 라는 용어는 다소 광범위하게 쓰이는데, 이 강좌에서는 주로 "인터넷 익스플로러에 임베드 된 형태의 컨트롤" 을 다룰 예정이다. 너무 말이 어려웠을 지 모르겠지만, 쉽게 한번 더 풀이해 보자면, 기존 ActiveX 컨트롤을 대체하는 Smart Client 를 구현해 본다는 것이다.

정성태 kevin@dotnetxpert.com

현재 (주) 닷넷 엑스퍼트 에서 기술컨설턴트로 일하고 있으며, 주로 COM-ActiveX, COM+, .NET Framework 관련한 작업을 하고 있다.


연재 순서
1회 : Smart Client 의 개요
2회 : Internet Explorer 와의 연동
3회 : 배포 연재 가이드
운영체제 : IIS 가 설치된 Windows 운영체제 - 필자의 경우 Windows 2003
개발도구 : Visual Studio .NET 2003, .NET Framework v1.1.4322
기초지식 : COM, C#, ASP.NET 기초
응용분야 : 현재로서는 기업 내부의 인트라넷 환경에서의 ActiveX 컨트롤 대체.
이후, 닷넷 프레임워크가 일반화되면 외부 웹사이트 에서의 ActiveX 컨트롤 대체

[강좌의 소스를 다운로드하고 싶다면 클릭하세요!!]


.NET Framework 이 나왔다. 어렵다던 NT Service 조차도 .NET Framework 이 나오면서 구현이 간단해졌다. 웹 프로그램도 마찬가지다. 예전 ASP 에서 "Microsoft Scripting Runtime 개체 라이브러리" 에서 제공되는 이외의 기능을 사용하려면 VC++/ VB 를 이용하여 COM 개체를 만들어야 했지만, 이제는 ASP.NET 에서 .NET Framework 의 Base Class Library 를 이용할 수 있어서 COM 개체를 제작할 필요성이 없어졌다. 이번 연재에서 다룰 "Smart Client" 는 기존의 "ActiveX 컨트롤" 을 교체할 수 있는 기술이다. 물론, ActiveX 컨트롤 제작보다 훨씬 쉬워졌음은 말할 것도 없다. 그 동안 수많은 ActiveX 를 제작해 오던 필자 개인적으로도 이번 "Smart Client" 는 환영할 만한 기술이 아닌가 생각된다.

먼저 접하게 되어 겪었던 시행착오를 비롯해서 예제 중심으로 설명을 해나갈 테니, 관심있는 독자들은 단계별로 하나씩 따라서 해보길 권한다. 참고로, IIS 는 5.0 과 6.0 에서 많은 차이고 있고, .NET Framework 역시 1.0 과 1.1 에는 많은 차이가 있다. 앞으로의 기사는 IIS 6.0 과 .NET Framework 1.1 을 기준으로 하므로 이것과 다른 환경을 가진 독자의 경우, 아래의 설명에서 상이한 부분이 있을지도 모르니 감안해 주기 바란다.

1. ActiveX 보다 쉬운 컨트롤
2. 간단한 컨트롤 제작
3. 이벤트 구현
4. 이벤트 동작을 위한 닷넷 보안 변경


1. ActiveX 보다 쉬운 컨트롤

현업에 계신 분들 중에서, 순수하게 웹 사이트의 출력을 DHTML 로만 하는 것이 너무도 힘겹다는 것을 토로한다. 대부분의 경우에 있어 고객의 요구는 DHTML 의 제약을 생각하지 않는다. 무조건 이러이러한 기능이 필요할 뿐이고, 그러한 기능을 Script 로 구현하려니 속도저하 및 코드의 유지보수에 어려움이 오는 것은 당연하다. 특히 루프가 많은 경우, 스크립트의 속도저하는 심각해지며, 운영체제와 독립된 Script 의 한계로 인해 구현이 불가능한 부분까지도 나올 수 밖에 없다. 그런 상황에서 해결책으로 제시된 것은 ActiveX 컨트롤이었다. Internet Explorer 를 기반으로 하는 그룹웨어를 보면, ActiveX 로 "도배" 를 한 사이트가 많다. "도배" 라는 용어를 썼는데, 절대 탓하려는 의미가 아니다. 요구사항대로 하려니, 답은 ActiveX 뿐이었고, 그로 인해 개발생산성이 현저하게 떨어졌을 것이다.

이젠 ActiveX 를 떠나야 할 시기가 된 것 같다. VC++ 에서 벗어나서 VB 수준의 편리함을 제공해주는 Smart Client 가 여러분 곁에서 기다리고 있다. Smart Client 의 실현 가능성에 있어 장애물이라면 아직 "닷넷 프레임워크" 가 널리 퍼지지 않았다는 사실이다. 일단, 그 부분은 시간이 해결해 줄 것이고, 가능한 범위를 찾아보면 인트라넷을 예로 들 수 있겠다. 정책적으로 닷넷 프레임워크를 설치할 수 있는 상황이라면, ActiveX 보다 개발생산성을 현저하게 높여줄 "Smart Client" 를 적용하는 것이 현명한 선택이 된다. 다음은 필자가 생각해 본 비교 도표이다.

Visual Basic Visual C++ Smart Client
구현의 용이성
클라이언트 보안
쉬운 배포
코드 인증 필요 필요 *필요/불필요

( *사실 Smart Client 역시 결국 코드 인증이 필요하게 된다는 것만 알아두자. 다른 점이라면 해당 DLL 에 할 필요는 없고, 별도의 보안설정을 해주는 모듈에 대해서만 코드 인증을 하면 된다. 이 부분에 대해서는 연재 3회에서 자세히 다루겠다. )

그것을 감안하더라도 모든 면에서 우수한 것을 한눈에 알 수 있다. Smart Client 는 제작 언어를 자유롭게 선택할 수 있으며, Code Access Security 에 기반한 보안으로 인해 사용자 입장에서도 안전하게 사용할 수가 있다. ActiveX 의 경우 CAB 파일등을 만들어야 했지만, "Smart Client" 는 단순히 DLL 또는 EXE 파일을 웹 상에 올려놓기만 하면 된다. ActiveX 와 마찬가지로 웹 서버가 어떤 것이냐는 중요하지 않다. 결국 Smart Client 코드의 실행은 클라이언트에서 이루어지기 때문이다. 심지어, 사용자 컴퓨터의 보안설정을 바꿀 필요가 없는 범위내에서의 기능구현이라면, 코드 인증조차도 필요없이 바로 배포가 가능하다. 그렇다고 해서, 앞으로의 설명들이 줄곧 쉬울 거라고 생각해서는 안된다. 기존 구현된 ActiveX 중에서 복잡한 것까지도 모두 대체할 만한 "Smart Client" 를 원한다면 다소 어려운 이야기까지 흘러갈테니 말이다.


2. 간단한 컨트롤 제작

처음부터, 너무 쉽다고 설명해서 내심 걱정된다. 사실, "간단한" 컨트롤인데도 정작 고려해야 할 것이 많기 때문이다. 아직은 COM 에 대한 요소도 적용되어 있고, WinForm 독립 프로그램과는 달리 클라이언트 접근에 대한 보안사항까지 민감하게 적용되다 보니 실제로는 "닷넷 프레임워크" 에 대한 전반적인 지식을 요구할 정도이다. 미리 Smart Client 를 공부해 보신 분도 계실 것이고, 비록 "간단한" 컨트롤 제작이지만, 이번 회를 모두 할애할 정도이니 차근차근 숙지해 보도록 하자.

실습

이제, 단계별로 구현을 해나가면서 설명을 할 텐데, 이번회에서는 기본적인 메서드, 프로퍼티, 이벤트를 구현한 Smart Client 로써 HTML 에서는 구현이 다소 복잡한 트리 컨트롤을 예제로 제작해 보겠다. 이번에 만드는 컨트롤은 나머지 연재에서 계속 확장될 것이므로, 직접 실습해 볼 것을 권한다.

ㄱ. [화면 1] 같이 Visual Studio.NET 통합환경을 실행시켜서, "WebApp" 라는 웹 Application 프로젝트를 생성한다.

[화면 1 : 웹 프로젝트 생성]

팁이라고 할 수 있는 설명을 덧붙여 보면, 실제로 [화면 1]과 같이 프로젝트를 생성하게 되면, Visual Studio.NET 이 IIS 루트 디렉토리로 지정된 곳에 만들게 된다. 보통 C:\InetPub\wwwroot\WebApp 폴더가 될 텐데, 사실 이렇게 프로젝트가 생성되길 바라는 분들은 없을 것이다. 그러니, 자신의 작업폴더 ( 필자의 경우에는, D:\workshop ) 아래에 "WebApp" 폴더를 만들고, [화면 2] 와 같이 등록정보 창에서 "웹공유" 설정을 한다. 그런 후, "WebApp" 웹 프로젝트를 만들면 사용자가 의도했던 "D:\workshop\WebApp" 폴더에 Visual Studio.NET 이 프로젝트 파일들을 생성하게 된다.

[화면 2 : WebApp 폴더를 웹공유 시킴]

ㄴ. [화면 3] 과 같이 Smart Client 를 구현할 "클래스 라이브러리" 프로젝트를 생성한다. ( 여러 언어 중에서 필자는 Visual C# 을 선택했다. )

[화면 3 : Visual C# 클래스 라이브러리 생성]

ㄷ. 이제, 프로젝트 준비는 끝났고, 예정했던 데로 Smart Client 컨트롤을 생성해 보자. [화면 4] 에서 보는 것처럼 "사용자 정의 컨트롤" 을 선택하고 "TreeControl.cs" 란 이름으로 추가하자.

[화면 4 : 새 항목 추가 - 사용자 정의 컨트롤]

ㄹ. 컨트롤 디자인 폼에 "도구상자" 로부터 "TreeView" 를 끌어다 놓고 이름을 "_treeView" 로 수정한다.

ㅁ. TreeControl.cs 에서 메서드와 프로퍼티를 구현하자. 자세한 코드는 [소스 다운로드] 를 참조하되, 독자 나름대로 자유롭게 추가해 보기 바란다.

메서드
public void LoadXML( string text ); public 이므로 스크립트에서 액세스 가능.XML 문서를 문자열로 받아서 트리에 보여줌.
private bool SetTreeData( XmlNodeList nodeList, TreeNode parentNode ); private 이므로 스크립트에서 액세스 불가능. 재귀호출을 통해 데이터를 실제로 트리에 렌더링.
프로퍼티
public string SelectedNodeText; [get] 선택된 노드의 XML 텍스트를 반환

ㅂ. 제대로 된 기능을 구현하기 위해서는 트리 컨트롤의 노드를 클릭시에 이벤트를 발생시켜야 할 것이다. 하지만, 이벤트에 대해서는 복잡하므로 잠시 미루겠다. 컴파일 후, SmartClient.dll 을 "WebApp" 웹 응용 프로그램의 WebForm1.aspx 가 있는 폴더에 복사하자. 실제 개발시에는 매번 DLL 이 변경될때마다 복사하기가 번거로우므로, [화면 5] 와 같이 출력 경로를 지정해 놓으면 편리할 것이다.

[화면 5 : 출력 경로 설정]

ㅅ. 이제, "WebApp" 프로젝트로 돌아가서 "WebForm1.aspx" 를 수정해 보자. cs 코드는 수정할 필요없고, HTML 을 다음과 같이 수정한다.

<%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="WebApp.WebForm1" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >

<html>
    <head>
        <title>WebForm2</title>

        <script language=jscript> -------------------------- ①
            function window.onload()
            {
                Form1._Control1.LoadXML( _xmlData.xml );
            }
        </script>

    <xml id=_xmlData> -------------------------------- ②
    <tree>
        <L expand="T">
            <D>마소</D><D>http://www.imaso.co.kr/</D><D>추가 DATA</D>
            <L expand="T">
                <D>닷넷엑스퍼트</D><D>http://www.dotnetxpert.com/</D><D>추가 Data1</D>
            </L>
        </L>
        <L expand="F">
            <D>Microsoft</D><D>http://www.microsoft.com</D><D>추가 Data2</D>
        </L>
    </tree>
    </xml>

    </head>
    <body MS_POSITIONING="GridLayout">

        <form id="Form1" method="post" runat="server">
            <OBJECT id="_Control1" style="WIDTH: 272px; HEIGHT: 193px"
                classid="SmartClient.dll#SmartClient.TreeControl" VIEWASTEXT>
            </OBJECT> -------------------------------- ③
        </form>
    </body>
</html>

단계별로 살펴보기로 하자.

① 예전의 ActiveX 컨트롤을 사용하는 것과 방식은 같다. 해당 Smart Client 의 public 메서드를 스크립트 상에서도 호출해 주면 된다.

② XML 데이터 아일랜드 로 해서 XML 데이터를 컨트롤에서 쉽게 사용할 수 있도록 HTML 내에 넣어 두었다. 그리 중요한 사항은 아니다.

③ Smart Client 가 HTML 내부에서 어떻게 사용될 수 있는지를 보여준다. <OBJECT/> 태그를 사용한다는 면에서는 ActiveX 와 동일하다. 다른 부분이라면, classid 뿐인데, 웹서버에서 SmartClient.dll 을 발견할 수 있는 상대경로 위치와 어떤 클래스를 활성화 시킬 것인지에 대한 타입 정보를 기술하고 있다. 나중에 알게 되겠지만, SmartClient.dll 파일을 regasm.exe 로 로컬에 COM 개체로 등록한다면, 이 부분 조차도 실제 CLASS ID 로 교체 가능하다.

ㅇ. 구현완료 및 테스트 준비가 모두 끝났다. WebApp 프로젝트를 컴파일 하고, 웹 브라우저에서 http://localhost/WebApp/WebForm1.aspx 로 가보자. [화면 6] 과 같은 결과가 보일 것이다. ActiveX 와 비교해 보면 얼마나 편리해 졌는 지 느껴지는 순간이다. 진작에, 개발이 이런 식으로 되었어야 하지 않았나 하는 생각마저 드는 것은 왜일까. 이번엔, http://127.0.0.1/WebApp/WebForm1.aspx 로 해보자. IIS 6.0 의 경우에 비밀번호를 물어볼 것이다. 127.0.0.1 을 "로컬 인트라넷" 이 아닌 "인터넷" 으로부터의 접근으로 인식하는 데다가, IIS 6.0 은 기본적으로 가상 디렉토리에 대해서 "익명접근" 을 허용하지 않도록 되어 있기 때문이다. 이 경우, 매번 불편하게 계정을 입력하던지, 아니면 IIS 6.0 에서 "WebApp" 가상디렉토리에 대해서 "익명접근" 허용을 체크해 두면 된다.

[화면 6 : 예제 실행화면]

한가지 더 언급하자면, "SmartClient.dll" 어셈블리에 "강력한 이름서명" 을 하게 되면, "127.0.0.1" 에서든 "localhost" 에서든 전혀 활성화가 되지 않는다. 어떠한 기준이 적용되는 지는 아직 모르겠지만, 상식적으로는 이해가 되지 않는 기준이다.


3. 이벤트 구현

어떻게 닷넷 프레임워크의 Class 가 COM 개체로 매핑이 되는지에 대해서는 내부 구현은 정확히 알 수 없다. 하지만, 어쨌든 IUnknown 관련한 인터페이스에 vtable 을 맞추어 주면 호출할 수는 있을 것이다. 마찬가지로 이벤트 역시 COM 의 규약을 따르기만 해준다면 상호연동을 하게 될 것이다. 그걸 개발자가 해주어야 할까? ActiveX 시절에는 그렇게 하는 것이 당연했지만, 닷넷 프레임워크의 Smart Client 로 와서는 코드라기 보다는 "특성" 으로 바뀌었다. 닷넷의 "특성" 을 이용하여 개발자가 "표시" 만 해두면 모든 코드는 컴파일러가 알아서 삽입해 준다. 이벤트 소스를 알리는 특성과, 이벤트를 발생하는 내부 코드만 준비하면 끝인 셈이다. 물론, 이벤트를 거는 것은 외부코드에서 해야 할 일이다.

이제부터 위에서 만든 Tree Control 에서, 노드가 선택이 되면 이벤트를 발생한 것을 스크립트에서 받고 URL 을 얻어내어 해당 주소로 네비게이션 하는 것을 구현해 보겠다.

ㄱ. 이벤트 소스 인터페이스 마련.

문법은 VC++ ATL 에서 IDL 다룰 때와 상당히 유사하다. SmartClient 프로젝트에서 "TreeEvent.cs" 파일을 새로 추가하고 다음과 같이 이벤트 인터페이스를 구현하자.

public interface ITreeControlCOMIncoming ----------------- ①
{
    void LoadXML( string text );
    string SelectedNodeText { get; }
}

[Guid("A59B958D-B363-454b-88AA-BE8626A131FA")] ------- ②
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] ------- ③
public interface ITreeEvent
{
    [DispId(0x60020000)] --------------------------- ④
    void NodeClicked();
}

① 기본적인 Smart Client 의 메서드를 스크립트에서 호출하고 싶을 때는 public 제한자를 주는 것으로 끝났지만, 이벤트를 구현하면서는 외부에서의 호출을 위한 목록을 인터페이스에서 기술해 주고 그것을 상속받아야 한다. 뒤에 TreeControl 클래스에 주게 될 ClassInterfaceType.None 으로 인해서 외부로 기능을 노출시킬 메서드나 프로퍼티를 이와 같이 인터페이스를 정의하여 관리하게 된다..

② 해당 Event Source 인터페이스에 대해서 임의적으로 유일한 GUID 값을 설정한다.

③ Script 에서 이벤트를 걸 것이기 때문에 IDispatch 가 적용되어야 한다.

④ 각각의 이벤트에 대해 임의적으로 DispID 상수값을 설정한다.


ㄴ. 이벤트 소스 인터페이스와 TreeControl 클래스와 연결

VC++ 로 ATL 을 해보지 않으신 분들은 위의 사항만 해도 낯설어 하실 것 같다. 하지만 거의 정형화된 틀이니 사용되는 특성들이 다소 낯설지라도 지금 보여드리는 "틀" 대로만 해주면 문제가 발생하진 않을 것이다.

[ClassInterface(ClassInterfaceType.None), ComSourceInterfaces(typeof(ITreeEvent))] ------- ①
public class TreeControl : System.Windows.Forms.UserControl, ITreeControlCOMIncoming --- ②
{
    private System.Windows.Forms.TreeView _treeView;

    public delegate void NodeClickedHandler(); ------------------- ③
    public event NodeClickedHandler NodeClicked;

    protected void OnNodeClicked()
    {
        if ( NodeClicked != null )
        {
            Invoke( NodeClicked, null );
        }
    }

    public string SelectedNodeText
    {
        get
        {
            if ( _treeView.SelectedNode == null )
            {
                return string.Empty;
            }

            XmlNode aNode = _treeView.SelectedNode.Tag as XmlNode;
            return aNode.OuterXml;
        }
    }
}

① ClassInterfaceType.None 으로 인해서 상속받은 interface 에 명시된 프로퍼티와 메서드만을 외부에 노출시키겠다는 것을 알리고 ComSourceInterface 특성으로 TreeControl 의 이벤트 소스 인터페이스가 ITreeEvent 라고 알리게 된다. 이 특성을 컴파일러가 인지할 것이고 그에 따른 코드를 자동으로 생산해 낼 것이다.

② ClassInterfaceType.None 특성지정으로 인해서 ITreeControlCOMIncoming 인터페이스에 명시적으로 지정된 메서드와 프로퍼티만을 외부에 공개합니다.

③ 이벤트 구현은 C# 이벤트 구현을 따른다. ComSourceInterface 에서 선언된 메서드 하나당 delegate 하나씩 선언하고 대응되는 event 를 정의하면 된다.


ㄷ. 이벤트 발생

TreeControl 의 경우, 노드가 선택될 때마다 외부에 이벤트를 발생시킬 것이므로 TreeView 컨트롤의 AfterSelect 이벤트가 발생할 때마다 아래와 같이 호출해 주면 된다.

private void _treeView_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e)
{
    OnNodeClicked();
}


ㄹ. 스크립트에서 이벤트 받기

역시 기존 ActiveX 이벤트 처리하는 것과 다를 것이 없다. 다음은 선택된 트리 노드로부터 XML 텍스트를 받아오고 그 데이터 중에서 URL 노드의 값을 읽어들여 해당 사이트로 이동을 한다.

<script event="NodeClicked()" for="_Control1">
    var xmlText = _Control1.SelectedNodeText;
    var xmlDoc = new ActiveXObject( "Microsoft.XMLDOM" );
    if ( xmlDoc.loadXML( xmlText ) == true )
    {
        document.location.href = xmlDoc.selectSingleNode( "L" ).childNodes.item( 1 ).text;
    }
</script>

모두, 구현을 했으면 컴파일 하고 http://127.0.0.1/WebApp/WebForm1.aspx 로 테스트 해보자. 이제까지의 코딩을 따라해 주신 여러분들께 죄송하지만, 위의 구현은 "예외" 발생으로 끝나고 만다. 왜 예외상황이 되어버린 것일까? 이런 현상은 Smart Client 에서 이벤트를 실행하는 것이 닷넷의 "보안" 에 위배되기 때문이다. 즉, "인터넷" 으로부터 다운로드 받은 모듈의 코드가 "Unmanaged 코드" 를 호출할 수 없도록 해놓은 것이다. 이벤트는 명백히 COM 개체로 구현이 되고 COM 은 Unmanaged 코드라서 "닷넷" 은 그것을 허용치 않는 것이다.

여기서, 한가지 잠시 의문이 생기는 독자가 있을 것이다. 결국 Smart Client 를 Script 에서 접근할 때는 마찬가지로 COM 호출을 하는 것인데, 그것은 왜 예외가 아니라는 것인지? 그 이유에 대해 해답을 이끌어 내자면 이런 식이다. 자바 스크립트에서 Smart Client 를 호출하는 것은 외부에서 닷넷 코드를 호출하는 것 뿐이다. 즉, 우리가 만든 컨트롤 내부의 닷넷 코드가 "Unmanaged Code" 를 실행하는 것이 아니고, 외부에서 "Unmanaged Code" 를 통하여 우리의 닷넷 코드를 실행시키는 것이다. 그와 반면에 이벤트의 처리는 다르다. COM 에서의 이벤트 처리는 "쌍방향 통신" 이다. 이벤트를 걸게(sinking) 되는 것은 예외 조건에 걸리지 않는다. 그래서 스크립트 엔진이 <script event="..." for="..." /> 을 해석하는 시점에 예외가 발생하지 않는 것이다. 마치, 컨트롤의 public 메서드 호출과 같이 외부에서 Unmanaged Code 를 통해서 실행하는 것 뿐이기 때문이다. 하지만, 이벤트 발생은 다르다. 이벤트 발생의 근원은 닷넷 코드이고, 그것은 곧 이벤트와 연결된 외부 IDispatch 인터페이스를 호출하는 것을 의미하며, IDispatch 인터페이스 호출자체는 "Unmanaged 코드" 이기 때문에 닷넷 보안 설정에 위배가 되는 것이다.

"인터넷으로부터 다운로드 받은 어셈블리 코드" 는 "Unmanaged 코드" 를 호출해서는 안된다.


4. 이벤트 동작을 위한 닷넷 보안 변경

Win32 시절에도 그랬지만, 보안은 다가서기가 힘들다. 그래도 닷넷은 그나마 쉬운편이니 너무 큰 부담은 갖지 말기 바란다. 위에서 이미 "이벤트" 를 발생시키는 것이 "Unmanaged Code 를 호출할 수 없다" 는 것으로 인해 예외가 발생한다고 했다. 그렇다면, 당연히 그 보안 사항을 허락한다면 "이벤트" 는 정상적으로 동작하게 될 것이다. 우선, 이번 호에서는 보안 설정을 "Microsoft .NET Framework 1.1 구성" 를 통해서 해보겠다. 시작메뉴에서 "프로그램/관리도구/Microsoft.NET Framework 1.1 구성"을 선택하자.

[화면 7 : .NET Configuration 1.1 실행화면]

http://localhost 의 경우에는 "LocalIntranet_Zone" 에 설정된 권한이 적용되고, http://127.0.0.1 로는 "Internet_Zone" 이 적용된다. 바꿔 말하면, IP 와 DNS 로 접근할 때는 "Internet_Zone" 이고, NETBIOS 이름이나 "localhost" 로 접근하는 것은 "LocalIntranet_Zone" 이다. 각각의 권한을 살펴보면 알겠지만, 인터넷 존이 보다 더 강화된 보안규칙으로 제한을 하고 있는 것을 볼 수 있다.

자, 그럼 무엇을 해야 겠는가? 당연히 "런타임보안정책 / 컴퓨터 / 코드 그룹 / All_Code / Internet_Zone" 의 보안설정을 바꿔주어야 할 것이다. ( 설정을 마친 후, http://127.0.0.1/ 로 접근한다면 이벤트 관련해서 예외가 발생하지 않는다. 하지만, http://localhost 로는 여전히 예외가 발생한다. 필자가 다음의 설명을 통해 "Internet_Zone" 을 바꾸겠으니, 이글을 읽는 독자는 "LocalIntranet_Zone" 을 바꿔보길 바란다. )

[화면 7] 에서 "Internet_Zone" 의 "등록정보" 창을 띄우고 "권한 집합" 탭으로 가보자.

[화면 8 : Internet_Zone 의 등록정보 창]

[화면 8] 에서 보는 것처럼, "권한 집합" 이 "Internet" 으로 설정되어져 있다. 그리고, "Internet" 권한집합은 "파일대화상자", "격리된 저장소 파일", "보안", "사용자인터페이스", "인쇄" 권한을 가지고 있다. 각각의 권한을 마우스로 클릭하고, "권한보기" 버튼을 눌러보자. "Internet" 권한집합은 다음 표와 같이 설정되어져 있다.

파일 대화상자 열기
격리된 저장소 파일 허용된 용도 사용자로 도메인 격리
디스크 할당 10240
보안 코드 실행사용
사용자 인터페이스 창 작업 안전한 최상위 창
클립보드 자체 클립보드
인쇄 안전한 인쇄

우리가 원하는 것은 "관리되지 않는 코드 호출 허용" 이다. [화면 7] 을 보면, ".NET Configuration 1.1 / 내컴퓨터 / 권한집합" 노드가 있는데, 우리가 원하는 "Internet" 권한집합을 선택하자. MMC 의 오른쪽 패널에 "권한 보기" 만이 존재한다. 반면에 "Everything" 권한 집합을 선택해 보자. 오른쪽 패널에 "권한 보기 / 권한 변경 / 권한 집합 이름 바꾸기" 가 있는 것이 확인된다. 즉, "Internet" 권한집합은 더 이상 변경 불가능하다는 것을 의미한다. Smart Client 만을 위한 권한 집합을 새로 하나 만들어야 하는데, 어차피 보안 설정이 "Internet" 권한 집합에서 하나만 추가할 것이기 때문에 기존 집합으로부터 복제해서 만드는 것으로 해보겠다.

ㄱ. "권한 집합 / Internet" 컨텍스트 메뉴에서 "복제" 를 선택한다. 그럼, 새롭게 "Internet 의 복사본" 권한 집합이 생긴다.

ㄴ. "속성" 창을 띄우고, "권한 집합 이름" 을 "SmartClientSet" 으로 변경한다.

ㄷ. 오른쪽 패널에서 "권한 변경" 을 선택한다.

ㄹ. "권한 집합 만들기" 창이 열리는 데, 더 추가하거나 삭제할 것은 없다. 오른쪽의 "할당된 권한" 목록에서 "보안" 을 선택하고, "속성" 버튼을 클릭하자. [화면 9] 에서처럼 추가로 "관리되지 않는 어셈블리 호출 허용" 을 체크하자.

[화면 9 : 권한 설정 - 관리되지 않는 어셈블리 호출 허용 추가]

ㅁ. "확인" 버튼과 "마침" 버튼을 차례로 누르자. 그럼, 새롭게 "SmartClientSet" 이란 새로운 "권한 집합" 을 만든 것이다.

이제 이것을 코드 그룹의 "Internet_Zone" 에 적용시키면 된다. 하지만, 잠깐 생각해 볼 것이 있다. "Internet_Zone" 전체에 "SmartClientSet" 권한집합을 적용시키는 것이 타당한가? 너무나 당연하게, 그것은 로컬 시스템에 치명적인 보안 결함을 안겨 주는 것이다. 자신의 컴퓨터에서 방문하는 모든 인터넷 사이트들의 "Smart Client" 에게 그러한 권한집합을 갖게 하는 것은 위험하다. 우린 단지, 특정 웹사이트를 지정해서 해당 권한을 추가해 주는 식이어야 한다.

ㄱ. 코드 그룹의 "Internet_Zone" 을 선택하고, 오른쪽 패널에 나오는 "자식 코드 그룹 추가" 메뉴를 선택하자. 물론, 컨텍스트 메뉴로도 접근이 가능하다.

ㄴ. "코드 그룹 만들기" 대화창에서 "이름" 을 InternetSmartClient_Zone 으로 설정하자. 독자 임의로 이름을 지어도 된다.

ㄷ. "조건 형식 선택" 을 해야 하는데, 우리가 관심있는 Smart Client 는 인터넷으로부터 다운로드하여 실행되기 때문에 선택해야 할 조건은 "URL" 이 된다. 선택하고 나면, 하단에 URL 입력 상자가 나오는데 그곳에 http://127.0.0.1/* 라고 입력한다.

ㄹ. "코드 그룹에 권한 집합 할당" 에서 우리가 이전에 만들어 두었던 "SmartClientSet" 을 선택한다.

이것으로, 설정은 모두 끝났다. 이전에 만들어 두었던 TreeControl 을 테스트 해보자. http://127.0.0.1/WebApp/WebForm1.aspx 로 탐색하고, 트리에 나오는 노드를 선택해 보자. "예외" 발생 없이 이벤트를 정상적으로 받는 것을 확인할 수 있다. 모든 설명이 끝이 났다. 이제 여러분 나름대로 주제를 가지고 또 다른 "Smart Client" 를 제작하여 테스트 해보기 바란다.

물론, 모든 문제가 깔끔하게 해결된 것은 아니다. 이로 인해 "보안을 수정해야 하는" 배포에 대한 문제가 발생한다. 이벤트를 사용하는 Smart Client 의 경우에는 모든 클라이언트 컴퓨터마다 그와 같은 보안 설정을 해주어야 한다는 것인가? 아쉽게도 그래야 한다. 하지만, 사용자로 하여금 직접 설정하게 할 수 있을 정도로 간단한 것이 아니다. 따라서, 배포하는 입장에서는 위의 설정을 자동으로 해주는 프로그램을 하나 만들어서 미리 사용자의 컴퓨터에서 실행을 하도록 해주는 식으로 배려를 해주어야 한다. 이와 같은 배포 문제에 대해서는 연재 3회에서 자세히 다루도록 하겠다.


연재 1회를 마치며

Smart Client 제작을 해보니 어떻다고 생각되는가? 닷넷만 알아서는 안되는 문제였다고 생각하지는 않는가? 그렇다. 아직까지는 "닷넷 프레임워크" 자체가 Windows 상에서 운영되고 있으며, Windows 에는 수많은 COM 기술이 녹아있다. 결국, "닷넷(으로 만든) 컨트롤" 이란 기존 COM 을 사용하는 무수한 Application 과의 연동을 위해서라도 "COM" 에 대한 배려를 안할 수 없고, 앞으로도 얼마 동안은 "COM" 에 대한 지식이 있는 사람이 "닷넷 컨트롤" 에 대해서도 많은 유연성을 발휘할 수가 있을 것이다. "인터넷 익스플로러" 6.0 버전이 나온지도 꽤 오랜 시간이 흘렀다. 마치 Visual Studio 97 을 내놓은 이후로 많은 공백이 있던 것과 비슷한 것이 아닐런지. 필자의 개인적인 생각으로는 인터넷 익스플로러 의 다음 버전에는 "닷넷 프레임워크" 와의 연동을 많은 부분 개선시켜서 내놓을 거라 생각하기에 내심 기대를 하고 있는 중이다.

어떻게, 어느 부분이 개선될지는 모르겠지만 그것은 불확실한 미래의 일이고, 연재 2회 기사에서는 현재의 프레임워크와 인터넷 익스플로러 안에서 기존의 ActiveX 가 썼던 기교를 Smart Client 로 어떻게 대체가 되는 지에 대해서 자세히 설명할테니 기대해 주기 바란다.


참고 URL

MSDN Magazine February 2003 : Give Your .NET-based Applications a Fast and Responsive UI with Multiple Threads
http://msdn.microsoft.com/msdnmag/issues/03/02/Multithreading/default.aspx

MSDN Magazine June 2002 : Code Access Security and Distribution Features in .NET Enhance Client-Side Apps
http://msdn.microsoft.com/msdnmag/issues/02/06/rich/

MSDN Magazine January 2002 : Host Secure, Lightweight Client-Side Controls in Microsoft Internet Explorer
http://msdn.microsoft.com/msdnmag/issues/02/01/UserCtrl/default.aspx 

2009/07/17 20:40 2009/07/17 20:40
Posted
Filed under C#

원본출처 -- http://zmeun.tistory.com/category/ASP.NET

 

이젠 하자! Client Side Debugging


Visual Studio.Net
은 이미 개발환경에 정말 많은 편리함을 제공해 주고 있다. 이러한 편리한 Tool로 인해서, 개발자는 로직 구현에 많이 집중할 수 있게 되었고, 개발시간 또한 많이 줄어든 건 사실이다.(하지만 이러한 Tool의 버그로 인해 지대 삽질을 경험하지 않은 개발자 또한 별로 없을 것이다. -_-;) 이 중에, 일상생활에서 가장 톡톡히 덕을 보고 있는 것이, 디버깅 관련 기능인데, Visual Studio.Net 2005가 출시되면서부터 추가된 Visualizer기능으로 인해, 개발자는 더 편하게 중단점이 적용된 부분의 값들을 확인 할 수 있다. 그런데 이런 디버깅은 단지 Server Side 코드에서만 적용해서 사용해 왔다. 왜냐그렇게 알고 있었으니까…(본인만 그런가?  -_-;) 그런데 우리가 몰랐던 것이, Visual Studio.Net 2005에서는 Client Side Debugging을 할 수 있는 기능을 제공 하고 있었다. 오후~ 이런이제부터 이 Client Script Debugging을 어떻게 사용하는지 알아보자.

 

Setting Client Script Debugging

먼저 다 알고 있겠지만, Client Side Script라는 것은 aspx파일 또는 html, js파일에 포함되는 VBScript, J# Script, JavaScript를 이야기하며, 이러한 코드들은 Internet Explorer와 같은 Client Application에서 Load되게 된다. 이렇게 때문에, 우리가 먼저 확인해 봐야 할 것은 바로 Internet Explorer Client Script Debugging을 처리 할 수 있는지 없는지를 확인해야 한다. 이것은 Internet Explorer의 도구메뉴에서 인터넷옵션 > 고급 탭에서 확인을 할 수 있는데, 그 부분은 아래와 같다.

Internet Option

[그림 1]


위 그림에서 보면 붉은 선으로 Box가 쳐진 옵션이 두 개 있는데, 이 부분이 모두 UnChecked되어 있어야 한다. 이 부분에 대한 것은 옵션 설명으로도 충분히 알 수 있을 것이다.

이것으로 Client Script Debugging을 할 수 있는 설정은 끝났다. (으흐~ 정말 간단하다.) 그럼 이제 예제 코드를 가지고 실제 Visual Studio.Net 2005에서 어떻게 Client Side Script를 디버깅 하는지 알아보자.

<html xmlns="http://www.w3.org/1999/xhtml" >

<head runat="server">

    <title>제목 없음</title>

    <script language="javascript">

        function btnPopup_Click()

       {

          var name;

          var helloStr;

           

          name  = document.getElementById("txtName");

         

          if(name.value.length == 0)

          {

            alert("Please Write your name...");

            name.focus();

           

            return;  

          }

          helloStr = "Hello!  '"+name.value+"' ~  Nice to meet you...";

         

          alert(helloStr);

       }

    </script>

</head>

<body>

    <form id="form1" runat="server">

        

    <div>

        <asp:Label ID="lblid" runat="server" Text="Write your name : " Font-Names="Verdana"></asp:Label>&nbsp;<input type="text" id="txtName"/>

       <br />

       <br />

       <button id="btnPopup" onclick="btnPopup_Click();">Click!</button>

    </div>

    </form>

</body>

</html>

[코드 1]

위 코드는 예제 코드로, TextBox에 이름을 입력 받고, Button을 클릭하면 JavaScript 함수가 호출되면서, 입력 받은 값을 가지고 alert창을 띄우는 코드다.

이렇게 코드를 구현하고 이제 실행을 해보자. 그럼 아래와 같은 결과가 나타나게 된다.

[그림 2]


[그림 3]


이제 보나마나 한 결과까지 봤으니, Client Script Debugging에 대해서 알아보자. 이런 스크립트 코드를 디버깅 하기 위해서는 먼저 디버깅하고자 하는 function에 코드를 추가해야 하는데, 이 코드는 바로 “debugger”라는 코드이다.

그럼 위 코드 중 디버깅 하고자 하는 btnPopup_Click() function 코드는 아래와 같이 된다.

function btnPopup_Click()

       {

          debugger;     // Client Side Script 디버깅 하기위해서 항상 debugger 코드를 // 추가해야 한다.

          var name;

          var helloStr;

           

          name  = document.getElementById("txtName");

         

          if(name.value.length == 0)

          {

            alert("Please Write your name...");

            name.focus();

           

            return;  

          }

          helloStr = "Hello!  '"+name.value+"' ~  Nice to meet you...";

         

          alert(helloStr);

       }

[코드 2]

debugger란 코드가 런타임에 Internet Explorer가 스크립트 디버깅을 시작하게 되면, 찾아가는 코드 되겠다. 이렇게 코드까지 

2009/07/17 20:40 2009/07/17 20:40
Posted
Filed under C#

원본출처 -- http://zmeun.tistory.com/category/ASP.NET

 

이젠 하자! Client Side Debugging


Visual Studio.Net
은 이미 개발환경에 정말 많은 편리함을 제공해 주고 있다. 이러한 편리한 Tool로 인해서, 개발자는 로직 구현에 많이 집중할 수 있게 되었고, 개발시간 또한 많이 줄어든 건 사실이다.(하지만 이러한 Tool의 버그로 인해 지대 삽질을 경험하지 않은 개발자 또한 별로 없을 것이다. -_-;) 이 중에, 일상생활에서 가장 톡톡히 덕을 보고 있는 것이, 디버깅 관련 기능인데, Visual Studio.Net 2005가 출시되면서부터 추가된 Visualizer기능으로 인해, 개발자는 더 편하게 중단점이 적용된 부분의 값들을 확인 할 수 있다. 그런데 이런 디버깅은 단지 Server Side 코드에서만 적용해서 사용해 왔다. 왜냐그렇게 알고 있었으니까…(본인만 그런가?  -_-;) 그런데 우리가 몰랐던 것이, Visual Studio.Net 2005에서는 Client Side Debugging을 할 수 있는 기능을 제공 하고 있었다. 오후~ 이런이제부터 이 Client Script Debugging을 어떻게 사용하는지 알아보자.

 

Setting Client Script Debugging

먼저 다 알고 있겠지만, Client Side Script라는 것은 aspx파일 또는 html, js파일에 포함되는 VBScript, J# Script, JavaScript를 이야기하며, 이러한 코드들은 Internet Explorer와 같은 Client Application에서 Load되게 된다. 이렇게 때문에, 우리가 먼저 확인해 봐야 할 것은 바로 Internet Explorer Client Script Debugging을 처리 할 수 있는지 없는지를 확인해야 한다. 이것은 Internet Explorer의 도구메뉴에서 인터넷옵션 > 고급 탭에서 확인을 할 수 있는데, 그 부분은 아래와 같다.

Internet Option

[그림 1]


위 그림에서 보면 붉은 선으로 Box가 쳐진 옵션이 두 개 있는데, 이 부분이 모두 UnChecked되어 있어야 한다. 이 부분에 대한 것은 옵션 설명으로도 충분히 알 수 있을 것이다.

이것으로 Client Script Debugging을 할 수 있는 설정은 끝났다. (으흐~ 정말 간단하다.) 그럼 이제 예제 코드를 가지고 실제 Visual Studio.Net 2005에서 어떻게 Client Side Script를 디버깅 하는지 알아보자.

<html xmlns="http://www.w3.org/1999/xhtml" >

<head runat="server">

    <title>제목 없음</title>

    <script language="javascript">

        function btnPopup_Click()

       {

          var name;

          var helloStr;

           

          name  = document.getElementById("txtName");

         

          if(name.value.length == 0)

          {

            alert("Please Write your name...");

            name.focus();

           

            return;  

          }

          helloStr = "Hello!  '"+name.value+"' ~  Nice to meet you...";

         

          alert(helloStr);

       }

    </script>

</head>

<body>

    <form id="form1" runat="server">

        

    <div>

        <asp:Label ID="lblid" runat="server" Text="Write your name : " Font-Names="Verdana"></asp:Label>&nbsp;<input type="text" id="txtName"/>

       <br />

       <br />

       <button id="btnPopup" onclick="btnPopup_Click();">Click!</button>

    </div>

    </form>

</body>

</html>

[코드 1]

위 코드는 예제 코드로, TextBox에 이름을 입력 받고, Button을 클릭하면 JavaScript 함수가 호출되면서, 입력 받은 값을 가지고 alert창을 띄우는 코드다.

이렇게 코드를 구현하고 이제 실행을 해보자. 그럼 아래와 같은 결과가 나타나게 된다.

[그림 2]


[그림 3]


이제 보나마나 한 결과까지 봤으니, Client Script Debugging에 대해서 알아보자. 이런 스크립트 코드를 디버깅 하기 위해서는 먼저 디버깅하고자 하는 function에 코드를 추가해야 하는데, 이 코드는 바로 “debugger”라는 코드이다.

그럼 위 코드 중 디버깅 하고자 하는 btnPopup_Click() function 코드는 아래와 같이 된다.

function btnPopup_Click()

       {

          debugger;     // Client Side Script 디버깅 하기위해서 항상 debugger 코드를 // 추가해야 한다.

          var name;

          var helloStr;

           

          name  = document.getElementById("txtName");

         

          if(name.value.length == 0)

          {

            alert("Please Write your name...");

            name.focus();

           

            return;  

          }

          helloStr = "Hello!  '"+name.value+"' ~  Nice to meet you...";

         

          alert(helloStr);

       }

[코드 2]

debugger란 코드가 런타임에 Internet Explorer가 스크립트 디버깅을 시작하게 되면, 찾아가는 코드 되겠다. 이렇게 코드까지 

2009/07/17 20:40 2009/07/17 20:40
Posted
Filed under C#
e.Data.GetDataPresent(DataFormats.FileDrop) 를 통해서 파일인지 아닌지 체크 할수 있음
2009/07/17 20:40 2009/07/17 20:40
Posted
Filed under C#

응용 프로그램에서 Active Directory 계층 구조의 내용과 상호 작용하려면 DirectoryEntry 또는 DirectorySearcher 구성 요소 인스턴스를 만듭니다. 자세한 내용은 Active Directory 개체 소개를 참조하십시오. DirectoryEntry 구성 요소나 DirectorySearcher 구성 요소를 사용하려면 System.DirectoryServices 네임스페이스에 대한 참조를 응용 프로그램에 추가해야 합니다. 자세한 내용은 참조 추가 및 제거를 참조하십시오. DirectorySearcher 구성 요소 만들기에 대한 자세한 내용은 Active Directory 계층 구조 검색을 참조하십시오.

다음과 같은 여러 방법을 사용하여 DirectoryEntry 구성 요소의 인스턴스를 만들 수 있습니다.

  • DirectoryEntry 구성 요소의 인스턴스를 도구 상자의 구성 요소 탭에서 디자이너로 끌어 올 수 있습니다.
  • 코드에서 DirectoryEntry 구성 요소의 인스턴스를 만들 수 있습니다.
    참고   도구 상자의 구성 요소 탭에 있는 대부분의 구성 요소와 달리 DirectoryEntry 구성 요소는 서버 탐색기에 나타나지 않으므로 이 창에서 구성 요소의 인스턴스를 만들 수 없습니다.

디자이너에서 DirectoryEntry 구성 요소의 인스턴스를 만들려면

  1. 도구 상자의 구성 요소 탭에서 DirectoryEntry 개체를 폼 또는 구성 요소의 디자인 화면으로 끌어 옵니다.
  2. 속성 창에서 다음 구문을 사용하여 구성 요소를 바인딩할 리소스가 Active Directory 계층 구조에서 차지하는 위치를 구성 요소의 Path 속성에 설정합니다.
    Provider://providerpath
    위치 설명
    Provider 액세스할 디렉터리에 대한 서비스 공급자를 나타내는 표시기입니다. 공급자 식별자는 대/소문자를 구분하여 다음 값 중 하나를 입력해야 합니다.
    • LDAP://
    • WinNT://
    • NDS://
    • NWCOMPAT://
    ProviderPath 선택한 서비스 공급자의 형식에 따라 공급자 경로의 매개 변수가 달라집니다. 자세한 내용은 ADSI 시스템 공급자를 참조하십시오.

    예를 들어, 아래에 다양한 공급자 형식에 대한 유효 경로가 나와 있습니다.

    LDAP://MyDom.fabrikam.com/CN=SomeCN,DC=DEV,DC=SOMEDC,DC=COM,O=Internet
    LDAP://CN=SomeCN,DC=DEV,DC=SOMEDC,DC=COM,O=Internet
    WinNT://MyDomain/Group
    WinNT://MyDomain/MyComputer/aPrinter/
    NDS://ndsServer/O=Internet/DC=COM/DC=SOMEDC/DC=DEV/CN=SomeCN
    NWCOMPAT://binderyServer/ADivision

프로그래밍 방식으로 DirectoryEntry 구성 요소의 인스턴스를 만들려면

  • 코드에서 바인딩할 개체의 경로를 매개 변수로 전달하여 DirectoryEntry 클래스의 인스턴스를 만듭니다.

    아래 예제에서는 DirectoryEntry 개체에 공급자 경로를 전달하는 방법을 보여 줍니다.

    ' Visual Basic
    Dim myDir As 
       New System.DirectoryServices.DirectoryEntry("provider://path")
    
    // C#
    System.DirectoryServices.DirectoryEntry myDir = 
       new System.DirectoryServices.DirectoryEntry("provider://path");

    아래 예제에서는 코드에서 DirectoryEntry 구성 요소 인스턴스를 만들고 LDAP 경로를 사용하여 초기화한 다음 폼 요소에 표시하기 위해 항목의 이름과 GUID를 검색하는 방법을 보여 줍니다.

    ' Visual Basic
    Dim strpath As String = "LDAP://DC=onecity,DC=corp,DC=fabrikam,DC=com"
    Dim myDE As New System.DirectoryServices.DirectoryEntry(strpath)
    Dim nameGUID As String
    nameGUID = myDE.Name & myDE.Guid.ToString()
    
    // C#
    String strpath = "LDAP://DC=onecity,DC=corp,DC=fabrikam,DC=com";
    System.DirectoryServices.DirectoryEntry myDE = new 
       System.DirectoryServices.DirectoryEntry(strpath);
    string nameGuid = myDE.Name + myDE.Guid.ToString();

참고 항목

Active Directory 개체 소개 | Active Directory 노드 제거 | Active Directory 계층 구조 검색 | 연습: Active Directory 개체 추가

2009/07/17 20:28 2009/07/17 20:28
Posted
Filed under C#
[펌] - http://www.xevious7.com/342 

#에서 MySQL을 연동하기 위해서 기본적으로 선행해야 될것들에
대한 짧은 정리

mysql org 사이트의 net관련 Connecter를 다운로드하여 설치한다.
http://dev.mysql.com/downloads/connector/net/5.2.html

관련 프로젝트에서 Project(프로젝트) -> Add Reference(참조추가) 에서
.NET 탭에서  MySQL.Data 를 추가한다.


실제로 프로그래밍을 위한 문서와 샘플은 다음의 디렉토리에 있다.
Program Files -> MySQL ->MySQL Connecter -> Document
Program Files -> MySQL ->MySQL Connecter -> Samples

접속의 예)
private MySqlConnection  conn;
private void connectBtn_Click(object sender, System.EventArgs e)
 {
  if (conn != null)
   conn.Close();

  string connStr = String.Format("server={0};user id={1}; password={2}; database=mysql; pooling=false",
   server.Text, userid.Text, password.Text );
// 코넥션 스트링을 외부텍스트콘트롤 server, userid , password 의
text값을 이용하여 생성
.

  try
  {
   conn = new MySqlConnection( connStr ); // 코넥션 스트링으로 새로운 코낵션생성
   conn.Open(); // 접속

   GetDatabases();
  }
  catch (MySqlException ex) // 익섹션처리는 MySqlException으로 정의
  {
   MessageBox.Show( "Error connecting to the server: " + ex.Message );
  }
 }

명령의 실행의 예)
private void GetDatabases()
 {
  MySqlDataReader reader = null;

  MySqlCommand cmd = new MySqlCommand("SHOW DATABASES", conn);
  try
  {
   reader = cmd.ExecuteReader();
   databaseList.Items.Clear();
   while (reader.Read())
   {
    databaseList.Items.Add( reader.GetString(0) ); // 리스트콘트롤에 결과값을 추가함
   }
  }
  catch (MySqlException ex)
  {
   MessageBox.Show("Failed to populate database list: " + ex.Message );
  }
  finally
  {
   if (reader != null) reader.Close();
  }
 }

위 소스는 샘플 디렉토리의 샘플소스에서 발췌하였고 , 주석은 설명을 위해
추가작성함.

2009/07/17 20:19 2009/07/17 20:19
Posted
Filed under C#
1. Flash Player 설치

2. VS2005 도구상자(Toolbox) - 항목선택(Choose Items) - COM 구성요소(Components) - Shockwave Flash Object 추가

3. AxInterop.ShockwaveFlashObjects.dll 을 Flash 를 사용하는 프로젝트의 obj/Debug 폴더 안에 추가

4. 도구상자에 추가된 SFO(ShockwaveFlashObject)를 디자인 창으로 가져온다.

 

c# 코드===================

private void axShockwaveFlash1_FlashCall(object sender, AxShockwaveFlashObjects._IShockwaveFlashEvents_FlashCallEvent e)
        {
            //Flash 로부터 정보 받기
            XmlDocument XmlDoc = new XmlDocument();
            XmlDoc.LoadXml(e.request);

            XmlNodeList ArgumentList = XmlDoc.GetElementsByTagName("arguments");

            String XmlArguments = ArgumentList[0].InnerText;// +Environment.NewLine;
            String[] arg = XmlArguments.Split('|');

            if (arg[0] == "GetWaitList")
                MessageBox.Show("Success");


        }   public Form1()
        {
            InitializeComponent();
            this.axShockwaveFlash1.FlashCall +=
              new AxShockwaveFlashObjects._IShockwaveFlashEvents_FlashCallEventHandler(this.axShockwaveFlash1_FlashCall);

        }


        private void axShockwaveFlash1_FlashCall(object sender, AxShockwaveFlashObjects._IShockwaveFlashEvents_FlashCallEvent e)
        {
            //Flash 로부터 정보 받기
            XmlDocument XmlDoc = new XmlDocument();
            XmlDoc.LoadXml(e.request);

            XmlNodeList ArgumentList = XmlDoc.GetElementsByTagName("arguments");

            String XmlArguments = ArgumentList[0].InnerText;// +Environment.NewLine;
            String[] arg = XmlArguments.Split('|');

            if (arg[0] == "ButtonClick")
            {
                MessageBox.Show("ButtonClick Success");
               
            }
            else if (arg[0] == "ReceivedFlex")
                MessageBox.Show("ReceivedFlex Success");


        }

        private void sendToFlash(string value1, string value2)
        {
            string args;

            args = "<invoke name=\"receive\" returntype=\"xml\">";
            args += "<arguments>";
            args += "<string>" + value1 + "</string>";
            args += "<string>" + value2 + "</string>";
            args += "</arguments>";
            args += "</invoke>";

            //Call Flash Function

            this.axShockwaveFlash1.CallFunction(args);

        }

        private void button1_Click(object sender, EventArgs e)
        {
            sendToFlash("SendToFlex", "bb");
        }

    }


Flex 코드 ======================

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="initApp()">
 
 <mx:Script>
  <![CDATA[
  import flash.external.ExternalInterface;
  import flash.events.*;
  import flash.utils.*;
  import flash.events.TimerEvent;
  import mx.controls.Alert;
  import flash.display.*;
 
  private function initApp():void
  {   
   if(ExternalInterface.available)
   {
    ExternalInterface.addCallback("receive", receive);    
   }
   
  }
 
  private function gender():void
  {
   ExternalInterface.call("call", "ButtonClick|");
 
  } 
 
  private function receive(value1:String, value2:String):void
  {
   if(value1=="SendToFlex")
   {    
   
   // mx.controls.Alert.show("통신 불가");
    ExternalInterface.call("call", "ReceivedFlex|");
   
   }
   
  }
 
  ]]>
 </mx:Script>
 <mx:Button x="137.5" y="370" label="Button" width="202" height="111" click="gender();"/>
  <mx:Text text="육심원" width="238" height="114" fontSize="36" fontWeight="bold" fontFamily="Georgia" textAlign="center" x="119.5" y="290" id="Textbox1"/>
 
</mx:Application>


[출처] c# flash 연동|작성자

2009/07/17 19:14 2009/07/17 19:14
Posted
Filed under C#
UNICODE와 한글 처리 BYTE
모든 문자를 유니코드로 처리하는 닷넷 프레임워크상에서
한글 문자열을 2바이트로 처리해서 원하는 바이트 길이만큼 자르는 방식이 필요하다.

[SAMPLE]
String line = "가나다라마";
char[] charData = new char[1024];
byte[] byteData = new byte[1024];
System.Text.Encoding myEncoding = System.Text.Encoding.GetEncoding("ks_c_5601-1987");

올바른
byteData = myEncoding.GetBytes(line); // 길이가 10 byte 생성
//byteData.GetLength(0) 결과는 10이다
2009/07/17 19:12 2009/07/17 19:12