# make sure you have exactly ONE object $info = Get-ComputerInfo # find names of non-empty properties $filledProperties = $info.PSObject.Properties.Name.Where{![string]::IsNullOrWhiteSpace($info.$_)} | Sort-Object # turn object into a hash table and show in a grid view window $filledProperties | ForEach-Object { $hash = [Ordered]@{} } { $hash[$_] = $info.$_ } { $hash } | Out-GridView
# get all WMI information $os = Get-CimInstance-ClassName Win32_OperatingSystem # find names of non-empty properties $filledProperties = $os.PSObject.Properties.Name.Where{![string]::IsNullOrWhiteSpace($os.$_)} | Sort-Object # show non-empty properties only $os | Select-Object-Property$filledProperties
functionInvoke-WakeOnLan { param ( # one or more MAC addresses [Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)] # MAC address must be a following this regex pattern [ValidatePattern('^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$')] [string[]] $MacAddress )
begin { # instantiate a UDP client $UDPclient = [System.Net.Sockets.UdpClient]::new() } process { foreach ($_in$MacAddress) { try { $currentMacAddress = $_
# get byte array from MAC address $mac = $currentMacAddress-split'[:-]' | # convert the hex number into byte ForEach-Object { [System.Convert]::ToByte($_, 16) }
#region compose the "magic packet"
# create a byte array with 102 bytes initialized to 255 each $packet = [byte[]](,0xFF * 102)
# leave the first 6 bytes untouched, and # repeat the target MAC address bytes in bytes 7 through 102 6..101 | ForEach-Object { # $_ is indexing in the byte array, # $_ % 6 produces repeating indices between 0 and 5 # (modulo operator) $packet[$_] = $mac[($_ % 6)] }
#endregion
# connect to port 4000 on broadcast address $UDPclient.Connect(([System.Net.IPAddress]::Broadcast),4000)
# send the magic packet to the broadcast address $null = $UDPclient.Send($packet, $packet.Length) Write-Verbose"Sent magic packet to $currentMacAddress..." } catch { Write-Warning"Unable to send ${mac}: $_" } } } end { # release the UDP client and free its memory $UDPclient.Close() $UDPclient.Dispose() } }
# define constructor with parameter for ID AutoLearnAttribute([string]$Id) : base() { $this.Id = $Id }
# Transform() is called whenever there is a variable or parameter assignment, # and returns the value that is actually assigned [object] Transform([System.Management.Automation.EngineIntrinsics]$engineIntrinsics, [object] $inputData) { # make sure the folder with hints exists $exists = Test-Path-Path$this.Path if (!$exists) { $null = New-Item-Path$this.Path -ItemType Directory }
# create a filename for hint list $filename = '{0}.hint'-f$this.Id $hintPath = Join-Path-Path$this.Path -ChildPath$filename
# use a hash table to keep hint list $hints = @{}
# read hint list if it exists $exists = Test-Path-Path$hintPath if ($exists) { Get-Content-Path$hintPath-Encoding Default | # remove leading and trailing blanks ForEach-Object { $_.Trim() } | # remove empty lines Where-Object { ![string]::IsNullOrEmpty($_) } | # add to hash table ForEach-Object { # value is not used, set it to $true $hints[$_] = $true } }
# does the user input start with the clearing key? if ($inputData.StartsWith($this.ClearKey)) { # remove the prefix $inputData = $inputData.SubString(1)
# clear the hint list $hints.Clear() }
# add new value to hint list if(![string]::IsNullOrWhiteSpace($inputData)) { $hints[$inputData] = $true } # save hints list $hints.Keys | Sort-Object | Set-Content-Path$hintPath-Encoding Default
# return the user input (if there was a clearing key at its start, # it is now stripped) return$inputData } }
# define [AutoComplete()] classAutoCompleteAttribute : System.Management.Automation.ArgumentCompleterAttribute { # define path to store hint lists [string]$Path = "$env:temp\hints"
# define ID to manage multiple hint lists [string]$Id = 'default'
# define constructor with parameter for ID AutoCompleteAttribute([string]$Id) : base([AutoCompleteAttribute]::_createScriptBlock($this)) { $this.Id = $Id }
# create a static helper method that creates the script block that the base constructor needs # this is necessary to be able to access the argument(s) submitted to the constructor # the method needs a reference to the object instance to (later) access its optional parameters hiddenstatic[ScriptBlock] _createScriptBlock([AutoCompleteAttribute] $instance) { $scriptblock = { # receive information about current state param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
# create filename for hint list $filename = '{0}.hint'-f$instance.Id $hintPath = Join-Path-Path$instance.Path -ChildPath$filename
# use a hash table to keep hint list $hints = @{}
# read hint list if it exists $exists = Test-Path-Path$hintPath if ($exists) { Get-Content-Path$hintPath-Encoding Default | # remove leading and trailing blanks ForEach-Object { $_.Trim() } | # remove empty lines Where-Object { ![string]::IsNullOrEmpty($_) } | # filter completion items based on existing text Where-Object { $_.LogName -like"$wordToComplete*" } | # create argument completion results Foreach-Object { [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) } } }.GetNewClosure() return$scriptblock } }