diff --git a/README.md b/README.md index 6b096e3..3ca0c7e 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,6 @@ - [Regex](#Regex) - [Items](#Items) - [Event](#Event) -- [XML](#XML) - [Application](#Application) - [Network](#Network) - [SMB](#SMB) @@ -16,10 +15,11 @@ - [PackageManagement](#PackageManagement) - [SQLite](#SQLite) - [PowerCLI](#PowerCLI) +- [EMShell](#EMShell) - [VBR](#VBR) - [REST API](#REST-API) - [Console API](#Console-API) -- [EMShell](#EMShell) +- [Convert-Language](#Convert-Language) - [Git](#Git) ### Help @@ -160,9 +160,6 @@ `Get-Process | Sort-Object -Descending CPU | select -First 10` вывести первых 10 объектов \ `Get-Process | Sort-Object -Descending CPU | select -Last 10` вывести последних 10 объектов -### ConvertTo-HTML -`Get-Process | select Name, CPU | ConvertTo-HTML -As Table > "$home\desktop\proc-table.html"` вывод в формате List (Format-List) или Table (Format-Table) - # Regex `-replace "1","2"` замена элементов в индексах массива (везде где присутствует 1, заменить на 2), для удаления используется только первое значение \ @@ -432,163 +429,6 @@ `$obj += [PSCustomObject]@{Time = $temp_fw.TimeCreated; Type = $type; Port = $port; Name = $name}` \ `}` -# XML (Extensible Markup Language) - -`$xml = [xml](Get-Content ~\desktop\home.rdg)` прочитать содержимое xml-файла \ -`$xml = New-Object System.Xml.XmlDocument` создать пустой xml объект \ -`$file = Resolve-Path("~\desktop\home.rdg")` забрать путь к файлу \ -`$xml.load($file)` открыть файл \ -`$xml | Select-Xml "//RDCMan/file/group/server/properties"` \ -`$xml.RDCMan.file.group.server.properties` \ -`$xml.RDCMan.file.group.server[1].properties` \ -`$xml.RDCMan.file.group.server[1].properties.displayName = "plex-02"` изменить значение \ -`$xml.RDCMan.file.group.server[1].properties.name = "192.168.3.200"` \ -`$xml.RDCMan.file.group.server[0].RemoveAll()` \ -`$xml.Save($file)` сохранить содержимое объекта в файла - -`Export-CliXml` экспортировать объект powershell в xml \ -`Import-Clixml` импортировать объект xml в powershell -``` -if (Test-Path $CredFile) { -$Cred = Import-Clixml -path $CredFile -} elseif (!(Test-Path $CredFile)) { -$Cred = Get-Credential -Message "Enter credential" -if ($Cred -ne $null) { -$Cred | Export-CliXml -Path $CredFile -} else { -return -} -} - -$FilterXPath = '' -$RDPAuths = Get-WinEvent -ComputerName $srv -LogName "Microsoft-Windows-TerminalServices-LocalSessionManager/Operational" -FilterXPath $FilterXPath -[xml[]]$xml = $RDPAuths | Foreach {$_.ToXml()} -$EventData = Foreach ($event in $xml.Event) { -New-Object PSObject -Property @{ -"Connection Time" = (Get-Date ($event.System.TimeCreated.SystemTime) -Format 'yyyy-MM-dd hh:mm K') -"User Name" = $event.UserData.EventXML.User -"User ID" = $event.UserData.EventXML.SessionID -"User Address" = $event.UserData.EventXML.Address -"Event ID" = $event.System.EventID -}} -$EventData -``` -### JSON (JavaScript Object Notation) -``` -log = -{ - level = 7; -}; - -$log = [xml]" - 7 -" - -$log = '{ - "log": { - "level": 7 - } -}' | ConvertFrom-Json -``` -`Invoke-RestMethod -Uri "https://jsonplaceholder.typicode.com/posts" -Method Get` GET-запрос для получения объекта JSON - -### YAML (Yet Another Markup Language) -``` -Import-Module PSYaml -$network = " -network: - ethernets: - ens160: - dhcp4: yes - dhcp6: no - nameservers: - addresses: # [8.8.8.8, 1.1.1.1] - - 8.8.8.8 - - 1.1.1.1 - version: 2 -" -$Result = ConvertFrom-Yaml $network -$Result.Values.ethernets.ens160.nameservers -``` -### CSV (Comma-Separated Values) -`Get-Service | Select Name,DisplayName,Status,StartType | Export-Csv -path "$home\Desktop\Get-Service.csv" -Append -Encoding Default` экспортировать в csv (-Encoding UTF8) \ -`Import-Csv "$home\Desktop\Get-Service.csv" -Delimiter ","` импортировать массив - -`$data = ConvertFrom-Csv @"` \ -`Region,State,Units,Price` \ -`West,Texas,927,923.71` \ -`$null,Tennessee,466,770.67` \ -`"@` - -### ImportExcel -`Install-Module -Name ImportExcel` \ -`$data | Export-Excel .\Data.xlsx` \ -`$data = Import-Excel .\Data.xlsx` - -`$data = ps` \ -`$Chart = New-ExcelChartDefinition -XRange CPU -YRange WS -Title "Process" -NoLegend` \ -`$data | Export-Excel .\ps.xlsx -AutoNameRange -ExcelChartDefinition $Chart -Show` - -### Excel.Application -``` -$path = "$home\Desktop\Services-to-Excel.xlsx" -$Excel = New-Object -ComObject Excel.Application -$Excel.Visible = $false # отключить открытие GUI -$ExcelWorkBook = $Excel.Workbooks.Add() # Создать книгу -$ExcelWorkSheet = $ExcelWorkBook.Worksheets.Item(1) # Создать лист -$ExcelWorkSheet.Name = "Services" # задать имя листа -$ExcelWorkSheet.Cells.Item(1,1) = "Name service" -# Задать имена столбцов: -$ExcelWorkSheet.Cells.Item(1,2) = "Description" -$ExcelWorkSheet.Cells.Item(1,3) = "Status" -$ExcelWorkSheet.Cells.Item(1,4) = "Startup type" -$ExcelWorkSheet.Rows.Item(1).Font.Bold = $true # выделить жирным шрифтом -$ExcelWorkSheet.Rows.Item(1).Font.size=14 -# Задать ширину колонок: -$ExcelWorkSheet.Columns.Item(1).ColumnWidth=30 -$ExcelWorkSheet.Columns.Item(2).ColumnWidth=80 -$ExcelWorkSheet.Columns.Item(3).ColumnWidth=15 -$ExcelWorkSheet.Columns.Item(4).ColumnWidth=25 -$services = Get-Service -$counter = 2 # задать начальный номер строки для записи -foreach ($service in $services) { -$status = $service.Status -if ($status -eq 1) { -$status_type = "Stopped" -} elseif ($status -eq 4) { -$status_type = "Running" -} -$Start = $service.StartType -if ($Start -eq 1) { -$start_type = "Delayed start" -} elseif ($Start -eq 2) { -$start_type = "Automatic" -} elseif ($Start -eq 3) { -$start_type = "Manually" -} elseif ($Start -eq 4) { -$start_type = "Disabled" -} -$ExcelWorkSheet.Columns.Item(1).Rows.Item($counter) = $service.Name -$ExcelWorkSheet.Columns.Item(2).Rows.Item($counter) = $service.DisplayName -$ExcelWorkSheet.Columns.Item(3).Rows.Item($counter) = $status_type -$ExcelWorkSheet.Columns.Item(4).Rows.Item($counter) = $start_type -if ($status_type -eq "Running") { -$ExcelWorkSheet.Columns.Item(3).Rows.Item($counter).Font.Bold = $true -} -$counter++ # +1 увеличить для счетчика строки Rows -} -$ExcelWorkBook.SaveAs($path) -$ExcelWorkBook.close($true) -$Excel.Quit() - -$Excel = New-Object -ComObject Excel.Application -$Excel.Visible = $false -$ExcelWorkBook = $excel.Workbooks.Open($path) # открыть xlsx-файл -$ExcelWorkBook.Sheets | select Name,Index # отобразить листы -$ExcelWorkSheet = $ExcelWorkBook.Sheets.Item(1) # открыть лист по номеру Index -1..100 | %{$ExcelWorkSheet.Range("A$_").Text} # прочитать значение из столбца А строки c 1 по 100 -$Excel.Quit() -``` # Application ### Get-Package @@ -1436,277 +1276,6 @@ Error: 1722 - сервер rpc недоступен (ошибка отката `Set-VMHostSysLogServer -VMHost esxi-05 -SysLogServer "tcp://192.168.3.100" -SysLogServerPort 3515` \ `Get-VMHostSysLogServer -VMHost esxi-05` -# VBR - -`Set-ExecutionPolicy AllSigned` or Set-ExecutionPolicy Bypass -Scope Process \ -`Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))` \ -`choco install veeam-backup-and-replication-console` \ -`Get-Module Veeam.Backup.PowerShell` \ -`Get-Command -Module Veeam.Backup.PowerShell` or Get-VBRCommand \ -`Connect-VBRServer -Server $srv -Credential $cred` # or -User and -Password # - Port 9392 # default \ -`Get-VBRJob` \ -`Get-VBRCommand *get*backup*` \ -`Get-VBRComputerBackupJob` \ -`Get-VBRBackup` \ -`Get-VBRBackupRepository` \ -`Get-VBRBackupSession` \ -`Get-VBRBackupServerCertificate` \ -`Get-VBRRestorePoint` \ -`Get-VBRViProxy` - -# REST-API - -`$pars = Invoke-WebRequest -Uri $url` \ -`$pars | Get-Member` \ -`$pars.Content` \ -`$pars.StatusCode -eq 200` \ -`$pars.Headers` \ -`$pars.ParsedHtml | Select lastModified` \ -`$pars.Links | fl title,innerText,href` \ -`$pars.Images.src` links on images \ -`iwr $url -OutFile $path` download - -`$pars = wget -Uri $url` \ -`$pars.Images.src | %{` \ -`$name = $_ -replace ".+(?<=/)"` \ -`wget $_ -OutFile "$home\Pictures\$name"` \ -`}` \ -`$count_all = $pars.Images.src.Count` \ -`$count_down = (Get-Item $path\*).count` \ -`"Downloaded $count_down of $count_all files to $path"` - -Methods: \ -GET - Read \ -POST - Create \ -PATCH - Partial update/modify \ -PUT - Update/replace \ -DELETE - Remove - -`https://veeam-11:9419/swagger/ui/index.html` \ -`$Header = @{` \ -`"x-api-version" = "1.0-rev2"` \ -`}` \ -`$Body = @{` \ -`"grant_type" = "password"` \ -`"username" = "$login"` \ -`"password" = "$password"` \ -`}` \ -`$vpost = iwr "https://veeam-11:9419/api/oauth2/token" -Method POST -Headers $Header -Body $Body -SkipCertificateCheck` \ -`$vtoken = (($vpost.Content) -split '"')[3]` - -`$token = $vtoken | ConvertTo-SecureString -AsPlainText –Force` \ -`$vjob = iwr "https://veeam-11:9419/api/v1/jobs" -Method GET -Headers $Header -Authentication Bearer -Token $token -SkipCertificateCheck` - -`$Header = @{` \ -`"x-api-version" = "1.0-rev1"` \ -`"Authorization" = "Bearer $vtoken"` \ -`}` \ -`$vjob = iwr "https://veeam-11:9419/api/v1/jobs" -Method GET -Headers $Header -SkipCertificateCheck` \ -`$vjob = $vjob.Content | ConvertFrom-Json` - -`$vjob = Invoke-RestMethod "https://veeam-11:9419/api/v1/jobs" -Method GET -Headers $Header -SkipCertificateCheck` \ -`$vjob.data.virtualMachines.includes.inventoryObject` - -# Console-API - -`[Console] | Get-Member -Static` \ -`[Console]::BackgroundColor = "Blue"` -``` -do { -if ([Console]::KeyAvailable) { -$keyInfo = [Console]::ReadKey($true) -break -} -Write-Host "." -NoNewline -sleep 1 -} while ($true) -Write-Host -$keyInfo - -function Get-KeyPress { -param ( -[Parameter(Mandatory)][ConsoleKey]$Key, -[System.ConsoleModifiers]$ModifierKey = 0 -) -if ([Console]::KeyAvailable) { -$pressedKey = [Console]::ReadKey($true) -$isPressedKey = $key -eq $pressedKey.Key -if ($isPressedKey) { -$pressedKey.Modifiers -eq $ModifierKey -} else { -[Console]::Beep(1800, 200) -$false -}}} - -Write-Warning 'Press Ctrl+Shift+Q to exit' -do { -Write-Host "." -NoNewline -$pressed = Get-KeyPress -Key Q -ModifierKey 'Control,Shift' -if ($pressed) {break} -sleep 1 -} while ($true) -``` -### Windows-API - -`Add-Type -AssemblyName System.Windows.Forms` \ -`[int][System.Windows.Forms.Keys]::F1` - -`65..90 | % {"{0} = {1}" -f $_, [System.Windows.Forms.Keys]$_}` -``` -function Get-ControlKey { -$key = 112 -$Signature = @' -[DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)] -public static extern short GetAsyncKeyState(int virtualKeyCode); -'@ -Add-Type -MemberDefinition $Signature -Name Keyboard -Namespace PsOneApi -[bool]([PsOneApi.Keyboard]::GetAsyncKeyState($key) -eq -32767) -} - -Write-Warning 'Press F1 to exit' -do { -Write-Host '.' -NoNewline -$pressed = Get-ControlKey -if ($pressed) { break } -Start-Sleep -Seconds 1 -} while ($true) -``` -### [Clicker] -``` -$cSource = @' -using System; -using System.Drawing; -using System.Runtime.InteropServices; -using System.Windows.Forms; -public class Clicker -{ -//https://msdn.microsoft.com/en-us/library/windows/desktop/ms646270(v=vs.85).aspx -[StructLayout(LayoutKind.Sequential)] -struct INPUT -{ - public int type; // 0 = INPUT_MOUSE, - // 1 = INPUT_KEYBOARD - // 2 = INPUT_HARDWARE - public MOUSEINPUT mi; -} -//https://msdn.microsoft.com/en-us/library/windows/desktop/ms646273(v=vs.85).aspx -[StructLayout(LayoutKind.Sequential)] -struct MOUSEINPUT -{ - public int dx ; - public int dy ; - public int mouseData ; - public int dwFlags; - public int time; - public IntPtr dwExtraInfo; -} -//This covers most use cases although complex mice may have additional buttons -//There are additional constants you can use for those cases, see the msdn page -const int MOUSEEVENTF_MOVED = 0x0001 ; -const int MOUSEEVENTF_LEFTDOWN = 0x0002 ; -const int MOUSEEVENTF_LEFTUP = 0x0004 ; -const int MOUSEEVENTF_RIGHTDOWN = 0x0008 ; -const int MOUSEEVENTF_RIGHTUP = 0x0010 ; -const int MOUSEEVENTF_MIDDLEDOWN = 0x0020 ; -const int MOUSEEVENTF_MIDDLEUP = 0x0040 ; -const int MOUSEEVENTF_WHEEL = 0x0080 ; -const int MOUSEEVENTF_XDOWN = 0x0100 ; -const int MOUSEEVENTF_XUP = 0x0200 ; -const int MOUSEEVENTF_ABSOLUTE = 0x8000 ; -const int screen_length = 0x10000 ; -//https://msdn.microsoft.com/en-us/library/windows/desktop/ms646310(v=vs.85).aspx -[System.Runtime.InteropServices.DllImport("user32.dll")] -extern static uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize); -public static void LeftClickAtPoint(int x, int y) -{ - //Move the mouse - INPUT[] input = new INPUT[3]; - input[0].mi.dx = x*(65535/System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width); - input[0].mi.dy = y*(65535/System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height); - input[0].mi.dwFlags = MOUSEEVENTF_MOVED | MOUSEEVENTF_ABSOLUTE; - //Left mouse button down - input[1].mi.dwFlags = MOUSEEVENTF_LEFTDOWN; - //Left mouse button up - input[2].mi.dwFlags = MOUSEEVENTF_LEFTUP; - SendInput(3, input, Marshal.SizeOf(input[0])); -} -} -'@ -``` -`Add-Type -TypeDefinition $cSource -ReferencedAssemblies System.Windows.Forms,System.Drawing` \ -`[Clicker]::LeftClickAtPoint(1900,1070)` - -### [Audio] -``` -Add-Type -Language CsharpVersion3 -TypeDefinition @" -using System.Runtime.InteropServices; -[Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] -interface IAudioEndpointVolume { -// f(), g(), ... are unused COM method slots. Define these if you care -int f(); int g(); int h(); int i(); -int SetMasterVolumeLevelScalar(float fLevel, System.Guid pguidEventContext); -int j(); -int GetMasterVolumeLevelScalar(out float pfLevel); -int k(); int l(); int m(); int n(); -int SetMute([MarshalAs(UnmanagedType.Bool)] bool bMute, System.Guid pguidEventContext); -int GetMute(out bool pbMute); -} -[Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] -interface IMMDevice { -int Activate(ref System.Guid id, int clsCtx, int activationParams, out IAudioEndpointVolume aev); -} -[Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] -interface IMMDeviceEnumerator { -int f(); // Unused -int GetDefaultAudioEndpoint(int dataFlow, int role, out IMMDevice endpoint); -} -[ComImport, Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")] class MMDeviceEnumeratorComObject { } -public class Audio { -static IAudioEndpointVolume Vol() { -var enumerator = new MMDeviceEnumeratorComObject() as IMMDeviceEnumerator; -IMMDevice dev = null; -Marshal.ThrowExceptionForHR(enumerator.GetDefaultAudioEndpoint(/*eRender*/ 0, /*eMultimedia*/ 1, out dev)); -IAudioEndpointVolume epv = null; -var epvid = typeof(IAudioEndpointVolume).GUID; -Marshal.ThrowExceptionForHR(dev.Activate(ref epvid, /*CLSCTX_ALL*/ 23, 0, out epv)); -return epv; -} -public static float Volume { -get {float v = -1; Marshal.ThrowExceptionForHR(Vol().GetMasterVolumeLevelScalar(out v)); return v;} -set {Marshal.ThrowExceptionForHR(Vol().SetMasterVolumeLevelScalar(value, System.Guid.Empty));} -} -public static bool Mute { -get { bool mute; Marshal.ThrowExceptionForHR(Vol().GetMute(out mute)); return mute; } -set { Marshal.ThrowExceptionForHR(Vol().SetMute(value, System.Guid.Empty)); } -} -} -"@ -``` -`[Audio]::Volume = 0.50` \ -`[Audio]::Mute = $true` - -### Register-Event - -`Register-EngineEvent` регистрирует подписку на события PowerShell или New-Event и создает задание (Get-Job) \ -`Register-EngineEvent -SourceIdentifier PowerShell.Exiting -Action {` \ -`$date = Get-Date -f hh:mm:ss; (New-Object -ComObject Wscript.Shell).Popup("PowerShell Exit: $date",0,"Action",64)` \ -`}` \ -`-SupportEvent` не выводит результат регистрации события на экран, в Get-EventSubscriber и Get-Job \ -`-Forward` перенаправляет события из удаленного сеанса (New-PSSession) в локальный сеанс - -`Register-ObjectEvent` регистрирует подписку на события объектов .NET \ -`$System_Obj | Get-Member -MemberType Event` отобразить список всех событий объекта \ -`Register-ObjectEvent -InputObject $System_Obj -EventName Click -SourceIdentifier SrvListClick -Action {` \ -`Write-Host $System_Obj.Text` \ -`}` \ -`Get-EventSubscriber` список зарегистрированных подписок на события в текущей сессии \ -`Unregister-Event -SourceIdentifier SrvListClick` удаляет регистрацию подписки на событие по имени события (или все *) \ -`Remove-Job -Name SrvListClick` удаляет задание \ -`-InputObject` объект или переменная, хранящая объект \ -`-EventName` событие (например, Click,MouseClick) \ -`-SourceIdentifier` название регистрируемого события \ -`-Action` действие при возникновении события - # EMShell `$srv_cas = "exchange-cas"` \ @@ -2063,6 +1632,439 @@ CopyQueue Length - длина репликационной очереди коп `Get-MailboxDatabaseCopyStatus * | where {$_.ContentIndexState -eq "Failed" -or $_.ContentIndexState -eq "FailedAndSuspended"}` отобразить у какой БД произошел сбой работы (FailedAndSuspended) или индекса (ContentIndexState) +# VBR + +`Set-ExecutionPolicy AllSigned` or Set-ExecutionPolicy Bypass -Scope Process \ +`Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))` \ +`choco install veeam-backup-and-replication-console` \ +`Get-Module Veeam.Backup.PowerShell` \ +`Get-Command -Module Veeam.Backup.PowerShell` or Get-VBRCommand \ +`Connect-VBRServer -Server $srv -Credential $cred` # or -User and -Password # - Port 9392 # default \ +`Get-VBRJob` \ +`Get-VBRCommand *get*backup*` \ +`Get-VBRComputerBackupJob` \ +`Get-VBRBackup` \ +`Get-VBRBackupRepository` \ +`Get-VBRBackupSession` \ +`Get-VBRBackupServerCertificate` \ +`Get-VBRRestorePoint` \ +`Get-VBRViProxy` + +# REST-API + +`$pars = Invoke-WebRequest -Uri $url` \ +`$pars | Get-Member` \ +`$pars.Content` \ +`$pars.StatusCode -eq 200` \ +`$pars.Headers` \ +`$pars.ParsedHtml | Select lastModified` \ +`$pars.Links | fl title,innerText,href` \ +`$pars.Images.src` links on images \ +`iwr $url -OutFile $path` download + +`$pars = wget -Uri $url` \ +`$pars.Images.src | %{` \ +`$name = $_ -replace ".+(?<=/)"` \ +`wget $_ -OutFile "$home\Pictures\$name"` \ +`}` \ +`$count_all = $pars.Images.src.Count` \ +`$count_down = (Get-Item $path\*).count` \ +`"Downloaded $count_down of $count_all files to $path"` + +Methods: \ +GET - Read \ +POST - Create \ +PATCH - Partial update/modify \ +PUT - Update/replace \ +DELETE - Remove + +`https://veeam-11:9419/swagger/ui/index.html` \ +`$Header = @{` \ +`"x-api-version" = "1.0-rev2"` \ +`}` \ +`$Body = @{` \ +`"grant_type" = "password"` \ +`"username" = "$login"` \ +`"password" = "$password"` \ +`}` \ +`$vpost = iwr "https://veeam-11:9419/api/oauth2/token" -Method POST -Headers $Header -Body $Body -SkipCertificateCheck` \ +`$vtoken = (($vpost.Content) -split '"')[3]` + +`$token = $vtoken | ConvertTo-SecureString -AsPlainText –Force` \ +`$vjob = iwr "https://veeam-11:9419/api/v1/jobs" -Method GET -Headers $Header -Authentication Bearer -Token $token -SkipCertificateCheck` + +`$Header = @{` \ +`"x-api-version" = "1.0-rev1"` \ +`"Authorization" = "Bearer $vtoken"` \ +`}` \ +`$vjob = iwr "https://veeam-11:9419/api/v1/jobs" -Method GET -Headers $Header -SkipCertificateCheck` \ +`$vjob = $vjob.Content | ConvertFrom-Json` + +`$vjob = Invoke-RestMethod "https://veeam-11:9419/api/v1/jobs" -Method GET -Headers $Header -SkipCertificateCheck` \ +`$vjob.data.virtualMachines.includes.inventoryObject` + +# Console-API + +`[Console] | Get-Member -Static` \ +`[Console]::BackgroundColor = "Blue"` +``` +do { +if ([Console]::KeyAvailable) { +$keyInfo = [Console]::ReadKey($true) +break +} +Write-Host "." -NoNewline +sleep 1 +} while ($true) +Write-Host +$keyInfo + +function Get-KeyPress { +param ( +[Parameter(Mandatory)][ConsoleKey]$Key, +[System.ConsoleModifiers]$ModifierKey = 0 +) +if ([Console]::KeyAvailable) { +$pressedKey = [Console]::ReadKey($true) +$isPressedKey = $key -eq $pressedKey.Key +if ($isPressedKey) { +$pressedKey.Modifiers -eq $ModifierKey +} else { +[Console]::Beep(1800, 200) +$false +}}} + +Write-Warning 'Press Ctrl+Shift+Q to exit' +do { +Write-Host "." -NoNewline +$pressed = Get-KeyPress -Key Q -ModifierKey 'Control,Shift' +if ($pressed) {break} +sleep 1 +} while ($true) +``` +### Windows-API + +`Add-Type -AssemblyName System.Windows.Forms` \ +`[int][System.Windows.Forms.Keys]::F1` + +`65..90 | % {"{0} = {1}" -f $_, [System.Windows.Forms.Keys]$_}` +``` +function Get-ControlKey { +$key = 112 +$Signature = @' +[DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)] +public static extern short GetAsyncKeyState(int virtualKeyCode); +'@ +Add-Type -MemberDefinition $Signature -Name Keyboard -Namespace PsOneApi +[bool]([PsOneApi.Keyboard]::GetAsyncKeyState($key) -eq -32767) +} + +Write-Warning 'Press F1 to exit' +do { +Write-Host '.' -NoNewline +$pressed = Get-ControlKey +if ($pressed) { break } +Start-Sleep -Seconds 1 +} while ($true) +``` +### [Clicker] +``` +$cSource = @' +using System; +using System.Drawing; +using System.Runtime.InteropServices; +using System.Windows.Forms; +public class Clicker +{ +//https://msdn.microsoft.com/en-us/library/windows/desktop/ms646270(v=vs.85).aspx +[StructLayout(LayoutKind.Sequential)] +struct INPUT +{ + public int type; // 0 = INPUT_MOUSE, + // 1 = INPUT_KEYBOARD + // 2 = INPUT_HARDWARE + public MOUSEINPUT mi; +} +//https://msdn.microsoft.com/en-us/library/windows/desktop/ms646273(v=vs.85).aspx +[StructLayout(LayoutKind.Sequential)] +struct MOUSEINPUT +{ + public int dx ; + public int dy ; + public int mouseData ; + public int dwFlags; + public int time; + public IntPtr dwExtraInfo; +} +//This covers most use cases although complex mice may have additional buttons +//There are additional constants you can use for those cases, see the msdn page +const int MOUSEEVENTF_MOVED = 0x0001 ; +const int MOUSEEVENTF_LEFTDOWN = 0x0002 ; +const int MOUSEEVENTF_LEFTUP = 0x0004 ; +const int MOUSEEVENTF_RIGHTDOWN = 0x0008 ; +const int MOUSEEVENTF_RIGHTUP = 0x0010 ; +const int MOUSEEVENTF_MIDDLEDOWN = 0x0020 ; +const int MOUSEEVENTF_MIDDLEUP = 0x0040 ; +const int MOUSEEVENTF_WHEEL = 0x0080 ; +const int MOUSEEVENTF_XDOWN = 0x0100 ; +const int MOUSEEVENTF_XUP = 0x0200 ; +const int MOUSEEVENTF_ABSOLUTE = 0x8000 ; +const int screen_length = 0x10000 ; +//https://msdn.microsoft.com/en-us/library/windows/desktop/ms646310(v=vs.85).aspx +[System.Runtime.InteropServices.DllImport("user32.dll")] +extern static uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize); +public static void LeftClickAtPoint(int x, int y) +{ + //Move the mouse + INPUT[] input = new INPUT[3]; + input[0].mi.dx = x*(65535/System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width); + input[0].mi.dy = y*(65535/System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height); + input[0].mi.dwFlags = MOUSEEVENTF_MOVED | MOUSEEVENTF_ABSOLUTE; + //Left mouse button down + input[1].mi.dwFlags = MOUSEEVENTF_LEFTDOWN; + //Left mouse button up + input[2].mi.dwFlags = MOUSEEVENTF_LEFTUP; + SendInput(3, input, Marshal.SizeOf(input[0])); +} +} +'@ +``` +`Add-Type -TypeDefinition $cSource -ReferencedAssemblies System.Windows.Forms,System.Drawing` \ +`[Clicker]::LeftClickAtPoint(1900,1070)` + +### [Audio] +``` +Add-Type -Language CsharpVersion3 -TypeDefinition @" +using System.Runtime.InteropServices; +[Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] +interface IAudioEndpointVolume { +// f(), g(), ... are unused COM method slots. Define these if you care +int f(); int g(); int h(); int i(); +int SetMasterVolumeLevelScalar(float fLevel, System.Guid pguidEventContext); +int j(); +int GetMasterVolumeLevelScalar(out float pfLevel); +int k(); int l(); int m(); int n(); +int SetMute([MarshalAs(UnmanagedType.Bool)] bool bMute, System.Guid pguidEventContext); +int GetMute(out bool pbMute); +} +[Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] +interface IMMDevice { +int Activate(ref System.Guid id, int clsCtx, int activationParams, out IAudioEndpointVolume aev); +} +[Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] +interface IMMDeviceEnumerator { +int f(); // Unused +int GetDefaultAudioEndpoint(int dataFlow, int role, out IMMDevice endpoint); +} +[ComImport, Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")] class MMDeviceEnumeratorComObject { } +public class Audio { +static IAudioEndpointVolume Vol() { +var enumerator = new MMDeviceEnumeratorComObject() as IMMDeviceEnumerator; +IMMDevice dev = null; +Marshal.ThrowExceptionForHR(enumerator.GetDefaultAudioEndpoint(/*eRender*/ 0, /*eMultimedia*/ 1, out dev)); +IAudioEndpointVolume epv = null; +var epvid = typeof(IAudioEndpointVolume).GUID; +Marshal.ThrowExceptionForHR(dev.Activate(ref epvid, /*CLSCTX_ALL*/ 23, 0, out epv)); +return epv; +} +public static float Volume { +get {float v = -1; Marshal.ThrowExceptionForHR(Vol().GetMasterVolumeLevelScalar(out v)); return v;} +set {Marshal.ThrowExceptionForHR(Vol().SetMasterVolumeLevelScalar(value, System.Guid.Empty));} +} +public static bool Mute { +get { bool mute; Marshal.ThrowExceptionForHR(Vol().GetMute(out mute)); return mute; } +set { Marshal.ThrowExceptionForHR(Vol().SetMute(value, System.Guid.Empty)); } +} +} +"@ +``` +`[Audio]::Volume = 0.50` \ +`[Audio]::Mute = $true` + +### Register-Event + +`Register-EngineEvent` регистрирует подписку на события PowerShell или New-Event и создает задание (Get-Job) \ +`Register-EngineEvent -SourceIdentifier PowerShell.Exiting -Action {` \ +`$date = Get-Date -f hh:mm:ss; (New-Object -ComObject Wscript.Shell).Popup("PowerShell Exit: $date",0,"Action",64)` \ +`}` \ +`-SupportEvent` не выводит результат регистрации события на экран, в Get-EventSubscriber и Get-Job \ +`-Forward` перенаправляет события из удаленного сеанса (New-PSSession) в локальный сеанс + +`Register-ObjectEvent` регистрирует подписку на события объектов .NET \ +`$System_Obj | Get-Member -MemberType Event` отобразить список всех событий объекта \ +`Register-ObjectEvent -InputObject $System_Obj -EventName Click -SourceIdentifier SrvListClick -Action {` \ +`Write-Host $System_Obj.Text` \ +`}` \ +`Get-EventSubscriber` список зарегистрированных подписок на события в текущей сессии \ +`Unregister-Event -SourceIdentifier SrvListClick` удаляет регистрацию подписки на событие по имени события (или все *) \ +`Remove-Job -Name SrvListClick` удаляет задание \ +`-InputObject` объект или переменная, хранящая объект \ +`-EventName` событие (например, Click,MouseClick) \ +`-SourceIdentifier` название регистрируемого события \ +`-Action` действие при возникновении события + +# Convert-Language + +### HTML (HyperText Markup Language) +`Get-Process | select Name, CPU | ConvertTo-HTML -As Table > "$home\desktop\proc-table.html"` вывод в формате List (Format-List) или Table (Format-Table) + +### XML (Extensible Markup Language) + +`$xml = [xml](Get-Content ~\desktop\home.rdg)` прочитать содержимое xml-файла \ +`$xml = New-Object System.Xml.XmlDocument` создать пустой xml объект \ +`$file = Resolve-Path("~\desktop\home.rdg")` забрать путь к файлу \ +`$xml.load($file)` открыть файл \ +`$xml | Select-Xml "//RDCMan/file/group/server/properties"` \ +`$xml.RDCMan.file.group.server.properties` \ +`$xml.RDCMan.file.group.server[1].properties` \ +`$xml.RDCMan.file.group.server[1].properties.displayName = "plex-02"` изменить значение \ +`$xml.RDCMan.file.group.server[1].properties.name = "192.168.3.200"` \ +`$xml.RDCMan.file.group.server[0].RemoveAll()` \ +`$xml.Save($file)` сохранить содержимое объекта в файла + +`Export-CliXml` экспортировать объект powershell в xml \ +`Import-Clixml` импортировать объект xml в powershell +``` +if (Test-Path $CredFile) { +$Cred = Import-Clixml -path $CredFile +} elseif (!(Test-Path $CredFile)) { +$Cred = Get-Credential -Message "Enter credential" +if ($Cred -ne $null) { +$Cred | Export-CliXml -Path $CredFile +} else { +return +} +} + +$FilterXPath = '' +$RDPAuths = Get-WinEvent -ComputerName $srv -LogName "Microsoft-Windows-TerminalServices-LocalSessionManager/Operational" -FilterXPath $FilterXPath +[xml[]]$xml = $RDPAuths | Foreach {$_.ToXml()} +$EventData = Foreach ($event in $xml.Event) { +New-Object PSObject -Property @{ +"Connection Time" = (Get-Date ($event.System.TimeCreated.SystemTime) -Format 'yyyy-MM-dd hh:mm K') +"User Name" = $event.UserData.EventXML.User +"User ID" = $event.UserData.EventXML.SessionID +"User Address" = $event.UserData.EventXML.Address +"Event ID" = $event.System.EventID +}} +$EventData +``` +### JSON (JavaScript Object Notation) +``` +log = +{ + level = 7; +}; + +$log = [xml]" + 7 +" + +$log = '{ + "log": { + "level": 7 + } +}' | ConvertFrom-Json +``` +`Invoke-RestMethod -Uri "https://jsonplaceholder.typicode.com/posts" -Method Get` GET-запрос для получения объекта JSON + +### YAML (Yet Another Markup Language) +``` +Import-Module PSYaml +$network = " +network: + ethernets: + ens160: + dhcp4: yes + dhcp6: no + nameservers: + addresses: # [8.8.8.8, 1.1.1.1] + - 8.8.8.8 + - 1.1.1.1 + version: 2 +" +$Result = ConvertFrom-Yaml $network +$Result.Values.ethernets.ens160.nameservers +``` +### CSV (Comma-Separated Values) +`Get-Service | Select Name,DisplayName,Status,StartType | Export-Csv -path "$home\Desktop\Get-Service.csv" -Append -Encoding Default` экспортировать в csv (-Encoding UTF8) \ +`Import-Csv "$home\Desktop\Get-Service.csv" -Delimiter ","` импортировать массив + +`$data = ConvertFrom-Csv @"` \ +`Region,State,Units,Price` \ +`West,Texas,927,923.71` \ +`$null,Tennessee,466,770.67` \ +`"@` + +### Excel.Application +``` +$path = "$home\Desktop\Services-to-Excel.xlsx" +$Excel = New-Object -ComObject Excel.Application +$Excel.Visible = $false # отключить открытие GUI +$ExcelWorkBook = $Excel.Workbooks.Add() # Создать книгу +$ExcelWorkSheet = $ExcelWorkBook.Worksheets.Item(1) # Создать лист +$ExcelWorkSheet.Name = "Services" # задать имя листа +$ExcelWorkSheet.Cells.Item(1,1) = "Name service" +# Задать имена столбцов: +$ExcelWorkSheet.Cells.Item(1,2) = "Description" +$ExcelWorkSheet.Cells.Item(1,3) = "Status" +$ExcelWorkSheet.Cells.Item(1,4) = "Startup type" +$ExcelWorkSheet.Rows.Item(1).Font.Bold = $true # выделить жирным шрифтом +$ExcelWorkSheet.Rows.Item(1).Font.size=14 +# Задать ширину колонок: +$ExcelWorkSheet.Columns.Item(1).ColumnWidth=30 +$ExcelWorkSheet.Columns.Item(2).ColumnWidth=80 +$ExcelWorkSheet.Columns.Item(3).ColumnWidth=15 +$ExcelWorkSheet.Columns.Item(4).ColumnWidth=25 +$services = Get-Service +$counter = 2 # задать начальный номер строки для записи +foreach ($service in $services) { +$status = $service.Status +if ($status -eq 1) { +$status_type = "Stopped" +} elseif ($status -eq 4) { +$status_type = "Running" +} +$Start = $service.StartType +if ($Start -eq 1) { +$start_type = "Delayed start" +} elseif ($Start -eq 2) { +$start_type = "Automatic" +} elseif ($Start -eq 3) { +$start_type = "Manually" +} elseif ($Start -eq 4) { +$start_type = "Disabled" +} +$ExcelWorkSheet.Columns.Item(1).Rows.Item($counter) = $service.Name +$ExcelWorkSheet.Columns.Item(2).Rows.Item($counter) = $service.DisplayName +$ExcelWorkSheet.Columns.Item(3).Rows.Item($counter) = $status_type +$ExcelWorkSheet.Columns.Item(4).Rows.Item($counter) = $start_type +if ($status_type -eq "Running") { +$ExcelWorkSheet.Columns.Item(3).Rows.Item($counter).Font.Bold = $true +} +$counter++ # +1 увеличить для счетчика строки Rows +} +$ExcelWorkBook.SaveAs($path) +$ExcelWorkBook.close($true) +$Excel.Quit() + +$Excel = New-Object -ComObject Excel.Application +$Excel.Visible = $false +$ExcelWorkBook = $excel.Workbooks.Open($path) # открыть xlsx-файл +$ExcelWorkBook.Sheets | select Name,Index # отобразить листы +$ExcelWorkSheet = $ExcelWorkBook.Sheets.Item(1) # открыть лист по номеру Index +1..100 | %{$ExcelWorkSheet.Range("A$_").Text} # прочитать значение из столбца А строки c 1 по 100 +$Excel.Quit() +``` +### ImportExcel +`Install-Module -Name ImportExcel` \ +`$data | Export-Excel .\Data.xlsx` \ +`$data = Import-Excel .\Data.xlsx` + +`$data = ps` \ +`$Chart = New-ExcelChartDefinition -XRange CPU -YRange WS -Title "Process" -NoLegend` \ +`$data | Export-Excel .\ps.xlsx -AutoNameRange -ExcelChartDefinition $Chart -Show` + # Git `git --version`