Почему мой скрипт PowerShell застревает при закрытии с панели задач? - PullRequest
0 голосов
/ 29 февраля 2020

Я пытаюсь создать небольшой скрипт, с помощью которого я могу изменить ключевое слово в файле на то, что я ввел в текстовое поле. Я делаю копию каталога с файлами и копирую их с уникальным именем каталога на карту с именем temp. Это также запускает файл. При закрытии скрипта или при нажатии Cancel запущенная программа закрывается и файлы снова удаляются.

Все работает нормально, но всякий раз, когда я закрываю форму через панель задач Windows, и я Если вы захотите снова запустить скрипт, форма не будет отображаться, и консоль PowerShell будет отображаться, даже если она свернута, полностью пуста и не может ничего редактировать. Я могу закрыть его с помощью Ctrl + C, но он снова зависает при следующем запуске скрипта.

Это первый скрипт, который я когда-либо делал, и я не уверен как исправить проблему.

Если есть способ удалить файлы в этом уникальном случайном каталоге, когда процесс остановлен, это было бы еще лучше. Например, если я закрою файл settings.txt, который я открыл с помощью скрипта, то удаляю все файлы.

[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")  
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") 
[void] [System.Windows.Forms.Application]::EnableVisualStyles() 

# Hide PowerShell Console
Add-Type -Name Window -Namespace Console -MemberDefinition '
[DllImport("Kernel32.dll")]
public static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow);
'
$consolePtr = [Console.Window]::GetConsoleWindow()
[Console.Window]::ShowWindow($consolePtr, 0)


# makes form
$form = New-Object System.Windows.Forms.Form
$form.Text = 'Data Entry Form'
$form.Size = New-Object System.Drawing.Size(200,180)
$form.StartPosition = 'CenterScreen'

$okButton = New-Object System.Windows.Forms.Button
$okButton.Location = New-Object System.Drawing.Point(10,70)
$okButton.Size = New-Object System.Drawing.Size(160,20)
$okButton.Text = 'OK'
$okButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton = $okButton
$form.Controls.Add($okButton)


$cancelButton = New-Object System.Windows.Forms.Button
$cancelButton.Location = New-Object System.Drawing.Point(10,100)
$cancelButton.Size = New-Object System.Drawing.Size(160,20)
$cancelButton.Text = 'Cancel'
$cancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$form.CancelButton = $cancelButton
$form.Controls.Add($cancelButton)

$label = New-Object System.Windows.Forms.Label
$label.Location = New-Object System.Drawing.Point(10,20)
$label.Size = New-Object System.Drawing.Size(170,20)
$label.Text = 'Please enter the Server name:'
$form.Controls.Add($label)

$textBox = New-Object System.Windows.Forms.TextBox
$textBox.Location = New-Object System.Drawing.Point(10,40)
$textBox.Size = New-Object System.Drawing.Size(160,20)
$form.Controls.Add($textBox)

$form.Topmost = $true

$form.Add_Shown({$textBox.Select()})
$result = $form.ShowDialog()

if ($result -eq [System.Windows.Forms.DialogResult]::OK)
{
    $server = $textBox.Text
    $server

    $folder = [System.IO.Path]::GetRandomFileName()

    Copy-Item -Path C:\powershell\main\  -Destination c:\powershell\temp –Recurse

    Rename-Item -Path "C:\powershell\temp\main\" -NewName $folder

    (Get-Content -Path "C:\powershell\temp\$folder\settings.txt" -raw) -replace '<SERVERNAME>',"$server" | Set-Content "C:\powershell\temp\$folder\settings.txt"

    $app = (Start-Process "C:\powershell\temp\$folder\settings.txt" -passthru).ID


$form.Size = New-Object System.Drawing.Size(250,100)
$form.StartPosition = 'CenterScreen'

$label.Location = New-Object System.Drawing.Point(10,20)
$label.Size = New-Object System.Drawing.Size(200,20)
$label.Text = "Click 'cancel' to close Server $server"


$cancelButton.Location = New-Object System.Drawing.Point(10,40)
$cancelButton.Size = New-Object System.Drawing.Size(180,20)
$cancelButton.Text = 'Cancel'


    $result = $form.ShowDialog()

    if($result -eq [System.Windows.Forms.DialogResult]::cancel)
    {
        Stop-Process $app
        Remove-Item –path "C:\powershell\temp\$folder\" –recurse
    }


}

1 Ответ

0 голосов
/ 02 марта 2020

Дайте компьютеру перезагрузиться, чтобы устранить утечки памяти, а затем протестируйте этот код.

[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")  
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") 
[void] [System.Windows.Forms.Application]::EnableVisualStyles() 

# The reason that your form does not open sometime is caused by a memory leak.  The code below should resolve the issue.
# If you add to the GUI them add that control below. If a variable does not have a .dispose() then .NET will clean it up.
# These are Events and will fire when the window closes.
# These will fix the memory leak issue.

$Form.Add_FormClosing({  
    $form.Dispose()
    $okButton.Dispose()
    $cancelButton.Dispose()
    $label.Dispose()
    $textBox.Dispose()
})

$Form2.Add_FormClosing({  
    $form2.Dispose()
    $label2.Dispose()
    $cancelButton2.Dispose()
})

# Hide PowerShell Console
Add-Type -Name Window -Namespace Console -MemberDefinition '
[DllImport("Kernel32.dll")]
public static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow);
'
$consolePtr = [Console.Window]::GetConsoleWindow()
[Console.Window]::ShowWindow($consolePtr, 0)


# makes form
$form = New-Object System.Windows.Forms.Form
$form.Text = 'Data Entry Form'
$form.Size = New-Object System.Drawing.Size(200,180)
$form.StartPosition = 'CenterScreen'

$okButton = New-Object System.Windows.Forms.Button
$okButton.Location = New-Object System.Drawing.Point(10,70)
$okButton.Size = New-Object System.Drawing.Size(160,20)
$okButton.Text = 'OK'
$okButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton = $okButton
$form.Controls.Add($okButton)


$cancelButton = New-Object System.Windows.Forms.Button
$cancelButton.Location = New-Object System.Drawing.Point(10,100)
$cancelButton.Size = New-Object System.Drawing.Size(160,20)
$cancelButton.Text = 'Cancel'
$cancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$form.CancelButton = $cancelButton
$form.Controls.Add($cancelButton)

$label = New-Object System.Windows.Forms.Label
$label.Location = New-Object System.Drawing.Point(10,20)
$label.Size = New-Object System.Drawing.Size(170,20)
$label.Text = 'Please enter the Server name:'
$form.Controls.Add($label)

$textBox = New-Object System.Windows.Forms.TextBox
$textBox.Location = New-Object System.Drawing.Point(10,40)
$textBox.Size = New-Object System.Drawing.Size(160,20)
$form.Controls.Add($textBox)

$form.Topmost = $true

# Is this line needed
#$form.Add_Shown({$textBox.Select()}) # this sometimes will not let me type in the textbox
$result = $form.ShowDialog()

if ($result -eq [System.Windows.Forms.DialogResult]::OK)
{
    $server = $textBox.Text
    $server

    $folder = [System.IO.Path]::GetRandomFileName()

    Copy-Item -Path C:\powershell\main\  -Destination c:\powershell\temp –Recurse

    Rename-Item -Path "C:\powershell\temp\main\" -NewName $folder

    (Get-Content -Path "C:\powershell\temp\$folder\settings.txt" -raw) -replace '<SERVERNAME>',"$server" | Set-Content "C:\powershell\temp\$folder\settings.txt"

    $app = (Start-Process "C:\powershell\temp\$folder\settings.txt" -passthru).ID

# This is winform.  They work on comobjects and you not reuse the variable name because it will not
# free up memory resource when the are reused.  I rename your variables to get around this issue.
$form2 = New-Object System.Windows.Forms.Form
$form2.Size = New-Object System.Drawing.Size(350,250)    
$form2.StartPosition = 'CenterScreen'


$label2 = New-Object System.Windows.Forms.Label
$label2.Location = New-Object System.Drawing.Point(10,20)
$label2.Size = New-Object System.Drawing.Size(350,20)
$label2.Text = "Click 'cancel' to close Server $server"
$form2.Controls.Add($label2)

$cancelButton2 = New-Object System.Windows.Forms.Button
$cancelButton2.Location = New-Object System.Drawing.Point(10,80)
$cancelButton2.Size = New-Object System.Drawing.Size(180,40)
$cancelButton2.Text = 'Cancel'
$form2.CancelButton = $cancelButton2
$form2.Controls.Add($cancelButton2)


    $result = $form2.ShowDialog()

    if($result -eq [System.Windows.Forms.DialogResult]::cancel)
    {
        Stop-Process $app
        Remove-Item –path "C:\powershell\temp\$folder\" –recurse
    }


}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...