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 굿데이