Lazy Diary @ Hatena Blog

PowerShell / Java / miscellaneous things about software development, Tips & Gochas. CC BY-SA 4.0/Apache License 2.0

Convert an array to CSV with PowerShell

Problem

You cannot convert an array with just pipeline the array to ConvertTo-Csv.

PS > $array = ("a", "b", "c", "a", "d")
PS > $array | ConvertTo-Csv
"Length"
"1"
"1"
"1"
"1"
"1"

... or just passing the array to ConvertTo-Csv.

PS > ConvertTo-Csv $array
"Length","LongLength","Rank","SyncRoot","IsReadOnly","IsFixedSize","IsSynchronized","Count"
"5","5","1","System.Object[]","False","True","False","5"

An array in object also will produce undesired result.

PS > $obj = New-Object PSObject
PS > $obj | Add-Member -MemberType NoteProperty -Name "CSV" -Value $array
PS > $obj | ConvertTo-Csv
"CSV"
"System.Object[]"
PS > ConvertTo-Csv $obj
"CSV"
"System.Object[]"

Reason

It seems by design.

Solution

You should use Add-Member with an loop and dummy property names.

PS > $obj = New-Object PSObject
PS > for ($i=0; $i -lt $array.Length; $i++) { $obj | Add-Member -MemberType NoteProperty -Name $i -Value $array[$i] }
PS > $obj | ConvertTo-Csv -NoTypeInformation | Select-Object -Skip 1
"a","b","c","a","d"

XmlNode.SelectNodes() always returns List in PowerShell 2.0

Problem:

In PowerShell, by using XML DOM API in .NET, you can access to a child element in XML as a ordinary property.

PS > $xml = New-Object System.Xml.XmlDocument
PS > $xml.LoadXml('<a><b id="1">foo</b></a>')
PS > $xml.SelectNodes('//a').b

id                                                            #text
--                                                            -----
1                                                             foo

But in PowerShell 2.0, the same script returns nothing ($null).

PS > $xml = New-Object System.Xml.XmlDocument
PS > $xml.LoadXml('<a><b id="1">foo</b></a>')
PS > $xml.SelectNodes('//a').b

Reason:

It seems to be by design, or caused by some unintentional change in implementation of PowerShell.

  • In PowerShell 4.0 or later, the result of SelectNodes() will be XmlElement if there is only one element in the result.
  • In PowerShell 2.0, the result of SelectNodes() will be always an list of XmlElement.

Solution:

You should always get child nodes through ForEach-Object. The script below does not return $null in PowerShell 2.0 and 4.0 or later.

PS > $xml = New-Object System.Xml.XmlDocument
PS > $xml.LoadXml('<a><b id="1">foo</b></a>')
PS > $xml.SelectNodes('//a') | ForEach-Object { $_ }

b
-
b

How to get a #text in XML even if the tag doesn't have attributes

Background:

In PowerShell (even in C# or VB.NET?), you can get a body of the tag (text content) with '#text#' property.

> $xml = New-Object System.Xml.XmlDocument
> $xml.LoadXml('<a><b id="1">foo</b></a>')
> $xml.SelectNodes('//a').b.'#text'
foo

Problem:

If a tag has no attributes, you cannot get text content with '#text#' property.

> $xml = New-Object System.Xml.XmlDocument
> $xml.LoadXml('<a><b>foo</b></a>')
> $xml.SelectNodes('//a').b.'#text'
(nothing shown)

Reason:

The type of $xml.SelectNodes('//a').b will be XmlElement when <b> has attributes. On the other hand, it will be String when <b> has no attributes.

> $xml = New-Object System.Xml.XmlDocument
> $xml.LoadXml('<a><b id="1">foo</b></a>')
> $xml.SelectNodes('//a').b.GetType().Name
XmlElement
> $xml.LoadXml('<a><b>foo</b></a>')
> $xml.SelectNodes('//a').b.GetType().Name
String

Solution:

Use XPath method rather than property on DOM object. SelectSingleNode() will alrays return XmlElement and you can use #text property.

> $xml = New-Object System.Xml.XmlDocument
> $xml.LoadXml('<a><b id="1">foo</b></a>')
> $xml.SelectNodes('//a').SelectSingleNode('//b').'#text'
foo
> $xml.LoadXml('<a><b>foo</b></a>')
> $xml.SelectNodes('//a').SelectSingleNode('//b').'#text'
foo

Who does recommend to encrypt the attachments in email

In Japan, so many companies have their own security policy like "When you send email with attachments, you must zip all the attachments with password, and send the password in another email". Some say this policy is pointless, but on the other hand, some standards recommend to do this encryption.

Who recommends to encrypt the attachments in email

What can you do with account lockout and its unlock

Purpose of account lockout

These are some purpose for account lockout, such as:

  • Detect login attempts 1
    • Example: Logging 2
  • Slow down login attempts
    • Example: Duration-based lockout, scrypt, Argon2
  • Interrupt login attempts
    • Example: Requires multi factor authentication
  • Passive counter measure for login attempts
    • Example: Requres a phone call for admin 3
  • Active counter measure for login attempts
    • Example: Take a photo by front camera 4
  • Prevent information leakage
    • Example: Data wipe

Method for unlock

There are some way to unlock the locked accounts, such as:

  • Operation-less unlock: Unlock after account lockout duration (e.g. Account Lockout Policies in Windows)
  • Operation by oneself: Unlock with e-mail or SMS (e.g. Twitter)
  • Operation by others: Unlock with the operation of administrators (e.g. Active Directory)

Note that the unlock operation by oneself should use authentication factors other than something you know (∋ passwords) to prevent continuous attacking.

Suitable purpose and situation

Each unlock method has suitable purposes and situations. For example, unlock after account lockout duration can detect and slow down login attempts, but cannot interrupt login attempts. Also, some system considers lockout duration as downtime (e.g. operator-side interface of call center systems; it requires real-time operation), and some doesn’t (e.g. Facebook; users can see articles and messages after unlocking). It depends on the features of the system. The table below shows the purposes that each unlock method fulfills.

# Purpose Unlock after lockout duration Unlock with e-mail or SMS Unlock with operation of administrators
1 Detect attempts
2 Slow down attempts
3 Interrupt attempts
4 Passive countermeasure
5 Active countermeasure
6 Prevent information leakage

  1. In this list, “login attempts” means brute force attack, dictionary attack, or password list attack. IP-based lockout to prevent reverse brute force attack is out of scope of this article.

  2. Strictly this is not a feature of account lockout function.

  3. In Japan, evert phone call (and its geolocation information) is logged by carriers, and the police can access to the logs.

  4. Only for smartphone apps or teleconference systems (it requires cameras and a adversary should be in front of them).