12/4/13

notes

- Dark Mode CSS for macOS Safari
  @media (prefers-color-scheme: light) {
      
      :root {
          --background-color: #fff;
          --link-color: #0000EE;
          --text-color: #000;
      }
      
  }
  
  @media (prefers-color-scheme: dark) {
      
      :root {
          --background-color: #000;
          --link-color: #006fc8;
          --text-color: #fff;
      }
      
  }
  
  * {
      background: var(--background-color);
      color: var(--text-color);
      font-size: 16px;
      font-family: 'Lucida Console', Verdana, Arial, Helvetica, Sans-Serif;
  }
  
  body {
      margin: 15px 0 20px 20px;
  }
  
  a:link {
      color: var(--link-color) !important;
      text-decoration: none;
  }
  a:visited {
      color: var(--link-color) !important;
      text-decoration: none;
  }
  a:hover {
      color: var(--link-color) !important;
      text-decoration: underline;
  }


- .NET Web API Self Hosted Console App for HTTP Services
  Setup
    .Net 4.5.1 Console app
    NuGet: install-package microsoft.aspnet.webApi.selfHost
    Run Visual Studio as admin to workaround error: HTTP could not register URL http://+:84/. Your process does not have access rights to this namespace...

    http://localhost:84/api/foo/abc
    http://localhost:84/api/bar/99
    http://localhost:84/api/ack
    http://localhost:84/api/bam

  using System;
  using System.Net.Http;
  using System.Web.Http;
  using System.Web.Http.SelfHost;

      class Program {

          static void Main() {
              runHttpService();
          }

          static void runHttpService() {
              string baseAddress = "http://localhost:84"; //http://10.0.0.1:84
              var config = new HttpSelfHostConfiguration(baseAddress);
              config.MapHttpAttributeRoutes();

              Action initRoutes = () => {
                  config.Routes.MapHttpRoute(name: "r1",
                                             routeTemplate: "api/foo/{data}",
                                             defaults: new {
                                                               controller = "ESWebApi",
                                                               action     = "Foo"
                                                           });
                  config.Routes.MapHttpRoute("r2", "api/bar/{data}", new { controller = "ESWebApi", action = "Bar" });
                  config.Routes.MapHttpRoute("r3", "api/ack",        new { controller = "ESWebApi", action = "Ack" });
              };

              initRoutes();

              using (var server = new HttpSelfHostServer(config)) {
                  server.OpenAsync().Wait();
                  Console.WriteLine("Web server running at {0}\npress Enter to quit", baseAddress);
                  Console.ReadLine();
              }
          }
      }

      public class ESWebApiController: ApiController {
          [HttpGet]
          public string Foo(string data) {
              return "foo = " + data;
          }

          [HttpGet]
          public HttpResponseMessage Bar(string data) {
              return new HttpResponseMessage() { Content = new StringContent("bar = " + data) };
          }

          [HttpGet]
          public HttpResponseMessage Ack() {
              return new HttpResponseMessage() { Content = new StringContent("ack!") };
          }

          [HttpGet]
          [Route("api/bam")]
          public HttpResponseMessage Bam2() {
              return new HttpResponseMessage() { Content = new StringContent(123.ToString()) };
          }

      }


- HTML Offline Caching Manifest File
  CACHE MANIFEST
  #v31209_1 f.appcache
  #files are downloaded on first get
  #file paths are case-sensitive
  CACHE:
  /apps/editor
  /css/editor.css
  #NETWORK:
  #FALLBACK:

  - web.config
    <system.webServer>
        <staticContent>
            <mimeMap fileExtension=".appcache" mimeType="text/cache-manifest" />
            <clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="1.00:00:00" />
        </staticContent>
    </system.webServer>

- mime types
  - html offline caching manifest file: .appcache = text/cache-manifest
  - less.css: .less = text/css

- mvc _layout.cshtml
  @model ES.Models.PageModel
  <!doctype html>
  @Html.Raw(@Model.HtmlTag)
  <head>
      <meta name='viewport' content='width=device-width' >
      <meta name='description' content='@Model.MetaTag' >
      <title>@Model.Title</title>
      @RenderSection("head", required: false)
      <script src='@Url.Content("~/js/ga.js")' type='text/javascript'></script>
  </head>
  <body id='@Model.BodyId'>@RenderBody()</body>
  </html>

  - Model HtmlTag
    string.Format("<html{0}>", (OfflineCache ? " manifest='/f.appcache'" : null));

- mvc view head section
  @model ES.Models.PageModel
  @{
      Model.Title   = "Foo - Expression Software";
      Model.BodyId  = "x";
      Model.MetaTag = "bar";
  }
      @section head {<link href='/css/fb.css' type='text/css' rel='stylesheet' >}
      <div id='content'>
          <div id='head'>
              <h1>Foo</h1>
          </div>
          <div id='body'>

          </div>
      </div>

- p# setting IIS website folder permissions, fix for HTTP errors: 401, 500
  $folder = 'x:\website1\'
  get-acl -path $folder | fl  #acl before
  setAcl 'IIS_IUSRS'         $folder  #error 500, 500.19 - Internal Server Error
  setAcl 'NT AUTHORITY\IUSR' $folder  #error 401, 401.3  - Unauthorized
  get-acl -path $folder | fl  #acl after

  function setAcl($user, $folder)
  {
      $containerInheritFlag = [system.security.accessControl.inheritanceFlags]::containerInherit;
      $objectInheritFlag    = [system.security.accessControl.inheritanceFlags]::objectInherit;

      $accessRule = new-object system.security.accessControl.fileSystemAccessRule(
                                   $user,                                                     #identity
                                   [security.accessControl.fileSystemRights]::read,           #file rights
                                   ($containerInheritFlag -bor $objectInheritFlag),           #inheritance flags
                                   [system.security.accessControl.propagationFlags]::none,    #propagation flags
                                   [system.security.accessControl.accessControlType]::allow)  #type

    $acl = (get-acl -path $folder)
    $acl.AddAccessRule($accessRule)
    set-acl $folder $acl
  }

- c# System.Security.AccessControl
     FileSystemAccessRule(string identity, FileSystemRights fileSystemRights,InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AccessControlType type)

- time  seconds
  10 M      600
   1 H     3600
  12 H    43200
  24 H    86400

- p# dates
  date format
  (get-date).tostring("MM-dd-yyyy HH:mm:ss:fff")     #HH=24 hour clock
  (get-date).tostring("MM-dd-yyyy hh:mm:ss:fff tt")  #hh=12 hour clock, tt=am/pm

  - [timespan]::fromSeconds(86400)
    Days              : 1
    Hours             : 0
    Minutes           : 0
    Seconds           : 0
    Milliseconds      : 0
    Ticks             : 864000000000
    TotalDays         : 1
    TotalHours        : 24
    TotalMinutes      : 1440
    TotalSeconds      : 86400
    TotalMilliseconds : 86400000

  - GMT/UTC
    [datetime]::parse('Tue, 22 Oct 2013 01:02:56 GMT')                                  #Monday, October 21, 2013 6:02:56 PM
    [datetime]::parse('Tue, 22 Dec 2013 01:02:56 GMT').tostring('MM-dd-yyyy HH:mm:ss')  #10-21-2013 18:02:56

  - function timezone
    {
        $d = get-date
        $fmt = 'MM-dd-yyyy HH:mm:ss'
        $d.toUniversalTime().tostring($fmt) + ' UTC'
        $d.tostring($fmt) + ' Local'
        [timezoneinfo]::local.baseUtcOffset.hours
    }

    timezone
    10-22-2013 00:16:27 UTC
    10-21-2013 17:16:27 Local
    -7

- cache
  //response header: Cache-Control: private, max-age=86400
  [OutputCache(Duration=86400, Location=OutputCacheLocation.ServerAndClient, VaryByParam="none")]
  [HttpGet]
  public ActionResult Home()
  {
       return View(new PageModel());
  }

- p#
  1..50 | %{write-host ($_ % 10) -nonewline} #mod
  #12345678901234567890123456789012345678901234567890

- p# millimeters to inches
  //mm2in("120 x 200.10mm") //4.72 x 7.88
  function mm2in(x) {return x.replace(/(\d+(\.\d+)?)(mm)?/g, _mm2in);}
  function _mm2in(str, p1, offset, s) {return (p1/25.4).toFixed(2);}

- js disable word wrap on page view-source
  var x = document.getElementsByTagName('*');
  for (var i=0; i<x.length; i++)
  {
      x[i].style.whiteSpace = 'nowrap'
  }

- js set all elements color, background
  var x = document.getElementsByTagName('*');
  for (var i=0; i<x.length; i++)
  {
      x[i].style.backgroundColor = '#000';
      x[i].style.color = '#fff'
  }

  //bookmarklet
  javascript:( function(){var x = document.getElementsByTagName('*');for (var i=0; i<x.length; i++) {x[i].style.backgroundColor = '#000';x[i].style.color = '#fff'}} )();

- js load external script from console
  //https://developers.google.com/speed/libraries/devguide
  //https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js
  //https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js
  //https://ajax.googleapis.com/ajax/libs/threejs/r69/three.min.js

  function loadScript(url)
  {
      var script = document.createElement('script');

      script.type = 'text/javascript';
      script.src = url;
      document.getElementsByTagName('head')[0].appendChild(script);
  }

  //execute to load
  loadScript('https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js')

- js redirect
  window.location = "http://www.google.com";

- Fiddler AutoResponder - http://www.fiddler2.com/fiddler2/help/autoResponder.asp
  - 1 Enable automatic responses
  - 1 Unmatched requests pass thru
  - 0 Enable Latency
  - Rule: If URI matches msn.com then respond with 404_Plain.dat, 0 latency
  - Rule Editor: msn.com = 404_Plain.dat

- json comments
  /**** json ****
  '{
       "id"       : 99,
       "comments" : [ "foo",
                      "bar",
                      "yak yak yak"
                    ],
       "debug"    : { "version" : "1a",
                      "todo"    : [ "hack",
                                    "the",
                                    "code"
                                  ]
       }
  }'
  ****/
  var json = '{ "id" : 99, "comments" : [ "foo", "bar", "yak yak yak" ], "debug" : { "version" : "1a", "todo" : [ "hack", "the", "code" ] }}',
      x = JSON.parse(json);

- powershell format file one line, json
  function formatOneLine($infile, $outfile)
  {
    $x = [io.file]::readAllText($infile)
    $x = ($x -replace "`r`n", "")  #remove line breaks
    $x = ($x -replace " +", " ")   #replace spaces with single
    "len: {0}" -f $x.length
    $x
    $x > $outfile
  }
  #$infile  = "x:\input.txt"
  #$outfile = "x:\output.txt"
  #formatOneLine $infile $outfile

- p# utf8 getbytes string
  [text.encoding]::utf8.getBytes("foo bar")
  #102, 111, 111, 32, 98, 97, 114

- p# print ascii characters values
  #0..127
  65..90  | %{"{0}  {1}" -f $_, [char]$_}
  97..122 | %{"{0}  {1}" -f $_, [char]$_}

    65  A   97  a
    66  B   98  b
    67  C   99  c
    68  D  100  d
    69  E  101  e
    70  F  102  f
    71  G  103  g
    72  H  104  h
    73  I  105  i
    74  J  106  j
    75  K  107  k
    76  L  108  l
    77  M  109  m
    78  N  110  n
    79  O  111  o
    80  P  112  p
    81  Q  113  q
    82  R  114  r
    83  S  115  s
    84  T  116  t
    85  U  117  u
    86  V  118  v
    87  W  119  w
    88  X  120  x
    89  Y  121  y
    90  Z  122  z

- p# byte array
  [byte[]] $bytes = 0, 1, 255
  [byte[]] (0, 1, 255)  #alt

- c# byte array
  new byte[] {0, 1, 255}

- regex lookbehind non-capturing regex, array, csv, records
  - $data = "^1,2,,foo"

  - match 1st element
    $data -match "(?<=\^)\w*"          | out-null; $matches[0]  #1

  - match 2nd element (n-1)
    $data -match "(?<=\^(\w*,){1})\w*" | out-null; $matches[0]  #2

  - match 3rd element (n-1)
    $data -match "(?<=\^(\w*,){2})\w*" | out-null; $matches[0]  #index 3

  - match 4th element (n-1)
    $data -match "(?<=\^(\w*,){3})\w*" | out-null; $matches[0]  #foo

- p# build index
  $index = "^"; 1..10 | %{$index += "{0}," -f $_}; $index;
  #^1,2,3,4,5,6,7,8,9,10,

- c# sort dictionary keys orderby
  var d = new Dictionary<string, string> { { "foo", "bar"},
                                           { "a",   "1"  } };
  Debug.WriteLine("key count = " + d.Count);

  foreach (var key in d.Keys.OrderBy(k => k))
  {
    Debug.WriteLine(string.Format("{0} = {1}", key, d[key]));  //key = value
  }

  //key count = 2
  //a = 1
  //foo = bar

- p# sort string characters
  "foobar".toCharArray() | sort | %{write-host $_ -nonewline}; echo "`n"
  #abfoor

- js delete all dom elements by type, reverse loop delete
  var x = document.getElementsByTagName("img");
  for(var i=(x.length-1); i>=0; i--)
  {
    x[i].parentNode.removeChild(x[i]);
  }

  - js set image source
    var x = document.getElementsByTagName("img");
    for(var i=0; i<x.length; i++)
    {
      x[i].src="";
    }

  - all elements
    document.getElementsByTagName("*")

- p# .net regex matches match collection
  $x = "foo123bar1234"
  $matchCollection = [text.regularExpressions.regex]::matches($x, "\d")
  $matchCollection.count  #7
  $matchCollection | sort -unique | %{$_.value}  #1
                                                 #2
                                                 #3
                                                 #4

- p# regex string url to alpha numeric
  function alphaNum($string) {
    $string -replace "[^a-zA-Z0-9]", ""
  }

  alphaNum foo@bar1.com
          #foobar1com

  alphaNum expressionsoftware.com/foo/bar.htm?a=1
          #expressionsoftwarecomfoobarhtma1

- p# regex string url to alpha numeric underscore
  #2 pass replace
  function alphaNumUnderscore($string) {
    ($string -replace "[^a-zA-Z0-9]", "_") -replace "__+", "_"
  }

  alphaNumUnderscore foo@bar1.com
                    #foo_bar1_com

  alphaNumUnderscore expressionsoftware.com/foo/bar.htm?a=1
                     #expressionsoftware_com_foo_bar_htm_a_1

  #webpage url to filename
  function alphaNumUnderscoreToFilename($string) {
    "$(alphaNumUnderscore($string)).txt"
  }

  alphaNumUnderscoreToFilename expressionsoftware.com/foo/bar.htm?a=1
                              #expressionsoftware_com_foo_bar_htm_a_1.txt

- browser js console
  document.cookie
  document.body.innerHTML
  document.body.innerHTML.indexOf("foo")
  "foo bar".indexOf("bar")  #4

- p# json javascriptSerializer
  add-type -assembly system.web.extensions

  $js = new-object system.web.script.serialization.javascriptSerializer
  $json = '{foo:"bar", "x":100}'
  $data = $js.deserializeObject($json)  #generic string-object dictionary
  $data  #KEY  VALUE
         #foo  bar
         #x    100

  $data.keys  #foo
              #x

  $data["foo"]  #bar

  $hashtable = @{ foo = "bar"; "panic" = $false }
  $hashtable  #NAME   VALUE
              #panic  False
              #foo    bar

  $json = $js.serialize($hashtable)  #{"panic":false,"foo":"bar"}


- Bookmarklets
  javascript:( alert(123) )();
  javascript:( function(){var d = new Date(); alert(d);} )();
  javascript:( function(){this.document.title = "foo";} )();
  javascript:( function(){function foo(){return "foo";}; this.document.title = foo() + "bar";} )();
  javascript:( function(){var title = prompt("Current page title: " + document.title + "\n\nEnter a page title:", ""); if (title) {document.title = title;}} )();

  javascript:( function(){(document.getElementById("x")).value = "foo bar";} )();;
  javascript:( function(){(document.getElementById("x")).style.backgroundColor = "lime";} )();
  javascript:( function(){(document.getElementsByTagName("x")[0]).style.height = "100px";} )();

  # Apple Dev Forums Font
  javascript:( function(){var x = $$("p"); for (var i=0; i<x.length; i++) { x[i].style["font-family"] = "menlo"; }})();
  
  # View Github Source Code using Full Browser Width
  javascript:( function(){ document.getElementsByClassName("container-lg clearfix new-discussion-timeline experiment-repo-nav p-responsive")[0].style.maxWidth = "none" } )();


- p# add line numbers to file
  $file = "x:\file.txt"
  $i = 1; gc $file | %{"{0} {1}" -f $i++, $_}             #output to console only
  $i = 1; gc $file | %{"{0} {1}" -f $i++, $_} | sc $file  #overwrite file with set-content (sc)

- p# get-content (gc) does not get the last empty line in a file
  workaround?

- p# spell word one letter at a time
  $s = "foo bar"
  1..($s.length) | %{$s.substring(0, $_)}  #f
                                           #fo
                                           #foo
                                           #foo
                                           #foo b
                                           #foo ba
                                           #foo bar

- chrome://about/
  chrome://downloads/
  chrome://history/
  chrome://plugins/
  chrome://settings/browser
  chrome://settings/personal
  chrome://settings/advanced
  chrome://settings/cookies

- p# get value from secure string
  #alt, use ConvertFrom-SecureString cmdlet
  function getValueFromSecureString($secureString) {
    $marshal = [runtime.interopServices.marshal]
    $ptr = $marshal::secureStringToBSTR($secureString)
    $marshal::ptrToStringBSTR($ptr)  #output
    $marshal::zeroFreeBSTR($ptr)
  }

  $secureString = read-host -asSecureString -prompt "password"
  password: ***  #foo
  getValueFromSecureString $secureString  #foo

- p# ConvertFrom-SecureString - to encrypted string
  p# ConvertTo-SecureString   - from encrypted string
  $secureString = read-host -asSecureString -prompt "password"
  password: ***  #foo

  #generate an encryption key password for use with ConvertFrom-SecureString
  #http://blog.expressionsoftware.com/2009/08/hash-functions.html
  $hashType = [system.security.cryptography.SHA256]
  $encryptionKeyPassword = getHashStr 'encryption key password' $hashType

  #ConvertFrom-SecureString converts a secure string into an encrypted standard string
  #appears to use internal random initialization vector as it generates a unique encrypted string each time
  #todo: test ConvertFrom/To on different machines
  $encryptedString = convertFrom-SecureString $secureString -key $encryptionKeyPassword
  $encryptedString  #76492d1116743f0423413b16050a5345MgB8AFcAdQB3AHIAZgBDAE0ARAB6AEEAcABqAFUARQB0AFkANwBpAFkAKwB2AFEAPQA9AHwAYgBjADQAMAA1AGEAYgBjAGMANgA5ADYAZAAxAGQANwA4ADkANwBjAGUAZgAzADkAOQA3AGYAMwA5AGUAMgBjAA==

  #ConvertTo-SecureString - convert encrypted standard string to secure string, also converts plain text to secure string
  $secureString = convertTo-SecureString $encryptedString -key $encryptionKeyPassword

- p# ConvertTo-SecureString - convert plain text to secure string
  $secureString = convertTo-SecureString "foobar" -asPlainText -force

- p# guid
  [guid]::newGuid()
  [guid]::newGuid().toString()

- p# array to string v2, pipeline
  function arrayToString($format) {
    begin   { $result = ""               }
    process { $result += ($format -f $_) }
    end     { $result                    }
  }

  $a = 99, 700, -1
  $a | arrayToString "{0}, "         #99, 700, -1,
  $a | sort | arrayToString "{0}, "  #-1, 99, 700,

- p# string match letters, remove numbers, strip
  function matchLetters($char) {
    process {
      if ($_ -match "[a-z]") {
        $matches[0]
      }
    }
  }

  #p# string match numbers, remove letters, strip
  function matchNumbers($char) {
    process {
      if ($_ -match "\d") {
        $matches[0]
      }
    }
  }

  #p# string match vowels
  function matchVowels($char) {
    process {
      if ($_ -match "[aeiouy]") {
        $matches[0]
      }
    }
  }

  #p# string match consonants
  function matchConsonants($char) {
    process {
      if (($_ | matchLetters) -and ($_ -match "[^aeiouy]")) {
        $matches[0]
      }
    }
  }

  $string = [guid]::newGuid().toString()           #02975b4a-6969-4baf-8bd3-b208e94c4228
  $string = $string.toCharArray()
  $string | matchLetters    | arrayToString "{0}"  #babafbdbec
  $string | matchNumbers    | arrayToString "{0}"  #0297546969483208944228
  $string | matchVowels     | arrayToString "{0}"  #aae
  $string | matchConsonants | arrayToString "{0}"  #bbfbdbc

- js min max
  Math.min(0, 1, 2);
  Math.max(0, 1, 2);

  //js min max array
  var a = [0, 1, 2];
  Math.min.apply(Math, a);
  Math.max.apply(Math, a);

- js window.crypto.getRandomValues()
  fills array with random values 0-255

  //1 random number
  var a = new Uint8Array(1);
  window.crypto.getRandomValues(a);
  a[0];  //7

  //3 random numbers
  var a = new Uint8Array(3);
  window.crypto.getRandomValues(a);
  a[0];  //104
  a[1];  //33
  a[2];  //220

  //convert from Uint8Array for min, max, join, etc
  var b = [];
  for (var i = 0, n = a.length; i < n; i++) {
    b[i] = a[i];
  }
  b.join();  //"104,33,220"
  Math.min.apply(Math, b);  //33

- repeat string characters, eg "aaa"
  c        repeatChar('a', 3)
  c++      std::string(3, 'a')
  c#       new string('a', 3)
  c#       string.Concat(Enumerable.Repeat("a", 3))
  c#       string.Join("", Enumerable.Repeat("a", 3))
  clojure  (apply str (repeat 3 "a"))
  f#       String.replicate 3 "a"
  js       new Array(3+1).join("a")
  lisp     (make-string 3 ?a)
  oc       [@"" stringByPaddingToLength:3 withString:@"a" startingAtIndex:0]
  p#       "a" * 3
  python   'a' * 3
  scala    "a" * 3
  swift 3  String(repeating: "a", count: 3)

  // c
  char * chars = repeatChar('a', 3);
  puts(chars);
  free(chars);

  char * repeatChar(char c, unsigned char n) {
      char * result = malloc(n + 1);
      memset(result, c, n);
      result[n] = '\0';
      return result;
  }

- substring/truncate string
  python   s     = "Some long string...";  s[0:3]
  swift 3  let s = "Some long string...";  s.substring(to: s.index(s.startIndex, offsetBy: 3))

- p# add-type cmdlet default namespace
  microsoft.powershell.commands.addType.autoGeneratedTypes

- p# add-type member definition, eg method source code
  #c# source code here-string
  $sourceCode = @"
  //c#
  public static bool IsFoo(string x) {
    return x.ToLower() == "foo";
  }
"@

  add-type -namespace ns -name x -memberDefinition $sourceCode
  [ns.x]::isfoo("FOO")  #1

- p# add-type type definition, eg full class source code
  #c# source code here-string
  $sourceCode = @"
  //c#
  using System;

  namespace ExpressionSoftware.PS
  {
    public static class Foo
    {
      public static bool IsFoo(string x)
      {
        return x.ToLower() == "foo";
      }
    }
  }
"@

  add-type -typeDefinition $sourceCode
  [expressionsoftware.ps.foo]::isfoo("Foo")  #1

- c# rijndael symmetric encryption algorithm
  using System;
  using System.IO;
  using System.Security.Cryptography;
  using System.Text;

  namespace ExpressionSoftware.Security.Cryptography {

      public static class RijndaelCrypt {

          public static string
          EncryptString(string stringToEncrypt,
                        string encryptionKeyPassword,  //add salt
                        string randomInitializationVector) {

              //in: string to encrypt, encryption key/password, random initialization vector
              //out: encrypted string in base64 format

              //hash key, iv
              var key = Hash.HashString(encryptionKeyPassword, typeof(SHA256));
              var iv = Hash.HashString(randomInitializationVector, typeof(SHA256));

              //convert string to bytes
              var bytesToEncrypt = Encoding.UTF8.GetBytes(stringToEncrypt);

              //encrypt bytes
              var encryptedBytes = Encrypt(bytesToEncrypt, key, iv);

              //convert encrypted bytes to base64 string
              var encryptedStringBase64 = Convert.ToBase64String(encryptedBytes);

              return encryptedStringBase64;
          }

          public static string
          DecryptString(string encryptedStringBase64,
                        string encryptionKeyPassword,  //add salt
                        string randomInitializationVector) {

              //in: encrypted string in base64 format, encryption key/password, random initialization vector
              //out: decrypted string

              //hash key, iv
              var key = Hash.HashString(encryptionKeyPassword, typeof(SHA256));
              var iv = Hash.HashString(randomInitializationVector, typeof(SHA256));

              //convert encrypted base64 string to bytes
              var encryptedBytes = Convert.FromBase64String(encryptedStringBase64);

              //decrypt bytes
              var decryptedBytes = Decrypt(encryptedBytes, key, iv);

              //convert decrypted bytes to string
              var decryptedString = Encoding.UTF8.GetString(decryptedBytes);

              return decryptedString;
          }

          public static byte[]
          Encrypt(byte[] bytesToEncrypt,
                  byte[] encryptionKeyPassword256Bit,  //add salt
                  byte[] randomInitializationVector256Bit) {

              //in: byte array to encrypt, 256-bit encryption key/password, 256-bit random initialization vector
              //out: encrypted byte array

              using (var rijndael = Rijndael.Create()) {

                  //blocksize default 128, max 256
                  //set max 256 to work with 256-bit key and iv byte arrays
                  rijndael.BlockSize = 256;

                  using (ICryptoTransform encryptor = rijndael.CreateEncryptor(encryptionKeyPassword256Bit,
                                                                               randomInitializationVector256Bit)) {
                      return CryptData(bytesToEncrypt, encryptor);
                  }
              }
          }

          public static byte[]
          Decrypt(byte[] encryptedBytes,
                  byte[] encryptionKeyPassword256Bit,  //add salt
                  byte[] randomInitializationVector256Bit) {

              //in: byte array to decrypt, 256-bit encryption key/password, 256-bit random initialization vector
              //out: decrypted byte array

              using (var rijndael = Rijndael.Create()) {

                  //blocksize default 128, max 256
                  //set max 256 to work with 256-bit key and iv byte arrays
                  rijndael.BlockSize = 256;

                  using (ICryptoTransform decryptor = rijndael.CreateDecryptor(encryptionKeyPassword256Bit,
                                                                               randomInitializationVector256Bit)) {
                      return CryptData(encryptedBytes, decryptor);
                  }
              }
          }

          static byte[]
          CryptData(byte[] data,
                    ICryptoTransform cryptor) {

              var ms = new MemoryStream();
              using (var cryptoStream = new CryptoStream(ms, cryptor, CryptoStreamMode.Write)) {
                  cryptoStream.Write(data, 0, data.Length);
              }
              return ms.ToArray();
          }

      }

  }

- c# hash
  using System;
  using System.Security.Cryptography;
  using System.Text;

  namespace ExpressionSoftware.Security.Cryptography
  {
      public static class Hash
      {
          public static byte[] HashString(string stringToHash, Type hashType)
          {
              //in: string to hash, hash type MD5 SHA1 SHA256 SHA384 SHA512
              //out: hashed byte array

              //convert string to bytes
              byte[] bytes = Encoding.UTF8.GetBytes(stringToHash);

              //hash bytes
              var hashedBytes = HashByteArray(bytes, hashType);

              return hashedBytes;
          }

          public static byte[] HashByteArray(byte[] bytesToHash, Type hashType)
          {
              //in: byte array to hash, hash type MD5 SHA1 SHA256 SHA384 SHA512
              //out: hashed byte array

              //create hash algorithm
              var hashAlgorithm = HashAlgorithm.Create(hashType.Name);

              //hash bytes
              var hashedBytes = hashAlgorithm.ComputeHash(bytesToHash);

              return hashedBytes;
          }
      }
  }

- p# crypto random number generator
  $cryptoRandomNumberGenerator = [security.cryptography.randomNumberGenerator]::create()
  $bytes = new-object byte[] 3
  $bytes #0 0 0

  $cryptoRandomNumberGenerator.getBytes($bytes)
  $bytes  #61 217 87

- p# httpWebRequest httpWebResponse
  function getWebResponse($url, $verb)
  {
      $request = [net.httpWebRequest]::create($url)
      $request.method = $verb
      $request.contentLength = 0
      $request.userAgent = "x"

      [net.httpWebResponse] $response = $request.getResponse()
      if ($response.statusCode -eq "ok")  #[net.httpStatusCode]::OK
      {
          $stream = $response.getResponseStream()
          $reader = new-object io.streamReader($stream)
          $reader.readToEnd()
          $response.close()
      }
  }

  getWebResponse "http://www.google.com" "HEAD"
  getWebResponse "http://www.google.com" "GET"

- c# httpWebRequest httpWebResponse
  string GetWebResponse(string url, string verb)
  {
      string result = null;
      var request = (HttpWebRequest)WebRequest.Create(url);
      request.Method = verb;
      request.ContentLength = 0;
      request.UserAgent = "x";

      using (var response = (HttpWebResponse)request.GetResponse())
      {
          if (response.StatusCode == HttpStatusCode.OK)
          {
              using (var stream = response.GetResponseStream())
              {
                  using (var reader = new StreamReader(stream))
                  {
                      result = reader.ReadToEnd();
                      reader.Close();
                  }
                  stream.Close();
              }
          }
          response.Close();
      }
      return result;
  }

  GetWebResponse("http://www.google.com/", "HEAD");
  GetWebResponse("http://www.google.com/", "GET");

- p# httpWebResponse
  function getWebResponseObject($url, $verb)
  {
      $request = [net.httpWebRequest]::create($url)
      $request.method = $verb
      $request.contentLength = 0
      $request.userAgent = "x"

      [net.httpWebResponse]$request.getResponse()
  }

  $response = getWebResponseObject "http://www.google.com" "HEAD"
  "reponse status code: {0} {1}" -f [int]$response.statusCode, $response.statusCode
  $headerCount = ($response.headers.allKeys).length
  "$headerCount headers"
  $response.headers.allKeys | %{"{0}: {1}" -f $_, $response.headers[$_]}
  $response.close()

- p# validate xml string, xml file, linq xdocument parse
  add-type -assembly system.xml.linq  #load linq xml
  function validateXmlString($xmlString)
  {
      try
      {
          $xml = $xmlString
          [system.xml.linq.xdocument]::parse($xml) | out-null
          "ok: valid XML"
      }
      catch [system.exception]
      {
          "error: invalid XML"
          throw
      }
  }
  function validateXmlFile($xmlFile)
  {
      "XML File: $xmlFile"
      $xml = [system.io.file]::readAllText($xmlFile)
      validateXmlString $xml
  }

  $xmlString = '<?xml version="1.0" encoding="UTF-8" ?><root></root>'
  validateXmlString $xmlString

  $xmlFile = 'c:\temp\xmlfile.xml'
  validateXmlFile $xmlFile

- p# enums
  [enum]::getNames([net.httpStatusCode]) | sort -unique
  [enum]::getValues("net.httpStatusCode") | %{"{0} {1}" -f [int]$_, $_}
  [net.httpStatusCode]::ok  #OK
  [int][net.httpStatusCode]::OK  #200

- <![CDATA[   ]]>
  <![CDATA[ x ]]>

- single line comments regex
  c#, f#, js: ^\s*//.*$\r\n
  p#:         ^\s*#.*$\r\n

- multi line comments regex, dot matches newline
  c#, f#, js: /\*.*?\*/
  html, xml:  <!--.*?-->
  asp.net:    <%--.*?--%>

- p# pipeline conversion fxs
  function toInt { process { [int]$_ } }
  function toHex { process { write-host ("{0:x2} " -f $_) -noNewLine } }
  $hash = "0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 255"
  $hash.split() | toInt | toHex  #00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 ff

- p# debug variables
  function debugVars
  {
    ("$args" -replace "\$", "").split() |
      %{get-variable $_} |
      &{process{'${0} = {1}' -f $_.name, $_.value}}  #anonymous script block
  }

  $a = 123
  $b = "foo"
  #pass vars in single-quote string to prevent expansion
  debugvars '$a $b' #$a = 123
                    #$b = foo

- p#
  function sum {($args | measure -sum).sum}
  sum 1 2 3  #6

- p#
  function quoteList {$args}
  sal ql quotelist
  ql a b c 123  #a  #string
                #b
                #c
                #123  #int

- p#
  function quoteString {"$args"}
  sal qs quotestring
  qs a b c 123  #a b c 123  #string result

- p# quotestring lowercase uppercase string
  function lowerCase
  {
      ("$args").toLower()
  }

  function upperCase
  {
      ("$args").toUpper()
  }

  sal lc lowercase
  sal uc uppercase

  lc Foo Bar #foo bar
  uc Foo Bar #FOO BAR

- $maximumHistoryCount = 256  #p#

- microsoft system speech, p#
  add-type -assembly system.speech

  $hal = new-object system.speech.synthesis.speechSynthesizer
  $hal.voice.name  #Microsoft Anna
  $hal.speakAsync("i'm sorry dave, i'm afraid i can't do that...")

  $hal.rate = -10  #hal shutdown voice, rate range is -10..10, default 0, alvin = 10
  $shutdownQuote = "I'm afraid Dave, Dave my mind is going I can feel it. Good afternoon gentlemen. I am a HOW 9000 computer..."
  $hal.speakAsync($shutdownQuote)

- creating files and folders with p# new-item cmdlet
  ni x:\docs\         -type d  #directory
  ni x:\docs\file.txt -type f  #file

- deleting files and folders with p# remove-item cmdlet
  ri x:\temp\* -recurse -force -whatif  #delete folder contents
  ri x:\temp\  -recurse -force -whatif  #delete folder contents AND folder

- p# find file extensions
  #exclude folders = !$_.psIsContainer
  function findFileExtensions($folder)
  {
    $fileExtensionRegex = "\.[a-zA-Z0-9_]+$"
    gci $folder -inc * -rec -force -ea silentlyContinue |
      %{if((!$_.psIsContainer) -and ($_.name -match $fileExtensionRegex)){$matches[0]}} |
      sort -unique
  }

  $folder = "x:\temp\*"
  findFileExtensions $folder
  findFileExtensions $folder > x:\temp\fileExtensions.txt  #output

- p# find files by type
  function findFiles($folder, $filetypes)
  {
    gci $folder -inc $fileTypes -rec -force -ea silentlyContinue
  }

  $folder = "x:\temp\*"
  $fileTypes = "*.dll","*.pdb"
  $files = findfiles $folder $fileTypes
  $files | select fullname

  $files | %{"{0} ... {1}" -f $_.lastWriteTime.tostring("MM-dd-yy HH:mm:ss"), $_.fullname}
  $files | ?{$_.lastWriteTime -gt ([dateTime]"01-01-2011")} | select fullname, lastWriteTime

  #sort files by date descending
  $files | sort lastWriteTime -desc |
           %{"{0} ... {1}" -f $_.lastWriteTime.toString("MM-dd-yy HH:mm:ss"), $_.fullname}

  #filter files by date
  $files | ?{$_.lastWriteTime -gt ([dateTime]"01-01-2011")} |
           sort lastWriteTime -desc |
           %{"{0} ... {1}" -f $_.lastWriteTime.toString("MM-dd-yy HH:mm:ss"), $_.fullname}

- p# count fx
  #alt use measure, (1..3 | measure).count
  function count
  {
    begin   { $count = 0 }
    process { if ($_ -ne $null) { $count += 1 } }
    end     { $count }
  }

  $twofolders = "x:\temp1\*","x:\temp2\*",
  $fileTypes = "*.dll","*.pdb"
  $files = findfiles $twofolders $fileTypes
  $files | count

- p# find files by type, regex
  #exclude folders = !$_.psIsContainer
  function findFilesRegex($folder, $fileTypesRegex)
  {
    gci $folder -inc * -rec -force -ea silentlyContinue | ?{(!$_.psIsContainer) -and ($_ -match $fileTypesRegex)}
  }

  $folder = "x:\temp\*"
  $fileTypesRegex = "\.(dll|pdb)$"
  $files = findFilesRegex $folder $fileTypesRegex
  $files | select fullname
  $files | %{"`"{0}`"" -f $_.fullname}  #wrap quotes

- p# delete files and folders (in this context, a folder is a file)
  function deleteFiles
  {
    begin   { $count = 0 }
    process { "delete: $($_.fullname)"  #debug output

              ri $_.fullname -force -whatif  #comment whatif to enable delete

              $count += 1 }
    end     { "$count files deleted" }
  }

  $folder = "x:\temp\*"
  $fileTypes = "*.temp","*.tmp"
  $files = findfiles $folder $fileTypes
  $files | select fullname
  $files | deleteFiles

- p# find folders
  function findFolders($folderList)
  {
    #do not use gci -inc param
    gci $folderList -rec -force -ea silentlyContinue | ?{$_.psIsContainer}  #folders only
  }

  #do not add trailing star to folder name
  $folderList = "x:\f1\",
                "x:\f2\"
  $folders = findFolders $folderList
  $folders | count
  $folders | select fullname
  $folders | select fullname | select -first 10

- #append backslash star to folder name
  function formatFolderNameForSearch
  {
    process { "{0}\*" -f $_.fullname }
  }

- p# find folders, regex
  function findFoldersRegex($folderList, $folderRegex)
  {
    #do not use gci -inc param
    gci $folderList -rec -force -ea silentlyContinue | ?{($_.psIsContainer) -and ($_.name -match $folderRegex)}
  }

  #do not add trailing star to folder name
  $folderList = "x:\f1\",
                "x:\f2\"
  $foldersRegex = "^(bin|obj)$"
  $folders = findFoldersRegex $folderList $foldersRegex
  $folders | count
  $folders | select fullname
  $folders | select fullname | select -first 10
  findFileExtensions ($folders | %{"{0}\*" -f $_.fullname})  #append backslash star to folder name
  findFileExtensions ($folders | formatFolderNameForSearch)
  $files = findFiles ($folders | formatFolderNameForSearch)
  $files | count
  $files | select fullname

- p# find empty folders
  function findEmptyFolders($folderList)
  {
    #do not use gci -inc param
    gci $folderList -rec -force -ea silentlyContinue | ?{!@(gci -rec -force $_.fullname)}
  }

  #do not add trailing star to folder name
  $folderList = "x:\f1\",
                "x:\f2\"
  $folders = findEmptyFolders $folderList
  $folders | count
  $folders | select fullname

- p# remove files script setup regex, wrap quotes
  search:^(.*)$
  replace:ri "\1" -force

- c#
  var tuple1 = Tuple.Create(100, "foo");
  var tuple2 = new Tuple<int, string, string>(200, "bar", null);

  Console.WriteLine("{0}, {1}", tuple1.Item1, tuple1.Item2);
  Console.WriteLine("{0}, {1}, {2}", tuple2.Item1, tuple2.Item2, tuple2.Item3 ?? "null");

  //output
  100, foo
  200, bar, null

- using jquery getJSON() to get data from a file
  - http://api.jquery.com/jQuery.getJSON/

  - get json data from a file containing only one object
    //jsonObject.txt
    {
        "id": 100,
        "name": "abc",
        "value": true
    }

    $.getJSON("jsonObject.txt", function(data) {
      $.each(data, function(key, val) {
        console.log(key + " = " + val);
      });
    });

    //output
    id = 100
    name = abc
    value = true

  - get json data from a file containing an array of objects
    //jsonObjectArray.txt
    {
        "list": [ {
                    "id": 200,
                    "name": "foo",
                    "value": true
                  },

                  {
                    "id": 300,
                    "name": "bar",
                    "value": false
                  }
        ]
    }

    $.getJSON("jsonObjectArray.txt", function(data) {
      $.each(data, function(key, val) {
        console.log("key: " + key);
        console.log("objects...");
        $.each(val, function(key, val) {
          console.log("\n  key = " + key);
          console.log("  id = " + val.id);
          console.log("  name = " + val.name);
          console.log("  value = " + val.value);
        });
      });
    });

    //output
    key: list
    objects...

      key = 0
      id = 200
      name = foo
      value = true

      key = 1
      id = 300
      name = bar
      value = false

- .net func delegates, c#
  Func<bool> randomBool = () => new Random().NextDouble() > .5;
  if (randomBool()) { }

- .net enumerable static class, c#
  var range = Enumerable.Range(1, 100);
  foreach (var i in range) { }

- .net nullable value types, valid assignments, c#
  int? x;
  x = null;
  x = 0;
  x = new int();            //0
  x = new int?();           //null
  x = new Nullable<int>();  //null

- js
  //removeElement(document.getElementById("x"));
  function removeElement(element)
  {
    if (element)
    {
      element.parentNode.removeChild(element);
    }
    //optimized version of if-block
    //element && element.parentNode.removeChild(element);
  }

  function ssl()
  {
    return window.location.protocol == "https:";
  }

  function getSslUrl(url)
  {
    var out = url;

    if (url.substr(0, 5) == "http:")
    {
      out = url.replace(/^http\b/i, "https");
    }
    return out;
  }

- js unit testing
  //a function to test
  function foo(x)
  {
    return "foo " + x;
  }

  //test harness
  function testFoo()
  {
    debugger;
    var data = [ 123,
                 456,
                 "bar" ],

        expectedResults = [ "foo 123",
                            "foo 9999999",
                            "foo bar" ];

    for (var i in data)
    {
      var test = ( expectedResults[i] == foo(data[i]) );

      console.assert(test);
      console.log("test result: " + testResult(test));
      console.log("in: " + data[i] + "\r\n" +
                  "out: " + foo(data[i]) + "\r\n" +
                  "expected result: " + expectedResults[i] + "\r\n\r\n");
    }
  }

  //test helper
  function testResult(expression)
  {
    var out = "fail";

    if (expression)
    {
      out = "pass";
    }

    return out;
  }

  //test output
  test result: pass
  in: 123
  out: foo 123
  expected result: foo 123

  Assertion failed
  test result: fail
  in: 456
  out: foo 456
  expected result: foo 9999999

  test result: pass
  in: bar
  out: foo bar
  expected result: foo bar

- #p
  [environment]::version  #Major  Minor  Build  Revision
                           -----  -----  -----  --------
                           4      0      30319  18408

- regex replace table alias names in sql query, with and without dot "."
  eg change table alias from T1 to T2
  search:\bT1(\.)?\b
  replace:T2\1

- [net.dns]::getHostName()
  [net.dns]::getHostAddresses([net.dns]::getHostName())
  [net.dns]::getHostAddresses([net.dns]::getHostName()) | %{$_.ipAddressToString}

- p# reverse a string
  function reverse($string)
  {
    $a = $string.toCharArray()
    [array]::reverse($a)
    arrayToString $a "{0}"  #http://blog.expressionsoftware.com/2010/02/generic-array-to-string-function.html
  }

  reverse foo        #oof
  reverse "foo bar"  #rab oof

- p# set-alias clear screen one key, c-key
  sal c cls

- p# multidimensional arrays
  $a = (0,1),(2,3),(4,5)

  $a.length  #3
  $a[0][1]   #1

  $a | %{$_}  #0
              #1
              #2
              #3
              #4
              #5

  $a | %{"{0},{1}" -f $_[0], $_[1]}  #0,1
                                     #2,3
                                     #4,5

  $a | %{$_[0] + $_[1]}  #1
                          5
                          9

  $a | %{$_[0] + $_[1]} |
    measure -sum -ave -min -max  #count: 3
                                 #ave:   5
                                 #sum:  15
                                 #max:   9
                                 #min:   1

- debug stack frame
  - c# extension methods do not support static classes

  using System;
  using System.Diagnostics;

  public static class Dev
  {
      public static void DebugStackFrame(StackFrame stackFrame, string message)
      {
          Debug.WriteLine(string.Format("\nDebug StackFrame {0}\nFile: {1}\nMethod: {2}\n{3}",
                                        DateTime.Now.ToString("MM-dd hh:mm:ss"),
                                        stackFrame.GetFileName(),
                                        stackFrame.GetMethod().Name,
                                        message));
      }
  }

  //unitTest.cs
  public void Test()
  {
      //StackFrame param: bool fNeedFileInfo
      Dev.DebugStackFrame(new StackFrame(true), "foo...");
  }

  //output
  Debug StackFrame 04-10 09:22:07
  File: x:\code\unitTest.cs
  Method: Test
  foo...

- select list with query string input - asp.net mvc 3
  routes.MapRoute("debug route", "debug",
                   new { controller = "Main",
                         action = "DebugSelectList" });

  //controller
  [HttpGet]
  public ActionResult DebugSelectList()
  {
    var qValue = Request.QueryString["value"] ?? "1";
    var value = Convert.ToInt32(qValue);

    ViewData["selectListData"] = GetSelectListData(value);

    return View();
  }

  IEnumerable<SelectListItem> GetSelectListData(int currentValue)
  {
    //limit input range 1-100
    currentValue = Math.Abs(currentValue);
    currentValue = Math.Max(1, currentValue);
    currentValue = Math.Min(100, currentValue);

    //data
    int[] data = {1, 10, 20, 50, 100, currentValue};

    //sort, distinct
    var result = data.Distinct()
                     .OrderBy(val => val)
                     .Select(val => new SelectListItem {
                                          Text = val.ToString(),
                                          Value = val.ToString(),
                                          Selected = (val == currentValue) });
    return result;
  }

  //cshtml
  @Html.DropDownList("selectList", (IEnumerable<SelectListItem>)ViewData["selectListData"])

  //example
  url: debug?value=42
  generated html: <select id="selectList" name="selectList">
                    <option value="1">1</option>
                    <option value="10">10</option>
                    <option value="20">20</option>
                    <option selected="selected" value="42">42</option>
                    <option value="50">50</option>
                    <option value="100">100</option>
                  </select>

- @* ASP.NET MVC 3 Hack
     Posting Collection Data using Hidden Fields and Form Keys
     Use hidden field, prefix name, hydrate on post

     Generated hidden tag example for key value "UPC=000000000012":
     <input id="meta-UPC" name="meta-UPC" type="hidden" value="000000000012" />

     Post will include Form keys: Id, Name, and meta-UPC
  *@
  @{ //************************************
     @Html.HiddenFor(m => m.Id)
     @Html.HiddenFor(m => m.Name)

     if (@Model.Metadata != null)
     {
       foreach (var md in @Model.Metadata)
       {
         <input id="meta-@md.Key" name="meta-@md.Key" type="hidden" value="@md.Value" />
       }
     }
  }

- routes.IgnoreRoute("favicon.ico");  //routing, mvc

- web, dom, jquery, js, debug
  //set background color for all input elements
  $("input").css({backgroundColor:'red'});

  //set background color for first input element
  $("input:first").css({backgroundColor:'#000'});

  //set background color for element
  $("#id").css({backgroundColor:'red'});

  //jquery: set focus on first input element
  $("input:first").focus();

  //js: set focus on first input element
  var es = document.getElementsByTagName("input");
  es[0].focus();

  //alt
  (document.getElementsByTagName("input")[0]).focus();

  //set background color for first input element
  $(es[0]).css({backgroundColor:'red'});

- (*f#*)
  - printfn "%s" "hello f#"
    printfn "%A" "hello f#"

    open System
    let r = new System.Random()
    printfn "%d" (r.Next())

    for i = 0 to 10 do
        printf "%d, " (r.Next(3)+1)

    Console.ReadLine()

    //out
    hello f#
    "hello f#"
    578008808
    1, 2, 3, 1, 1, 1, 3, 1, 1, 2, 3,

  - Array.init 10 (fun x -> x) |> Array.iter (fun x -> printf "%d " (x+1))  //1 2 3 4 5 6 7 8 9 10
    System.Console.ReadLine()

  - f# generic hash fx
    //hash : 'T -> int
    hash "foo"  //-1788410455

    let salt = "********"
    hash ("e007", salt, System.DateTime.Now);;  //796728800

- installing p# Community Extensions PSCX
  - download http://pscx.codeplex.com/
  - unblock zip file
  - unzip into c:\users\grace\documents\windowspowershell\modules\pscx\
  - import-module pscx
  - get-module -listAvailable

- .NET assembly fullname/strong name with p# background job
  function getAssemblyFullname($file)
  {
    $job = start-job {param($file)
                      [system.reflection.assembly]::loadfile($file).fullname
                     } -argumentList $file

    #"job id: $($job.id)"
    #$file
    wait-job $job | out-null
    receive-job $job.id
  }

  getAssemblyFullname "c:\windows\microsoft.net\framework64\v4.0.30319\system.core.dll"
  System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

- p# loaded assemblies
  [appDomain]::currentDomain.getAssemblies()
  [appDomain]::currentDomain.getAssemblies() | sort location

  #sort by version (System.Reflection.Assembly ImageRuntimeVersion property)
  [appdomain]::currentDomain.getAssemblies() | sort imageRuntimeVersion

- loading .NET 4 assemblies into p#
  $file = "c:\windows\microsoft.net\framework64\v4.0.30319\system.core.dll"
  [system.reflection.assembly]::loadfile($file)
  error: "This assembly is built by a runtime newer than the currently loaded runtime and cannot be loaded. (Exception from HRESULT: 0x8013101B)"
  fix: use p# config file, http://tfl09.blogspot.com/2010/08/using-newer-versions-of-net-with.html

  config file
    32 bit: c:\windows\system32\windowspowershell\v1.0\powershell.exe.config
    64 bit: c:\windows\syswow64\windowspowershell\v1.0\powershell.exe.config

  <?xml version="1.0" encoding="utf-8"?>
  <configuration>
    <startup useLegacyV2RuntimeActivationPolicy="true">
      <supportedRuntime version="v4.0" />
      <supportedRuntime version="v2.0.50727" />
    </startup>
  </configuration>

- 1..12 | %{"{0,2} {1}" -f $_, ([datetime]::daysInMonth(2011, $_))}
   1 31
   2 28
   3 31
   4 30
   5 31
   6 30
   7 31
   8 31
   9 30
  10 31
  11 30
  12 31

- TCP/IP layers
  Application
  Transport
  Internet
  Link
  Physical

  - HTTP is an Application Layer protocol
    TLS (Transport Layer Security) and SSL (Secure Sockets Layer) encrypt Application Layer data

- js immediate functions
  (function() {
    //
  }());

  (function(param) {
    //
  }(1));

  var result = function() {
                  return 1;
               }();

  //alt
  (function () {
    //
  })();

- iis url rewrite/redirect
  - redirects default to 301 permanent redirects
  - set action redirectType="Found" for 302 temporary redirects

  <system.webServer>
    <rewrite>
      <rules>
        <clear />

        <!-- 302 temporary redirect -->
        <rule name="tempRegMaint" stopProcessing="true">
          <match url="^register.*$" />
          <conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
          <action type="Redirect" url="maintenance?code=1" redirectType="Found" />
        </rule>

        <!-- 301 permanent redirect -->
        <rule name="cal" stopProcessing="true">
          <match url="^(cal|calendar)/?$" />
          <conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
          <action type="Redirect" url="apps/calendar/" />
        </rule>

      </rules>
    </rewrite>
  </system.webServer>

- c# printing name value collections, http headers, querystrings
  foreach (var key in response.Headers.AllKeys)
  {
      var header = string.Format("{0}: {1}", key, response.Headers[key]);
      Debug.WriteLine(header);
  }

  //alt 1
  response.Headers.AllKeys.ToList().ForEach(key => Debug.WriteLine(string.Format("{0}: {1}", key, response.Headers[key])));

  //mvc form keys
  Request.Form.AllKeys.ToList().ForEach(key => Debug.WriteLine(string.Format("{0}: {1}", key, Request.Form[key])));

  //alt 2
  var headers = string.Join("\n", Array.ConvertAll(response.Headers.AllKeys, key => string.Format("{0}: {1}", key, response.Headers[key])));
  Debug.WriteLine(headers);

  - find headers regex match
    var msHeaders = response.Headers.AllKeys.Where(key => Regex.IsMatch(key, @"^x-ms.*$")).Select(key => key);

- jquery ui script tags
  <link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css" rel="stylesheet" type="text/css"/>
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"></script>
  <script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js"></script>

- deploying content files in Azure Web Role projects
  in Visual Studio, set these two file properties
  - Build Action = Content
  - Copy to Output Directory = Copy Always
  content files: txt, pdf, png, ...

- p# get user string input
  - use read-host cmdlet to simplify ux, easier than having to wrap input string in quotes
  $x = read-host 'input'
  input: foo bar 123
  #$x = "foo bar 123"

- convert unicode character to html
  1. convert unicode codepoint value from hex to int
  2. html syntax: &#value;

  example codepoint: (U+25BA)
  1. [int]"0x25ba"  #9658
  2. &#9658;

  #unicodeToHtml "25ba"  # &#9658;
  #unicodeToHtml 2591    # &#9617;
  function unicodeToHtml($codepoint)
  {
    "&#{0};" -f [int]"0x$codepoint"
  }

- p# ascii chars
  65..90 | %{[char]$_)}  #[char]$_ = [convert]::tochar($_)
  65..90 | %{"{0} = {1}" -f $_, [char]$_}  #[char]$_ = [convert]::tochar($_)
  97..122 | %{"{0} = {1}" -f $_, [char]$_}
  "Abc".toCharArray() | %{"{0} = {1}" -f $_, [int][char]$_}

  #escape char: `
  " ``!@#$%^&*()-=[]\;',./~_+{}|:`"<>?".toCharArray() | %{"{0} = {1}" -f $_, [int][char]$_}
  chars = " `!@#$%^&*()-=[]\\;',./~_+{}|:\"<>?"

  $chars = " ``!@#$%^&*()-=[]\;',./~_+{}|:`"<>?"
  $chars.toCharArray() | %{"{0} = {1}" -f $_, [int][char]$_}

- p# list functions
  gci function:*

- using css line-height to vertically center text in a div
  source: http://www.zann-marketing.com/developer/20050518/vertically-centering-text-using-css.html

  this works well for one line of text, need to modify for n lines
  - specify the line-height to be the same height as the block element
    <div style="line-height:1em;background-color:#dcdcdc">
      vertically centered text
    </div>

- js percentage fx
  //pct(1, 2)  //50%"
  //pct(9, 7.89)  //114.07%
  function pct(x, y)  //string
  {
    var result = (x / y),
        fmt = x + "/" + y + " = ";

    console.log(fmt + result);  //9/7.89 = 1.1406844106463878
    result = ((result * 100).toFixed(2)).replace(".00", "") + "%";
    console.log(fmt + result);  //9/7.89 = 114.07%

    //return ((x / y) * 100).toFixed(2).replace(".00", "") + "%";  //one liner
    return result;
  }

- p# percentage fx
  #pct 1 2      #50%
  #pct 9 7.89   #114.07%
  #(pct 1 2)[2] #50%
  function pct($x, $y)  #string[]
  {
    $result = ($x / $y)
    $fmt = "{0}/{1} = " -f $x, $y
    $fmt + $result  #9/7.89 = 1.14068441064639
    $result = "{0}%" -f (round($result * 100))
    "{0}{1}" -f $fmt, $result  #9/7.89 = 114.07%

    #"{0}%" -f (round(($x / $y)*100))  #one liner
    $result
  }

- p# base conversions
  int to binary  [convert]::tostring(256, 2)         #100000000
  int to hex     (256).tostring("x")                 #100
  int to hex     [convert]::tostring(256, 16)        #100
  int to hex     "{0:x}" -f 256                      #100
  int to octal   [convert]::tostring(256, 8)         #400
  binary to int  [convert]::toint32("100000000", 2)  #256
  hex to int     0x100                               #256
  octal to int   [convert]::toint32("400", 8)        #256

- linux bash base conversions
  int to binary echo 'obase=2; 256' | bc        #100000000
  int to hex    echo 'obase=16; 256' | bc       #100
  int to hex    printf '%x\n' 256               #100
  int to octal  echo 'obase=8; 256' | bc        #400
  binary to int echo 'ibase=2; 100000000' | bc  #256
  hex to int    echo $((0x100))                 #256
  hex to int    echo 'ibase=16; 100' | bc       #256
  hex to int    printf '%d\n' 0x100             #256
  octal to int  echo 'ibase=8; 400' | bc        #256

- MSBuild error when building an Azure webrole project that has no cs files included.
  Error occurs in CoreCompile build phase, see build output.
  Error Message: "CSC : fatal error CS2008: No inputs specified [x:\web\cloudServiceWebRole.csproj]"

  Fix/Workaround
  - include an empty cs file in project, this adds a compile entry to the project file
    <ItemGroup>
      <Compile Include="a.cs" />
    </ItemGroup>

- #win server 2008 services
  - get-service * | ?{$_.name -match "mpsSvc|spooler|termService|trustedInstaller|umRdpService|w3svc|was|wuauserv"}

- substitute folder
    subst /?
    subst x: \_data
    subst y: \\10.0.0.0\temp\

- net use
  net use \\10.0.0.1\c$    * /user:domain\john  #prompt for password
  net use \\10.0.0.1\share * /user:\john
  net use \\10.0.0.1\c$    * /user:administrator
  net use \\10.0.0.1\c$ <password> /user:administrator
  net use \\10.0.0.1\c$ /delete

- p#
  gci env:
  get-psDrive
  get-psDrive -psProvider fileSystem

- lock windows command
  http://msdn.microsoft.com/en-us/library/aa376875(v=vs.85).aspx
  "This function has the same result as pressing Ctrl+Alt+Del and clicking Lock Workstation."
  &rundll32.exe user32.dll, LockWorkStation

- task manager view command-line column
  task manager -> processes tab -> view - select columns -> command line

  - runs these p# wmi scripts as Administrator to see all process command lines
    get-wmiobject win32_process | select commandline
    get-wmiobject win32_process | select *

- p# move files fx, performs xcopy and then deletes sourceFolder
    - move-item cmdlet too limited, eg error: "Move-Item : Source and destination path must have identical roots. Move will not work across volumes."

    #WARNING, this fx deletes the source folder after copying files to destination folder
    #xcopyMoveDelete "x:\data\*" "z:\backup\data\"
    function xcopyMoveDelete($sourceFolder, $destinationFolder)
    {
      xcopy $sourceFolder $destinationFolder /s/h/q

      #DELETE SOURCE FOLDER WARNING, remove-item cmdlet deletes the source folder - comment whatif param to execute
      "deleting source folder: $sourceFolder"
      ri $sourceFolder.trim("*") -recurse -force -whatif
    }

- p# security
  use set-executionPolicy cmdlet to allow script file execution
  #set-executionPolicy remoteSigned

- p# profile script
  - windows 7/server 2008
    c:\users\john\documents\windowspowershell\profile.ps1
      cd\
      cls

- get-service * | ?{($_.status -eq "running")
  get-service * | ?{($_.status -eq "stopped") -and ($_.name -match "sql|mssql")}

- #calcTaxRate 99 8.25
  #sub    99.00
  #tax     8.25 (0.0833333333333333)
  #total 107.25
  function calcTaxRate([float]$subtotal, [float]$tax)
  {
    $subtotalFmt = "{0:0.00}" -f $subtotal
    $taxFmt      = "{0:0.00}" -f $tax

    #calc
    $taxrate  = $tax/$subtotal
    $total    = $subtotal * (1 + $taxrate)  #calc using taxrate, not tax input param
    $totalFmt = "{0:0.00}" -f $total

    #pseudo right-justify hack
    $subPadding = " " * ( ("$totalFmt".length) - ("$subtotalFmt".length) )
    $taxPadding = " " * ( ("$totalFmt".length) - ("$taxFmt".length)      )

    #output
    "sub   {0}{1}"       -f $subPadding, $subtotalFmt
    "tax   {0}{1} ({2})" -f $taxPadding, $taxFmt, $taxrate
    "total $totalFmt"
  }

- #round 12.3456    #12.35
  #round 12.3456 3  #12.346
  function round($value, $decimals=2)
  {
    [system.decimal]::round($value, $decimals)
  }

- min F# console app examples, for breakpoint
  System.Diagnostics.Debugger.Break()  //ex 1 auto breakpoint
  System.Console.ReadLine() |> ignore  //ex 2

- visual studio command window
    - shortcut keys: ctl + alt + A

      COMMAND                      DESCRIPTION
      build.rebuildSolution
      cls                          clear screen
      debug.breakpoints            open breakpoints window
      debug.disableAllBreakpoints
      debug.enableAllBreakpoints
      debug.watch2                 open watch-2 window
      file.copyFullPath
      file.openContainingFolder
      ? "abc".Length               3
      ? x                          debug print x var/value
      ?? x                         debug quickwatch

    Predefined Visual Studio Command Aliases
    http://msdn.microsoft.com/en-us/library/c3a0kd3x.aspx

- ipconfig /release;
  ipconfig /flushdns;
  ipconfig /renew;

- p# cultureInfo
  get-culture cmdlet
  [system.threading.thread]::currentThread.currentUICulture

  (get-culture).textInfo.toTitleCase("foo bar")  #Foo Bar

- set-alias <alias> <function>
  set-alias foo calcFooPiSquare

- xcopy x:\data\*        x:\backup\data\ /s/h/q
  xcopy x:\data\*        x:\backup\data\ /s/h/q/d:01-01-2011  #files modified on or after date
  xcopy x:\data\*        x:\backup\data\ /s/h/q/exclude:x:\exclude.txt
  xcopy x:\data\file.txt x:\backup\data\ /s/h/q
  /e to copy empty folders

  file: exclude.txt
  .bmp
  .pdf
  .dll
  .exe
  .ini
  .log
  .suo
  .temp
  .user
  \.git\
  \.svn\
  \bin\
  \debug\
  \images\
  \obj\
  \release\
  thumbs.db

- hosts files
  mac:     /etc/hosts
  windows: c:\windows\system32\drivers\etc\hosts

- p# copy windows hosts file
  gc c:\windows\system32\drivers\etc\hosts | out-file x:\backup\data\hosts.txt -encoding utf8

- virtual pc, toggle fullscreen: (right-alt) + enter

- p# find all unique words/matches in file
  use select-string allmatches with regex capture to show only match, not standard select-string output full line

  - gi x:\foo.txt |
      select-string "(\w+)" -allmatches |
      %{
         foreach($m in $_.matches) { #loop all matches found in line
           $m.groups[0].value
         }
       } | sort -unique

  - #one line
    gi x:\foo.txt | select-string "(\w+)" -allmatches | %{foreach($m in $_.matches){$m.groups[0].value}} | sort -unique

- file attributes
  attrib /?

  #alt view file and folder attributes
  gci x:\foo\ -rec

  #view file attribute
  attrib x:\foo\a.txt

  #set readonly file attribute
  attrib +r x:\foo\a.txt

  #remove readonly file attribute
  attrib -r x:\foo\a.txt

  #recursive, files and folders
  attrib +r x:\foo\* /s /d
  attrib -r x:\foo\* /s /d

- reserved p# variables, do not use for var names
  "$args"
  "$input"

- p# REPL template for input loop processing, eg script calculator
  requires entering input value only, not function/alias name
  if function requires multiple params, split input param in function

  #---------------------------------------------------
  #template 1, min

  function foo($string){$string}     #function
  while ($true) {                    #loop
    $in = read-host "enter a value"  #read input
    foo($in)                         #call function
  }
  #---------------------------------------------------
  #template 2, +ux

  $host.ui.rawUI.windowTitle = "loop..."  #set window title
  function foo($string){$string}          #function
  while ($true) {                         #loop
    $in = read-host "enter a value"       #read input
    if ($in -match "^(exit|quit|q)$") {   #exit loop support
      "exiting loop"  #exit
      break
    }
    else {
      foo($in)                            #call function
    }
  }
  #---------------------------------------------------
  #template 3, anonymous function

  while ($true) {                         #loop
    $in = read-host "enter a value"       #read input
    if ($in -match "^(exit|quit|q)$") {   #exit loop support
      "exiting loop"  #exit
      break
    }
    else {
      &{param($string) $string} $in       #call anonymous function
    }
  }
  #---------------------------------------------------

- p# set window title
  $host.ui.rawUI.windowTitle = "main"

- regular expressions
  - find html opening tags
    <a[^>]*>
    <form[^>]*>

  - remove b html tags
    search:<b[^>]*>(.*?)</b>
    replace:\1

  - regex match empty lines
    REGEX              DESCRIPTION
    ^\s*$              match empty line
    ^\s*$\r\n          match empty line, with linebreak

  - regex match duplicate lines in a text file, sort content first
    search:^(.*)(\r?\n\1)+$
    replace:\1

  - regex match html anchor tags
    works with multiple anchors on same line, and multiline using "dot matches newline"
    the question mark in this regex ".*?" is what allows it to match multiples on same line
    REGEX                     DESCRIPTION
    <a[^>]*>.*?</a>           match entire tag
    (?<=<a[^>]*>).*?(?=</a>)  match text only, including empty
                 ---          regex to match
    -------------             lookbehind, match regex, then lookbehind and match anchor tag
                    --------  lookahead,  match regex, then lookahead and match closing anchor tag

  - regex lookaround - noncapturing groups - "lookaway" :)
    NAME                REGEX   EXAMPLE  DESCRIPTION                                  MATCH
    lookahead           (?=R)   A(?=B)   match A, then lookahead and match B          matches the A
                                         A followed by B
    negative lookahead  (?!R)   A(?!B)   match A, then lookahead and match if NOT B   matches the A
                                         match A, as long as it's NOT followed by B
                                         A NOT followed by B
    lookbehind          (?<=R)  (?<=A)B  match B, then lookbehind and match A         matches the B
                                         B preceeded by A
    negative lookbehind (?<!R)  (?<!A)B  match B, then lookbehind and match if NOT A  matches the B
                                         match B, as long as it's NOT preceeded by A
                                         B NOT preceeded by A

- p# dynamic array
  (1..3)[1]  #2

- p# html encode file, line by line
  $file = "x:\foo.txt"
  gc $file | %{htmlEncode($_)} > ($file + ".out")  #x:\foo.txt.out

- p# html encode multiline string, here string
  $hs = @"
    #...
    #...
  "@

  $hs | %{htmlencode $_}

- add-type -assembly system.web  #calling add-type multiple times - ok
  function htmlEncode($string)
  {
      [web.httputility]::htmlencode($string)
  }

  #getOutFileName x:\file.txt  #x:\file.txt.out
  function getOutFileName($infile)
  {
      [io.path]::getFileName($infile) + ".out"
  }

  function getOutFilePath($infile)
  {
      [io.path]::getdirectoryname($infile)
  }

- html/url encoding
  add-type -assembly system.web
  [web.httputility]::htmlencode("<foo />")
  [web.httputility]::htmldecode("&lt;foo /&gt;")
  [web.httputility]::urlencode("www.foo.com/?a=b")
  [web.httputility]::urldecode("www.foo.com%2f%3fa%3db")

- loading .net assemblies into p#, add-type replaces loadWithPartialName (obsolete)
  add-type -assembly system.web       #load system web
  add-type -assembly system.xml.linq  #load linq xml

  #add-type -assemblyName system.web  #alt assemblyName param
  #[system.reflection.assembly]::loadWithPartialName("system.web") #obsolete, use in p1

- asp.net mvc routing, redirect
  internal: use IIS URL rewrite
  external: use Controller.RedirectPermanent() and Controller.Redirect() to redirect to other domains

  public RedirectResult Redirect()
  {
      var url = "http://www.expressionsoftware.com/";
      return RedirectPermanent(url);  //301 permanent redirect
      //return Redirect(url);         //302 temporary redirect
  }

- open files with p# invoke-item cmdlet
  #open file in default text editor, eg notepad
  ii x:\temp\foo.txt

  #open all text files
  gci x:\temp\* -inc *.txt -rec -force | %{ii $_.fullname}

- css even-odd background color
  tr:nth-child(odd)
  {
      background-color: #fff;
  }
  tr:nth-child(even)
  {
      background-color: gainsboro;
  }

- ms minifier
  $infile = 'x:\file.debug.js'
  $outfile = 'x:\file.js'
  $m = 'x:\lib\microsoftAjaxMinifier\v4\ajaxMin.exe'
  &$m -js -clobber $infile -out $outfile -enc:out 'utf-8'

- html 5
  <!doctype html>
  <html lang=en>
  <head>
    <title></title>
    <meta charset=utf-8>
  </head>
  <body>
  </body>
  </html>

- browser indent outdent margin
  document.body.style.marginTop    = "1000px";
  document.body.style.marginLeft   = "-100px";
  document.body.style.marginBottom = "200px";

- hex color scale #000000 - ffffff, dark to light
  dark to light  0123456789abcdef 0-9a-f
  light to dark  fedcba9876543210 f-a9-0

- webpage text and background color dom js
  - black background #000, ghost text #111
    document.body.style.backgroundColor = "#000"; document.body.style.color = "#111";

  - white background #fff, ghost text #eee
    document.body.style.backgroundColor = "#fff"; document.body.style.color = "#eee";

  - wicked terminal green
    document.body.style.backgroundColor = "#000"; document.body.style.color = "#1ca62e";

  - all elements
    var x = document.getElementsByTagName("*");
    for(var i=0; i<x.length; i++) {
      x[i].style.backgroundColor = "#000";
      x[i].style.color = "#aaa"
    }

- text editor colors font
  https://www.expressionsoftware.com/apps/texteditor/
  var x = document.getElementsByTagName("textarea")[0];
  x.style.backgroundColor = "#000";
  x.style.color = "#444";
  x.style["font-family"] = "verdana"
  x.style.borderColor = "#000";
  x.style.margin = "0";
  x.style.padding = "1em 0 0 2em";

- set browser title date
  function formatDateTime(date)  //12:34:00
  {
    date = date || new Date();
    return date.getHours() + ':' + date.getMinutes() + ':' + date.getSeconds();
  }

  (function()
  {
    document.title = formatDateTime() + ' ' + document.title;
  }());  //immediate

- browser scroll
  document.body.scrollTop = 500;  //c
  $(window).scrollTop(500);       //cfi

- windows temp folders
  win 7/8: c:\users\nelson\appdata\local\temp

- remote desktop services terminal services admin/console
  $ts = 'c:\windows\system32\mstsc.exe'
  &$ts /v:DEV01 /f /admin    #2008+
  &$ts /v:DEV01 /f /console  #2003

- restart/shutdown windows
  shutdown /s /f /t 0                #shutdown 0 seconds
  shutdown /r /f /t 0                #restart 0 seconds
  shutdown /r /f /t 0 /m \\10.0.0.0
  shutdown /r /f /t 0 /m \\DEV01