PowerShell WinForms interactive Prototyping/Debugging

Credits:

Motivation

  • PowerShell’s interactive nature lends it to be a handy way to experiment with .Net objects… including UI elements like WinForms/WPF…
  • Yet firing up UI’s classically take over the active thread to service the user interaction (e.g. mouse events etc)…
  • Without the extra gravy below, our otherwise handy interactive powershell locks up tight until we close down the Windows Forms application thus releasing the main thread back to the command line
  • The following gravy throws a Windows Form onto a background thread such that we can continue to manipulate the UI objects WHILE THEY’RE RUNNING, yay!

The Gravy

create RunSpaceWinForm.ps1 as such

function RunSpaceWinForm {
    param($frm)
    if (!$frm) {return}

    #RunSpace is a PowerShell thread
    [System.Management.Automation.Runspaces.Runspace]$rs = [Management.Automation.Runspaces.RunspaceFactory]::CreateRunspace()
    $rs.ApartmentState = "STA"
    $rs.ThreadOptions = "ReuseThread"
    $rs.Open()

    # make the WinForm object instantiated in current scope also available inside the runspace
    $rs.SessionStateProxy.SetVariable("frm", $frm)

    $ps = [System.Management.Automation.PowerShell]::Create()
    $ps.Runspace = $rs
    $rs.SessionStateProxy.SetVariable("ps", $ps)

    [System.IAsyncResult]$invokeHandle = $null
    $rs.SessionStateProxy.SetVariable("invokeHandle", $invokeHandle)

    # nugget: here's basically where the magic sauce kicks in
    # create the script that will run on the background thread, this lets WinForm have it's WndProc message pump while freeing our current PowerShell thread to further manipulate WinForm objects
    $ps.AddScript({
      #this call will take over the thread until the application is shut down by closing the main form
      [System.Windows.Forms.Application]::Run($frm)

      # clean up the powershell thread objects
      $ps.Runspace.Close()

      #honestly not sure if these commands work and are beneficial
      $ps.EndInvoke($invokeHandle)
      $ps.Runspace.Dispose() #this will block the runspace state on "closing" until you close the interactive powershell window
      $ps.Dispose()
    }) | Out-Null
    $invokeHandle = $ps.BeginInvoke()
    return "Use Debug-Runspace -id $($rs.Id) to activate breakpoints"
}

... READ MORE ...

Migrate from Delicious to Diigo

Delicious set the standard but they’ve been a bit of a bumpy ride lately with reliability… according to their blog blog they recently moved back to old code base and Del.icio.us domain (ah memories :)… and then just as of today just got their settings page operational such that I could successfully export my bookmarks and hop to another free link lily pad… the export yields a simple html file full of links.
 

I’ve initially setted on Diigo… it’s pretty slick… there’s a nicely robust Chrome plugin.
 

Below is a little jQuery i threw together to truncate my Delicious links at a certain cutoff date so I’m not loading a bunch of old junk.
Edit the exported html file and add jquery in the head like so and F5 refresh the page.

<head>
  <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.3/jquery.min.js"></script>
</head>

then run this JS straight from the F12 developer tools console in Chrome, or whatever you prefer

// this approach works on "bookmark file" format. e.g. what Delicious.com exports
// basically just an html file full of <a> tags wrapped with <dt>'s inside one big <dl>
// key attributes: ADD_DATE="1461441710" TAGS="BestStuffEver"
// the date format is in seconds... to make it JS Date compatible just multiply value by 1000 (i.e. milliseconds)

// find the "add_date" of the oldest entry you want to keep
var cutoffDate = new Date(1345307846000)

// this then deletes all the links older than cutoffDate
$("a").each(function(idx, el) {
  if( new Date($(el).attr("add_date")*1000) < cutoffDate ) { var par = $(el).parent(); par.next("dd").remove(); par.remove(); }
});

// then just save-as that page

// and import to Diigo :)
// https://www.diigo.com/tools/import_all

... READ MORE ...

SQL Server PDO PHP7

  1. get the DLL – grab latest x64.zip
  2. add to your php.ini extension list:
    [ExtensionList]
    extension=php_pdo_sqlsrv_7_nts.dll
    
  3. here’s sample call code:
    <?php
    
    try {
         $conn = new PDO( "sqlsrv:Server= ip_address; Database = mydb ", $user, $pwd);
         $conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
    }
    catch(Exception $e){
         die(var_dump($e));
    }
    
    $stmt = $conn->query($qry);
    $result = $stmt->fetchAll();
    $row = $result[0];
    $colval = $row["fieldname"];
    ?>
    

... READ MORE ...

PHP7 Debugging under Visual Studio 2015

I suggest installing PHP7 through the IIS Web Platform Installer so it does the Handler Mapping vs having to mess with that manually (i.e. assigning PHP extension to php-cgi.exe) – but there’s a lot of guides out there for doing that yourself if you want. That’ll probably leave you with a slightly older version so then just go install latest PHP7 bits over the top – we want the non-thread-safe (NTS) builds when running under IIS FastCGI (supposedly the most performant approach) Ideally you don’t mind springing for PHP Tools for Visual Studio… this package provides comforts like Intellisense and PHP project templates… and I also noticed that PHP Tools automatically configures XDebug debugging bits for us which is nice vs figuring that out manually (at least the first time)… turns out its just some php.ini settings (see below). so basically you just launch site in Visual Studio debug (F5) and PHP Tools will ask you if you want it to configure debugging for you… the brief wrinkle here is that it then went off and installed/configured PHP5.x… hence the main reason I’m posting this – to affirm we can then indeed just go copy the pertinent settings from the PHP5.ini to our PHP7.ini… if you go look at the php5.ini that PHP Tools set up you’ll see the following settings added at the bottom (for me it went under: C:\Program Files (x86)\iis express\PHP\v5.6): [XDEBUG] zend_extension=”C:\Program Files (x86)\IIS Express\PHP\v5.6\ext\php_xdebug.dll” xdebug.remote_enable = on xdebug.remote_handler = dbgp xdebug.remote_host = 127.0.0.1 xdebug.remote_port = 9000 xdebug.remote_mode = req so then we need to go get xdebug for php7

... READ MORE ...

Free SSL Certs

LetsEncrypt.org is a wonderfully progressive initiative… free certs for all, to promote better internet security, nice!
 

this windows tool made quick work of plugging it into IIS vs the more unix’y stuff they suggest on their home page
literally just seconds to launch the win tool and hitting a key to select which IIS site you want the cert for… none of the ol’ CSR hassle, yay!
 

Tips:

  • your web server has to be reachable on the public internet at the domain url (port 80) you wish to gen the cert for
  • the win tool will be most automatic when you plug your domain into the host-header (port 80)

Note: The LetEncrypt certs come set to expire in 90 days – BUT, the windows tool schedules a recurring task to reach out and automatically renew the certs before that expiration. Pretty slick… will have watch if that actually works come time.
 

... READ MORE ...

Knockout-Validation lib – clean patterns

GitHub home

leverages the jQueryValidation lib

All Bootstrap v3 compatible

Coolest architectural nugget = applying validation rules to VM observables (not inside HTML <input> markup)

one clear reason why that is a better way -> when the VM field is bound to multiple UI points, you only define the rule once vs many

var myVM = function() {

    var self = {};

    // simple required
    self.orderId = ko.observable().extend({ required: true });

    // conditionally required
    self.orderId = ko.observable().extend({ required: { onlyIf: self.isDelivery } });

    // required with field name in error message - LUVIN HOW SIMPLE THIS IS!
    self.orderId = ko.observable().extend({ required: "Order#" });

    // conditionally required with fieldname
    self.orderId = ko.observable().extend({ required: { params: "Order#", onlyIf: self.isDelivery } });

    return self;
}();

... READ MORE ...

Shred GPX WPT XML with SQL Server

declare @xml xml = '<gpx>
<wpt lat="35.0977419" lon="-80.89258">
  <name>10112 Industrial Dr. Pineville, NC 28134, Pineville, NC, 28134</name>
  <desc>10112 Industrial Dr, Pineville, NC 28134, USA</desc>
</wpt>
<wpt lat="30.8276466" lon="-83.9967315">
  <name>323 Industrial Blvd Thomasville, GA 31792, Thomasville, GA, 31792</name>
  <desc>323 Industrial Blvd, Thomasville, GA 31792, USA</desc>
</wpt>
<wpt lat="26.4237949" lon="-81.415628">
  <name>283 E Jefferson St Immokalee, FL 34142, Immokalee, FL, 34142</name>
  <desc>283 Jefferson Ave E, Immokalee, FL 34142, USA</desc>
</wpt>
</gpx>'

SELECT 
  n.value('@lat', 'varchar(100)'),
  n.value('@lon', 'varchar(100)'),
  n.value('desc[1]', 'varchar(100)')
FROM @xml.nodes('/gpx/wpt') Rows(n)

... READ MORE ...

WordPress – show all Tags in Cloud

wordpress defaults to only showing the first 45 tags
tweak this file => \wp-includes\widgets\class-wp-widget-tag-cloud.php
add the “number=0” parameter to this code:

    /**
         * Filter the taxonomy used in the Tag Cloud widget.
         *
         * @since 2.8.0
         * @since 3.0.0 Added taxonomy drop-down.
         *
         * @see wp_tag_cloud()
         *
         * @param array $current_taxonomy The taxonomy to use in the tag cloud. Default 'tags'.
         */
        $tag_cloud = wp_tag_cloud( apply_filters( 'widget_tag_cloud_args', array(
            'taxonomy' => $current_taxonomy,
            'echo' => false,
      'number' => 0
        ) ) );

... READ MORE ...

Knockout, Validation, Bootstrap skinned File Input

Visual example:


 
Highlights:

  • Skinning the native html <input type=”file”> by setting it’s opacity=0 and positioning above a bootstrap looking button… this way when you click the pretty button you’re really clicking on the invisible native button which launches the file open dialog.
  • Bootstrap input-group aesthetically bundles the visual elements – file button, filename box, valiation message and clear button
  • Knockout Custom Binding on the file input change event to save into VM observable
  • Knockout-Validation lib to require selected file to be an image type – nice thing here is keeping that logic in the js ViewModel vs dirtying the html with it.
     
     

... READ MORE ...