1. C#을 사용한 빠른 툴 개발 ㈜ 다이슨 인터렉티브파이퍼 스튜디오 CQ팀 이름 : 최흥배 E-Mail : jacking75@gmail.com Blog : http://blog.naver.com/jacking75스프링 노트 : http://jacking.springnote.com
2. Agenda 툴 개발 이야기 C#에 대한 이야기 사례 : DB 툴 사례 : 사내 패치 시스템
3. 제 강연의 핵심은…… 기민하게 개발 툴을 만들자 생산성이 좋은 프로그래밍 언어를 사용하자
17. 문제: 서버에서 정의한 패킷을C#에서는 사용할 수 없으며, C++에서는 구조체로된 데이터를 보내고 받지만 C#에서는 불가능. 해결: 1. Marshaling 사용
18. [StructLayout(LayoutKind.Sequential, Pack = 1)] public class ConnectBridgeRq { public ConnectBridgeRq() { Header = new HEADER(); acIP = new byte[17]; } public void GetBuffer(byte[] outBuffer) { if (0 == outBuffer.Length) outBuffer = new byte[Protocol.MAX_PACKET_DATA]; unsafe { fixed (byte* fixed_buffer = outBuffer) { Marshal.StructureToPtr(this, (IntPtr)fixed_buffer, false); } } } public HEADER Header; // 헤더 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 17)] public byte[] acIP; // 아이피 }
19. void Send() { LoginAuthorRetLoginPacket = new LoginAuthorRet(); LoginPacket.Header.a1 = (ushort)(Marshal.SizeOf(LoginPacket) - Marshal.SizeOf(LoginPacket.Header)); LoginPacket.Header.a2 = ClientNetworkLib.PACKET_DEFINE.PK_LOGIN_AUTHOR_REQ; intiIPLen = strIP.Length; Buffer.BlockCopy(Encoding.ASCII.GetBytes(strID), 0, LoginPacket.acIP, 0, iIPLen); byte[] packet1 = new byte[Protocol.MAX_PACKET_DATA]; LoginPacket.GetBuffer(packet1); ClientSock.SendPacket(packet1, Marshal.SizeOf(LoginPacket)); } 서버로 보내는 패킷의 클래스 정의 및 사용이 간단하지 않음. 서버로 보낼 때는 사용할 수 있어도 받을 때는 사용하지 못함.
27. 3. C#에서 WM_COPYDATA 사용 문제: .NET에서는 WM_COPYDATA 라는 것이 없음 해결 : 관리 되지 않는 코드를 사용 참고 URL http://www.codeproject.com/KB/cs/ipc_wmcopy.aspxhttp://www.codeproject.com/KB/threads/InterprocessCommunicator.aspxhttp://www.codeproject.com/KB/cs/wm_copydata_use.aspx
28. 4. C#에서 C++ 코드 사용 C++ 코드를 DLL C++/CLI로 Wraping C#에서 사용 참고 URL http://sj21.wo.to/tt/483 http://sj21.wo.to/tt/484 http://blogs.msdn.com/junfeng/archive/2006/05/20/599434.aspx
36. DB 데이터를 xml 파일로 저장 DataSetResultDataSet = new DataSet(); string strQuery = "SELECT * FROM " + TableName; DbCommandcmd = ConnectionInstance.CreateCommand(); cmd.CommandText = strQuery; DataAdapter.SelectCommand = cmd; DataAdapter.Fill(ResultDataSet, strTable); ResultDataSet.WriteXml(“ItemTable.xml”);
37. C++로 한다면…….. 코드로 표현 하기에는 너무 길어서 간략한 의사 코드로 XML 파서 선택 XML 파서 사용 법 학습 DB 쿼리 각 Table에 맞게 데이터 읽기 참고 http://jacking75.cafe24.com/Tip/TinyXml_SimpleUse.htm 각 Table에 맞게 XML 형식으로 쓰기
38. xml 데이터를 DB 에 저장 DataSetResultDataSet = new DataSet(); string strQuery = "SELECT * FROM " + “테이블 이름”; DataSetds = new DataSet(); ds.ReadXml(“XML 파일”); …….. DataAdapter.Update(dataset, TableName);
45. 실제 코드 량은 100 라인 이내 패치 파일을 압축 하기 위해 SharpZibLib사용 (공개 라이브러리 사용)
46. 주로 사용한 API 지정된 폴더에 있는 모든 파일을 조사 string[] Cur_AllFiles = Directory.GetFiles(textBox1.Text, "*.*", SearchOption.AllDirectories); 파일 비교를 위해 FileInfoCur_fileinfo = new FileInfo(CurVerFile); Cur_fileinfo.LastWriteTime Cur_fileinfo.Length
47. SharpZipLib사용 SharpZipLib : http://icsharpcode.net/OpenSource/SharpZipLib/Default.aspx 사용 법 http://dobon.net/vb/dotnet/links/createzipfile.html
49. 실제 코드 량은 200 ~ 300 라인 이내 런처 업데이트를 위해 ‘AutoIt’ 스크립트 언어 사용
50. 주로 사용한 API 웹 페이지 출력 WebBrowser컨트롤 사용 webBrowser.Navigate(“http://blog.naver.com/jacking75");
51. 웹 서버에 있는 설정 파일 다운로드 및 읽기 WebRequestmyWebRequest = WebRequest.Create(“다운로드 할 파일 이름”); WebResponsemyWebResponse = myWebRequest.GetResponse(); Stream ReceiveStream = myWebResponse.GetResponseStream(); StreamReadersr = new StreamReader(ReceiveStream);
52. 패치 파일 다운로드 하기 WebClientmyWebClient = new WebClient(); myStringWebResource = remoteUri + fileName; myWebClient.DownloadFile( myStringWebResource, fileName);
54. 런처 재 실행을 위한 AutoIt스크립트 MsgBox( 0, "런처 업데이트", "런처가 업데이트 되었습니다. 잠시 후 다시 시작합니다" ) ; 1.5초 Sleep( 1500 ) ProcessClose("CQGame.exe") ; 1.5초 Sleep( 1500 ) ; 기존 파일 삭제 FileDelete( “CQGame.exe" ) ; 새 파일 이름 변경 FileMove( "New_CQGame.exe", "CQGame.exe", 1 ) FileDelete( "New_CQGame.exe" ) ; 실행 Run( "CQGame.exe" )
55. .NET Framework가 없어도 C# 프로그램 실행 가능 PostBuilder를 사용하면 된다 http://www.xenocode.com/Products/Postbuild/ 외부 서비스에서도 바로 사용할 수 있다