- Add tbExceptfile textbox for excluding files from processing - Implement settings persistence with config.ini file - Add FTP upload functionality with complete connection parameters - Enhance file filtering logic with exception handling - Improve UI layout with organized form design - Add password masking for FTP credentials - Include comprehensive error handling and user feedback 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
473 lines
17 KiB
C#
473 lines
17 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data;
|
|
using System.Drawing;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
using System.IO;
|
|
using System.Text.RegularExpressions;
|
|
using System.Net;
|
|
|
|
namespace UpdateInfoMaker
|
|
{
|
|
public partial class Form1 : Form
|
|
{
|
|
private string currentIniPath = "";
|
|
private Dictionary<string, Dictionary<string, string>> iniData = new Dictionary<string, Dictionary<string, string>>();
|
|
private List<string> fileList = new List<string>();
|
|
private string configFilePath = Path.Combine(Application.StartupPath, "config.ini");
|
|
|
|
public Form1()
|
|
{
|
|
InitializeComponent();
|
|
LoadSettings();
|
|
}
|
|
|
|
private void btRead_Click(object sender, EventArgs e)
|
|
{
|
|
using (var od = new OpenFileDialog())
|
|
{
|
|
od.Filter = "inf file|*.inf|All files|*.*";
|
|
if (od.ShowDialog() == DialogResult.OK)
|
|
{
|
|
//ini 파일을 읽어서 텍스트박스에 표시
|
|
currentIniPath = od.FileName;
|
|
ReadIniFile(currentIniPath);
|
|
UpdateUIFromIniData();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void btWrite_Click(object sender, EventArgs e)
|
|
{
|
|
using (var od = new SaveFileDialog())
|
|
{
|
|
od.Filter = "inf file|*.inf|All files|*.*";
|
|
if (od.ShowDialog() == DialogResult.OK)
|
|
{
|
|
//ini 파일을 다시 생성한다
|
|
UpdateIniDataFromUI();
|
|
WriteIniFile(od.FileName);
|
|
MessageBox.Show("INI 파일이 성공적으로 저장되었습니다.", "저장 완료", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void btUpdateFilelist_Click(object sender, EventArgs e)
|
|
{
|
|
//read에서 읽은 파일으 폴더내에서 exe,dll,xml,config 파일목록을 읽어서 목록을 구성한다
|
|
if (string.IsNullOrEmpty(currentIniPath))
|
|
{
|
|
MessageBox.Show("먼저 INF 파일을 읽어주세요.", "알림", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
|
return;
|
|
}
|
|
|
|
string folderPath = Path.GetDirectoryName(currentIniPath);
|
|
UpdateFileList(folderPath);
|
|
UpdateFileListView();
|
|
SaveSettings();
|
|
}
|
|
|
|
private void ReadIniFile(string filePath)
|
|
{
|
|
iniData.Clear();
|
|
fileList.Clear();
|
|
|
|
if (!File.Exists(filePath))
|
|
return;
|
|
|
|
string[] lines = File.ReadAllLines(filePath, Encoding.Default);
|
|
string currentSection = "";
|
|
|
|
foreach (string line in lines)
|
|
{
|
|
string trimmedLine = line.Trim();
|
|
|
|
if (string.IsNullOrEmpty(trimmedLine) || trimmedLine.StartsWith(";"))
|
|
continue;
|
|
|
|
if (trimmedLine.StartsWith("[") && trimmedLine.EndsWith("]"))
|
|
{
|
|
currentSection = trimmedLine.Substring(1, trimmedLine.Length - 2);
|
|
if (!iniData.ContainsKey(currentSection))
|
|
iniData[currentSection] = new Dictionary<string, string>();
|
|
}
|
|
else if (!string.IsNullOrEmpty(currentSection) && trimmedLine.Contains("="))
|
|
{
|
|
int equalIndex = trimmedLine.IndexOf('=');
|
|
string key = trimmedLine.Substring(0, equalIndex).Trim();
|
|
string value = trimmedLine.Substring(equalIndex + 1).Trim();
|
|
|
|
if (currentSection == "files" && key == "Files")
|
|
{
|
|
iniData[currentSection][key] = value;
|
|
}
|
|
else if (currentSection == "files" && !key.StartsWith("\\"))
|
|
{
|
|
// 파일 목록 항목
|
|
fileList.Add(trimmedLine);
|
|
}
|
|
else
|
|
{
|
|
iniData[currentSection][key] = value;
|
|
}
|
|
}
|
|
else if (currentSection == "files" && trimmedLine.StartsWith("\\"))
|
|
{
|
|
fileList.Add(trimmedLine);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void WriteIniFile(string filePath)
|
|
{
|
|
var lines = new List<string>();
|
|
|
|
// Version 섹션
|
|
if (iniData.ContainsKey("Version"))
|
|
{
|
|
lines.Add("[Version]");
|
|
foreach (var kvp in iniData["Version"])
|
|
{
|
|
lines.Add($"{kvp.Key}={kvp.Value}");
|
|
}
|
|
lines.Add("");
|
|
}
|
|
|
|
// program_info 섹션
|
|
if (iniData.ContainsKey("program_info"))
|
|
{
|
|
lines.Add("[program_info]");
|
|
foreach (var kvp in iniData["program_info"])
|
|
{
|
|
lines.Add($"{kvp.Key}={kvp.Value}");
|
|
}
|
|
lines.Add("");
|
|
}
|
|
|
|
// files 섹션
|
|
if (iniData.ContainsKey("files"))
|
|
{
|
|
lines.Add("[files]");
|
|
if (iniData["files"].ContainsKey("Files"))
|
|
{
|
|
lines.Add($"Files={fileList.Count}");
|
|
}
|
|
|
|
foreach (string file in fileList)
|
|
{
|
|
lines.Add(file);
|
|
}
|
|
lines.Add("[NoteEndLine]");
|
|
}
|
|
|
|
File.WriteAllLines(filePath, lines, Encoding.Default);
|
|
}
|
|
|
|
private void UpdateUIFromIniData()
|
|
{
|
|
if (iniData.ContainsKey("Version"))
|
|
{
|
|
if (iniData["Version"].ContainsKey("count"))
|
|
tbCount.Text = iniData["Version"]["count"];
|
|
if (iniData["Version"].ContainsKey("date"))
|
|
tbDate.Text = iniData["Version"]["date"];
|
|
}
|
|
|
|
if (iniData.ContainsKey("program_info"))
|
|
{
|
|
if (iniData["program_info"].ContainsKey("server_url"))
|
|
tbServerURL.Text = iniData["program_info"]["server_url"];
|
|
if (iniData["program_info"].ContainsKey("exe"))
|
|
tbExeFileName.Text = iniData["program_info"]["exe"];
|
|
}
|
|
|
|
UpdateFileListView();
|
|
}
|
|
|
|
private void UpdateIniDataFromUI()
|
|
{
|
|
// Version 섹션 업데이트
|
|
if (!iniData.ContainsKey("Version"))
|
|
iniData["Version"] = new Dictionary<string, string>();
|
|
|
|
iniData["Version"]["count"] = tbCount.Text;
|
|
iniData["Version"]["date"] = tbDate.Text;
|
|
|
|
// program_info 섹션 업데이트
|
|
if (!iniData.ContainsKey("program_info"))
|
|
iniData["program_info"] = new Dictionary<string, string>();
|
|
|
|
iniData["program_info"]["server_url"] = tbServerURL.Text;
|
|
iniData["program_info"]["exe"] = tbExeFileName.Text;
|
|
|
|
// files 섹션 업데이트
|
|
if (!iniData.ContainsKey("files"))
|
|
iniData["files"] = new Dictionary<string, string>();
|
|
|
|
iniData["files"]["Files"] = fileList.Count.ToString();
|
|
}
|
|
|
|
private void UpdateFileList(string folderPath)
|
|
{
|
|
fileList.Clear();
|
|
|
|
if (!Directory.Exists(folderPath))
|
|
return;
|
|
|
|
string[] extensions = { "*.inf","*.exe", "*.dll", "*.xml", "*.config" };
|
|
|
|
// 제외할 파일 목록 가져오기
|
|
HashSet<string> exceptFiles = GetExceptFiles();
|
|
|
|
foreach (string extension in extensions)
|
|
{
|
|
string[] files = Directory.GetFiles(folderPath, extension, SearchOption.TopDirectoryOnly);
|
|
foreach (string file in files)
|
|
{
|
|
string fileName = Path.GetFileName(file);
|
|
|
|
// 제외 파일 목록에 없는 경우에만 추가
|
|
if (!exceptFiles.Contains(fileName))
|
|
{
|
|
fileList.Add($"\\{fileName}");
|
|
}
|
|
}
|
|
}
|
|
|
|
// 파일 개수 업데이트
|
|
if (!iniData.ContainsKey("files"))
|
|
iniData["files"] = new Dictionary<string, string>();
|
|
iniData["files"]["Files"] = fileList.Count.ToString();
|
|
}
|
|
|
|
private void UpdateFileListView()
|
|
{
|
|
listView1.Items.Clear();
|
|
|
|
foreach (string file in fileList)
|
|
{
|
|
string fileName = file.TrimStart('\\');
|
|
string filePath = Path.Combine(Path.GetDirectoryName(currentIniPath), fileName);
|
|
|
|
var item = new ListViewItem(fileName);
|
|
|
|
if (File.Exists(filePath))
|
|
{
|
|
FileInfo fileInfo = new FileInfo(filePath);
|
|
item.SubItems.Add(FormatFileSize(fileInfo.Length));
|
|
}
|
|
else
|
|
{
|
|
item.SubItems.Add("X");
|
|
}
|
|
|
|
listView1.Items.Add(item);
|
|
}
|
|
}
|
|
|
|
private string FormatFileSize(long bytes)
|
|
{
|
|
string[] sizes = { "B", "KB", "MB", "GB" };
|
|
double len = bytes;
|
|
int order = 0;
|
|
|
|
while (len >= 1024 && order < sizes.Length - 1)
|
|
{
|
|
order++;
|
|
len = len / 1024;
|
|
}
|
|
|
|
return $"{len:0.##} {sizes[order]}";
|
|
}
|
|
|
|
private HashSet<string> GetExceptFiles()
|
|
{
|
|
var exceptFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
|
|
|
if (!string.IsNullOrWhiteSpace(tbExceptfile.Text))
|
|
{
|
|
string[] files = tbExceptfile.Text.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
|
|
foreach (string file in files)
|
|
{
|
|
exceptFiles.Add(file.Trim());
|
|
}
|
|
}
|
|
|
|
return exceptFiles;
|
|
}
|
|
|
|
private void LoadSettings()
|
|
{
|
|
try
|
|
{
|
|
if (File.Exists(configFilePath))
|
|
{
|
|
string[] lines = File.ReadAllLines(configFilePath, Encoding.Default);
|
|
foreach (string line in lines)
|
|
{
|
|
if (line.StartsWith("exceptfiles="))
|
|
{
|
|
tbExceptfile.Text = line.Substring("exceptfiles=".Length);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// 기본값 설정
|
|
tbExceptfile.Text = "Factory_Client.exe";
|
|
SaveSettings();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show($"설정 파일 로드 중 오류가 발생했습니다: {ex.Message}", "오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
tbExceptfile.Text = "Factory_Client.exe";
|
|
}
|
|
}
|
|
|
|
private void SaveSettings()
|
|
{
|
|
try
|
|
{
|
|
string[] lines = { $"exceptfiles={tbExceptfile.Text}" };
|
|
File.WriteAllLines(configFilePath, lines, Encoding.Default);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show($"설정 파일 저장 중 오류가 발생했습니다: {ex.Message}", "오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
}
|
|
}
|
|
|
|
private void tbUploadFile_Click(object sender, EventArgs e)
|
|
{
|
|
//파일목록의 파일을 지정된 FTP정보를 가지고 업로드해야함
|
|
UploadFilesToFTP();
|
|
}
|
|
|
|
private void UploadFilesToFTP()
|
|
{
|
|
// FTP 정보 유효성 검사
|
|
if (string.IsNullOrWhiteSpace(tbFTPServer.Text) ||
|
|
string.IsNullOrWhiteSpace(tbFTPId.Text) ||
|
|
string.IsNullOrWhiteSpace(tbFTPPW.Text))
|
|
{
|
|
MessageBox.Show("FTP 서버, 아이디, 패스워드를 모두 입력해주세요.", "알림", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
|
return;
|
|
}
|
|
|
|
if (fileList.Count == 0)
|
|
{
|
|
MessageBox.Show("업로드할 파일이 없습니다. 먼저 파일 목록을 업데이트해주세요.", "알림", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
|
return;
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(currentIniPath))
|
|
{
|
|
MessageBox.Show("먼저 INF 파일을 읽어주세요.", "알림", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
string sourceFolder = Path.GetDirectoryName(currentIniPath);
|
|
string ftpServer = tbFTPServer.Text.Trim();
|
|
string ftpUser = tbFTPId.Text.Trim();
|
|
string ftpPassword = tbFTPPW.Text.Trim();
|
|
string ftpPath = tbFTPPath.Text.Trim();
|
|
int ftpPort = 21;
|
|
|
|
if (!int.TryParse(tbFTPPort.Text, out ftpPort))
|
|
{
|
|
ftpPort = 21;
|
|
}
|
|
|
|
int successCount = 0;
|
|
int failCount = 0;
|
|
var failedFiles = new List<string>();
|
|
|
|
foreach (string file in fileList)
|
|
{
|
|
string fileName = file.TrimStart('\\');
|
|
string localFilePath = Path.Combine(sourceFolder, fileName);
|
|
|
|
if (!File.Exists(localFilePath))
|
|
{
|
|
failedFiles.Add($"{fileName} (파일 없음)");
|
|
failCount++;
|
|
continue;
|
|
}
|
|
|
|
try
|
|
{
|
|
// FTP URI 생성
|
|
string ftpUri;
|
|
if (ftpPath.EndsWith("/"))
|
|
ftpUri = $"ftp://{ftpServer}:{ftpPort}{ftpPath}{fileName}";
|
|
else
|
|
ftpUri = $"ftp://{ftpServer}:{ftpPort}{ftpPath}/{fileName}";
|
|
|
|
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftpUri);
|
|
request.Method = WebRequestMethods.Ftp.UploadFile;
|
|
request.Credentials = new NetworkCredential(ftpUser, ftpPassword);
|
|
request.UsePassive = chkFTPPassive.Checked;
|
|
request.UseBinary = true;
|
|
request.KeepAlive = false;
|
|
|
|
// 파일 업로드
|
|
using (FileStream fileStream = new FileStream(localFilePath, FileMode.Open, FileAccess.Read))
|
|
using (Stream ftpStream = request.GetRequestStream())
|
|
{
|
|
byte[] buffer = new byte[10240];
|
|
int read;
|
|
while ((read = fileStream.Read(buffer, 0, buffer.Length)) > 0)
|
|
{
|
|
ftpStream.Write(buffer, 0, read);
|
|
}
|
|
}
|
|
|
|
// 응답 확인
|
|
using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
|
|
{
|
|
if (response.StatusCode == FtpStatusCode.ClosingData ||
|
|
response.StatusCode == FtpStatusCode.FileActionOK)
|
|
{
|
|
successCount++;
|
|
}
|
|
else
|
|
{
|
|
failedFiles.Add($"{fileName} (상태: {response.StatusDescription})");
|
|
failCount++;
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
failedFiles.Add($"{fileName} ({ex.Message})");
|
|
failCount++;
|
|
}
|
|
}
|
|
|
|
// 결과 메시지 표시
|
|
string resultMessage = $"업로드 완료\n\n성공: {successCount}개\n실패: {failCount}개";
|
|
|
|
if (failedFiles.Count > 0)
|
|
{
|
|
resultMessage += "\n\n실패한 파일들:\n" + string.Join("\n", failedFiles);
|
|
}
|
|
|
|
MessageBox.Show(resultMessage, "FTP 업로드 결과", MessageBoxButtons.OK,
|
|
failCount > 0 ? MessageBoxIcon.Warning : MessageBoxIcon.Information);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show($"FTP 업로드 중 오류가 발생했습니다: {ex.Message}", "오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
}
|
|
}
|
|
}
|
|
}
|