From 6c351eae5888dad1d53942c694014481e1d9def4 Mon Sep 17 00:00:00 2001
From: Alex Kup <116945542+Lifailon@users.noreply.github.com>
Date: Tue, 18 Apr 2023 13:21:00 +0300
Subject: [PATCH] Update README.md
---
README.md | 868 +++++++++++++++++++++++++++---------------------------
1 file changed, 435 insertions(+), 433 deletions(-)
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`