C# Debug / Release 체크해서 코드 실행하기

CSharp
C#으로 개발을 하다 보면은 Debug에서만 작동해서 테스트를 위할 때가 있습니다. Release와 동일하게 하면 좋지만은 겨우 확인을 위해서만 필요한 사항인데, 빌드할때 빼먹으면은 남기도 하고 하는등이 피폐한 부분이 있어서 조금은 코드를 찾아보니 좋은 조건문이 있어서 기록을 합니다. #if DEBUG Console.WriteLine("Mode=Debug"); #else Console.WriteLine("Mode=Release"); #endif 이제 그냥 디버그와 릴리즈 일때 구분하지 않고 코드를 나두고 작업을 합니다. 물론 최종 출시전에는 위에 코드가 없는편이 깔끔하고 좋지만은 한창 개발중인 기능에 대해서는 긴급하게 업데이트도 필요하기 때문에 나두면은 좋습니다. 물론 실행을 막아주기도 하는등의 좋은 기능도 있습니다. 주석을 잘 남기는것도 좋지만 확실히 디버그 일때와 릴리즈 모드에 대해서도 구분을 하고 개발을 하면 좋을것 같습니다.
Read More

윈도우 시간 동기화

CSharp
프로그램을 개발하면서 윈도우의 시간동기화가 필수적으로 필요하게 되었습니다. 당연히 윈도우가 자동으로 잘 동기화를 하고 있겠지만은 그렇지 않은 경우에는 강제로 동기화를 해야 하는데, 컴퓨터가 그냥 자동으로 작업을 할 경우에 시간에 예약이 있을 경우에 시간이 동기화가 되지 않으면은 작업이 늦어지기에 한번씩 동기화를 해줘야 합니다. /// <summary> /// Gets the current DateTime from time-a.nist.gov. /// </summary> /// <returns>A DateTime containing the current time.</returns> public static DateTime GetNetworkTime() {     return GetNetworkTime("time.windows.com"); // time-a.nist.gov }   /// <summary> /// Gets the current DateTime from <paramref name="ntpServer"/>. /// </summary> /// <param name="ntpServer">The hostname of the NTP server.</param> /// <returns>A DateTime containing the current time.</returns> public static DateTime GetNetworkTime(string ntpServer) {     IPAddress[] address = Dns.GetHostEntry(ntpServer).AddressList;       if (address == null || address.Length == 0)         throw new ArgumentException("Could not resolve ip address from '" + ntpServer + "'.", "ntpServer");…
Read More

$(document).ready 보다 실행이 늦은 $(window).load

JavaScript
<script> $(window).load(function() { alert(2); }); $(document).ready(function() { alert(1); }); </script> WebPage를 작업하다 보면은 모든것을 Loading이 끝나고 실행해야 하는 상태가 있습니다. 보통은 ready를 사용하지만은 DOM 객체만 loading이 되면은 바로 실행이 됩니다.이렇게 DOM 객체 상관없이 외부이미지 리소스 모두 loading를 하고 실행이 되어야 할 경우에는 load를 사용하면 됩니다.위에 예제처럼 2개의 사용방법이 다르니 한번 살펴보시기 바랍니다.
Read More

안드로이드 웹뷰 기능 제작중

Android
package com.sihwawon.android import android.R.attr import android.R.attr.* import android.annotation.SuppressLint import android.app.AlertDialog import android.app.Dialog import android.content.DialogInterface import android.content.Intent import android.graphics.Bitmap import android.net.Uri import android.net.http.SslError import android.os.Build import android.os.Bundle import android.os.Environment import android.os.Message import android.provider.MediaStore import android.util.Log import android.view.View import android.view.ViewGroup import android.webkit.* import android.widget.ProgressBar import androidx.appcompat.app.AppCompatActivity import java.io.File import java.util.* import java.util.UUID import android.widget.Toast import android.view.Gravity import android.webkit.WebView import android.webkit.WebViewClient import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import android.webkit.ValueCallback import java.io.IOException import java.text.SimpleDateFormat import android.app.Activity import android.content.Intent.ACTION_VIEW import android.content.res.Configuration import android.text.TextUtils import android.webkit.WebChromeClient import android.os.Parcelable import androidx.core.content.FileProvider import android.webkit.WebChromeClient.FileChooserParams import androidx.annotation.RequiresApi import android.print.PrintAttributes import android.print.PrintManager import android.view.KeyEvent import kotlin.time.days class MainActivity : AppCompatActivity() { private lateinit var mWebView: WebView private var pWebView: WebView? = null private lateinit var mProgressBar: ProgressBar private var thisUrl: String? = null private var barcode: String? = "" private var popup: Boolean? =…
Read More

Javascript 3자리 콤마 및 소수점 2자리 입력 받기

JavaScript
웹페이지를 개발하다 보면은 사용자가 보이기 편하도록 단위마다 콤마도 붙여줘야 하고 소수점도 받아야 합니다. 하지만, 숫자외에 입력을 받다보면은 문제가 생길수 있어서 아래의 코드를 적용하면은 숫자외에는 입력을 받지 않기 때문에 사용자의 입력을 제한 할 수 있습니다. <!DOCTYPE html> <html> <body> <input type="text" id="input1" placeholder="숫자를 입력해주세요" onKeyUp="removeChar(event);inputNumberFormat(this);" onKeyDown="inputNumberFormat(this);" > <script> //문자 제거 function removeChar(event) { event = event || window.event; var keyID = (event.which) ? event.which : event.keyCode; if (keyID == 8 || keyID == 46 || keyID == 37 || keyID == 39) return; else //숫자와 소수점만 입력가능 event.target.value = event.target.value.replace(/[^-\.0-9]/g, ""); } //콤마 찍기 function comma(obj) { var regx = new RegExp(/(-?\d+)(\d{3})/); var bExists = obj.indexOf(".", 0);//0번째부터 .을 찾는다. var strArr = obj.split('.'); while (regx.test(strArr[0])) {//문자열에 정규식 특수문자가 포함되어 있는지 체크 //정수 부분에만 콤마 달기 strArr[0] = strArr[0].replace(regx, "$1,$2");//콤마추가하기 } if…
Read More

WebView 기능을 이용한 앱 개발중

Android
오랜만에 기술적인 내용이 아닌 일반적인 내용을 작성을 하게 되었습니다. 이번에 새롭게 공부를 시작하면서 Web과 App을 이용한 하이브리드(?) 용으로 App을 개발하게 되었습니다. 아직 시작 단계이지만 순항을 하는중이라고 생각을 합니다. 현재는 안드로이드의 기능중 WebView를 이용해서 순서 Web에 대한 표시를 하고, 웹에 포함된 기능중 일부에 대해서는 App과 사용작용으로 작동하는 기능을 개발중에 있습니다. 해당 기능이 되면은 말 그대로 하이브리드 형식이되지 않을까 싶습니다. 순수하게 웹으로만 작동하는것도 아니고, App만으로도 작동하지 않지만 서로가 상호 보완을 통해서 기능이 작동을 하리라고 생각이 됩니다. 아직 내용을 정리하기에는 부족하고 정리가 미흡하지만 조만간 해당 내용에 대해서 글을 작성하지 않을까 싶습니다. 카테고리를 만들고 나서 예고 차원에서 일단 기술적인 내용이 없는 글을 먼저 작성을 해서 신규 카테고리가 있다는것도 알리고 카테고리의 글을 하나씩 채워 나갈 생각 입니다. 잘하시는 분들이 볼 경우에는 많이 미흡할 수 있지만 이런 내용이 있다는 정도로 제가 정리해서 남기기 위한 글입니다. 이번에…
Read More

개인 소스 관리를 시작 하였습니다.

프로그램
회사에서는 이미 Gitlab를 통해서 개발코드에 대한 형상관리를 하고 있습니다. 하지만 개인적으로는 그다지 필요가 없다고 생각을 해서 하지 않던것을 이번에 모두 정리해서 등록하는데 꽤 시간을 할애해서 작업을 진행하였습니다. 그래도 개인적으로 연습삼아 한 일에 대해서는 모두 올리려고 하니 너무 많아서 조금 간추리는 작업을 해서 어느정도 남에게 공개한 프로그램들에 한해서만 하는것도 꽤 시간이 걸리는 작업을 하게 되었습니다. 그래도 이제 개인적인 저장소에서 FTP를 통해서 소스 관리하던것을 올리고 나서 보니 여러가지 일을 하였고, 여러가시 소소한것이 많다는 생각을 하였습니다. 시작하고 마무리 하지 않은 일도 계획만 잡아 두거나 혹은 다른 사람의 코드를 연구하기 위해서 만들어 놓은것들이 한둘이 아니라서 정리가 꽤 애를 먹었습니다. 그래도 큰맘 먹고 정리를 하니 디렉토리도 정리가 되고 한결 찾기가 수월해져서 좋은듯 합니다. 그동안에 소스 형상관리를 어느곳에 이용할까 혹은 개인 서버를 만들까 하면서 고민을 많이 하였습니다. 솔직히 오픈소스로 공개할 정도가 되지 않으니 github를 이용하기도 조금…
Read More

기록물

Database
MES 개념도 그냥 관계도를 그려본것입니다. 상세한 자료는 솔직히 인터넷에 공개를 할 수 없어서 이렇게 구분을 해야 하지 않을까 하는 형태로 그려본 것입니다. MES 개발이라는것을 처음해보는것이라서 준비과정이 상당히 많고 어딘가에 참조를 해서 개발을 한다는것이 조금은 시간이 걸리는것 같습니다. 각자 고유의 기능을 포함하고 DATA를 관리하는 방법을 보여주지 않으려고 해서 화면만으로 보고 기능을 개발하는것은 상당히 고역입니다. 하지만 한번에 성공한다고 하기 보다는 실제 DATA를 입력을 하고 진행을 하다 보면은 조금씩 보완이 되고 업데이트가 되면서 조금씩 완성형에 다가가지 않을까 하는 생각을 하게 되기에 초기 자료로서 기록을 남겨 둡니다.
Read More

[CSharp] Zip 파일 압축, 해제

CSharp
참조할 어셈블리System.IO.CompressionSystem.IO.Compression.FileSystem // 압축 풀기 using (ZipArchive zipArchive = ZipFile.OpenRead(LOCAL_FILE)) { foreach (ZipArchiveEntry zipArchiveEntry in zipArchive.Entries) { try { string folderPath = Path.GetDirectoryName(Path.Combine(LOCAL_ZIPARCHIVE_PATH, zipArchiveEntry.FullName)); // if (!Directory.Exists(LOCAL_ZIPARCHIVE_PATH)) { Directory.CreateDirectory(LOCAL_ZIPARCHIVE_PATH); } // zipArchiveEntry.ExtractToFile(Path.Combine(LOCAL_ZIPARCHIVE_PATH, zipArchiveEntry.FullName), true); } catch (PathTooLongException pt_ex) { Console.WriteLine(pt_ex); } } } // 압축하기 using (FileStream fileStream = new FileStream(SFTP_DOWNLOAD_LOCAL_PATH, FileMode.Create, FileAccess.ReadWrite)) { using (ZipArchive zipArchive = new ZipArchive(fileStream, ZipArchiveMode.Update)) { try { foreach (string filePath in Directory.EnumerateFiles(DOWNLOAD_LOCAL_ZIPARCHIVE_PATH, "*.*", SearchOption.AllDirectories)) { string relativePath = filePath.Substring(DOWNLOAD_LOCAL_ZIPARCHIVE_PATH.Length + 1); try { zipArchive.CreateEntryFromFile(filePath, relativePath); } catch (PathTooLongException pt_ex) { Console.WriteLine(pt_ex); } } } catch (Exception ex) { Console.WriteLine(ex); } finally { zipArchive.Dispose(); fileStream.Close(); } } } 단순하게 참조만 추가하니 정상적으로 되지 않아서 참조 방법을 조금더 자세히 기록을 합니다. 변경일 : 2021.06.19
Read More

[CSharp] SFTP

CSharp
ConnectionInfo ci = new ConnectionInfo(SFTP_HOST, SFTP_PORT, SFTP_USER, new PasswordAuthenticationMethod(SFTP_USER, SFTP_PASS)); using (var sftpClient = new SftpClient(ci)) { try { // sftpClient.KeepAliveInterval = TimeSpan.FromSeconds(60); sftpClient.ConnectionInfo.Timeout = TimeSpan.FromMinutes(180); sftpClient.OperationTimeout = TimeSpan.FromMinutes(180); sftpClient.Connect(); sftpClient.DeleteFile(SFTP_PATH); sftpClient.Disconnect(); // sftpClient.Connect(); sftpClient.BufferSize = 4 * 1024; using (FileStream fs = new FileStream(LOCAL_FILE, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { sftpClient.BufferSize = 4 * 1024; sftpClient.UploadFile(fs, FILE_NAME, true); } sftpClient.Disconnect(); // sftpClient.Connect(); sftpClient.DownloadFile(SFTP_DOWNLOAD_SERVER_PATH, LOCAL_FILE); sftpClient.Disconnect(); } catch (System.Net.Sockets.SocketException socket_ex) { MessageBox.Show(socket_ex.Message, "경고"); } catch (Renci.SshNet.Common.SshAuthenticationException ssh_ex) { MessageBox.Show(ssh_ex.Message, "경고"); } }
Read More

[CSharp] MySQL 접속 처리

CSharp, Database
using (dbConnection = new MySqlConnection("Server={0}Port={1};Database={2};Uid={3};Pwd={4}")) { try { /* INSERT, UPDATE 처리 */ dbConnection.Open(); dbQuery = string.Format("UPDATE `table` SET colume = '{0}' WHERE idx = '{1}'", VALUE, IDX); dbConnection.Open(); dbCmd = new MySqlCommand(dbQuery, dbConnection); dbCmd.ExecuteNonQuery(); dbConnection.Close(); /* bind 형식 */ dbConnection.Open(); dbQuery = "INSERT INTO log (`content`,`ip`,`creator`) VALUES (@content,@ip,@creator); "; dbCmd = new MySqlCommand(dbQuery, dbConnection); var bind1 = new MySqlParameter("@content", this.logString() + TEXT +"했습니다."); dbCmd.Parameters.Add(bind1); if( dbCmd.ExecuteNonQuery() == 1) { //성공 } dbConnection.Close(); /* SELECT */ dbConnection.Open(); dbQuery = string.Format("SELECT * FROM `table` WHERE idx = '{0}'; ", IDX); dbCmd = new MySqlCommand(dbQuery, dbConnection); dbTable = dbCmd.ExecuteReader(); if (dbTable.HasRows) { while (dbTable.Read()) { dbTable["cnt"].ToString().Trim(); } } } catch (MySqlException db_ex) { MessageBox.Show(db_ex.Message, "경고"); } finally { } } 그냥 소스코드의 일부 기능을 정리한 코드 입니다. 누군가가 바로 사용할 정도의 코드가…
Read More

[CSharp] datagirdivew 설정

CSharp
C#으로 개발을 하다 보면은 datagridview를 사용할 일이 너무 많아서 한번 기록을 해두기 위해서 글을 작성합니다. System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle(); dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter; dataGridViewCellStyle1.Font = new System.Drawing.Font("맑은 고딕", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(165))); dataGridViewCellStyle1.Padding = new System.Windows.Forms.Padding(0, 5, 0, 5); dataGridViewCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.True; //줄바꿈 this.dataGridViewFileList.Columns.Clear(); this.dataGridViewFileList.Rows.Clear(); this.dataGridViewFileList.Refresh(); this.dataGridViewFileList.BorderStyle = BorderStyle.None; this.dataGridViewFileList.RowHeadersBorderStyle = DataGridViewHeaderBorderStyle.None; this.dataGridViewFileList.ColumnHeadersBorderStyle = DataGridViewHeaderBorderStyle.None; this.dataGridViewFileList.CellBorderStyle = DataGridViewCellBorderStyle.SingleHorizontal; this.dataGridViewFileList.BackgroundColor = Color.White; this.dataGridViewFileList.DefaultCellStyle.SelectionBackColor = Color.FromArgb(0, 161, 218);//선택시 this.dataGridViewFileList.DefaultCellStyle.SelectionForeColor = Color.White; //선택시 this.dataGridViewFileList.AlternatingRowsDefaultCellStyle.BackColor = Color.AliceBlue;//Color.FromArgb(236, 240, 241); this.dataGridViewFileList.ColumnHeadersDefaultCellStyle.BackColor = Color.FromArgb(228, 170, 102); this.dataGridViewFileList.ColumnHeadersDefaultCellStyle.ForeColor = Color.White; this.dataGridViewFileList.SelectionMode = DataGridViewSelectionMode.FullRowSelect; this.dataGridViewFileList.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None; this.dataGridViewFileList.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None; this.dataGridViewFileList.DefaultCellStyle.WrapMode = DataGridViewTriState.True; //줄바꿈 this.dataGridViewFileList.Font = new System.Drawing.Font("맑은 고딕", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(165))); this.dataGridViewFileList.Visible = true; this.dataGridViewFileList.ReadOnly = true; this.dataGridViewFileList.MultiSelect = false; this.dataGridViewFileList.AutoGenerateColumns = false; this.dataGridViewFileList.RowHeadersVisible = false; this.dataGridViewFileList.ShowCellErrors = false; this.dataGridViewFileList.ShowCellToolTips = false; this.dataGridViewFileList.ShowEditingIcon = false; this.dataGridViewFileList.ShowRowErrors…
Read More

[C#] 파일 관리 Application

CSharp
회사에서 급하게 진행된 Application 입니다. Web서비스중에서 첨부파일에 대해서만 Application에서 관리를 하기 위해서 만들어진것입니다. web의 기능과 동일하게 작동을 해야 하는 부분에서 DB 분석을 해서 Web과 동일하게 작동을 하도록 만든점이 상당한 노력을 기울였습니다. 그외 부분은 파일 전송과 파일감시 기능은 Application의 고유 기능이라서 그다지 힘들었다기보다는 새로운 기술을 익히는 과정이라서 즐겁기까지 하였습니다. 해당 Application은 웹에 올린 파일을 Local에 다운받고 해당 파일의 변경 여부를 하여서 다시 Web Server에 올려주는 과정을 합니다. Up,Down 과정에서는 Web의 제약사항인 파일 사이즈의 문제를 해결 하기 위해서 SFTP 기능을 이용해서 파일을 Up,Down하도록 해서 대용량 파일이라도 Server에 올라가도록 하는 기능을 구현을 하였습니다. 또한, 압축된 파일을 자동적으로 압축해제 하고 파일을 볼 수 있도록 하면 그 파일중 1개라도 변경이되면은 다시 압축을 하는 과정도 거치게 되어 있어서 조금 복잡하게 변한 부분도 없지 않아 있지만, 사용자분들이 일단은 괜찮다는 평이 좋았습니다.
Read More

MySQL 엑셀로 산출물 만들기

CSharp, Database
문서를 작성해야 하는 일이 항상 있습니다. 그중에서 가장 귀찮은 일이 MySQL의 DB의 형식이나 현재 어떤 스키마를 가지고 있는지를 문서를 만드는 일이 정말 귀찮습니다. 물론 처음 문서를 작성하고 나서 큰 변화가 없다면은 다행이지만 항상 똑같은 상태라고 할 수가 없다 보니 매번 문서를 만들어야 하는 일이 정말 귀찮기만 할뿐입니다. 그렇다고 매번 Database에 들어가서 명령어를 실행하고 만드는것도 일입니다. 고정된 형태면 좋지만 다른 사람에게 공유하기 위해서로 문서로 만들어야 하는 일이 발생을 하게 되면은 또 다시 세팅하고 실행하고 결과값을 저장하는 일이 반복되는 일을 줄이는것이 가장 큰 목표였습니다. C#으로 만들다보니 엑셀 파일 만드는것이 가장 큰 일이였습니다. 내가 설치된 컴퓨터의 환경에 맞추면은 가장 좋지만은 프로그램이라 함은 어느정도 범용성을 가져야 하기에 엑셀로 출력하는 방식에서 많은 고민을 하였습니다. 물론 그전에 MySQL에서 정보를 빼 내는 로직 자체는 이미 완성되어 있어서 그래도 실행을 하면 되지만 마무리가 되지 않아서 한참을 헤메이다가 우연한…
Read More

PHP 503에러 의도적으로 내기

PHP
<?php header('HTTP/1.1 503 Service Temporarily Unavailable'); header('Status: 503 Service Temporarily Unavailable'); header('Retry-After: 300');//300 seconds ?> PHP를 하면서 상태코드를 돌려줘야 할때가 있습니다. 그럴경우 파일은 있지만 접근권한을 제한하기 위한 코드가 필요해서 간단히 작성해 본것입니다. 503 코드로 돌려주기 때문에 서버의 기능이 잘못되었다고 판단을 하도록 하지만, 실제 이 파일은 그냥 모든것을 503으로 해서 접근을 하지 않았으면 해서 만든것입니다. 정상적인 코드로 사용하는것이 아니라서 잘못된것이지만, 무작위로 파일을 접속하는 봇에게 착각을 불러 일으켜서 이 파일은 정상적인 기능을 하지만 지금은 에러가 있다고 판단하게 해서 그냥 한곳으로 모을려고 만든 파일입니다. 그래서 아마 다른 형식으로 가져도 되지만, 이 코드를 사용하게 된것에 대해서 정확한 용도는 아니라는 점을 알려드립니다.
Read More