Bom dia para todos,
Eu tenho um problema com um script do PowerShell.
Contexto
Estou tentando criar um programa para editar o arquivo pop tf2 no powershell, agora estou tentando ter um programa que abra um arquivo txt, exiba o conteúdo de cada ondaspawn e um botão para copiar o ondaspawn.
Aqui está o script do PowerShell que escrevi atualmente com um pouco de ajuda.
# Import necessary assemblies for Windows Forms
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
# Function to create OpenFileDialog
function Show-OpenFileDialog {
$openFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$openFileDialog.InitialDirectory = [System.Environment]::GetFolderPath('MyDocuments')
$openFileDialog.Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*"
$openFileDialog.Title = "Select a Text File"
$result = $openFileDialog.ShowDialog()
if ($result -eq [System.Windows.Forms.DialogResult]::OK) {
return $openFileDialog.FileName
} else {
return $null
}
}
# Function to load file content and extract WaveSpawn sections
function Load-FileContent {
param (
[string]$filePath,
[System.Windows.Forms.ListBox]$listBox,
[ref]$waveSpawnDetails
)
$listBox.Items.Clear()
$waveSpawnDetails.Value.Clear()
if (Test-Path $filePath) {
$content = Get-Content -Path $filePath -Raw
# Extract all WaveSpawn sections with a more robust regex pattern
$waveSpawns = [regex]::Matches($content, 'WaveSpawn\s*\{(?:[^\{\}]*|(?<Open>\{)|(?<-Open>\}))*\}(?(Open)(?!))')
$waveSpawns | ForEach-Object {
$waveSpawn = $_.Value
if ($waveSpawn -match 'Name\s+(\w+)') {
$name = $matches[1]
$listBox.Items.Add($name)
$waveSpawnDetails.Value[$name] = $waveSpawn
}
}
} else {
[System.Windows.Forms.MessageBox]::Show("File not found: $filePath", "Error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
}
}
# Function to display details of the selected WaveSpawn
function Show-WaveSpawnDetails {
param (
[string]$waveSpawnName,
[System.Windows.Forms.TextBox]$textBox,
[hashtable]$waveSpawnDetails
)
if ($waveSpawnDetails.ContainsKey($waveSpawnName)) {
$textBox.Text = $waveSpawnDetails[$waveSpawnName]
} else {
$textBox.Text = "WaveSpawn details not found."
}
}
# Main form
$form = New-Object Windows.Forms.Form
$form.Text = "WaveSpawns"
$form.Size = New-Object Drawing.Size(800, 600)
# ListBox to display WaveSpawns
$listBox = New-Object Windows.Forms.ListBox
$listBox.Size = New-Object Drawing.Size(300, 500)
$listBox.Location = New-Object Drawing.Point(10, 10)
# TextBox to display selected WaveSpawn details
$textBox = New-Object Windows.Forms.TextBox
$textBox.Size = New-Object Drawing.Size(450, 500)
$textBox.Location = New-Object Drawing.Point(320, 10)
$textBox.Multiline = $true
$textBox.ScrollBars = [System.Windows.Forms.ScrollBars]::Vertical
# Button to copy WaveSpawn details to clipboard
$copyButton = New-Object Windows.Forms.Button
$copyButton.Text = "Copy"
$copyButton.Size = New-Object Drawing.Size(75, 23)
$copyButton.Location = New-Object Drawing.Point(320, 520)
$copyButton.Add_Click({
Set-Clipboard -Value $textBox.Text
[System.Windows.Forms.MessageBox]::Show("WaveSpawn copied to clipboard!")
})
# Button to open file
$openButton = New-Object Windows.Forms.Button
$openButton.Text = "Open File"
$openButton.Size = New-Object Drawing.Size(75, 23)
$openButton.Location = New-Object Drawing.Point(10, 520)
$openButton.Add_Click({
$filePath = Show-OpenFileDialog
if ($filePath) {
Load-FileContent -filePath $filePath -listBox $listBox -waveSpawnDetails ([ref]$waveSpawnDetails)
}
})
# Add event handler for ListBox selection
$listBox.SelectedIndexChanged.Add({
$selectedWaveSpawnName = $listBox.SelectedItem.ToString()
Show-WaveSpawnDetails -waveSpawnName $selectedWaveSpawnName -textBox $textBox -waveSpawnDetails $waveSpawnDetails
})
# Add controls to form
$form.Controls.Add($listBox)
$form.Controls.Add($textBox)
$form.Controls.Add($copyButton)
$form.Controls.Add($openButton)
# Initialize hashtable to store WaveSpawn details
$global:waveSpawnDetails = @{}
# Show the form
$form.ShowDialog()
O arquivo "pop" de teste
//This mission is a dummy mission and is probably not working, it just here to test the powershell script in "real condition"
#base robot_standard.pop
#base robot_giant.pop
WaveSchedule
{
StartingCurrency 900
RespawnWaveTime 4
CanBotsAttackWhileInSpawnRoom no
Mission
{
Objective DestroySentries
BeginAtWave 1
RunForThisManyWaves 3
InitialCooldown 30
CooldownTime 30
DesiredCount 1
Where spawnbot_mission_sentrybuster
TFBot
{
Template T_TFBot_SentryBuster
}
}
Wave //wave 1
{
StartWaveOutput
{
Target wave_start_relay
Action Trigger
}
DoneOutput
{
Target wave_finished_relay
Action Trigger
}
WaveSpawn
{
Name wave1
TotalCurrency 300
TotalCount 4
MaxActive 6
SpawnCount 1
WaitBeforeStarting 0
WaitBetweenSpawns 12
Where spawnbot
TFBot
{
Template T_TFBot_Giant_Pyro
Tag bot_giant
Attributes AlwaysFireWeapon
}
}
WaveSpawn
{
Name wave1
TotalCurrency 100
TotalCount 24
MaxActive 12
SpawnCount 2
WaitBeforeStarting 2
WaitBetweenSpawns 2.5
Where spawnbot_side
Squad
{
TFBot
{
Class Soldier
Skill normal
}
TFBot
{
Template T_TFBot_Medic_QuickFix
Tag bot_squad_member
ItemAttributes
{
ItemName "The Quick-Fix"
"ubercharge rate bonus" 0.1
}
}
}
}
WaveSpawn
{
Name wave2
WaitForAllSpawned w1a
TotalCurrency 100
TotalCount 3
MaxActive 3
SpawnCount 1
WaitBeforeStarting 7
WaitBetweenSpawns 7
Where spawnbot
TFBot
{
Template T_TFBot_Giant_Demoman
Tag bot_giant
}
}
WaveSpawn
{
Name wave2
WaitForAllSpawned w1a
TotalCurrency 300
TotalCount 1
MaxActive 1
SpawnCount 1
WaitBeforeStarting 2
WaitBetweenSpawns 1
FirstSpawnOutput
{
Target boss_spawn_relay
Action Trigger
}
Tank
{
Name "Tank"
Health 15000
Speed 70
StartingPathTrackNode tank_path_1
OnKilledOutput
{
Target boss_dead_relay
Action Trigger
}
OnBombDroppedOutput
{
Target boss_deploy_relay
Action Trigger
}
}
}
WaveSpawn
{
Name wave3
WaitForAllSpawned w1b
TotalCurrency 50
TotalCount 2
MaxActive 2
SpawnCount 1
WaitBeforeStarting 4
WaitBetweenSpawns 7
Where spawnbot_side
TFBot
{
Template T_TFBot_Giant_Scout_FAN
Tag bot_giant
}
}
WaveSpawn
{
Name wave3
WaitForAllSpawned w1b
Support 1
TotalCurrency 50
TotalCount 50
MaxActive 10
Support Limited
SpawnCount 5
WaitBeforeStarting 7
WaitBetweenSpawns 1
Where spawnbot_invasion
TFBot
{
Class Demoman
}
}
}
}
Também aqui está a mensagem de erro quando tento copiar um wavepawn. Este é o único erro que estou recebendo.
mpossible d’appeler une méthode dans une expression Null.
Au caractère P:\Document\Fichier texte\Switch_supervision - Copie.ps1:99 : 1
+ $listBox.SelectedIndexChanged.Add({
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation : (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Alguém pode me ajudar a descobrir o que está acontecendo com o script e por que duas das funções principais não funcionam?
ATUALIZAÇÃO: A solução foi encontrada por @Someone se alguém estiver interessado aqui no código funcional:
# Import necessary assemblies for Windows Forms
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
# Function to create OpenFileDialog
function Show-OpenFileDialog {
$openFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$openFileDialog.InitialDirectory = [System.Environment]::GetFolderPath('MyDocuments')
$openFileDialog.Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*"
$openFileDialog.Title = "Select a Text File"
$result = $openFileDialog.ShowDialog()
if ($result -eq [System.Windows.Forms.DialogResult]::OK) {
return $openFileDialog.FileName
} else {
return $null
}
}
# Function to load file content and extract WaveSpawn sections
function Load-FileContent {
param (
[string]$filePath,
[System.Windows.Forms.ListBox]$listBox,
[ref]$waveSpawnDetails
)
$listBox.Items.Clear()
$waveSpawnDetails.Value.Clear()
if (Test-Path $filePath) {
$content = Get-Content -Path $filePath -Raw
# Extract all WaveSpawn sections with a more robust regex pattern
$waveSpawns = [regex]::Matches($content, 'WaveSpawn\s*\{(?:[^\{\}]*|(?<Open>\{)|(?<-Open>\}))*\}(?(Open)(?!))')
$waveSpawns | ForEach-Object {
$waveSpawn = $_.Value
if ($waveSpawn -match 'Name\s+(\w+)') {
$name = $matches[1]
$listBox.Items.Add($name)
$waveSpawnDetails.Value[$name] = $waveSpawn
}
}
} else {
[System.Windows.Forms.MessageBox]::Show("File not found: $filePath", "Error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
}
}
# Function to display details of the selected WaveSpawn
function Show-WaveSpawnDetails {
param (
[string]$waveSpawnName,
[System.Windows.Forms.TextBox]$textBox,
[hashtable]$waveSpawnDetails
)
if ($waveSpawnDetails.ContainsKey($waveSpawnName)) {
$textBox.Text = $waveSpawnDetails[$waveSpawnName]
} else {
$textBox.Text = "WaveSpawn details not found."
}
}
# Main form
$form = New-Object Windows.Forms.Form
$form.Text = "WaveSpawns"
$form.Size = New-Object Drawing.Size(800, 600)
# ListBox to display WaveSpawns
$listBox = New-Object Windows.Forms.ListBox
$listBox.Size = New-Object Drawing.Size(300, 500)
$listBox.Location = New-Object Drawing.Point(10, 10)
# TextBox to display selected WaveSpawn details
$textBox = New-Object Windows.Forms.TextBox
$textBox.Size = New-Object Drawing.Size(450, 500)
$textBox.Location = New-Object Drawing.Point(320, 10)
$textBox.Multiline = $true
$textBox.ScrollBars = [System.Windows.Forms.ScrollBars]::Vertical
# Button to copy WaveSpawn details to clipboard
$copyButton = New-Object Windows.Forms.Button
$copyButton.Text = "Copy"
$copyButton.Size = New-Object Drawing.Size(75, 23)
$copyButton.Location = New-Object Drawing.Point(320, 520)
$copyButton.Add_Click({
Set-Clipboard -Value $textBox.Text
[System.Windows.Forms.MessageBox]::Show("WaveSpawn copied to clipboard!")
})
# Button to open file
$openButton = New-Object Windows.Forms.Button
$openButton.Text = "Open File"
$openButton.Size = New-Object Drawing.Size(75, 23)
$openButton.Location = New-Object Drawing.Point(10, 520)
$openButton.Add_Click({
$filePath = Show-OpenFileDialog
if ($filePath) {
Load-FileContent -filePath $filePath -listBox $listBox -waveSpawnDetails ([ref]$waveSpawnDetails)
}
})
# Add event handler for ListBox selection
$listBox.Add_SelectedIndexChanged({
$selectedWaveSpawnName = $listBox.SelectedItem.ToString()
Show-WaveSpawnDetails -waveSpawnName $selectedWaveSpawnName -textBox $textBox -waveSpawnDetails $waveSpawnDetails
})
# Add controls to form
$form.Controls.Add($listBox)
$form.Controls.Add($textBox)
$form.Controls.Add($copyButton)
$form.Controls.Add($openButton)
# Initialize hashtable to store WaveSpawn details
$global:waveSpawnDetails = @{}
# Show the form
$form.ShowDialog()
Como o erro indica, há um erro na sua linha:
$listBox.SelectedIndexChanged.Add({
A sintaxe correta para adicionar um evento a um objeto é:$listBox.Add_SelectedIndexChanged({