stephen lam

blog about nothing

Funny thingy about Format-Wide for PowerShell
2017-FEB-15

I had created the following function a while back to display an Array of String in a nice way through columns, and not a long list as the default for Write-Host.

function format-displaylist{ 
<# 
 .DESCRIPTION 
  Display an array larger than certain members into nice column(s) for 
  easy readability 
#> 
 param( 
  [Parameter(Mandatory=$true, 
   ValueFromPipeline=$true)] 
  $arrayList, 
  [Parameter(Mandatory=$false, 
   ValueFromPipeline=$true, 
   HelpMessage="Use the name properly of a multi-dimension array")] 
  [switch]$displayName 
 ) 
 switch($arrayList.Count){ 
  {($_ -le 10)}{$column = 1} 
  {($_ -gt 10) -and ($_ -le 15)}{$column = 2} 
  default{$column = 3} 
 } 
 $tempArr = @() 
 $tempInx = 1 
 switch($displayName){ 
  $false { 
   foreach($item in $arrayList){ 
    $tempArr += "$tempInx) $item" 
    $tempInx = $tempInx + 1 
   } 
  } 
  $true { 
   foreach($item in $arrayList){ 
    $tempArr += "$tempInx) " + $item.Name 
    $tempInx = $tempInx + 1 
   } 
  } 
 } 
 Write-Host ($tempArr | Format-Wide {$_} -Column $column -Force | Out-String)
}

So the issue with that function is that it adds 3 carriage return to the last line, and made the whole thing look ridiculously ugly looking. It bother me, but I didn't have time or willingness to take a look into why it would do that. That is, until today. While writing a new script, I was constantly calling this function and the displaying of the 3 carriage return was driving me mad. I decide to delve in and see what's causing it, and what I can do to resolve it.

After trying numerous other things, I noticed that I was Out-String, and I thought to myself why I was doing that. I'm not planning to work with the string, I just want to display the string itself. So I replaced:

Write-Host ($tempArr | Format-Wide {$_} -Column $column -Force | Out-String)

with

$tempArr | Format-Wide {$_} -Column $column -Force | Out-Host

and it gave me an output that I'm happy with. There's still return carriage (2), but it's something I'm happy with.

READ
Configuring nginx reverse proxy for Exchange 2010
2016-NOV-16

This will be a quick post that I hope other might find usefully when deploying nginx as a reverse proxy for Exchange 2010 SP3. With my particular setup, we had two reverse proxy servers; one on the DMZ, and the other was on the LAN and firewall rules that only allow them to communicate with each other through standard HTTP/S ports.

Here's quick dirty diagram of the final setup:

Internet -> Firewall -> DMZ -> Reverse Proxy 1 -> Firewall -> Reverse Proxy 2 -> Exchange

nginx conf

Reverse proxy 1
server { 
        listen 443 ssl; 
        server_name outlookserver.com; 
        ssl_certificate /path/to/outlookserver.crt; 
        ssl_certificate_key /path/to/outlookserver.key; 
        ssl_prefer_server_ciphers On; 
        ssl_protocols TLSv1.1 TLSv1.2; 
        ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH"; 
        ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0 
        ssl_dhparam /path/to/dhparam.pem; 
        ssl_session_cache shared:SSL:10m; 
        add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload"; 
        add_header X-Content-Type-Options nosniff; 
        add_header X-Frame-Options ALLOW; 

        location / { 
                proxy_set_header Host $host; 
                proxy_set_header X-Real-IP $remote_addr; 
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
                proxy_set_header X-Forwarded-Proto $scheme; 

                # Fix the "It appears that your reverse proxy set up is broken" error. 
                proxy_pass https://reverseproxy2; 
                proxy_read_timeout 360; 

                error_log /var/log/nginx/owa-ssl-error.log; 
                access_log /var/log/nginx/owa-ssl-access.log; 
    } 
} 
Reverse proxy 1
server { 
        server_name outlookserver.com; 
        listen 443; 

        ssl on; 
        ssl_certificate /path/to/outlookserver.crt; 
        ssl_certificate_key /path/to/outlookserver.key; 
        ssl_session_timeout 5m;
        location / { 
                return 301 https://outlookserver.com/owa; 
        } 

        proxy_http_version 1.1; 
        proxy_read_timeout 360; 
        proxy_pass_header Date; 
        proxy_pass_header Server; 
        proxy_pass_header Authorization; 
        proxy_set_header Host $host; 
        proxy_set_header X-Real-IP $remote_addr; 
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
        proxy_pass_request_headers on; 
        more_set_input_headers 'Authorization: $http_authorization'; 
        proxy_set_header Accept-Encoding ""; 
        more_set_headers -s 401 'WWW-Authenticate: Basic realm="outlookserver.com"'; 
        # proxy_request_buffering off; 
        proxy_buffering off; 
        proxy_set_header Connection "Keep-Alive"; 

        location ~* ^/owa { proxy_pass https://exchangeserver; } 
        location ~* ^/Microsoft-Server-ActiveSync { proxy_pass https://exchangeserver; } 
        location ~* ^/ecp { proxy_pass https://exchangeserver; } 
        location ~* ^/rpc { proxy_pass https://exchangeserver; } 

        error_log /var/log/nginx/owa-ssl-error.log; 
        access_log /var/log/nginx/owa-ssl-access.log; 
} 
READ
PowerShell script to check if computer is online
2016-OCT-26

I wrote this PowerShell function a while back. I might have a better/newer version of this somewhere, if I find it, I'll update this post with it. With that said, this requires the Quest ActiveRoles cmdlets. I don't like what Dell is doing with the Quest cmdlets, but at least you can find version 1.51 download still for free.

<# 
    .SYNOPSIS 
        Take an IP address or a computer name as input and test to see if that 
        computer is valid, and if it's pingable 

    .DESCRIPTION 
        Takes an input and does some validation on the input 

    .EXAMPLE 
        Using with an IP address 
        Check-Computer 192.168.1.1 

    .EXAMPLE 
        Using with a computer name 
        Check-Computer ott-0001 

    .NOTES 
        Stephen Lam 
#> 
function Check-Computer ($ipOrCompName) 
{ 
    #//Add Quest CMDlets as it's needed for this script 
    Add-PSSnapin Quest.ActiveRoles.ADManagement -ErrorAction SilentlyContinue 

    if($ipOrCompName -ne $null) 
    { 
        #//Test to see if the $ipOrCompName is a valid IP format 
        #//IP is in a valid IP format; it will use Test-Connection CMDlet to see 
        #//if that IP is pingable  
        if([bool]($ipOrCompName -as [Net.IPAddress])){ 
            if(Test-Connection -ComputerName $ipOrCompName -Count 1 -Quiet -ErrorAction SilentlyContinue){ 
                $compName = [System.Net.Dns]::GetHostEntry($ipOrCompName).HostName 
            } 
            else{ 
                #//Couldn't find a computer that's base on the IP address 
                $compName = $null 
            } 
        } 

        #//Since the input is not in a valid IP format, it will test to see if this is or 
        #//a part of a computer name 
        else{ 
            #//Searches the whole AD for computer that starts with $ipOrCompName 
            $compTest = Get-QADComputer -Identity $ipOrCompName* 

            #//Checks to see if there's more than one computer object that returns from the search 
            #//If there is, it will either list all the computer it found and allow the user to  
            #//select the computer they want, or if it's just one computer that returns from the 
            #//search, it will use that one automatically 
            if ($compTest -ne $null){ 
                #//More than one computer object found with that search criteria 
                If($compTest.count -gt 1){ 
                    $counter = 1 
                    Write-Host "Found" $compTest.Count "that matches" $ipOrCompName 
                    foreach($obj in $compTest){ 
                        Write-Host "$counter)" $obj.Name 
                        $counter++ 
                    } 
                    $select = Read-Host "Please enter the your selection (eg. 1 for" $compTest[0].Name")" 

                    #//Checks to see if the selected computer is pingable/online 
                    if(Test-Connection -ComputerName $compTest[$select-1].Name -Count 1 -Quiet){ 
                        $compName = $compTest[$select-1].Name 
                    } 
                    else{ 
                        #//Couldn't ping the computer 
                        $compName = $null 
                    } 
                } 

                #//Only one computer object found in the AD that matches the criteria 
                else{ 
                    #//Checks to see if the selected computer is pingable/online 
                    if(Test-Connection -ComputerName $compTest.Name -Count 1 -Quiet -ErrorAction SilentlyContinue){ 
                        $compName = $compTest.Name 
                    } 
                    else{ 
                        $compName = $null 
                    } 
                } 
            } 

            else{ 
                $compName = $null 
            } 
        } 
    } 
    else{   
        #//No computer found base on the IPorCompName 
        $compName = $null 
    } 
    #//Returns the $compName either with a name or $null if it did not find anything 
    return $compName 
}
READ
First commit to GitHub
2016-OCT-13

So I did my first commit to my GitHub for this theme. I need to read about the licensing regarding Semantic-UI's work and make sure they are properly credited. Either way, I'm glad the initial commit/push is done. I doubt any other PicoCMS user will use this theme beside myself, but it's available now for anybody to clone and start using.

I don't know how active I'll be developing this further, but I'll slowly work on this to my fit my needs, and continue to learn more about front end design work while doing so. I really enjoy learning more about PicoCMS, Twig and Semantic-UI so far, and I feel that the more I learn regarding these things, the more it helps out with my professional life.

READ
Cover page added
2016-OCT-12

I added a cover page for the this blog, to make it look a little more fancy. I'm pretty happy with how it turned out, but it's basically the Semantic-UI's layout example, but I did change some stuff. I added a background, and set the menu borders to none. The background image I used is a super gaussian blurred shot that Tuong and I took while on vacation at Maui.

All to say, I'm quite happy with what I have right now. I have done most of what I set out to do for this theme, but there's a couple of more features I want to add. I'll see if I have time to do it, and if it's worth the effort.

READ
OLDER
1 of 2