PHP SQL Server blob hosting

from here
see this post for sql server driver downloads


header('Content-type: application/pdf');
// leave this out to open directly in browser: header('Content-Disposition: attachment; filename="my.pdf"');
$sql = "select InvoiceDocument from SalesInvoicePDF where InvoiceID = '123'";
$stmt = sqlsrv_query($conn, $sql);
if ( sqlsrv_fetch($stmt) )
    //this pulls the first field via "0"
    $data = sqlsrv_get_field($stmt, 0, SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY));
    // write binary sql stream directly to http response

... READ MORE ...

Lighter Spin on ADAL in Xamarin Forms


new-up the elusive “PlatformParameters” in your AppDeligate.cs::FinishedLoading / MainActivity.cs::OnCreate

ts;wm (too short; want more ; )

thankfully we have solid writeups on ADAL with XF… this post is just me trying to boil it down to essence and PCL as much as possible…
(BTW: ADAL = Active Directory Auth Lib… i needed it for PowerBI embedding)


the first post keeps the platform specific surface area pretty minimal but also winds up wrappering the stock ADAL classes quite a bit…
the second post seems pretty minimal and leverages CustomRenderers for the right timing to grab this context… seems like a good general trick to tuck away…

the approach i came to is grabbing this context right up front in app initialization and then providing it through dependency injection later…
both pieces of that are basically one liners which feels nice
also it’s now conveniently available to other services should needs arise…
and theoretically we’ve kept things clean for TDD but honestly i don’t readily see how to test this flow since it requires interactive auth… i’ll have to read up on how people generally recommend mocking this kind of thing

iOS AppDeligate.cs::FinishedLoading()

  public partial class AppDelegate : Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
    public override bool FinishedLaunching(UIApplication app, NSDictionary options)

      var prismApp = new App(new iOSInitializer());

      var finishedLaunchingResult = base.FinishedLaunching(app, options);
      //KeyWindow won't be populated until after FinishedLaunching
      prismApp.Container.RegisterInstance(typeof(IPlatformParameters), new PlatformParameters(UIApplication.SharedApplication.KeyWindow.RootViewController)); // ** here's the beef **

      return finishedLaunchingResult;

... READ MORE ...

Toggle XAML <> Code-Behind in Visual Studio 2015, ReSharper, Xamarin Forms

Quickly bouncing between .XAML and corresponding .CS file just seems like an obvious need… i feel like we used to have this in WPF but it’s been a few years for me.

Short Story:

  • install Visual Commander
  • this does require the ReSharper command for “related files”… sorry if that’s not an expense you care to bear but it’s a great tool for numerous reasons if you can.
  • Visual Studio > VCmd menu > Edit Macro…
  • paste in the code below
  • now just CLOSE the edit macro window and save (i’ve found saving other than closing to be a very wonky user experience)

at this point you could run this macro via the VCmd menu or the default CTRL-M, CTRL-1 keystroke, but i prefer to assign F7 hotkey to satisfy my muscle memory , so…
(see screenshot below)

  • Visual Studio > Tools menu > Options > Environment > Keyboard
  • “Show Commands Containing” edit box: vcmd.
  • select” VCmd.Command01″ (each macro gets assigned to a subsequent slot)
  • “Use new shortcut in” edit box: Text Editor
  • “Press shortcut keys” edit box: F7
  • then click “Assign” button and “OK” and you’re done
using EnvDTE;
using EnvDTE80;

public class C : VisualCommanderExt.ICommand
    public void Run(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package) 
        DTE.ExecuteCommand("ReSharper.ReSharper_GoToRelatedFiles"); //normally bound to CTRL-ALT-F7 if you need to test visual flow
        System.Windows.Forms.SendKeys.Send("{DOWN}{ENTER}"); //the down happened to work out for me so far due to fortunate naming convention... we'll have to see if it lasts

... READ MORE ...

Using “C# Interactive” aka CSI/CSX for ETL


interactive C# offers typical REPL benefits ala powershell without the mental context switch required to leave our beloved C# syntax =)


  • great MSDN reference article
  • CSX syntax can be executed from either Visual Studio 2015 (as of update 1) > View > Other Windows > C# Interactive
  • -or- C:\Program Files (x86)\MSBuild\14.0\bin\csi.exe
    • then #load file.csx


    this example is based on a low fidelity web page as the raw data source
    … it’s really nice to have all the convenient one liner RESTy methods of System.Net.WebClient available now vs the lower level WebRequest/WebResponse pattern that came with .Net 1.0. E.g. client.DownloadString, DownloadFile, etc.


    trivially demonstrative in this case, simply a string.Split call 🙂


    demonstrates leveraging SQL Server’s Table-Valued-Parameter functionality to bulk upload rows which are then conveniently manifested inside the receiving stored procedure as a standard sql rowset, ready for tpyical DML like joining to other tables, etc.

    SQL definition

    CREATE TYPE dbo.SpreaderData_UDT AS TABLE
        [SpreaderDataID] [INT] PRIMARY KEY,
        [SpreaderID] [INT],
        [Speed] [INT],
        [Density] [INT],
        [SpreadQty] [INT],
        [Setting] [VARCHAR](100)
    -- crucial - SQL Server yields a unintuitive error message when this has not been done
    CREATE PROCEDURE [dbo].SpreaderData_Table_u
    @SpreaderData dbo.SpreaderData_UDT READONLY -- <= ***** crucial
      sd.Setting = sd2.Setting
    FROM dbo.SpreaderData sd
    JOIN @SpreaderData sd2 ON sd2.SpreaderDataID = sd.SpreaderDataID

    ... READ MORE ...

GreaseMonkey hacking Gmail


i wanted to see if i could get category bundling working in gmail ala outlook… it’s always been a nice mental flow for me to carve out pending events from littering the “inbox zero” but still see them right there in front so i don’t forget to check up on them vs hidden a click away under a “folder”

update – don’t miss the “labs” functionality for doing exactly this kind of category bundling


the integration with gmail’s normal behavior isn’t perfect so this is still very experimental stages but it’s a pretty satisfying quick hack…


  • i followed a this tutorial for getting the gmail API cooking including OAUTH2…
  • the greasemonkey end of the code has some helper functions to get all the usual libraries loaded up like bootstrap, font-awesome and knockout… currently i’m only leveraging jQuery and Lobibox (love those sexy growls!)
  • tweak the code to call vs messages to see your label Id’s… they’re not the names we see in the gmail UI


obvious next nice to haves rush to mind:

  • bundle by multiple specified categories (aka labels)
  • clicking on message in new section actually does navigate to message since that was an easy gimme but it’s not as slick in the vertical split mode… i tried tracing the code that dynamically populates the side panel with the message body and it’s just to abstract, so it’ll have to be a matter of popping that in myself, but shouldn’t be too tough since we’re already loading the whole message body behind the scenes.
  • flip to real ECMAScript 2016 module loader or whatever’s clever right now… without a build engine to make things happen for script.js it seems like we’re still waiting for a fully native solution… i could do require.js approach but that seems to be on the outs already???

example screenshot



// ==UserScript==
// @name         GmailMonkey
// @namespace
// @version      0.1
// @description  try to take over the world!
// @author       Brent Anderson
// @match*
// @grant        none
// @run-at        document-end
// ==/UserScript==

//gmail api stuff//////////////////////////////////////////////////////////////////////////

function objArrayGetByProperty(array, propertyName, value) {
  var result = $.grep(array, function(e){ return e[propertyName] === value; });
  return result.length ? result[0].value : null;

function loadMessages() {
  var request ={
    "userId": "me", //nugget: special userId of me to indicate the currently authenticated user
    "labelIds": "Label_59",
    "maxResults": 200

  request.execute(function(response) {
    if (response.error) {
      Lobibox.notify("error", { size: "mini", delay: false, msg: "[] " + response.error.message });

    $.each(response.messages, function() {
      var messageRequest ={
        "userId": "me",

      messageRequest.execute(function (message) {
        var from = objArrayGetByProperty(message.payload.headers, "name", "From").replace(/"/g,"");
        var subj = objArrayGetByProperty(message.payload.headers, "name", "Subject");
        var date = formatDate(new Date(objArrayGetByProperty(message.payload.headers, "name", "Date")), "MMM DD");

        var onclick = "window.location.href += '/""'";

        mainTable.append(verticalSplit ? '\
          <tr class="zA yO apv" onclick="'+onclick+'">\
          <td colspan="2" rowspan="3"></td>\
          <td class="yX xY apy">'+from+'</td>\
          <td class="yf xY apt">'+date+'</td>\
          <td class="xY" rowspan="3"></td>\
          <tr class="zA yO apv" onclick="'+onclick+'">\
          <td colspan="2" class="xY apD" style="font-weight: bold">'+subj+'</td>\
          <tr class="zA yO apv apw" onclick="'+onclick+'">\
          <td colspan="2" class="xY apA apB y2">'+message.snippet+'</td>\
          ': '\
          <tr class="zA yO" onclick="window.location.href += \'/''\'">\
          <td colspan="4"></td>\
          <td class="xY">'+from+'</td>\
          <td colspan="2" class="xY" style="overflow: hidden">'+subj+'</td>\
          <td class="xW xY">'+date+'</td>\

//from here:
function handleAuthClick() {
    client_id: clientId,
    scope: scopes,
    immediate: false
  }, function (authResult) {
    if(authResult && !authResult.error) {
      gapi.client.load("gmail", "v1", loadMessages); // <<<<<<<<<<<<<<<<<<<<<<<
    } else {
      $("#authorize-button").on("click", handleAuthClick);
  return false;

function nextTechInit() {
  waitForIt(":2", function(found) {
    $("html, body").css("font-size", "inherit"); //override bootstrap's annoying default


    Lobibox.notify.DEFAULTS.soundPath = "//";
    Lobibox.notify.DEFAULTS.delay = 3000;
    //Lobibox.notify("error", { size: "mini", delay: false, msg: "lobibox test" });

    mainTable = $(".Cp > div > table");
    verticalSplit = mainTable.find("colgroup > col").length === 5;

    mainTable = $(mainTable).find("tbody");
      '<tr><td colspan="'+(verticalSplit?5:8)+'"><div style="margin-top: 1em" class="">Pending</div></td></tr>');


function formatDate(date, format) {
  var monthNames = [
    "January", "February", "March",
    "April", "May", "June", "July",
    "August", "September", "October",
    "November", "December"

  var day = date.getDate();
  var monthIndex = date.getMonth();
  var year = date.getFullYear();

  return format.replace("MMM", monthNames[monthIndex].slice(0,3)).replace("DD", day);


function waitForIt(elementId, then) {
  //console.log("waitForIt: " +elementId);
  var found = document.getElementById(":2");
  if ( !found ) {
    //console.log("not found!"); 
    setTimeout(function() {waitForIt(elementId, then);}, 500);

function loader(refsArray) {
  var element;
  for(var i = 0; i < refsArray.length; i++) {
    url = refsArray[i].toString();

    if (url.indexOf(".js") !== -1 || url.slice(0,8) === "function") {
      element = document.createElement("script");
      if (url.slice(0,8) === "function") { 
        element.innerHTML = url;
        continue; //nugget! inline script doesn't fire an onload event
      else element.src = url;
      if (i < refsArray.length-1) { //if we're not on the last element already, recurse on the remaining items
        var remaining = refsArray.slice(i+1);
        element.onload = function() {

    else if (url.indexOf(".css") !== -1) {
      element = document.createElement("link");
      element.rel = "stylesheet";
      element.type = "text/css";
      element.href = url;

    else throw("unexpected reference extension, expecting .css or .js or a function, but got: "+url);


//by simple convention, list all CSS first, then JS...
//each JS will subsequently load the next as a simple dependency mechanism so specify JS's in appropriate order
//further, including a function(s) will inline <script> it
  'var mainTable;\r\n'+
  'var verticalSplit = false;\r\n'+
  'var clientId = "";\r\n'+
  'var apiKey = "xxxxx";\r\n'+
  'var scopes = "";\r\n\r\n'+

... READ MORE ...

Script to generate dozens of required iOS app icon images


there are a number of free icon generating web sites available which begs the question whether a script like this provides any value… but leveraging a robust image manipulation utility like imageMagick to apply unique aesthetics makes a DIY approach like this more compelling… along those lines, in the current script, i’m applying:

  • custom “centering” – for the splash images where the icon sits inside of a larger background, i’ve found positioning the icon 2/7ths of the way down from top to be the most pleasing
  • outer glow




@echo off

::keeps all variable definitions local to batch file so no need to cleanup after

::*** make sure to start with 1024x1024 original ***
set inFile=!original.png
if not [%1] EQU [] set inFile=%1

rename "%inFile%" ""
erase Default*.png Icon.ico Icon*.png Icon.ico Splash*.png Itunes*.png
rename "" "%inFile%"

:: this was a handy page that did most BUT NOT ALL of what i saw in the "Resources" folder generated from the Xamarin project template...

:: so i decided to have a crack at generating the remaining "Default" aka splash screen images since they represented an interesting challenge of:
:: 1) resizing onto a larger background
:: 2) applying "outer glow" to mitigate the blue-on-blue...
::    albeit, i could've chosen a more simpatico background color, but i favor sticking with defaults until something really kicks me in a different direction

::***install fantastically handy ImageMagick tool from =>
::main options docs:

::clarify options used:
::-channel portion yields more desireable hard edge on shadow, see:
::+swap is necessary because we need the input image to initially come first in order to render it's corresponding shadow but then we want the shadow behind... and the + sign is handy shortcut to swap the last 2 layers in pipeline w/o having to explicitly specify
::-gravity North centers horizontally and at top vertically and then the -extent sets the outer "canvas" size with the negative offset bringing the icon down from the top
::the double %% on -level is required to escape the normal processing of "%" as a batch variable

@echo on
goto pause

magick "%inFile%" -define icon:auto-resize="256,128,96,64,48,32,16" ( +clone -shadow 100x80-0-0 -channel A -level 0,50%% +channel ) +swap -background none -layers merge -gravity center "Icon.ico"

call :IconSub 29 Icon-Small
call :IconSub 40 Icon-Small-40
call :IconSub 50 Icon-Small-50
call :IconSub 57 Icon
call :IconSub 58 Icon-Small@2x
call :IconSub 60 Icon-60 ::including this one only because it's referenced in LaunchScreen.storyboard, even though i'm not using LaunchScreen because i want the app to Splash with the big background style image
call :IconSub 72 Icon-72
call :IconSub 76 Icon-76
call :IconSub 80 Icon-Small-40@2x
call :IconSub 100 Icon-Small-50@2x
call :IconSub 114 Icon@2x
call :IconSub 120 Icon-60@2x
call :IconSub 144 Icon-72@2x
call :IconSub 152 Icon-76@2x
call :IconSub 512 iTunesArtwork
call :IconSub 1024 iTunesArtwork@2x

call :SplashSub 320 480 Default
call :SplashSub 640 960 Default@2x
call :SplashSub 640 1136 Default
call :SplashSub 768 1004 Default-Portrait
call :SplashSub 1536 2008 Default-Portrait@2x
call :SplashSub 1024 748 Default-Landscape
call :SplashSub 2048 1496 Default-Landscape

@echo off
echo  ____                                               _   _ 
echo / ___^|   _   _    ___    ___    ___   ___   ___    ^| ^| ^| ^|
echo \___ \  ^| ^| ^| ^|  / __^|  / __^|  / _ \ / __^| / __^|   ^| ^| ^| ^|
echo  ___) ^| ^| ^|_^| ^| ^| (__  ^| (__  ^|  __/ \__ \ \__ \   ^|_^| ^|_^|
echo ^|____/   \__,_^|  \___^|  \___^|  \___^| ^|___/ ^|___/   (_) (_)

@ping localhost -n 10 >nul:

@echo off
:: %1 = desired size
:: %2 = file name
set /a shadowSize=%1*8/100
if %shadowSize% EQU 0 set shadowSize=1
magick "%inFile%" -resize %1 ( +clone -shadow 100x%shadowSize%-0-0 -channel A -level 0,50%% +channel ) +swap -background none -layers merge -gravity center -resize %1 %2.png
@echo on
@goto :EOF

@echo off
:: %1 = width
:: %2 = height
:: %3 = file name
set smallestDimension=%2
if %1 LSS %2 set smallestDimension=%1
::the shadow creates a natural "padding" effect, so start out with icon same as smallest dimension
set /a iconSize=%smallestDimension%
set /a shadowSize=%smallestDimension%*8/100
::center the icon 1/3 of the whitespace available down from top
set /a verticalOffset=(%2-%iconSize%)*2/7

::default Xamarin project blue background #3498DB
:: handy script to generate following commands if you already have a folder with the desired resulting images:
:: >magick identify -format "magick \"\%inFile\%\" -resize %w %f\n" Icon*.png iTunes*.png
magick "%inFile%" -resize %iconSize% ( +clone -shadow 100x%shadowSize%-0-0 -channel A -level 0,50%% +channel ) +swap -background "#3498DB" -layers merge -resize %iconSize% -gravity North -extent %1x%2+0-%verticalOffset% %3.png

@echo on
@goto :EOF

... READ MORE ...

[Solved] Greasemonkey/Tampermonkey jQuery sideload and setInterval

i was having a heck of a time keeping a reliable handle on jQuery in the Pandora page… it would be there upon initial Greasemonkey script fire but then upon subsequent setInterval executions, jQuery was nowhere to be found… facinating…

notable: as i was debugging, i started to see that Chrome was cycling through four ( 4 ! ) different VMxxxx “copies” of the greasemonkey script upon each setInterval execution… questions like why? and why 4? abound if anyone cares to enlighten me

so it struck me that i just need to make sure jQuery is available in each one of those “sessions”…

noteable: the “sideload” is accomplished via jQuery’s native “noConflict” facility… this post explains how it works… the gist is that each load of jQuery does indeed replace “$” BUT it also saves the previous into _$, such that $.noConflict can restore “$” to the previous version… this is what allows Pandora’s copy of jQuery to remain as-is… crucial in this case because Pandora depends on additional add-ons that it loads as expando properties on its instance of jQuery.

after that was in the bag, i couldn’t help dwelling on what else might be possible and had another aha moment… from tracing the pandora js execution i learned that there were pretty obvious variables getting set for allowed features (e.g. “allowSkipTrackWithoutLimit”)… i’d banged my head pretty deap trying to replace the main pandora.js script with one where those values were tweaked… blocking the original via AdBlockPlus was easy as well as loading the tweaked pandora.js inline <script> but that approach ran aground on not being able to precisely sequence the alternative script in the same order with it’s dependencies… Chrome doesn’t implement the crucial window.beforescriptexecute event which would probably make this feasible… the main pandora.js is wrappered in a self contained function call so we can’t monkey patch its innards… but then it struck me, jQuery is global… and what if they’re getting these values via jQuery.ajax… such that i could override and tweak… sure enough, that approach panned all the way out!

update – after that last round, i realized the whole thing about sideloading jQuery was unecessary, i just needed to use the inline script approach to make sure my code executed on the page context vs whatever weird context TamperMonkey normally does… so the following script now reflects the cleaner evolved approach

// ==UserScript==
// @name          Pandora - "still listening" click
// @author        Brent Anderson
// @homepage
// @match*
// @grants        none
// @run-at        document-end
// ==/UserScript==

function recurringTweaks() {
  //this click, remove, click sequence skips embedded video ads and gets the tunes playing again
  var stillListeningButton = $("#still_listening_ignore");
  if (":visible")) {;
    //above brute force video ad skip leaves player controls disabled, this resolves that side effect

  var adContainer = $("#ad_container");
  if (adContainer.length) {
    //remove right side ad section...
    //and allow the album covers area to fill the space
    $(".contentContainer").css("width", "100%");
    $("#adLayout").css("width", "80%");

    //remove some other "upgrade" bits

// monkey patch jQuery.ajax so we can override some nice stuff =)
var hijax = function() {
  if (typeof $ !== 'undefined') {
    var oldAjax = $.ajax;
    var newAjax = function(a, b) {
      var oldSuccess = a.success;
      a.success = function(data, textStatus, jqHXR) {

        // infinite skip! =)
        $(data).find('name:contains(allowSkipTrackWithoutLimit) + value > boolean').replaceWith('<boolean>1</boolean>');

        //auto skip ads
        if (a.url.indexOf("method=registerImpression") !== -1) {
          $(".skipButton a").click();

        //debug: console.log('url: ' + a.url + ', data: '+(''+data === '[object XMLDocument]' ? data.children[0].innerHTML : data));
        oldSuccess(data, textStatus, jqHXR);
      oldAjax(a, b);
    $.ajax = newAjax;

    setInterval(recurringTweaks, 2000);



// load <script> inline to the page so it has access to jQuery "$" global vs TamperMonkey's alternative context
if (!document.getElementById("hijax")) {
  var hijaxScript = document.createElement("script");
  hijaxScript.setAttribute("id", "hijax");
  hijaxScript.innerHTML = recurringTweaks.toString() + "\r\n" + hijax.toString().replace(/^function.*{|}$/g, "");

//sorry, turning this post into a catch all for stuff that might come in handy elsewhere

//the original jquery "sideload" code
function loadJq() {
    if (!window.jq) {
        script = document.createElement("script");
        script.src = "";
        script.onload = function() { window.jq = $.noConflict(true); cosmetics(); };
    else cosmetics();


  window.addEventListener('beforescriptexecute', function(e) {
      if ("pandora.js") != -1) {
          //e.stopPropagation(); //??
 = ''; //??
 = "patched script";
  }, true);

var a = document.getElementsByTagName("script");
for each (var e in a) {
  if (!e) continue; // oddly, this does sometimes grab null elements.
  var b = e.getAttribute("src");
  if (b && b.indexOf("pandora.js") != -1) {

// @grants         GM_xmlhttpRequest
  method: "GET",
  url: "", //"",
  onload: function(response) {

    //here's the beef!
    //var tweaked = response.responseText.replace("this.PC=b.allowSkipTrackWithoutLimit", "this.PC = true;");

    var tweaked = response.responseText;
    document.head.appendChild(document.createElement('script')).innerHTML = tweaked;


... READ MORE ...

[SOLVED] Bare CNAME with MX record

just thought i’d throw this out into the interwebz since it seems to be such a well known no-can-do that is actually a very handy can-do (where applicable)…


DNS admin warnings advise against doing a “bare” (no prefix) CNAME along with an MX record, example



What i’m successfully demonstrating here is clearly non-standard according to the specs
however, i’ve proven it does work for SOME servers implementation of the standards (including major provider Office 365 on the MX side) so it’s worth trying with your servers if this provides a convenient solution for your needs… and it will be immediately verifiably working or not; no “sometimes” ambiguity to worry about.

... READ MORE ...

ESXi = Win+Mac Xamarin iOS dev nirvana


  • i was looking for a single machine Mac + Win solution… working from one primary desktop and remoting to the other…
  • this is of course how VMware Workstation product sits naturally but that arrangement gave me heartburn (see Motivation)
  • ESXi requires some relatively esoteric configurations of HDD, Video & USB to yield the same single machine convenience, hence these notes


Hosting Mac VM side under Windows VMware Workstation i ran into very unreliable connection from Visual Studio 2015 to Xamarin’s Mac Build Agent (believe me, tried all latest VS2015 update bits as well as Xamarin alpha channel)… only after MANY MANY frustrating retries would it eventually connect as well as surprising Xamarin Studio NuGet package gallery connectivity roadblock with virtual Mac’s network interface in NAT mode which seemed to be the only way Build Agent would ever connect… NuGet worked under Bridged but then Visual Studio couldn’t connect… arrrrg going the other way with Windows virtualized under Mac host via either Parallels or Fusion always took an unacceptable hit on Windows / Visual Studio performance… year after year both mainstream commercial Mac hosted virtualization products have been riddled with issues and chronically dead ended support forum posts

... READ MORE ...