Search This Blog

Aug 4, 2023

Demo-parallel-foreach

 This requires PowerShell v7

$sub=New-Object System.Collections.ArrayList
$destSubs = [System.Collections.ArrayList]::Synchronized($sub)
$allsubs=@(1,2,3,4,5)
$externalVariable=3
$AllSubs | Sort-Object -Property Name | ForEach-Object -Parallel {

    # Any external variable reference needs to be localized using "using"
    $localVariable = $using:externalVariable
    ($_ -lt $localVariable)

    # Obtain reference to the bag with `using` modifier
    $localCostsVariable = $using:destsubs

    # Add to bag
    $localCostsVariable.Add($_)
}

$destSubs
write-host ""
$sub


# NOTE: many AD object properties won't be visible inside of a parallel script block.
# Need to trigger PS AD adapter driver to populate the result set first
# https://stackoverflow.com/questions/75851412/powershell-foreach-object-parallel-not-all-properties-of-piped-in-object-are-a
#

$users = get-aduser -filter $filter -properties samAccountName,lastLogonTimestamp
#$users=$users|select *    # uncomment this line in order to make below work
$users|foreach -parallel {
   [do something with $_.samAccountName]   # --> this works fine. samAccountName can be read properly
   [do something with $_.lastLogonTimestamp]    # --> this doesn't work. lastLogonTimestamp is always NULL regardless if it is actually populated

}

Jul 20, 2023

MS Graph RESTful Queries

  1.  Links
    1. Graph Explorer
    2. MS Odata Document
    3. Oasis Odata v4.0.1 URL Conventions, specifically, pay attention to 
      1. URL components
      2. Resource path and how to address entities, properties etc.
      3. Query Options
  2. An Odata URL is consist of 3 parts



    1. root URL: GET request made to root URL returns service document (that defines all resources available via the service)
    2. resource path: Entity or entity sets that are accessible via RESTful API
    3. Query option: select, filter, count, skip, order, top etc. See next section 
  3. Addressing
    1. Getting entity set:    GET serviceRoot/users
    2. Getting individual entity by key:    GET serviceRoot/users('john.doe@example.com')
    3. Getting entity property    GET serviceRoot/users/displayName
    4. Getting entity property raw value:    GET serviceRoot/users/displayName/$value
    5. Getting entity set:    GET serviceRoot/users
    6. Getting entity set:    GET serviceRoot/users
    7. Addressing metadata in powershell: $obj.'@odata.type'
      The key here is that the dot (.) between "odata" and "type" is not denotation of a sub-property, but just a normal text character as part of the property name '@odata.type' (so we quote the whole string)
  4. Query options
    1. Filter:
      1. Filter operators: eq/ne/gt/ge/lt/le/and/or/not/has/in
      2. Filter functions: contains/startsWith/endsWith/indexOf/concat/subString
      3. Collection functions: hasSubset/hasSubsequence
      4. More functions on Oasis URL above
      5. Example #1:    GET serviceRoot/users?$filter=upn eq 'johnDoe@example.com'
      6. Example #2, filter against complex type. This query finds airports whose address contains "San Francisco", where address is a property of a complex type Location:    GET serviceRoot/Airports?$filter=contains(Location/Address, 'San Francisco')
      7. Example #3:    GET serviceRoot/users?$filter=upn in {upn1@x.com,upn2@x.com}'
    2. Expand:
      1. Navigation properties: any property that can link to another entity. For example, "memberof", "manager" property of a user
      2. Example #1:    GET serviceRoot/users?$filter=upn eq 'johnDoe@example.com'$expand=manager
      3. Example #2:    $uObj=get-mgUser ... -expandproperty manager; $uObj.manager.additionalProperties.displayName
      4. Example #3:    get-mgUser ... -expandproperty "manager(`$select=displayName,jobTitle)"
    3. Select:
      1. Example #1:    GET serviceRoot/users?$select=*
    4. OrderBy:
      1. Example #1:    GET serviceRoot/users?$expand=manager($orderby=department)
      2. Example #2, order by the count of members:    GET serviceRoot/groups?$orderby=members/$count
    5. Top/Skip/Count
    6. any/all operator
      1. GET serviceRoot/People?$filter=Emails/any(s:endswith(s, 'contoso.com'))
  5. Literals
    1. null/$it/$root/$this
  6. placeholder

Jul 14, 2023

Enabling SMS Communication Using Azure Communication Service

Recently adding SMS alerting function to a monitoring program that my son wrote. Below are high level steps for North America developers.


  1. Assuming you already have App Service Plan and App Service in Azure
  2. Request SMS service
    1. Search "Communication Service" -> "create" to create a communication service instance
    2. Once created, under "Phone numbers", request a phone number. 
      1. Only toll free number can send SMS messages
      2. Cost (as of July 2023): $2/month + per message cost (neglectable)
      3. You can also request short code ID or aliphatic ID for extra cost
  3. Submit request for SMS sending
    1. In same page of the communication service instance, under "Regulatory Documents", submit a request. 
    2. "opt-in type" refers to how "customers" (as the regulatory is designed around marketing SMS messages) opt-in/opt-out. It could be SMS, web portal, paper form, etc. You have to provide evidence(screenshot) that there is such opt-in option available to customers
    3. It could take weeks to get approval
    4. Your outbound messages are blocked until your request is approved in Canada. In the States, you can send limited number of messages before approval
  4. Sample code to send SMS message