Запуск Powershell полностью без головы - PullRequest
2 голосов
/ 11 июня 2019

Я хочу отправить «Уведомление о баллоне» на удаленный компьютер в моей сети. Каждая машина в сети работает на Windows 10. Событие должно быть инициировано с веб-сайта, созданного с помощью php. Я сделал это с помощью следующего кода:

PHP

$powershell_path = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe";
$script_path = "[..path to the ps1 script..]\\test.ps1";

$exec = $powershell_path." -executionPolicy Unrestricted ".$script_path." -computer_name ".$args['remote_computer'];
shell_exec($exec." 2>&1");

Test.ps1

param(
    [parameter(mandatory=$true)][string]$computer_name
)

function Send-Balloon {

    Param(
        [parameter(mandatory=$true)][string]$To,
        [parameter(mandatory=$true)][string]$balloon_title,
        [parameter(mandatory=$true)][string]$balloon_text,
        [parameter(mandatory=$false)][int]$show_time,
        [parameter(mandatory=$false)][string]$scripts_path,
        [parameter(mandatory=$false)][string]$script_name
    )

    if(!$show_time) { $show_time = 15000 }
    if(!$scripts_path) { $scripts_path = "C:\temp\" }
    if(!$script_name) { $script_name = "task.ps1" }

    $remote_computer = $To

    if(!(Test-Connection -ComputerName $remote_computer -Count 1 -ErrorAction     SilentlyContinue)) {
        Write-Warning "$remote_computer could not be reached"
        break
    }

    $str = @"
        Add-Type -AssemblyName  System.Windows.Forms
        `$balloon = [System.Windows.Forms.NotifyIcon]::new()
        `$path = (Get-Process -id `$pid).Path
        `$balloon.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon(`$path)
        `$balloon.BalloonTipIcon  = [System.Windows.Forms.ToolTipIcon]::Info
        `$balloon.BalloonTipTitle = '$balloon_title'
        `$balloon.BalloonTipText  = '$balloon_text'
        `$balloon.Visible  = `$true
        `$balloon.ShowBalloonTip(100000)
    "@

    $script = [scriptblock]::Create($str)
    $script | Out-File $scripts_path\$script_name
    $remote_path = "\\$remote_computer\c$\temp"

    if(!(Test-Path $remote_path)) {
        New-Item -ItemType Directory -Path $remote_path
    }
    Copy-Item -Path $scripts_path\$script_name -Destination $remote_path

    $task_scriptblock = {
        $schedule_script = 'C:\temp\task.ps1'
        $seconds = 2
        $a = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-WindowStyle hidden -Command $schedule_script"
        $tr = New-ScheduledTaskTrigger -Once -At ((Get-Date) + (New-TimeSpan -Seconds $seconds))
        $p = New-ScheduledTaskPrincipal -UserId (Get-CimInstance -ClassName Win32_ComputerSystem | Select-Object -expand UserName)
        $tn = "!random_task_name_" + (-join ((65..90) + (97..122) | Get-Random -Count 10 | % {[char]$_}))
        $t = Register-ScheduledTask -TaskName $tn -Trigger $tr -Action $a -Principal $p
        Start-Sleep ($seconds + 1)
        Get-ScheduledTask -TaskName $tn | Unregister-ScheduledTask -Confirm:$false
        Remove-Item -Path $schedule_script
    }
    Invoke-Command -ComputerName $remote_computer -ScriptBlock $task_scriptblock 
}

Send-Balloon -To $computer_name -balloon_title "test" -balloon_text "just a test"

Этот код копирует скрипт из $ str в временную папку данного удаленного компьютера. После этого он говорит удаленному компьютеру выполнить созданный файл. После выполнения удаляет файл ps1.

Это работает как намерение и (в основном) безупречно. Моя проблема сейчас в том, что powershell с '-WindowStyle hidden' на самом деле не скрыт. На долю секунды вы видите, как консоль PowerShell выскакивает и мгновенно исчезает. Я читал, что это «нормальное» поведение, и ему можно противодействовать, вызывая ps1-файл из другого контекста, такого как скрипт vbs.

VBS

command = "powershell.exe -nologo -command [path to the ps1-file]"
set shell = CreateObject("WScript.Shell")
shell.Run command,0

Дело в том, что это кажется слишком сложным, поскольку у меня есть скрипт php для запуска скрипта ps1 для копирования файла ps1 и vbs. Затем вызовите скопированный скрипт vbs, который вызывает скопированный ps1, чтобы показать простое уведомление.

Существует ли простой способ вызова сценария ps1 через php на удаленном компьютере, не видя консоль powershell? Или еще лучше: есть ли более простой способ вызвать «всплывающие уведомления» на удаленном компьютере, о котором я еще не думал?

...