619 lines
29 KiB
PowerShell
619 lines
29 KiB
PowerShell
# ================================================================================
|
|
# 파일: Scripts/UI-Tab-BatchTask.ps1
|
|
# 역할: '일괄 작업 (CSV)' 탭 UI 및 기능 구현 (리팩토링 최종 완전판)
|
|
#
|
|
# 작성자: 양범진
|
|
# 버전: 1.13
|
|
# 생성일자: 2025-06-05
|
|
# 최종 수정일자: 2025-06-12
|
|
#
|
|
# 설명:
|
|
# - 가독성 향상을 위해 코드 포매팅, 주석 추가, 불필요한 콘솔 출력 제거.
|
|
# - 누락된 함수 정의를 복원하여 스크립트 실행 오류 최종 해결.
|
|
# - 모든 기능이 포함된 최종 안정화 버전.
|
|
# ================================================================================
|
|
|
|
#region '일괄 작업' 탭 UI 초기화 및 이벤트 핸들러
|
|
|
|
# --------------------------------------------------------------------------------
|
|
# 헬퍼 함수 정의
|
|
# --------------------------------------------------------------------------------
|
|
|
|
# 선택된 작업 유형에 따라 안내 메시지를 업데이트하는 함수
|
|
function Update-BatchGuide {
|
|
param($taskType)
|
|
|
|
# 작업 유형에 따라 다른 안내 텍스트를 설정
|
|
$guideText = switch ($taskType) {
|
|
"계정 생성" {
|
|
@"
|
|
** CSV로 계정 생성하기 **
|
|
|
|
'템플릿 다운로드'로 받은 CSV 파일을 아래 형식에 맞게 작성하세요.
|
|
|
|
- **LastNameKr**: 사용자의 한글 성 (예: 홍)
|
|
- **FirstNameKr**: 사용자의 한글 이름 (예: 길동)
|
|
- **AccountNameEn**: 로그인 ID (SamAccountName). 아래 규칙을 따라야 합니다.
|
|
- 소문자 영문과 숫자만 사용 가능
|
|
- 3자 이상, 20자 이하
|
|
- **Password**: 사용자의 초기 비밀번호.
|
|
- **OU_Name**: 사용자가 생성될 조직 단위(OU)의 경로.
|
|
- 최상위 OU: `Dev`
|
|
- 하위 OU: `상위OU/하위OU` (예: `Dev/Test001`)
|
|
"@
|
|
}
|
|
"계정 삭제" {
|
|
@"
|
|
** CSV로 계정 삭제하기 **
|
|
|
|
'템플릿 다운로드'로 받은 CSV 파일을 아래 형식에 맞게 작성하세요.
|
|
|
|
- **SamAccountName**: 삭제할 사용자의 로그인 ID.
|
|
"@
|
|
}
|
|
}
|
|
# 안내 레이블의 텍스트를 업데이트
|
|
$script:batch_labelGuide.Text = $guideText.Trim()
|
|
}
|
|
|
|
# 'Dev/Test'와 같은 OU 경로를 'OU=Test,OU=Dev,DC=...' 형식의 DN(Distinguished Name)으로 변환하는 함수
|
|
function Convert-OUPathToDN {
|
|
param([string]$OUPath)
|
|
if (-not $OUPath) {
|
|
return $null
|
|
}
|
|
# '/'를 기준으로 경로를 분리하고, 빈 항목은 제거
|
|
$ouParts = $OUPath.Split('/') | Where-Object { -not [string]::IsNullOrWhiteSpace($_) }
|
|
# AD DN 형식에 맞게 순서를 뒤집음 (하위 OU가 먼저 오도록)
|
|
[array]::Reverse($ouParts)
|
|
# 각 부분을 'OU=이름' 형식으로 변환
|
|
$ouDNs = $ouParts | ForEach-Object { "OU=$_" }
|
|
# 쉼표로 연결하고 기본 도메인 DN을 추가하여 최종 DN 완성
|
|
return ($ouDNs -join ",") + ",$($script:CurrentADDomainDN)"
|
|
}
|
|
|
|
# --------------------------------------------------------------------------------
|
|
# 이벤트 핸들러 정의 (스크립트 블록)
|
|
# --------------------------------------------------------------------------------
|
|
|
|
# '작업 유형' 콤보박스 선택이 변경될 때 호출
|
|
$batch_TaskType_Changed = {
|
|
# UI 컨트롤 상태 초기화
|
|
$script:batch_dataGridView.DataSource = $null
|
|
$script:batch_textBoxCsvPath.Text = ""
|
|
$script:batch_buttonValidate.Enabled = $false
|
|
$script:batch_buttonExecute.Enabled = $false
|
|
$script:batch_progressBar.Value = 0
|
|
$script:batch_dataGridView.Visible = $false
|
|
$script:batch_labelGuide.Visible = $true
|
|
|
|
# 새 작업 유형에 맞는 안내 가이드 표시
|
|
Update-BatchGuide -taskType $script:batch_comboBoxTaskType.SelectedItem.ToString()
|
|
}
|
|
|
|
# '템플릿 다운로드' 버튼 클릭 시 호출
|
|
$batch_buttonDownloadTemplate_Click = {
|
|
$taskType = $script:batch_comboBoxTaskType.SelectedItem.ToString()
|
|
$headers = ""
|
|
$sampleData = ""
|
|
|
|
# 작업 유형에 따라 CSV 헤더와 샘플 데이터 설정
|
|
switch ($taskType) {
|
|
"계정 생성" {
|
|
$headers = "LastNameKr,FirstNameKr,AccountNameEn,Password,OU_Name"
|
|
$sampleData = "김,가네,mrkim,Password123!,Dev/Test001"
|
|
}
|
|
"계정 삭제" {
|
|
$headers = "SamAccountName"
|
|
$sampleData = "testuser"
|
|
}
|
|
default {
|
|
return # 지원하지 않는 작업 유형이면 종료
|
|
}
|
|
}
|
|
|
|
# 파일 저장 대화상자 생성
|
|
$sfd = New-Object System.Windows.Forms.SaveFileDialog
|
|
$sfd.Filter = "CSV 파일 (*.csv)|*.csv"
|
|
$sfd.FileName = "$($taskType)_template.csv"
|
|
|
|
if ($sfd.ShowDialog() -eq "OK") {
|
|
try {
|
|
# 헤더와 샘플 데이터를 포함한 CSV 콘텐츠 생성
|
|
$csvContent = @($headers, $sampleData)
|
|
# UTF8 인코딩으로 파일 저장
|
|
Set-Content -Path $sfd.FileName -Value $csvContent -Encoding UTF8
|
|
[System.Windows.Forms.MessageBox]::Show("샘플 데이터가 포함된 템플릿 파일이 저장되었습니다.`n$($sfd.FileName)", "저장 완료", "OK", "Information")
|
|
}
|
|
catch {
|
|
# 파일 저장 중 오류 발생 시 상세 오류 대화상자 표시
|
|
Show-DetailedErrorDialog -ErrorRecord $_
|
|
}
|
|
}
|
|
}
|
|
|
|
# '파일 찾아보기' 버튼 클릭 시 호출
|
|
$batch_buttonBrowseCsv_Click = {
|
|
# 파일 열기 대화상자 생성
|
|
$ofd = New-Object System.Windows.Forms.OpenFileDialog
|
|
$ofd.Filter = "CSV 파일 (*.csv)|*.csv"
|
|
|
|
if ($ofd.ShowDialog() -eq "OK") {
|
|
try {
|
|
# CSV 파일의 첫 줄(헤더)을 읽어옴
|
|
$headersInFile = (Get-Content -Path $ofd.FileName -TotalCount 1).Split(',') | ForEach-Object { $_.Trim('"') }
|
|
$taskType = $script:batch_comboBoxTaskType.SelectedItem.ToString()
|
|
|
|
# 현재 선택된 작업에 필요한 헤더 정의
|
|
$requiredHeaders = if ($taskType -eq "계정 생성") { @("LastNameKr", "FirstNameKr", "AccountNameEn", "Password", "OU_Name") } else { @("SamAccountName") }
|
|
|
|
# 파일의 헤더와 필요한 헤더가 일치하는지 비교
|
|
if (($headersInFile | Compare-Object -ReferenceObject $requiredHeaders -SyncWindow 0).Length -ne 0) {
|
|
[System.Windows.Forms.MessageBox]::Show("CSV 파일의 헤더가 선택된 작업 유형과 일치하지 않습니다.`n템플릿을 다운로드하여 형식을 확인해주세요.", "CSV 형식 오류", "OK", "Warning")
|
|
return
|
|
}
|
|
|
|
# 파일 경로 텍스트박스 업데이트 및 CSV 파일 가져오기
|
|
$script:batch_textBoxCsvPath.Text = $ofd.FileName
|
|
$csvData = Import-Csv -Path $ofd.FileName -Encoding UTF8
|
|
|
|
if ($csvData.Count -eq 0) {
|
|
[System.Windows.Forms.MessageBox]::Show("CSV 파일에 데이터가 없습니다.", "알림", "OK", "Information")
|
|
return
|
|
}
|
|
|
|
# CSV 데이터를 표시할 DataTable 객체 생성
|
|
$dt = New-Object System.Data.DataTable
|
|
$csvData[0].PSObject.Properties.Name | ForEach-Object { $dt.Columns.Add($_) } | Out-Null
|
|
$dt.Columns.Add("결과") | Out-Null # 결과 표시를 위한 열 추가
|
|
|
|
# CSV의 각 행을 DataTable에 추가
|
|
foreach ($row in $csvData) {
|
|
$dr = $dt.NewRow()
|
|
foreach ($prop in $row.PSObject.Properties) {
|
|
$dr[$prop.Name] = $prop.Value
|
|
}
|
|
$dt.Rows.Add($dr)
|
|
}
|
|
|
|
# 데이터 그리드뷰에 DataTable 바인딩 및 UI 상태 업데이트
|
|
$script:batch_dataGridView.DataSource = $dt
|
|
$script:batch_dataGridView.Columns["결과"].ReadOnly = $true
|
|
$script:batch_dataGridView.Columns["결과"].DefaultCellStyle.BackColor = [System.Drawing.Color]::Gainsboro
|
|
|
|
Write-Log "$($csvData.Count)개의 항목을 CSV 파일에서 로드했습니다."
|
|
$script:batch_buttonValidate.Enabled = $true
|
|
$script:batch_buttonExecute.Enabled = $false
|
|
$script:batch_progressBar.Value = 0
|
|
$script:batch_dataGridView.Visible = $true
|
|
$script:batch_labelGuide.Visible = $false
|
|
}
|
|
catch {
|
|
# 파일 읽기 실패 등 예외 발생 시 상세 오류 대화상자 표시
|
|
Show-DetailedErrorDialog -ErrorRecord $_
|
|
$script:batch_buttonValidate.Enabled = $false
|
|
}
|
|
}
|
|
}
|
|
|
|
# 데이터 그리드뷰의 셀 값이 변경될 때 호출
|
|
$batch_dataGridView_CellValueChanged = {
|
|
param($src, $e)
|
|
$rowIndex = $e.RowIndex
|
|
$colIndex = $e.ColumnIndex
|
|
|
|
if ($rowIndex -ge 0 -and $colIndex -ge 0) {
|
|
$dataGridView = $src
|
|
# '결과' 열은 시스템이 업데이트하므로 사용자의 수정에 반응하지 않음
|
|
if ($dataGridView.Columns[$colIndex].Name -eq "결과") {
|
|
return
|
|
}
|
|
|
|
# 사용자가 데이터를 수정했음을 시각적으로 표시
|
|
$row = $dataGridView.Rows[$rowIndex]
|
|
$resultCell = $row.Cells["결과"]
|
|
if ($resultCell.Value -notlike "수정됨*") {
|
|
$resultCell.Value = "수정됨 (검사 필요)"
|
|
$row.DefaultCellStyle.BackColor = [System.Drawing.Color]::LightYellow
|
|
$script:batch_buttonExecute.Enabled = $false # 수정 후에는 다시 유효성 검사가 필요함
|
|
}
|
|
}
|
|
}
|
|
|
|
# 데이터 그리드뷰에 새 행을 추가할 때 호출 (컨텍스트 메뉴)
|
|
$batch_buttonAddRow_Click = {
|
|
param($src, $e)
|
|
$dataTable = $script:batch_dataGridView.DataSource
|
|
|
|
# 그리드에 데이터가 아직 없는 경우, DataTable을 새로 생성
|
|
if ($null -eq $dataTable) {
|
|
$taskType = $script:batch_comboBoxTaskType.SelectedItem.ToString()
|
|
$headers = if ($taskType -eq "계정 생성") { @("LastNameKr", "FirstNameKr", "AccountNameEn", "Password", "OU_Name") } else { @("SamAccountName") }
|
|
|
|
$dataTable = New-Object System.Data.DataTable
|
|
$headers | ForEach-Object { $dataTable.Columns.Add($_) } | Out-Null
|
|
$dataTable.Columns.Add("결과") | Out-Null
|
|
|
|
$script:batch_dataGridView.DataSource = $dataTable
|
|
$script:batch_dataGridView.Columns["결과"].ReadOnly = $true
|
|
$script:batch_dataGridView.Columns["결과"].DefaultCellStyle.BackColor = [System.Drawing.Color]::Gainsboro
|
|
$script:batch_dataGridView.Visible = $true
|
|
$script:batch_labelGuide.Visible = $false
|
|
$script:batch_buttonValidate.Enabled = $true
|
|
}
|
|
|
|
# 새 행을 추가하고 초기 상태 설정
|
|
$newRow = $dataTable.NewRow()
|
|
$newRow["결과"] = "신규 (검사 필요)"
|
|
$dataTable.Rows.Add($newRow)
|
|
|
|
# 새로 추가된 행으로 스크롤 이동
|
|
$script:batch_dataGridView.FirstDisplayedScrollingRowIndex = $script:batch_dataGridView.Rows.Count - 1
|
|
}
|
|
|
|
# 데이터 그리드뷰에서 선택된 행을 삭제할 때 호출 (컨텍스트 메뉴)
|
|
$batch_buttonDeleteRow_Click = {
|
|
param($src, $e)
|
|
$selectedRows = $script:batch_dataGridView.SelectedRows
|
|
if ($selectedRows.Count -eq 0) {
|
|
return
|
|
}
|
|
# 여러 행 삭제 시 인덱스 문제를 피하기 위해 역순으로 정렬 후 삭제
|
|
foreach ($row in $selectedRows | Sort-Object Index -Descending) {
|
|
if (-not $row.IsNewRow) {
|
|
$script:batch_dataGridView.Rows.Remove($row)
|
|
}
|
|
}
|
|
}
|
|
|
|
# '유효성 검사' 버튼 클릭 시 호출
|
|
$batch_buttonValidate_Click = {
|
|
$dataTable = $script:batch_dataGridView.DataSource
|
|
if ($null -eq $dataTable -or $dataTable.Rows.Count -eq 0) {
|
|
return
|
|
}
|
|
|
|
$taskType = $script:batch_comboBoxTaskType.SelectedItem.ToString()
|
|
$script:batch_buttonExecute.Enabled = $false
|
|
|
|
# 동기식으로 유효성 검사 스크립트 블록을 실행하고, 오류가 발생한 행의 수를 반환받음
|
|
$invalidRowsCount = Invoke-Synchronous -TriggerControl $this -StatusMessage "사전 유효성 검사를 수행합니다..." -RequiresAzureAD -ScriptBlock {
|
|
$invalidCount = 0
|
|
$totalCount = $dataTable.Rows.Count
|
|
$processedCount = 0
|
|
|
|
foreach ($dataRow in $dataTable.Rows) {
|
|
$processedCount++
|
|
$script:batch_progressBar.Value = ($processedCount / $totalCount) * 100
|
|
|
|
try {
|
|
if ($taskType -eq "계정 생성") {
|
|
# 필수 값, OU 경로, 계정명 중복 여부 등 검사
|
|
if (-not ($dataRow.LastNameKr -and $dataRow.FirstNameKr -and $dataRow.AccountNameEn -and $dataRow.OU_Name -and $dataRow.Password)) { throw "필수 열이 비어있습니다." }
|
|
$ouDN = Convert-OUPathToDN -OUPath $dataRow.OU_Name
|
|
if (-not (Get-ADOrganizationalUnit -Identity $ouDN -Server $script:Configuration.OnPremDomainController -ErrorAction SilentlyContinue)) { throw "OU 경로 '$($dataRow.OU_Name)'를 찾을 수 없습니다." }
|
|
$validationResult = Test-SamAccountName -AccountName $dataRow.AccountNameEn -CheckAzureAD
|
|
if (-not $validationResult.IsValid) { throw $validationResult.Reason }
|
|
}
|
|
elseif ($taskType -eq "계정 삭제") {
|
|
# 필수 값, 계정 존재 여부 검사
|
|
if (-not $dataRow.SamAccountName) { throw "필수 열(SamAccountName)이 비어있습니다." }
|
|
if (-not (Get-ADUser -Filter "SamAccountName -eq '$($dataRow.SamAccountName)'" -Server $script:Configuration.OnPremDomainController)) { throw "존재하지 않는 계정입니다." }
|
|
}
|
|
# 유효성 검사 통과 시 결과 업데이트
|
|
$dataRow["결과"] = "✅ 유효"
|
|
}
|
|
catch {
|
|
# 오류 발생 시 결과에 오류 메시지 기록
|
|
$errorMessage = $_.Exception.Message.Trim()
|
|
$dataRow["결과"] = "❌ 오류: $errorMessage"
|
|
$invalidCount++
|
|
}
|
|
}
|
|
# 스크립트 블록의 결과로 오류 개수 반환
|
|
return $invalidCount
|
|
}
|
|
|
|
# 그리드의 각 행을 결과에 따라 색상으로 구분
|
|
foreach ($row in $script:batch_dataGridView.Rows) {
|
|
$resultCell = $row.Cells["결과"]
|
|
if ($resultCell.Value -like "❌*") {
|
|
$row.DefaultCellStyle.BackColor = [System.Drawing.Color]::LightPink
|
|
}
|
|
else {
|
|
$row.DefaultCellStyle.BackColor = [System.Drawing.Color]::White
|
|
}
|
|
}
|
|
|
|
if ($invalidRowsCount -gt 0) {
|
|
$msg = "$($invalidRowsCount)개의 유효하지 않은 항목이 발견되었습니다. 그리드에서 오류 내용을 확인하고 CSV 파일을 수정한 후 다시 시도하세요."
|
|
[System.Windows.Forms.MessageBox]::Show($msg, "유효성 검사 실패", "OK", "Warning")
|
|
}
|
|
elseif ($invalidRowsCount -eq 0) { # 0일 경우에만 성공으로 간주
|
|
$script:batch_buttonExecute.Enabled = $true
|
|
[System.Windows.Forms.MessageBox]::Show("모든 항목이 유효합니다. '일괄 작업 실행' 버튼을 눌러 작업을 시작하세요.", "검사 완료", "OK", "Information")
|
|
}
|
|
}
|
|
|
|
# '일괄 작업 실행' 버튼 클릭 시 호출
|
|
$batch_buttonExecute_Click = {
|
|
$dataTable = $script:batch_dataGridView.DataSource
|
|
if ($null -eq $dataTable -or $dataTable.Rows.Count -eq 0) {
|
|
return
|
|
}
|
|
|
|
# 유효성 검사를 먼저 수행했는지 확인
|
|
if ([string]::IsNullOrWhiteSpace($dataTable.Rows[0]["결과"])) {
|
|
[System.Windows.Forms.MessageBox]::Show("먼저 '유효성 검사'를 실행하여 데이터의 유효성을 확인해야 합니다.", "검사 필요", "OK", "Warning")
|
|
return
|
|
}
|
|
# 오류가 있는 항목이 있는지 확인
|
|
$invalidRows = $dataTable.Select("[결과] LIKE '❌*'")
|
|
if ($invalidRows.Count -gt 0) {
|
|
[System.Windows.Forms.MessageBox]::Show("오류 항목이 존재합니다. 유효성 검사를 다시 수행하거나 CSV 파일을 수정해주세요.", "오류 발견", "OK", "Error")
|
|
return
|
|
}
|
|
# 실행할 유효한 항목이 있는지 확인
|
|
$validRows = $dataTable.Select("[결과] = '✅ 유효'")
|
|
if ($validRows.Count -eq 0) {
|
|
[System.Windows.Forms.MessageBox]::Show("실행할 유효한 항목이 없습니다.", "작업 불가", "OK", "Information")
|
|
return
|
|
}
|
|
|
|
# 최종 실행 확인
|
|
$taskType = $script:batch_comboBoxTaskType.SelectedItem.ToString()
|
|
$confirmMsg = "유효한 $($validRows.Length)개 항목에 대해 '$taskType' 일괄 작업을 시작하시겠습니까?"
|
|
if ([System.Windows.Forms.MessageBox]::Show($confirmMsg, "최종 확인", "YesNo", "Question") -ne "Yes") {
|
|
return
|
|
}
|
|
|
|
# 동기식으로 일괄 작업 실행
|
|
Invoke-Synchronous -TriggerControl $this -StatusMessage "일괄 작업을 실행합니다..." -ScriptBlock {
|
|
$successfulSyncCount = 0
|
|
foreach ($dataRow in $validRows) {
|
|
try {
|
|
if ($taskType -eq "계정 생성") {
|
|
# AD 사용자 생성을 위한 파라미터 설정
|
|
$ouDN = Convert-OUPathToDN -OUPath $dataRow.OU_Name
|
|
$userPrincipalName = "$($dataRow.AccountNameEn)@$($script:Configuration.UPNSuffix)"
|
|
$params = @{
|
|
Name = "$($dataRow.LastNameKr)$($dataRow.FirstNameKr) [$($dataRow.AccountNameEn)]"
|
|
DisplayName = "$($dataRow.LastNameKr)$($dataRow.FirstNameKr) [$($dataRow.AccountNameEn)]"
|
|
SamAccountName = $dataRow.AccountNameEn
|
|
UserPrincipalName = $userPrincipalName
|
|
EmailAddress = $userPrincipalName
|
|
Path = $ouDN
|
|
GivenName = $dataRow.FirstNameKr
|
|
Surname = $dataRow.LastNameKr
|
|
AccountPassword = (ConvertTo-SecureString ($dataRow.Password) -AsPlainText -Force)
|
|
Enabled = $true
|
|
ChangePasswordAtLogon = $false
|
|
Server = $script:Configuration.OnPremDomainController
|
|
}
|
|
New-ADUser @params -ErrorAction Stop
|
|
}
|
|
elseif ($taskType -eq "계정 삭제") {
|
|
Remove-ADUser -Identity $dataRow.SamAccountName.Trim() -Confirm:$false -Server $script:Configuration.OnPremDomainController -ErrorAction Stop
|
|
}
|
|
|
|
# 작업 성공 시 결과 업데이트
|
|
$dataRow["결과"] = "✅ 처리 완료"
|
|
$successfulSyncCount++
|
|
}
|
|
catch {
|
|
# 작업 실패 시 결과에 오류 메시지 기록
|
|
$errorMessage = $_.Exception.Message.Trim()
|
|
$dataRow["결과"] = "❌ 실행 실패: $errorMessage"
|
|
}
|
|
}
|
|
# 성공적으로 처리된 건이 하나라도 있으면 AAD Connect Delta 동기화 실행
|
|
if ($successfulSyncCount -gt 0) {
|
|
Write-Log "$successfulSyncCount 건의 성공적인 작업에 대해 AAD Connect 동기화(Delta)를 시작합니다..."
|
|
Invoke-AadConnectSync -PolicyType Delta
|
|
}
|
|
}
|
|
|
|
# 그리드의 각 행을 최종 결과에 따라 색상으로 구분
|
|
foreach ($row in $script:batch_dataGridView.Rows) {
|
|
if ($row.Cells["결과"].Value -eq "✅ 처리 완료") {
|
|
$row.DefaultCellStyle.BackColor = [System.Drawing.Color]::PaleGreen
|
|
}
|
|
elseif ($row.Cells["결과"].Value -like "❌ 실행 실패*") {
|
|
$row.DefaultCellStyle.BackColor = [System.Drawing.Color]::OrangeRed
|
|
}
|
|
}
|
|
|
|
[System.Windows.Forms.MessageBox]::Show("일괄 작업이 완료되었습니다. 최종 결과는 그리드를 확인하세요.`n새로운 작업을 하시려면 다시 CSV 파일을 로드해주세요.", "작업 완료", "OK", "Information")
|
|
|
|
# 작업 완료 후 UI 상태 초기화
|
|
$script:batch_textBoxCsvPath.Text = ""
|
|
$script:batch_progressBar.Value = 0
|
|
$script:batch_buttonExecute.Enabled = $false
|
|
$script:batch_buttonValidate.Enabled = $false
|
|
}
|
|
|
|
# --------------------------------------------------------------------------------
|
|
# 이벤트 등록 함수
|
|
# --------------------------------------------------------------------------------
|
|
|
|
function Register-BatchTaskEvents {
|
|
# 각 컨트롤에 정의된 이벤트 핸들러(스크립트 블록)를 연결
|
|
$script:batch_comboBoxTaskType.add_SelectedIndexChanged($batch_TaskType_Changed)
|
|
$script:batch_buttonDownloadTemplate.add_Click($batch_buttonDownloadTemplate_Click)
|
|
$script:batch_buttonBrowseCsv.add_Click($batch_buttonBrowseCsv_Click)
|
|
$script:batch_buttonValidate.add_Click($batch_buttonValidate_Click)
|
|
$script:batch_buttonExecute.add_Click($batch_buttonExecute_Click)
|
|
$script:batch_dataGridView.add_CellValueChanged($batch_dataGridView_CellValueChanged)
|
|
|
|
# 데이터 그리드뷰의 우클릭 컨텍스트 메뉴 설정
|
|
$contextMenu = New-Object System.Windows.Forms.ContextMenuStrip
|
|
$menuItemAdd = New-Object System.Windows.Forms.ToolStripMenuItem("새 행 추가")
|
|
$menuItemDelete = New-Object System.Windows.Forms.ToolStripMenuItem("선택 행 삭제")
|
|
|
|
$menuItemAdd.Add_Click($batch_buttonAddRow_Click)
|
|
$menuItemDelete.Add_Click($batch_buttonDeleteRow_Click)
|
|
|
|
$contextMenu.Items.AddRange(@($menuItemAdd, $menuItemDelete)) | Out-Null
|
|
|
|
# 컨텍스트 메뉴가 열릴 때, 행이 선택된 경우에만 '삭제' 메뉴를 활성화
|
|
$contextMenu.Add_Opening({
|
|
param($src, $e)
|
|
$src.Items[1].Enabled = ($script:batch_dataGridView.SelectedRows.Count -gt 0)
|
|
})
|
|
|
|
$script:batch_dataGridView.ContextMenuStrip = $contextMenu
|
|
}
|
|
|
|
# --------------------------------------------------------------------------------
|
|
# 탭 UI 초기화 함수
|
|
# --------------------------------------------------------------------------------
|
|
|
|
function Initialize-BatchTaskTab {
|
|
Param(
|
|
[System.Windows.Forms.TabPage]$parentTab
|
|
)
|
|
|
|
# 메인 레이아웃 (TableLayoutPanel) 설정
|
|
$layout = New-Object System.Windows.Forms.TableLayoutPanel
|
|
$layout.Dock = "Fill"
|
|
$layout.Padding = [System.Windows.Forms.Padding](10)
|
|
$layout.ColumnCount = 4
|
|
$layout.RowCount = 4
|
|
$layout.ColumnStyles.Add((New-Object System.Windows.Forms.ColumnStyle([System.Windows.Forms.SizeType]::Absolute, 100))) | Out-Null
|
|
$layout.ColumnStyles.Add((New-Object System.Windows.Forms.ColumnStyle([System.Windows.Forms.SizeType]::Percent, 100))) | Out-Null
|
|
$layout.ColumnStyles.Add((New-Object System.Windows.Forms.ColumnStyle([System.Windows.Forms.SizeType]::Absolute, 150))) | Out-Null
|
|
$layout.ColumnStyles.Add((New-Object System.Windows.Forms.ColumnStyle([System.Windows.Forms.SizeType]::Absolute, 160))) | Out-Null
|
|
$layout.RowStyles.Add((New-Object System.Windows.Forms.RowStyle([System.Windows.Forms.SizeType]::Absolute, 40))) | Out-Null
|
|
$layout.RowStyles.Add((New-Object System.Windows.Forms.RowStyle([System.Windows.Forms.SizeType]::Absolute, 40))) | Out-Null
|
|
$layout.RowStyles.Add((New-Object System.Windows.Forms.RowStyle([System.Windows.Forms.SizeType]::Percent, 100))) | Out-Null
|
|
$layout.RowStyles.Add((New-Object System.Windows.Forms.RowStyle([System.Windows.Forms.SizeType]::Absolute, 50))) | Out-Null
|
|
$parentTab.Controls.Add($layout) | Out-Null
|
|
|
|
# UI 컨트롤 생성
|
|
# 0행: 작업 유형 선택 영역
|
|
$labelTaskType = New-Object System.Windows.Forms.Label
|
|
$script:batch_comboBoxTaskType = New-Object System.Windows.Forms.ComboBox
|
|
$script:batch_buttonDownloadTemplate = New-Object System.Windows.Forms.Button
|
|
|
|
# 1행: CSV 파일 선택 영역
|
|
$labelCsvPath = New-Object System.Windows.Forms.Label
|
|
$script:batch_textBoxCsvPath = New-Object System.Windows.Forms.TextBox
|
|
$script:batch_buttonBrowseCsv = New-Object System.Windows.Forms.Button
|
|
|
|
# 2행: 데이터 표시 영역 (그리드뷰, 안내문)
|
|
$gridPanel = New-Object System.Windows.Forms.Panel
|
|
$script:batch_dataGridView = New-Object System.Windows.Forms.DataGridView
|
|
$script:batch_labelGuide = New-Object System.Windows.Forms.Label
|
|
|
|
# 3행: 진행률 및 실행 버튼 영역
|
|
$script:batch_progressBar = New-Object System.Windows.Forms.ProgressBar
|
|
$execButtonLayout = New-Object System.Windows.Forms.TableLayoutPanel
|
|
$script:batch_buttonValidate = New-Object System.Windows.Forms.Button
|
|
$script:batch_buttonExecute = New-Object System.Windows.Forms.Button
|
|
|
|
# UI 컨트롤 속성 설정
|
|
# - 작업 유형 레이블
|
|
$labelTaskType.Text = "작업 유형:"
|
|
$labelTaskType.Dock = "Fill"
|
|
$labelTaskType.TextAlign = "MiddleLeft"
|
|
|
|
# - 작업 유형 콤보박스
|
|
$script:batch_comboBoxTaskType.Dock = "Fill"
|
|
$script:batch_comboBoxTaskType.DropDownStyle = "DropDownList"
|
|
$script:batch_comboBoxTaskType.Items.AddRange(@("계정 생성", "계정 삭제")) | Out-Null
|
|
$script:batch_comboBoxTaskType.SelectedIndex = 0
|
|
|
|
# - 템플릿 다운로드 버튼
|
|
$script:batch_buttonDownloadTemplate.Text = "템플릿 다운로드(&D)"
|
|
$script:batch_buttonDownloadTemplate.Dock = "Fill"
|
|
|
|
# - CSV 파일 경로 레이블
|
|
$labelCsvPath.Text = "CSV 파일 경로:"
|
|
$labelCsvPath.Dock = "Fill"
|
|
$labelCsvPath.TextAlign = "MiddleLeft"
|
|
|
|
# - CSV 파일 경로 텍스트박스
|
|
$script:batch_textBoxCsvPath.Dock = "Fill"
|
|
$script:batch_textBoxCsvPath.ReadOnly = $true
|
|
|
|
# - 파일 찾아보기 버튼
|
|
$script:batch_buttonBrowseCsv.Text = "파일 찾아보기(&B)..."
|
|
$script:batch_buttonBrowseCsv.Dock = "Fill"
|
|
|
|
# - 그리드뷰를 담을 패널
|
|
$gridPanel.Dock = "Fill"
|
|
|
|
# - 데이터 그리드뷰
|
|
$script:batch_dataGridView.Dock = "Fill"
|
|
$script:batch_dataGridView.ReadOnly = $false
|
|
$script:batch_dataGridView.AllowUserToAddRows = $false
|
|
$script:batch_dataGridView.AllowUserToDeleteRows = $false
|
|
$script:batch_dataGridView.AutoSizeColumnsMode = "Fill"
|
|
$script:batch_dataGridView.Visible = $false
|
|
$script:batch_dataGridView.SelectionMode = "FullRowSelect"
|
|
|
|
# - 안내 가이드 레이블
|
|
$script:batch_labelGuide.Dock = "Fill"
|
|
$script:batch_labelGuide.TextAlign = "MiddleLeft"
|
|
$script:batch_labelGuide.Padding = New-Object System.Windows.Forms.Padding(20, 0, 0, 0)
|
|
$script:batch_labelGuide.Font = New-Object System.Drawing.Font("Malgun Gothic", 9.5)
|
|
$script:batch_labelGuide.ForeColor = [System.Drawing.Color]::DimGray
|
|
|
|
# - 진행률 표시줄
|
|
$script:batch_progressBar.Dock = "Fill"
|
|
$script:batch_progressBar.Maximum = 100
|
|
$script:batch_progressBar.Value = 0
|
|
|
|
# - 실행 버튼들을 담을 레이아웃
|
|
$execButtonLayout.Dock = "Fill"
|
|
$execButtonLayout.ColumnCount = 2
|
|
$execButtonLayout.ColumnStyles.Add((New-Object System.Windows.Forms.ColumnStyle([System.Windows.Forms.SizeType]::Percent, 50))) | Out-Null
|
|
$execButtonLayout.ColumnStyles.Add((New-Object System.Windows.Forms.ColumnStyle([System.Windows.Forms.SizeType]::Percent, 50))) | Out-Null
|
|
|
|
# - 유효성 검사 버튼
|
|
$script:batch_buttonValidate.Text = "유효성 검사(&V)"
|
|
$script:batch_buttonValidate.Dock = "Fill"
|
|
$script:batch_buttonValidate.Enabled = $false
|
|
|
|
# - 일괄 작업 실행 버튼
|
|
$script:batch_buttonExecute.Text = "일괄 작업 실행(&X)"
|
|
$script:batch_buttonExecute.Dock = "Fill"
|
|
$script:batch_buttonExecute.Enabled = $false
|
|
$script:batch_buttonExecute.Font = New-Object System.Drawing.Font("Segoe UI", 10, [System.Drawing.FontStyle]::Bold)
|
|
|
|
# 컨트롤들을 메인 레이아웃에 배치
|
|
# 0행: 작업 유형 선택
|
|
$layout.Controls.Add($labelTaskType, 0, 0) | Out-Null
|
|
$layout.Controls.Add($script:batch_comboBoxTaskType, 1, 0) | Out-Null
|
|
$layout.SetColumnSpan($script:batch_comboBoxTaskType, 2)
|
|
$layout.Controls.Add($script:batch_buttonDownloadTemplate, 3, 0) | Out-Null
|
|
|
|
# 1행: CSV 파일 경로
|
|
$layout.Controls.Add($labelCsvPath, 0, 1) | Out-Null
|
|
$layout.Controls.Add($script:batch_textBoxCsvPath, 1, 1) | Out-Null
|
|
$layout.SetColumnSpan($script:batch_textBoxCsvPath, 2)
|
|
$layout.Controls.Add($script:batch_buttonBrowseCsv, 3, 1) | Out-Null
|
|
|
|
# 2행: 데이터 그리드 및 안내문
|
|
$gridPanel.Controls.Add($script:batch_dataGridView) | Out-Null
|
|
$gridPanel.Controls.Add($script:batch_labelGuide) | Out-Null
|
|
$layout.Controls.Add($gridPanel, 0, 2) | Out-Null
|
|
$layout.SetColumnSpan($gridPanel, 4)
|
|
|
|
# 3행: 진행률 및 실행 버튼
|
|
$execButtonLayout.Controls.Add($script:batch_buttonValidate, 0, 0) | Out-Null
|
|
$execButtonLayout.Controls.Add($script:batch_buttonExecute, 1, 0) | Out-Null
|
|
$layout.Controls.Add($script:batch_progressBar, 0, 3) | Out-Null
|
|
$layout.SetColumnSpan($script:batch_progressBar, 2)
|
|
$layout.Controls.Add($execButtonLayout, 2, 3) | Out-Null
|
|
$layout.SetColumnSpan($execButtonLayout, 2)
|
|
|
|
# 이벤트 핸들러 등록
|
|
Register-BatchTaskEvents
|
|
|
|
# 탭 초기화 시 '작업 유형 변경' 이벤트를 수동으로 호출하여 UI 초기 상태를 설정
|
|
$batch_TaskType_Changed.Invoke($null, $null)
|
|
}
|
|
#endregion
|
|
|
|
Write-Host "UI-Tab-BatchTask.ps1 로드 완료." -ForegroundColor Cyan |