Test Web Site Availability

When a web site is unavailable, often the question is whether it’s you, or whether the web site is generally down for everyone else, too. PowerShell can ask a web service to check web site availability for you. Here is a simple wrapper function:

function Test-Url
{
  param
  (
    [Parameter(Mandatory,ValueFromPipeline)]
    [string]
    $Url
  )
  
  Add-Type -AssemblyName System.Web
  
  $check = "https://isitdown.site/api/v3/"
  $encoded = [System.Web.HttpUtility]::UrlEncode($url)
  $callUrl = "$check$encoded"
  
  Invoke-RestMethod -Uri $callUrl |
    Select-Object -Property Host, IsItDown, Response_Code
}

It calls a RESTful API and submits the URL to check via URL arguments. That’s why the URL to test needs to be URL-encoded. Next, the code calls Invoke-RestMethod and received the test result as an object.

 
PS C:> Test-Url -Url powershellmagazine.com

host                   isitdown response_code
----                   -------- -------------
powershellmagazine.com    False           200
 

Please note that the web service used in this example is free, and does not require registration or an API key. The downside is that the web service is throttled, so if you check a large number of URLs, it may respond with an exception stating that you submitted too many requests. When this happens, just wait a moment and try again.


psconf.eu – PowerShell Conference EU 2019 – June 4-7, Hannover Germany – visit www.psconf.eu There aren’t too many trainings around for experienced PowerShell scripters where you really still learn something new. But there’s one place you don’t want to miss: PowerShell Conference EU – with 40 renown international speakers including PowerShell team members and MVPs, plus 350 professional and creative PowerShell scripters. Registration is open at www.psconf.eu, and the full 3-track 4-days agenda becomes available soon. Once a year it’s just a smart move to come together, update know-how, learn about security and mitigations, and bring home fresh ideas and authoritative guidance. We’d sure love to see and hear from you!

Twitter This Tip! ReTweet this Tip!

Unit Conversion via Web Service

Accessing RESTful web services is trivial for PowerShell: simply send your input data to a public web service, and receive the results.

Here are three PowerShell functions designed to each do a numeric conversion:

function Convert-InchToCentimeter
{
  param
  (
    [Parameter(Mandatory)]
    [Double]
    $Inch
  )
  [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
  $url = 'https://ucum.nlm.nih.gov/ucum-service/v1/ucumtransform/{0}/from/%5Bin_i%5D/to/cm' -f $Inch
  $result = Invoke-RestMethod -Uri $url -UseBasicParsing 
  $result.UCUMWebServiceResponse.Response
}


function Convert-FootToMicrometer
{
  param
  (
    [Parameter(Mandatory)]
    [Double]
    $Foot
  )
  [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
  $url = 'https://ucum.nlm.nih.gov/ucum-service/v1/ucumtransform/{0}/from/%5Bft_i%5D/to/um' -f $Foot
  $result = Invoke-RestMethod -Uri $url -UseBasicParsing 
  $result.UCUMWebServiceResponse.Response
}


function Convert-GramToOunce
{
  param
  (
    [Parameter(Mandatory)]
    [Double]
    $Gram
  )
  [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
  $url = 'https://ucum.nlm.nih.gov/ucum-service/v1/ucumtransform/{0}/from/g/to/%5Boz_ap%5D' -f $Gram
  $result = Invoke-RestMethod -Uri $url -UseBasicParsing 
  $result.UCUMWebServiceResponse.Response
}

Provided you have Internet access, then doing conversions is as simple as a function call:

 
PS C:> Convert-GramToOunce -Gram 230

SourceQuantity SourceUnit TargetUnit ResultQuantity
-------------- ---------- ---------- --------------
230.0          g          [oz_ap]    7.3946717   
 

The important points to keep in mind are:

  • You need to allow Tls12 to enable HTTPS connections (see code)
  • You need to follow the rules set forth by the web service, i.e. when it requires whole numbers, you cannot submit decimals

There are plenty more conversions available at https://ucum.nlm.nih.gov/ucum-service.html#conversion, so you can use the functions provided as a template to create more conversion functions.


Twitter This Tip! ReTweet this Tip!

Validating Active Directory Credentials

PowerShell can validate AD username and passwords against the Active Directory:

Add-Type -AssemblyName System.DirectoryServices.AccountManagement
$account = New-Object System.DirectoryServices.AccountManagement.PrincipalContext([DirectoryServices.AccountManagement.ContextType]::Domain, $env:userdomain)

$account.ValidateCredentials('user12', 'topSecret')

Note that this approach is for diagnostic purposes only. It accepts a plain text password.


Twitter This Tip! ReTweet this Tip!

Numbering Output (Part 1)

If you’d like to add an incrementing number to your output, here is a simple way:

Get-Process |
  Select-Object -Property '#', ProcessName, CPU -First 10 |
  ForEach-Object -begin { $i = 0} -process {
    $i++
    $_.'#' = $i
    $_
  } -end {}

Select-Object adds a new property called “#”, and ForEach-Object adds an auto-incrementing number to it. The result looks similar to this:

 
 # ProcessName               CPU
 - -----------               ---
 1 AdobeCollabSync       65,5625
 2 AdobeCollabSync           0,5
 3 AGMService            
...
 

Twitter This Tip! ReTweet this Tip!

Accepting Masked Passwords

If you ever write PowerShell functions that need to accept sensitive input such as passwords, make sure you allow users to submit SecureString input. If you accept passwords via clear text, there is a substantial risk that others may see the password while being entered, or (even worse) that the password is logged and later can be found in dump files.

Here is a simple framework that illustrates how you can achieve safe input:

function Enter-Secret
{
    param
    (
        [Parameter(Mandatory)]
        [SecureString]
        $SafeInput
    )

    $PlainText = [Management.Automation.PSCredential]::
    new('x',$SafeInput).GetNetworkCredential().Password

    "User entered $PlainText"

}

When the user runs Enter-Secret, the password can be entered in a masked way. Internally, the function converts the secure string into plain text. This way, the secret password is never visible and will never be logged.

The conversion from SecureString to String is performed by creating a temporary credential object. Credential objects have a built-in method (GetNetworkCredential()) to convert a SecureString to a String.


Twitter This Tip! ReTweet this Tip!

Finding Hidden PowerShell Applications

The most widely known PowerShell hosts are certainly powershell.exe and powershell_ise.exe because they ship out-of-the-box. However, there can be many more (and hidden) PowerShell hosts running. Any software that instantiates the PowerShell engine is a PowerShell host. This could be Visual Studio Code (with the PowerShell extension installed), Visual Studio, or any other similar software.

To find out all currently running PowerShell hosts, run this:

Get-ChildItem -Path "\.pipe" -Filter '*pshost*' |
    ForEach-Object {
        $id = $_.Name.Split('.')[2]
        if ($id -ne $pid)
        {
            Get-Process -ID $id
        }
    }

The result may look like this:

 
Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName                                      
-------  ------    -----      -----     ------     --  -- -----------                                      
   1131     101   628520      42440             11216   0 SupportAssistAgent                               
   1011      82   269920     299208      85,30  17420   1 powershell_ise                                   
    520      29    68012      75880       1,23  33532   1 powershell                                       
    590      31    69508      77712       2,02  36636   1 powershell                                       
    545      27    67952      76668       1,14  37584   1 powershell                                       
   4114     654   801136     965032     129,69  28968   1 devenv    
 

“SupportAssistAgent” was opened by Visual Studio Code, and “devenv” represents the internal PowerShell host launched by Visual Studio.


Twitter This Tip! ReTweet this Tip!