2008. 12. 30. 11:30

가상(virtual)메서드
 => 상속받는 클래스의 형변환을 위해 사용

추상클래스: 추상(abstract)메서드를 하나 이상 가지고 있는 클래스
 => 다중상속을 위해 사용

인터페이스(interface)
 => 다중상속을 위해 사용

추상클래스와 인터페이스의 차이점
 1) 추상클래스는 추상클래스를 상속받을수 있고, 일반클래스에 상속을 할 수 있지만,
     인터페이스는 오직 인터페이스 사이에서만 상속이 가능하다.
 2) 인터페이스는 접근권한자를 사용하지 않지만, 추상 클래스는 사용을 한다.
 3) 추상 클래스는 여러 형태의 구현을 포함할 수 있지만, 인터페이스는 할 수 없다.
 4) 인터페이스는 추상 메소드를 포함할 수 없다.


개념정리중...

Posted by 굿데이
2008. 12. 23. 22:46
궁금하신분들은 보시길...

무서운 "돼기고기촌충

http://www.nemopan.com/community_broad/648866
Posted by 굿데이
2008. 12. 23. 00:32

스마트클라이언트 서명키 만들기

개인인증서 만드는 명령어 참고 주소:
ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.VisualStudio.v80.ko/dv_fxdeploy/html/a05b5f2f-d1f2-471a-8096-8b11f7554265.htm

스마트 클라이언트에서 클릭원스 매니페스트 서명 인증키가 제공되는데 이것은 기본적으로
테스트 인증서 입니다.

이 인증서는 생성 후 1년 밖에 사용하지 못합니다.

즉 1년 이후로는 만기가 되기 때문에 새로운 버전이 배포 되어도 업데이트가 이루어지지 않고
오류가 발생하여 아예 실행이 되지 않습니다.

더군다나 이렇게 생성된 테스트 인증서는 만기날짜 조정이 불가능 합니다.

그렇기 때문에 날짜가 조정가능한 한 인증서를 만들기 위해서는 cmd 창에서 아래 코드를 실행하면
개인인증서가 만들어 집니다.

makecert -r -pe -n "CN=HEC" -b 01/11/2006 -e 10/12/2100 -sky exchange -ss my


출처
http://www.setisigns.net/94

Posted by 굿데이
2008. 12. 22. 17:55
현재.. 대부분의 글들이 스마트클라이언트에 대한 것 들입니다.

ActiveX로 된 업/다운로드 컴포넌트들에 대한 약간은 답답함(?)에서 비롯된

자체개발욕구 때문에 닷넷으로 개발가능한 기술들에 대한 정보를 모으는 중입니다.

물론 웹하드에 사용할 컴포넌트 이므로 나스와도 무관하진 않군요.

만들수 있을지.. 언제 만들지는 모르지만.. 그냥 지금은 이렇게 의욕에 넘처 자료구하고,

테스트 해보는 중입니다.

언제쯤 개발 가능 하려나.. 이놈에 허접 ㅠㅠ
Posted by 굿데이
2008. 12. 22. 11:29

IE임베디드 스마트클라이언트를 테스트겸 작성해보면서 겪었던 문제점과 해결방법을
간단하게 정리해보겠습니다.

혹시나, 저와 같은 문제를 겪으실지도 모르는 분들을 위해.. 팁으로 알아두셨으면 합니다.

몇개 안되지만.. 도움이 되었으면 합니다. ^^



1. 스마트클라이언트에서 소켓 라이브러리 사용시 지연문제

2. DLL 추가 검색 문제

3. DLL 중복 다운로드 문제

4. 기타문제



저로 하여금 난감스럽게 만들었던 문제들입니다. 혹시나 해당되시는 분들이 있으시다면..
도움이 되길 바랍니다.

참고로 원리와 이유는 배제하고 해결법만 기재하겠습니다. 원리와 이유에 대해 자세히 알고자
하시는 분은.. 아래 사이트를 참고하시기 바랍니다.


"유경상"님과 "정성태"님의 글이 잘 정리되어있습니다.


http://taeyo.net/ (ASP.NET(외부)란에 정성태님의 스마트클라이언트 관련 게시물)

http://www.simpleisbest.net/archive/2006/01/02/360.aspx (유경상님의 닷넷블로그입니다.(추천))


그외, 데브피아 (강좌&팁 / 질답게시판)





1. 스마트클라이언트에서 소켓 라이브러리 API사용시 지연문제의 해결 ---------------------------


   http://www.devpia.com/forum/BoardView.aspx?forumname=csharp_lec&page=1&no=1059&code=

   링크로 직접보시는게 가장 적절한듯 싶어 링크를 걸어 놓습니다.


   주 내용은, IE임베디드 형태의 스마트클라이언트에서 소켓 라이브러리 API를 사용하기 전에

   System.Configuration.ConfigurationSettings.GetConfig("system.net/settings");
   구문을 먼저 삽입하라 입니다.


   본 내용은 강좌는 아니고 팁이므로 원리에 대해서는 설명하지 않겠습니다.


   * 일부 PC에서는 해당 구문의 삽입여부와 무관하게 정상적으로 동작하는것을 확인했습니다만
   역시나 넣어주는것이 안전합니다.




2. DLL추가 검색문제-----------------------------------------------------------
   스마트클라이언트 배포시 Fiddler를 통해 모니터링 하시다 보시면.



위와 같이 이미 DLL를 검색하고 다운로드 했음에도 불구하고 여기저기 다른곳을 검색하며,
파일을 찾을수 없다는 404에러를 뿌립니다. 이 문제의 해결책은 다음과 같습니다.

  일단 스마트클라이언트의 Config파일을 작성해야 합니다. 파일명은 "XXXX.dll.config" 입니다.  
 *.dll.config가 되야하므로 이점 주의하시기
바랍니다. config파일의 내용은 없어도 무방합니다.

  config파일은 배포할 스마트클라이언트 dll파일과 같은 곳에 위치해야합니다.


  웹파일에 다음구문을 추가합니다.  
  <link rel = "Configuration" href = "SmartClient_DLL/SmartClient.dll.config">


  * 참조경로 주의.


  역시나 이유와 원리에 대해서는 설명하지 않도록 하겠습니다. "정성태"님의 글에서는 문제점만 나타내었고.
  해결책이 제시되어있지 않지만 "유경상"님의 블로그에는 위와 같이 하는 이유에 대해
  자세히 설명되어있습니다. 해당 블로그를 참고 하시기 바랍니다.


  위와 같이 처리했다면, 배포시 여러군데서 중복검색하는 부하를 줄일 수 있습니다.

  해결된 모습입니다.


 


   


   

3. DLL 중복 다운로드 문제 ---------------------------------------------------------


   2번의 문제 해결을 읽어보시다가 발견하셨으리라 생각합니다.

   그림을 보시면   dll과 DLL 이렇게 확장자의 대소문자를 바꿔서 두번 다운로드 된것을 보실수 있을겁니다.


   이 문제에 대한 이유는 아쉽게도 찾을 수 없었습니다.

   

   허나, 데브피아 질답게시판에서 "유경상"님이 답변해주신 게시물을 발견했습니다.
   그곳에 해결책이 기재되어있더군요.


   해결책은 웹소스파일에서


   <OBJECT id="SC" style="WIDTH: 740px; HEIGHT: 544px"
   classid="SmartClient_DLL/SmartClient.dll#SmartClient.OTIS_WebViewer"  VIEWASTEXT VIEWASTEXT>
   </OBJECT>


   dll로 소문자기재를 하지말고, DLL로 대문자를 사용하라는 것이었습니다. (이유는 아쉽게도 모릅니다.)


   <OBJECT id="SC" style="WIDTH: 740px; HEIGHT: 544px"
   classid="SmartClient_DLL/SmartClient.DLL#SmartClient.OTIS_WebViewer"  VIEWASTEXT VIEWASTEXT>
   </OBJECT>



    중복다운로드를 해결한 모습입니다.


   




4. 기타 문제들...----------------------------------------------------------------------


   1) 컨트롤이 웹상에서 보이지만 동작하지 않을때


      >>  권한집합을 FullTrust로 준다음 제대로 동작하는지 재확인한다. 정상적이라면 소스코드중 권한을
   넘어서는 것이 없는지 확인하고
 권한의 범위를 재설정해본다.





   2) FullTrust권한을 주었음에도 불구하고, 컨트롤에 웹에서 보이기만 할뿐 동작하지 않을때.


       >> 프레임워크 1.1이 맞는지 확인한다. 상위버젼이 설치되어 있지 않은지 확인하고 만약 그렇다면


       C:\Program Files\Internet Explorer 폴더에 iexplore.exe.config 파일을 새로 생성하고,


       <?xml version="1.0" encoding="utf-8" ?>

          <configuration>

                <startup>

                      <requiredRuntime version="v1.1.4322"/>

                </startup>

           </configuration>


        이와 같이 익스플로러 실행시 사용할 프레임워크의 버젼을 지정해준다.





    3) 변경된 내용이 즉각 적용되지 않을때.


       >> 내용을 수정했다면, AssemblyInfo.cs파일의 어셈블리 버젼을 바꿔보자.


       >> 새로고침을 하지 말고 익스플로러를 완전히 종료하고 새로 열어보자.










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


이 외에도 여러가지 문제점이 있었지만.. 막상 쓸려니 기억이 나질 안네요...(에휴 바본가봐.ㅜ.ㅜ)

다시한번 말씀드리지만. 이글은 강좌는 아니므로.. 중요한 원리와 이유에 대한 언급을 하지않았습니다.

훨씬 좋게 정리된 글들이 있으므로 그것을 참고하시기를 바라는 바입니다.



다만 직접 해보면서 겪었던 문제들에 대한 해결책들이 여기저기 흩어져 있었기에..
그것을 모아놓은 글이라 생각해주세요.


그럼 이만 끝냅니다. ^^


출처

http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=18&MAEULNo=8&no=1163&ref=1163
Posted by 굿데이
2008. 12. 22. 10:25

Smart Client (PrintPreviewDialog와 OpenFileDialog의 사용)

스마트 클라이언트란 말 그대로 똑똑한 클라이언트라 할 수 있다.
기존의 ActiveX컨트롤과 비슷한 기능을 하지만 그보다 훨씬 간단히 접근 할 수 있다. 물론 그렇게 만만한 놈은 아니다.
지금부터 스마트 클라이언트를 이용하여 웹브라우저에서 인쇄 및 파일 업로드 기능을 작성해 보도록 하자.

기존의 <input type=file>태그를 통하여 파일업로드를 할 경우 기본 컨트롤의 모양을 보기 좋게 바꾸기는 상당히 어려운 점이 많이 있었다.

하지만 스마트 클라이언트를 이용하면 간단히 이미지를 클릭할때 OpenFileDialog를 띄울 수 있다.

그럼 예제를 시작해 보도록 하자!!


using System;
using System.Drawing;
using System.Drawing.Printing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace RichWinForm
{
 //외부 스크립트의 호출을 위한 인터페이스
 public interface IPrintControlCOMIncomming
 {
  void show(string oData);
  string showDialog();
 }

 //외부 스크립트에서 public메서드를 호출하기위한
 [ClassInterface(ClassInterfaceType.None)]

//유저컨트롤과 인터페이스(외부의 스크립트에서 public메서드 호출을 위해)를 상속받는다.
 public class Print: System.Windows.Forms.UserControl, IPrintControlCOMIncomming
 {
  private System.Windows.Forms.Button btnFile;
  System.Windows.Forms.TextBox textBox1;
  System.Windows.Forms.Button button1;

  //미리보기 다이얼로그 인스턴스 생성
  PrintPreviewDialog ppd = new System.Windows.Forms.PrintPreviewDialog();

  //파일선택 다이얼로그
  OpenFileDialog ofd = new OpenFileDialog();

  //미리보기의 문서 인스턴스 생성
  PrintDocument pd = new PrintDocument();
 
  //초기화
  private void InitializeComponent()
  {
   this.button1 = new System.Windows.Forms.Button();
   this.textBox1 = new System.Windows.Forms.TextBox();
   this.btnFile = new System.Windows.Forms.Button();
   this.SuspendLayout();
   //
   // button1
   //
   this.button1.BackColor = System.Drawing.SystemColors.Control;
   this.button1.Font = new System.Drawing.Font("돋움", 12F,  System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Pixel);
   this.button1.Location = new System.Drawing.Point(16, 16);
   this.button1.Name = "button1";
   this.button1.Size = new System.Drawing.Size(104, 23);
   this.button1.TabIndex = 0;
   this.button1.Text = "인쇄하기(윈폼)";
   this.button1.Click += new System.EventHandler(this.button1_Click);
   //
   // textBox1
   //
   this.textBox1.Location = new System.Drawing.Point(16, 56);
   this.textBox1.Name = "textBox1";
   this.textBox1.Size = new System.Drawing.Size(216, 21);
   this.textBox1.TabIndex = 1;
   this.textBox1.Text = "";
   //
   // btnFile
   //
   this.btnFile.BackColor = System.Drawing.SystemColors.Control;
   this.btnFile.Font = new System.Drawing.Font("돋움", 12F,
System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Pixel);
   this.btnFile.Location = new System.Drawing.Point(112, 104);
   this.btnFile.Name = "btnFile";
   this.btnFile.Size = new System.Drawing.Size(120, 23);
   this.btnFile.TabIndex = 3;
   this.btnFile.Text = "파일 업로드(윈폼)";
   this.btnFile.Click += new System.EventHandler(this.btnFile_Click);
   //
   // Print
   //
   this.BackColor = System.Drawing.SystemColors.ControlLight;
   this.Controls.Add(this.btnFile);
   this.Controls.Add(this.textBox1);
   this.Controls.Add(this.button1);
   this.Name = "Print";
   this.Size = new System.Drawing.Size(248, 176);
   this.ResumeLayout(false);

  }
 
  //생성자
  public Print()
  {
   InitializeComponent();
   this.pd.PrintPage += new PrintPageEventHandler(this.OnPrintPage);
  }
 
  //페이지를 설정하는 이벤트 메서드
  private void OnPrintPage(object obj, PrintPageEventArgs e)
  {
   string text = "앗싸!!! 된다...";
   System.Drawing.Font printFont = new System.Drawing.Font("돋움", 12, System.Drawing.FontStyle.Regular);

   e.Graphics.DrawString(text, printFont, System.Drawing.Brushes.Black, 0, 0);
  }
 
  //윈폼 버튼 클릭시
  private void button1_Click(object sender, System.EventArgs e)
  {
   //문서의 이름 설정
   pd.DocumentName="tt";
   //미리보기 다이얼로그에 문서 지정
   ppd.Document = pd;
   //다이얼로그 출력
   ppd.ShowDialog();
  }

  #region IPrintControlCOMIncomming 멤버

  //외부 스크립트 이벤트에 의하여 호줄 되는 메서드
  public void show(string oData)
  {
   //외부에서 데이터를 가져와서
   //버튼의 이름으로 설정
   textBox1.Text = oData;
   //문서의 이름 설정
   pd.DocumentName="tt";
   //미리보기 다이얼로그에 문서 지정
   ppd.Document = pd;
   //다이얼로그 출력
   ppd.ShowDialog();
  }

  //웹폼 버튼 선택 시 파일 경로 출력
  public string showDialog()
  {
   if(ofd.ShowDialog() == DialogResult.OK)
   {
    return ofd.FileName;
   }
   return null;
  }
  #endregion
 

  //윈폼 버튼 선택 시 파일 경로 출력
  private void btnFile_Click(object sender, System.EventArgs e)
  {
   if(ofd.ShowDialog() == DialogResult.OK)
   {
    textBox1.Text = ofd.FileName;
   }
  }
 }
}


dll을 호출하는 HTML 코드

기존의 ActiveX와 동일하게 <OBJECT>태그를 통하여 dll을 사용한다.

<%@ Page language="c#" Codebehind="MyForm.aspx.cs" AutoEventWireup="false" Inherits="RichWinForm.WebForm1" %>
<HTML>
 <HEAD>
  <title>WebForm1</title>
  <meta content="Microsoft Visual Studio .NET 7.1" name="GENERATOR">
  <meta content="C#" name="CODE_LANGUAGE">
  <meta content="JavaScript" name="vs_defaultClientScript">
  <meta content="
http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema">
  <script language="javascript">
  function printClick()
  {
   MyForm.PrintPrev.show("외부에서 들어온 데이터 입니다.");
  }
  function openFile()
  {
   Output.innerText = MyForm.PrintPrev.showDialog();
  }
  </script>
  <script for="Slider" event="Scroll (source,args)" language="javascript">
   Output.innerText = MyForm.Slider.Value;
  </script>
 </HEAD>
 <body>
  <form id="MyForm" method="post" runat="server">
   <OBJECT id="PrintPrev" height="200" width="300" classid="http:Print.dll#RichWinForm.Print" VIEWASTEXT>
   </OBJECT>
   <br>
   <br>
   웹 버튼으로 인쇄해보자 :
   <input type="button" value="미리보기" onclick="printClick()">
   <br>
   <br>
   웹 버튼으로 파일업로드 :
   <input type="button" value="파일찾기" onclick="openFile()">
   <asp:Button id="btnSave" runat="server" Text="저장"></asp:Button>
  </form>
  <span id="Output" runat="server">0</span>
 
 </body>
</HTML
>

Posted by 굿데이
2008. 12. 22. 10:00

Smart Client


  Smart Client는 자동 Update 기능을 손쉽게 구현할 수 있는 기능이다.  자동 Update 기능은 개념은 다르지만 이미 V3, 아래아 한글 등 많은 프로그램에서 기능을 구현해 놓았다.

 Smart Client 기능은 타 응용 프로그램에서는 새버젼의 파일이 있을 경우 사용자에게 Update 할것인지를 선택하게 하나, Smart Client는 실행시 자동으로 Update된다.

  이 기능을 응용하면 웹 브라우저에서 실행되는 것 처럼 구성할 수도 있다.

   웹 브라우저에 포함되어 실행되는 프로그램은 기존에 ActiveX나 JAVA로 프로그램하여 구성하였다. 그러나 이 경우 사이트 방문자가 모르는 사이 프로그램이 설치되어 많은 문제를 야기 시켰다. 이를 해결하기 위해 Windows XP SP2이상에서는 보안 경고를 내보내고 있긴하나 완전한 해결책은 아니다.

  따라서 C#에서는 웹 브라우저에 포함되어 실행되는 형태는 지원하지 않는다. 따로 응용 어플리케이션을 다운 받아 실행할 수 있는 Smart Client 프로그램을 제작하여 배포함에 의해 웹 브라우저와는 별도의 화면으로 실행하도록 한다.

  이것은 필자가 C#을 접하면서 기대한 것과는 사뭇다르다. 필자는 ActiveX 같은 프로그램을 훨씬더 손쉬운 방법으로 제작할 수 있으리라 기대를 했었다. 그러나 Smart Client를 이용하면 ActiveX로 구성한 것과 비슷한 효과를 줄 수는 있다.

   응용 어플리케이션을 일반적으로 작성하여 IIS에 등록을 하고, 이 응용 어플리케이션을 자동으로 Update 할 수 있는 Smart Client 프로그램을 작성하고 배포하여 실행 하면 IIS 서버에 등록된 응용 어플리케이션을 다운 받아 실행하는 방식을 사용한다.

  이제 실제 Smart Client 프로그램을 제작해 보자. 여기서 사용할 응용 어플리케이션은  DLL과 Web Service에서 설명한 계산기를 이용할 것이다.

   기본 프로그램 제작에서 설명한 방식으로 프로젝트를 수동으로 하나 만든다. 프로젝트 이름은 CalcSmartClient로 한다. 참조에 System.dll과 System.Windows.Form.dll을 추가하고 CalcSmartClient.cs를 만든후 다음과 같이 코딩을 한다.

using System;

using System.Windows.Forms;

using System.Reflection;


class ShapeSmartClient

{

    public static void Main()

    {   

        try

        {

            Assembly assembly = Assembly.LoadFrom(

                "http://localhost/Calculator.exe");


            Type type = assembly.GetType("Calculator.MainForm");

            type.InvokeMember("Main",

                BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod,

                null, null, null);

        }

        catch(Exception ex)

        {

            MessageBox.Show("서버 에러입니다. 네트워크를 확인 한 후 실행하세요");

        }

    }

}


이제 응용 어플리케이션을 약간 수정하여 IIS에 등록해보자. 어플리케이션 수정은 간단하다. 기본 프로그램 제작에서 잠시 언급했었는데 Main 함수 앞에 public으로 선언하는 것이다.

또한 IIS에 등록하는 것도 간단하다. http://localhost에 해당하는 디렉토리(설정을 변경하지 않았으면 c:\inetpub\wwwroot가 그 위치이다)에 실행파일(dll을 사용하면 dll 파일도 같이)을 복사하기만 하면 된다.

1. 실행파일의 위치를 설정한다.

            Assembly assembly = Assembly.LoadFrom(

                "http://localhost/Calculator.exe");

2. Main을 포함한 클래스 이름을 설정한다. 클래스 이름은 namespace.class의 형태로 입력한다.

            Type type = assembly.GetType("Calculator.MainForm");

3. Main을 호출한다.

            type.InvokeMember("Main",

                BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod,

                null, null, null);


이것이 Smart Client 제작의 전 과정이다.


   이제 제작한 SmartClientClient를 실행 해보자.

   Calculator가 잘 실행 될 것이다.

   탐색기를 실행하여 C:\WINDOWS\assembly로 가면 왼쪽 Tree에 Download가 있을 것이다. 좀 특수한 구조로 되어 있어 실제 오른쪽 파일 보이는 곳에는 존재하지 않은 디렉토리이다. Download를 선택하면 다음과 같이 나타난다.

 Calculator가 여러게 있는 것을 볼 수 있다. 실제 CalcSmartClient.exe를 실행하면 이곳에 Calculator.exe를 찾아 존재하지 않거나, 파일의 크기, 날짜, Version을 비교하여 다르면 서버로부터 다운 받아 실행한다. 참고로 실행 파일에서 사용하는 dll 파일을 그 루틴이 load 될 때(처음 사용될 때, 계산기 프로그램에서는 처음으로 = 키를 누를때) 자동으로 복사된다.

  여기서 우리는 Calculator 제작시 버전에 대해 전혀 신경쓰지 않았다. Calculator 프로젝트를 열어 Assembly.cs를 열어 보자.

  [assembly: AssemblyVersion("1.0.*")]라는 부분을 볼 수 있을 것이다. 마지막에 *는 자동으로 버전이 입력되도록 한 것이다. 이렇게 설정하면(초기 설정) 1.0.으로 시작하면서 나머지는 자동으로 입력이될 것이다. 자동으로 입력이 되는 부분이 Soruce를 수정하여 빌드를 할 때 마다 바뀌어 버전이 부여된다. 참고로 이 부분을 포함하여 전체 버전을 수동으로 입력하여도 된다. SmartClient를 이용하여 배포하는 경우에는 필요없는 다운로드를 피하기 위해 수동으로 관리하는 것이 좋다.


   이제 인터넷에서 실행되는 프로그램 처럼 보이게 해보자. Smart Client 프로그램 입력에서 http://localhost/Calculator.exe라고 입력 했던 부분 중 localhost 대신 실제 IP를 입력하여 빌드 하고 생성된 실행파일인 CalcSmartClient.exe를 http://localhost/의 위치로 복사한다.

   HTML 파일(여기서는 test.htm)을 하나 만들어 다음과 같이 입력한다.

<html>

<body>

<a href="CalcSmartClient.exe">실행</a>

</body>

</html>

  같은 PC에서건 외부 PC에서건 test.htm 파일을 인터넷 익스플로어에서 열면 다음과 같이 화면에 나타난다.

   

  여기에 DLL과 Web Service에서 설명한 보안 설정 법과 앞으로 설명할 보안 설정법을 표시하는 것이 좋다. 이것은 단순 HTML 작성법으로 작성해서 실행 주변에 Link 걸어 주면 되므로 설명하지 않는다.

  실행을 선택하면 다음과 같은 대화 상자가 생성된다.

  실행을 선택하면 다음과 같이 보안 경고 대화 상자가 생성된다.

   실행 버튼을 누르면 실행이 된다.

   실제 인터넷에서 실행되는 프로그램처럼 보이고자 한다면 위 두 버튼을 안나오게 하면 될 것이다. 이것은 웹서버를 신뢰할 수 있는 사이트로 등록함에 의해 이루어 진다.

  인터넷 익스플로어를 실행하여 도구 메뉴의 부메뉴 인터넷 옵션을 선택하여 생성된 대화 상자에서 보안 탭을 누르면 다음과 같이 화면에 나타난다.

  사이트를 선택하면 다음과 같은 대화 상자가 생성된다.

   영역에 웹 사이트 추가에 http://서버 IP의 형태로 입력하고, 이 영역에 있는 모든 사이트에 대해 서버 확인(https:) 필요 체크 버튼을 해제하고 추가를 선택한 후 확인을 누르면 신뢰할 수 있는 사이트로 등록이 된다.

  이것은 ActiveX와는 완전히 다르다. ActiveX는 인터넷 익스플로어에 포함되어 실행되나 이 프로그램은 인터넷에서 실행되는 것 처럼 보이지만 인터넷 익스플로어와는 전혀 별개로 동작한다. 앞에서도 이야기 했지만 Microsoft 사에서는 보안 문제 때문에 ActiveX 와 같은 형태의 프로그램을 버릴려고 하고 있다. ActiveX와 비교해 단점은 일부는 일반 HTML 화면과 응용 어플리케이션 화면을 같이 보여 줄수 없고 별도의 화면으로 띄워야 한다는 것이다. 일반적으로 프로그램은 응용 어플리케이션을 독립적으로 띄워도 상관없는 것이 대부분이다.


다운로드

Posted by 굿데이
2008. 12. 20. 15:38
뷁님의 웹하드에 사용된 업로드 컴포넌트는 너무 불안정하죠?!

자주 다운되고... 그래서는 사용할수가 없을겁니다.

그리고 다운로드도 이어받기 기능이 있는 컴포넌트가 있었으면 해서
무료로 공개된 컴포넌트을 찾아보게 되었습니다.

올팅닷컴
http://www.allting.com/ 에서 개인사용자에게 무료로 배포중인
ATC 컴포넌트를 소개할까 합니다.

아래는 해당 홈페이지에서 소개하는 내용을 가져왔습니다.


업로드 컨트롤(ATUC)

ATTransferCtrl 업로드는 HTTP 폼기반 파일 업로드(RFC1867) 준수하여 제작되어, 모든 서버측 스크립트(PHP, ASP, JSP, ASP.NET)와 100% 연동됩니다.

최대 2기가까지 업로드할 수 있으며, 파일 업로드 과정을 각 파일별로 비주얼하게 보여주며, 이미지파일 미리보기, Drag&Drop, 폼 요소 전송, 부가 정보 전송 기능등 풍부한 기능으로 업로드 작업을 쉽고 강력하게 지원합니다.

업로드 컴포넌트 예제보기 클릭!



다운로드 컨트롤(ATDC)



ATTransferCtrl 다운로드는 HTTP1.1 표준(RFC2316)을 준수하여 제작되어 파일 이어받기를 지원하며, 다운로드 상태를 각 파일별로 비주얼하게 보여주므로서 다운로드시 사용자의 편의를 제공합니다.

파일 목록 기능으로 파일을 선택적 다운로드할 수 있으며, 최대 17,179,869,184기가바이트(2^64, 사실상 무제한 다운로드)까지 다운로드를 지원합니다.

HTML 파일로 UI디자인이 가능하므로 서비스 목적에 따른 완벽한 커스터마이징이 가능합니다.

다중 파일 전송 및 대용량 파일 전송에는 반드시 필요한 서비스가 될 것입니다.


다운로드 예제보기 클릭!



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

뷁님의 웹하드에 적용해본 결과 상당히 만족스러운 결과를 얻었습니다.

이젠 정말 웹하드 다운 웹하드를 사용하는 느낌(?!) 입니다.

그럼 다음에는 이 컴포넌트를 적용한 웹하드를 공개하고, 어떻게 사용하는지 알려드리겠습니다.

Posted by 굿데이
2008. 12. 20. 05:14

사용자 삽입 이미지
































플로우 차트만 보면 무척 간단하다.

업데이트할 내용이 있는지 검사해서 있으면 하고 없으면 말고. 이게 끝이다.


자동업데이트 기능은 인터넷의 혜택으로 인해 요즘 프로그램에선 필수 이다.

예제 보고 간단하게 함 따라 해봤는데 나름대로 구미에 맞게 수정하다 보니 제법 그럴싸해졌다.

첨엔 ini 파일을 사용했는데 그거보단 레지스트리가 난거 같아서 레지스트리에 업데이트 정보를 저장해서 사용한다.

DB와 연동해서 프로그램별로 버전관리가 가능하게 했다.



업데이트 관리 DB – 업데이트 프로그램 통합 관리

3개의 테이블 사용 프로그램 관리, 업데이트 관리, 업데이트 로그

프로그램 아이디로 구분 하나의 자동업데이트 프로그램을 이용해 모든 프로그램에 적용하여 사용할 수 있다.

설정파일의 프로그램 아이디로 업데이트 관리 테이블을 검색하고 업데이트 내용을 가져와서 해당 파일들을 다운로드 받은 후 업데이트 결과를 업데이트 로그 테이블에 저장해준다.

각 프로그램 단위로 업데이트 상황을 파악할 수 있다.


업데이트 파일 검색

버전 정보를 날짜 형식으로 지정해서 현재 버전 보다 높은 버전이 있는지 검색

SELECT TOP 1 IDX, ID, VERSION, CONTENTS FROM UPDATE_LIST WHERE ID=@ID AND VERSION>@VERSION ORDER BY VERSION ASC

업데이트 로그 등록

업데이트할 모든 파일을 다운로드 받은 후 로그 기록

INSERT INTO UPDATE_LOG (UPDATE_IDX, IP, DOWN_DATE) VALUES (@IDX, @IP, GETDATE())






DB는 아무거나 상관없다.

처음에는 프로그램에서 직접 디비에 접속을 했는데 업데이트 로그 기록하려고 클라이언트의 IP정보를 어떻게 받아오나 고민하다가

좀더 효과적인 방법을 찾았다.

프로그램에서 디비에 직접 접속하는게 아니고 특정 웹페이지로 접속을 해서 업데이트 정보를 가져온다.

가져온 정보로 업데이트 하고 다시 웹페이지를 접속해서 로그를 저장하면 된다.

이렇게 하면 우선 프로그램에 디비 접속 정보가 없어도 되기 때문에 좀더 보안에 안전하다.

그리고 약간의 유연성이 더 있을 것 같다.


프로그램이 처음 실행될때 업데이트를 체크하도록 했는데 시작 프로그램에 등록해 놓으니 프로그램이 먼저 시작하고 나서 나중에

인터넷에 연결이 되는 상황이 발생한다.

인터넷 연결이 나중에 되더라도 프로그램이야 잘 돌아가지만 업데이트는 전혀 안되는 상황이 생길 수 있다.

그래서 프로그램 실행 중간에 한번씩 업데이트 체크하는 부분을 추가해야 된다.



08.08.06 보완사항

메인 프로그램에서 10초에 한번씩 작업을 진행하는데 타이머 위치가 잘못 되서 특정 예외 상황 발생시 거의 무한 루프에 빠져버리는 문제점을 발견했다.

몇일 쉬다가 다시 코드를 보니 원인 찾는데 넘 오래 걸렸다.

타이머 시작 위치 변경 해서 해결 했다.


40대의 컴에서 동시에 작업을 하다 보니 디비 서버가 뻗어버렸다.

디비서버 동시 접속수 늘려주고 디비 작업 후 연결 닫는 구문을 모두 추가해주었다.


메인 프로그램에서 자동업데이트 체크하는 부분하고 마무리 작업 처리하는 부분만 추가해주면 일단 마무리.





자동업데이트 소스

using System;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Web;
using Microsoft.Win32;
using System.Data.SqlClient;
using MySql.Data.MySqlClient;
using System.ComponentModel;

namespace Keyword_Search_Starter
{
    public partial class Starter : Form
    {
private string sLocalFilePath; // 실행 경로 private string sServerFilePath; // 다운받을 서버주소 private string sResultMsg; // 업데이트 체크 결과 메세지(Error, OK) private string sID = null; // 프로그램 아이디 private string sIDX = null; // 업데이트 리스트 키값 private string sAuto = null; // 자동업데이트 유무(1, 0) private string sVersion = null; // 업데이트 버전 - 6자리날짜(080803) private string sStartProgram = null; // 업데이트 후 실행할 프로그램 private string sUserIP = null; // 접속 아이피 로그기록 private int iUpdateCount = 0; // 파일 다운로드 숫자 - 전송완료 될 때마다 증가함 private string sRegKey = "Software\\Pharos"; private string sUpdateAddr = "http://blog.naver.com/inidu2/Upload/UpdateListView.aspx"; public Starter() { InitializeComponent(); } #region Starter_Load 레지스트리 정보 읽기 private void Starter_Load(object sender, EventArgs e) { sLocalFilePath = AppDomain.CurrentDomain.BaseDirectory; // 레지스트리 설정 내용 확인 RegistryKey reg = Registry.LocalMachine; reg = reg.CreateSubKey(sRegKey); sID = (string)reg.GetValue("ID", null); sStartProgram = (string)reg.GetValue("StartProgram", null); sVersion = (string)reg.GetValue("Version", null); sAuto = Convert.ToString(reg.GetValue("Auto", null)); if (reg.GetValue("UpdateAddr", null) != null) { sUpdateAddr = Convert.ToString(reg.GetValue("UpdateAddr", null)); } lbTitle.Text += " ID : " + sID; GetUpdateList(); } #endregion #region GetUpdateList() 업데이트 리스트 가져오기 private void GetUpdateList() { string path = sUpdateAddr + "?id=" + sID + "&version=" + sVersion; try { HttpWebRequest hwr = (HttpWebRequest)WebRequest.Create(path); HttpWebResponse hwrp = (HttpWebResponse)hwr.GetResponse();
Stream strm = hwrp.GetResponseStream(); StreamReader sr = new StreamReader(strm); listView1.Items.Clear(); int line = 1, n = 1; string temp = null; while (sr.Peek() > -1) { temp = sr.ReadLine(); switch (line) { case 1: sResultMsg = temp; break; // 결과 메시지 case 2: sUserIP = temp; break; // 접속 IP case 3: sIDX = temp; break; // 업데이트 리스트 키 case 4: sVersion = temp; break; // Version case 5: sServerFilePath = temp; break; // Path default: // File List listView1.Items.Add(n.ToString()); listView1.Items[n - 1].SubItems.Add(temp); listView1.Items[n - 1].SubItems.Add("전송대기"); n++; break; } line++; } sr.Close(); strm.Close(); } catch { } finally { } // 업데이트 항목이 없으면 무시하고 프로그램 실행 if (listView1.Items.Count == 0) { AppStart(); } else { btnStart.Enabled = false; DownLoad(); } } #endregion #region DownLoad() 다운로드 protected void DownLoad() { this.Cursor = Cursors.WaitCursor; // 다운로드할 파일이 있으면 다운로드 if (listView1.Items.Count > 0) { for (int i = 0; i < listView1.Items.Count; i++) { string serverFile = sServerFilePath + listView1.Items[i].SubItems[1].Text; string localFile = sLocalFilePath + listView1.Items[i].SubItems[1].Text; try { WebClient webClient = new WebClient(); listView1.Items[i].SubItems[2].Text = "전송중"; webClient.DownloadFileCompleted +=
new AsyncCompletedEventHandler(Completed); webClient.DownloadProgressChanged +=
new DownloadProgressChangedEventHandler(ProgressChanged); webClient.DownloadFileAsync(new Uri(serverFile), @localFile); listView1.Items[i].SubItems[2].Text = "전송완료"; } catch (Exception ex) { listView1.Items[i].SubItems[2].Text = "전송에러"; MessageBox.Show(serverFile + "\r\n" + ex.Message + "\r\n" + ex.StackTrace); } } } this.Cursor = Cursors.Default; } #endregion private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e) { progressBar1.Value = e.ProgressPercentage; lbState.Text = e.ProgressPercentage.ToString() + "%"; } #region Completed 전송완료 private void Completed(object sender, AsyncCompletedEventArgs e) { iUpdateCount++; if (iUpdateCount == listView1.Items.Count) { this.UpdateLog(); this.AppStart(); } } #endregion #region AppStart() 프로그램 실행 private void AppStart() { try { string AppPath = AppDomain.CurrentDomain.BaseDirectory; System.Diagnostics.Process ps = new System.Diagnostics.Process(); ps.StartInfo.FileName = AppPath + sStartProgram; ps.Start(); // 타이머 작업으로 업데이트 감시 Application.Exit(); } catch (Exception ex) { MessageBox.Show(ex.Message + "\r\n" + ex.StackTrace); } } #endregion #region UpdateLog() 업데이트 로그 작성 및 버전 정보 업데이트 private void UpdateLog() { // 레지스트리 설정 내용 확인 RegistryKey reg = Registry.LocalMachine; reg = reg.CreateSubKey(sRegKey); reg.SetValue("Version", sVersion); reg.SetValue("LastUpdate", DateTime.Now); // 업데이트 로그 string path = sUpdateAddr + "?mode=log&idx=" + sIDX; HttpWebRequest hwr = (HttpWebRequest)WebRequest.Create(path); HttpWebResponse hwrp = (HttpWebResponse)hwr.GetResponse(); } #endregion private void btnStart_Click(object sender, EventArgs e) { DownLoad(); } } }

[출처] 자동 업데이트|작성자 파로스

Posted by 굿데이
2008. 12. 20. 05:05
1. 소스를 정리하였습니다.

아래 표는 각 프로젝트와 그에 속한 클래스에 대한 설명입니다.

Hau 자동 업데이터 컴퍼넌트 프로젝트. 아래 두 프로젝트에 의해 참조됨.
     AutoUpdater 자동 업데이터 컴퍼넌트
     RemoteFile 웹서버의 파일을 표현
     TransferingInfo 전송 상태를 표현
     UpdateListDataSet 업데이트 파일 목록을 읽고 쓰기 위한 스키마
Hau.Sample 자동 업데이터 컴퍼넌트를 이용하는 샘플 프로젝트
     NomAutoUpdater 자동 업데이터 컴퍼넌트를 이용하여 구현된 NoM의 자동 업데이터
Hau.UpdateListEditor 업데이트 파일 목록 편집기 프로젝트
    UpdateListEditorForm 업데이트 파일 목록 편집기

2. AutoUpdater에 LocalRoot 라는 속성이 추가되었습니다.

이전 버전에는 다운로드 위치가 항상 AutoUpdater 컴퍼넌트가 사용된 실행파일과 같은 위치였지만, 이제는 LocalRoot 속성을 지정하면 아무 곳에나 다운로드를 받을 수 있게 되었습니다.


3. 업데이트 파일 목록 편집기에서 제외 정규식과, 그리드의 편집 기능이 없어졌습니다.


4. 업데이트 파일 목록 편집기 '마지막 수정 시각 1초 증가' 버튼이 추가되었습니다.

이 기능은 기존 업데이트 목록을 열어서 특정 파일만 최신 버전으로 지정하는 경우에 유용하게 사용할 수 있습니다.

1초가 증가된 행의 배경색은 베이지로 변경됩니다. 또한 한번 1초가 증가된 행은 더 이상 증가되지 않습니다. (논리적으로 2초 이상을 증가시킬 이유가 없습니다.)


5. 업데이트 파일 목록 편집기의 그리드에서 Delete 키를 누르면 행이 두 개씩 삭제되던 버그를 수정하였습니다.




출처
http://kimgwajang.tistory.com/135

Posted by 굿데이