Usei o ChatGPT para gerar o código e entender como fazer isso sozinho, e funciona na maior parte do tempo. O script verifica minhas pastas de TV e Filmes em busca de arquivos ausentes para melhorar o funcionamento do Plex (folder.jpg, theme.mp3 e assim por diante) e mostra quais estão faltando e quantos.
Funciona perfeitamente na pasta de filmes, mas eu não consigo (nem a IA) descobrir como consertar isso clicando no botão TV ou TV encerrada e fazendo com que ele pesquise nessas pastas.
Meu melhor palpite é que a variável $pathMap na linha 167 é a chave e não está sendo atualizada corretamente para esta parte - $global:fixedPath = $pathMap
Alguém poderia corrigir isso e me explicar como descobrir como fazer isso?
Windows 10 22H2 e Powershell PSVersão 5.1.19041.5737
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
# Create form
$form = New-Object System.Windows.Forms.Form
$form.Text = "Marion's Plex checker"
$form.Size = New-Object System.Drawing.Size(700, 700)
$form.StartPosition = "CenterScreen"
# Fixed folder path
$fixedPath = "D:\ServerFolders\Videos\02 - Movies"
# Path label
$label = New-Object System.Windows.Forms.Label
$label.Text = "Checking subfolders in: $fixedPath"
$label.Location = New-Object System.Drawing.Point(120, 20)
$label.Size = New-Object System.Drawing.Size(550, 20)
$form.Controls.Add($label)
# Summary label
$summaryLabel = New-Object System.Windows.Forms.Label
$summaryLabel.Text = ""
$summaryLabel.Location = New-Object System.Drawing.Point(120, 45)
$summaryLabel.Size = New-Object System.Drawing.Size(550, 20)
$form.Controls.Add($summaryLabel)
# Output box
$logBox = New-Object System.Windows.Forms.TextBox
$logBox.Multiline = $true
$logBox.ScrollBars = "Vertical"
$logBox.Location = New-Object System.Drawing.Point(120, 75)
$logBox.Size = New-Object System.Drawing.Size(550, 350)
$logBox.Anchor = "Top,Bottom,Left,Right"
$logBox.ReadOnly = $true
$form.Controls.Add($logBox)
# Search file buttons (on the left)
$fileTypes = @("theme.mp3", "folder.jpg", "background.jpg", "poster.jpg")
$fileButtons = @{}
$yPos = 20
$global:selectedFile = "theme.mp3"
foreach ($file in $fileTypes) {
$btn = New-Object System.Windows.Forms.Button
$btn.Text = $file
$btn.Tag = $file
$btn.Location = New-Object System.Drawing.Point(10, $yPos)
$btn.Size = New-Object System.Drawing.Size(100, 30)
$form.Controls.Add($btn)
$fileButtons[$file] = $btn
$yPos += 40
$btn.Add_Click({
$global:selectedFile = $this.Tag
# Reset styles
foreach ($b in $fileButtons.Values) {
$b.UseVisualStyleBackColor = $true
}
# Highlight selected
# Reset styles
foreach ($b in $fileButtons.Values) {
$b.UseVisualStyleBackColor = $true
$b.BackColor = [System.Drawing.SystemColors]::Control
}
# Highlight selected
$this.UseVisualStyleBackColor = $false
$this.BackColor = 'LightBlue'
$summaryLabel.Text = "Selected file: $global:selectedFile"
})
}
# Scan button
$scanButton = New-Object System.Windows.Forms.Button
$scanButton.Text = "Scan"
$scanButton.Location = New-Object System.Drawing.Point(10, 440)
$scanButton.Size = New-Object System.Drawing.Size(100, 30)
$form.Controls.Add($scanButton)
# Create a new button for Movies, positioned to the right of the Scan button
$moviesButton = New-Object System.Windows.Forms.Button
$moviesButton.Text = "Movies"
$moviesButton.Size = New-Object System.Drawing.Size(100, 30)
$moviesButton.Location = New-Object System.Drawing.Point(120, 440)
# Create a new button for TV, positioned next to the Movies button
$tvButton = New-Object System.Windows.Forms.Button
$tvButton.Text = "TV"
$tvButton.Size = New-Object System.Drawing.Size(100, 30)
$tvButton.Location = New-Object System.Drawing.Point(230, 440)
# Create a new button for TV Ended, positioned next to the TV button
$tvEndedButton = New-Object System.Windows.Forms.Button
$tvEndedButton.Text = "TV Ended"
$tvEndedButton.Size = New-Object System.Drawing.Size(100, 30)
$tvEndedButton.Location = New-Object System.Drawing.Point(340, 440) # Right of the TV button
$tvEndedButton.Add_Click({
Start-Process "D:\ServerFolders\Videos\TV (Ended)" # Link to the TV Ended path
})
$form.Controls.Add($tvEndedButton)
# Path variables for Movies, TV, and TV Ended
$pathMap = @{
"Movies" = "D:\ServerFolders\Videos\02 - Movies"
"TV Current" = "D:\ServerFolders\Videos\01 - TV"
"TV Ended" = "D:\ServerFolders\Videos\TV (Ended)"
}
# Default path for Movies
$global:fixedPath = $pathMap["Movies"]
$pathLabel.Text = "Scanning path: $global:fixedPath"
# Add click event for Movies button
$moviesButton.Add_Click({
$global:fixedPath = $pathMap["Movies"]
$pathLabel.Text = "Scanning path: $global:fixedPath"
# Change button colors to indicate active path
$moviesButton.BackColor = 'LightGreen'
$tvButton.BackColor = [System.Drawing.SystemColors]::Control
$tvEndedButton.BackColor = [System.Drawing.SystemColors]::Control
# Start scanning the Movies path
Write-Host "Scanning Movies path: $global:fixedPath"
Scan-Folder -path $global:fixedPath
})
# Add click event for TV button
$tvButton.Add_Click({
$global:fixedPath = $pathMap["TV Current"]
$pathLabel.Text = "Scanning path: $global:fixedPath"
# Change button colors to indicate active path
$tvButton.BackColor = 'LightGreen'
$moviesButton.BackColor = [System.Drawing.SystemColors]::Control
$tvEndedButton.BackColor = [System.Drawing.SystemColors]::Control
# Start scanning the TV Current path
Write-Host "Scanning TV path: $global:fixedPath"
Scan-Folder -path $global:fixedPath
})
# Add click event for TV Ended button
$tvEndedButton.Add_Click({
$global:fixedPath = $pathMap["TV Ended"]
$pathLabel.Text = "Scanning path: $global:fixedPath"
# Change button colors to indicate active path
$tvEndedButton.BackColor = 'LightGreen'
$moviesButton.BackColor = [System.Drawing.SystemColors]::Control
$tvButton.BackColor = [System.Drawing.SystemColors]::Control
# Start scanning the TV Ended path
Write-Host "Scanning TV Ended path: $global:fixedPath"
Scan-Folder -path $global:fixedPath
})
# Function to scan the folder
function Scan-Folder {
param(
[string]$path
)
Write-Host "Scanning folder: $path"
# Insert the actual folder scanning logic here
}
# Path variables for Movies, TV, and TV Ended
$pathMap = @{
"Movies" = "D:\ServerFolders\Videos\02 - Movies"
"TV Current" = "D:\ServerFolders\Videos\01 - TV"
"TV Ended" = "D:\ServerFolders\Videos\TV (Ended)"
}
# Default path for Movies
$global:fixedPath = $pathMap["Movies"]
# Add click event for Movies button
$moviesButton.Add_Click({
$global:fixedPath = $pathMap["Movies"]
$pathLabel.Text = "Scanning path: $global:fixedPath"
# Change button colors to indicate active path
$moviesButton.BackColor = 'LightGreen'
$tvButton.BackColor = [System.Drawing.SystemColors]::Control
$tvEndedButton.BackColor = [System.Drawing.SystemColors]::Control
# Trigger the scanning logic
Scan-Folder -path $global:fixedPath
})
# Add click event for TV button
$tvButton.Add_Click({
$global:fixedPath = $pathMap["TV Current"]
$pathLabel.Text = "Scanning path: $global:fixedPath"
# Change button colors to indicate active path
$tvButton.BackColor = 'LightGreen'
$moviesButton.BackColor = [System.Drawing.SystemColors]::Control
$tvEndedButton.BackColor = [System.Drawing.SystemColors]::Control
# Trigger the scanning logic
Scan-Folder -path $global:fixedPath
})
# Add click event for TV Ended button
$tvEndedButton.Add_Click({
$global:fixedPath = $pathMap["TV Ended"]
$pathLabel.Text = "Scanning path: $global:fixedPath"
# Change button colors to indicate active path
$tvEndedButton.BackColor = 'LightGreen'
$moviesButton.BackColor = [System.Drawing.SystemColors]::Control
$tvButton.BackColor = [System.Drawing.SystemColors]::Control
# Trigger the scanning logic
Scan-Folder -path $global:fixedPath
})
# Function to scan the folder
function Scan-Folder {
param(
[string]$path
)
Write-Host "Scanning folder: $path"
# Insert the actual scanning logic here to process the folder
}
# Right of the Movies button
$tvButton.Add_Click({
Start-Process "D:\ServerFolders\Videos\01 - TV" # Link to the TV path
})
$form.Controls.Add($tvButton)
# Right of the Scan button
$moviesButton.Add_Click({
Start-Process "D:\ServerFolders\Videos\02 - Movies" # Link to the Movies path
})
$form.Controls.Add($moviesButton)
# Globals
$global:missingItems = @()
function Run-Scan {
$logBox.Clear()
$summaryLabel.Text = ""
$log = @()
$logPath = Join-Path $fixedPath "missing_${global:selectedFile}_log.txt"
$csvPath = Join-Path $fixedPath "missing_${global:selectedFile}_report.csv"
$global:missingItems = @()
if (-not (Test-Path $fixedPath)) {
[System.Windows.Forms.MessageBox]::Show("Invalid folder path.", "Error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
return
}
$folders = Get-ChildItem -Path $fixedPath -Directory
foreach ($folder in $folders) {
$targetFile = Join-Path $folder.FullName $global:selectedFile
if (-not (Test-Path -LiteralPath $targetFile)) {
$global:missingItems += $folder
$logLine = "$($folder.Name)"
$logBox.AppendText($logLine + "`r`n")
$log += $logLine
}
}
if ($global:missingItems.Count -eq 0) {
$summaryLabel.Text = "All folders have $($global:selectedFile)."
} else {
$summaryLabel.Text = "Missing $($global:selectedFile) from [$($global:missingItems.Count)] folders."
}
$log | Out-File -FilePath $logPath -Encoding UTF8
$logBox.AppendText("`r`nLog saved to: $logPath`r`n")
$exportButton.Enabled = $global:missingItems.Count -gt 0
}
$scanButton.Add_Click({ Run-Scan })
# Export to CSV button
$exportButton = New-Object System.Windows.Forms.Button
$exportButton.Text = "Export to CSV"
$exportButton.Location = New-Object System.Drawing.Point(10, 400)
$exportButton.Size = New-Object System.Drawing.Size(100, 30)
$exportButton.Enabled = $false
$form.Controls.Add($exportButton)
$exportButton.Add_Click({
$csvPath = Join-Path $fixedPath "missing_$($global:selectedFile)_report.csv"
$csvPath = Join-Path $fixedPath "missing_$($global:selectedFile)_report.csv"
$headerLines = @(
"File type: $($global:selectedFile)",
"Total missing: $($global:missingItems.Count)`r`n"
)
$headerLines | Out-File -FilePath $csvPath -Encoding UTF8
$global:missingItems | ForEach-Object {
[PSCustomObject]@{ FolderName = $_.Name; Path = $_.FullName }
} | Export-Csv -Path $csvPath -Append -NoTypeInformation -Encoding UTF8
$logBox.AppendText("CSV exported to: $csvPath`r`n")
})
$form.Topmost = $true
$form.Add_Shown({ $form.Activate() })
[void]$form.ShowDialog()
Seu problema é de escopo de variável :
Você usa ambos
$fixedPath
e$global:fixedPath
para se referir ao que você acha que são a mesma variável, mas não são:Os scripts do PowerShell são executados em um escopo filho do chamador por padrão, o que significa que o escopo do script (que pode ter escopos filhos próprios, principalmente dentro de funções) não é o mesmo que o escopo global (
$global:
); você pode usar o$script:
especificador de escopo para se referir ao escopo de nível superior do script (mesmo de funções incorporadas).Embora você possa ler variáveis definidas em um escopo ancestral referenciando-as apenas pelo nome (por exemplo,
$fixedPath
), quando você atribui um valor a elas sem um especificador de escopo , você cria implicitamente uma nova variável com esse nome no escopo atual , que então obscurece (eclipsa) a cópia ancestral - a menos que você se refira explicitamente a ela por meio de um especificador de escopo.$global:fixedPath
e$fixedPath
no seu código, o último, a cópia em escopo de script oculta a cópia global se você tentar lê-la posteriormente com apenas$fixedPath
.Em outras palavras: atualizações posteriores para
$global:fixedPath
não serão vistas se você usar apenas$fixedPath
, que é o que constitui o seu problema.Para robustez e clareza conceitual, sugiro sempre usar um especificador de escopo para se referir a variáveis projetadas para uso entre escopos; no entanto, não use , pois variáveis globais são invariavelmente globais
$global:
de sessão e, portanto, permanecem após a saída do script, poluindo o namespace global.Em vez disso, use o
$script:
escopo :Ou seja, substitua todas as ocorrências de
$global:fixedPath
e$fixedPath
por$script:fixedPath