Easy *Native* Windows Self Extracting EXE Builder (SFX)

This is an oldie but goody… the gist is that even latest Windows 10 still ships with working IExpress.exe which is a self extracting exe builder! Who knew.

In my case, very handy for bundling a batch file and it’s dependencies into a single exe for a buddy.

For the record, I started out with 7zip’s SFX facility and eventually got it working but it’s a bit more clunky… besides the steps required to build an auto launch exe, you’ll get a mildly undesirable “Program Compatibility Assistant” “This program might not have installed correctly” warning… the IExpress generated exe doesn’t seem to have this issue.

Launching IExpress.exe without any args will present the wizard which will walk you through building a “SED” config file with several commonly desired “setup.exe” options like user confirmation prompt, etc… importantly, this includes specifying a batch file you wish to be launched after extract.

Handy batch for recreating exe whenever you update your script:

::start sets appropriate working directory
::especially crucial when launched as admin (which normally defaults to c:\windows\system32)
::and allows us to use relative file references in the SED config file so that launching from any path works (including UNC)

start "Title" /d"%~dp0" iexpress /n Project.sed

Tips

  • The program to be launched can indeed be a .BAT/.CMD
  • The IExpress SED wizard will hard code paths, just edit afterwards and remove to be relative. It works.
  • This would of course work for PowerShell or any other script that can be launched via its runner, either bundled in the EXE or native, e.g. ScriptCS

VS Code, Typescript – Bare Metal New Project

i’m basically following this guide, while humbly attempting to trim down to bare necessity and re-align configs with crucial bits that’ve shifted since then… and likely to continue shifting 😐

  1. install Node… there’s many ways but their setup.exe is handy… this includes npm
  2. from cmd.exe: npm install -g typescript (-g means globally vs project specific)
  3. install VS Code via setup.exe
  4. launch VS Code… commands inside VS Code designated as “vsc>” from here-on
  5. vsc> File > Open > New Folder > “projectFolder” > then Open that folder
  6. vsc> F1 > type “task” > “Configure Task Runner” > Enter > “TypeScript – Watch Mode” > Enter
    1. this will create a crucial tasks.json file with working default settings…
    2. -AND- that “watch mode” choice means the moment you save any .ts file, the IDE will automatically regen the corresponding .js files… which plays into live edit and continue style debugging
  7. vsc> File > New File > populate with the following json block and save as tsconfig.json … this directs vscode to “transpile” .ts script to standard .js for us
    {
        "compilerOptions": {
            "target": "es5", 
            "outDir": "out/",
            "sourceMap": true
        }    
    }
  1. vsc> File > New File > throw in something simple like console.log("Hello World!"); and save as app.ts
  2. vsc> build aka compile via CTRL+SHIFT+B… after a few pregnant seconds, this will gen some stuff in the out folder that we specified in above tsconfig.json
  3. vsc> CTRL+SHIFT+D to get into Debug panel > click the gear icon which creates and opens default launch.json which should have working defaults going by what we’ve done previously
  4. crucial and subtle, navigate back to the app.ts file as the active tab you wish to run/debug (this corresponds with the relative reference, "program": "${file}", in launch.json)
  5. now we should be able to simply hit F5 to run/debug from here-on as we’d normally expect… F9 to set breakpoints, etc.

hopefully you’re off to the races and you can bootstrap yourself further by googling

i am a bit “ashamed” this is still so obtuse

Syncfusion Xamarin.Forms SfDataGrid – Binding to List<Dictionary<,>>

corresponding syncfusion forums post

Binding to Collection<Dictionary<,>> can be accomplished but doesn’t appear to be well documented… this WPF SfDataGrid doc gave the clue.

The basic trick is to set the SfDataGrid’s column.MappingName = “Fields[FieldName]”;
where Fields is a Dictionary property on your DictionaryWrapper class.

I couldn’t get List<Dictionary<string, object>> working directly without the wrapper class “hiding” the dictionary from what I think is an SfDataGrid bug. The app crash exception call stack ultimately winds up on an invalid Linq related get_Item() call.

Below is sample working code including “SimpleTable” wrapper for List and Newtonsoft type converter for deserializing Json “table” directly into this datastructure… this facilitates delivery of tabular resultsets from web api’s… see my SqlClientHelpers.ToJson method as one implementation that works succinctly within Azure Functions for example.

FYI, I believe there is also a bug with SfDataGrid column sorting logic when bound to this kind of Dictionary, a non-fatal exception fires. I worked around by implementing grid.SortColumnsChanging.

Sample Deserialize call:

var data = "[{\"Source\":\"Web\",\"Batch Id\":1}, {\"Source\":\"Manual\",\"Batch Id\":2}]";
var table = JsonConvert.DeserializeObject<SimpleTable>(data);

Binding sample with crucial MappingName syntax:

grid.ItemsSource = table;
grid.Columns.Add(new GridTextColumn()
{
  HeaderText = "Source",
  MappingName = "Vals[Source]" // **** HERE'S THE KICKER ****
});

SimpleTable.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace DataHelpers
{
  [JsonConverter(typeof(DictRow_DictDeserializer))]
  public class DictRow
  {
    public Dictionary<string, object> Vals { get; set; }
    public DictRow(Dictionary<string, object> dict) { Vals = dict; }
  }

  public class SimpleTable : List<DictRow>
  {
    public SimpleTable(IEnumerable<DictRow> list) : base(list) { }
  }

  public class DictRow_DictDeserializer : JsonConverter
  {
    public override bool CanRead => true;
    public override bool CanWrite => false;
    public override bool CanConvert(Type objectType) => objectType == typeof(Dictionary<string, object>);

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
      return new DictRow(serializer.Deserialize<Dictionary<string, object>>(reader));
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
      throw new NotSupportedException();
    }
  }
}

Android Emulator Nuggets

Installing Google Play

  • This worked very nicely minimally for Android v7.1.1 “with Google APIs”…
  • Need to launch emulator.exe with -writable-system -selinux permissive args
  • grab the version of OpenGapps you want
  • Basically follow this guide but stop at “Restarting and Creating another Image”
    • Then adb root & adb remount
    • and I found that I just needed to adb shell mkdir /system/priv-app/Phonesky & adb push Phonesky.apk /system/priv-app/Phonesky not the other priv-apps
  • and I also didn’t have to create a new image vs simply rebooting

Root

one time

  • Grab SuperSU Recovery Download and extract “su”
  • adb root & adb remount
  • adb push su /system/xbin/
  • adb shell chmod a+x /system/xbin/su

create .cmd script for each launch

  • {path}\emulator.exe -avd Nexus_9_API_25 -writable-system -selinux permissive
  • adb wait-for-device & adb root & adb remount & adb shell "su -ad &"
    • -ad stands for auto-daemon and just sounds cool…
    • i haven’t seen anybody set this up to where android automatically launches the su daemon)
  • then just go install SuperSU from the Play Store
    • DO NOT allow it to upgrade the su binary upon prompting… that always hung my virtual device after reboot
  • and lastly fire up a Root Checker from Play Store to make sure

Clipboard integration

  • Android Studio (as of v2.3) directly supports Windows <=> Emulator cliboard integration (ref)
  • ADB shell input text "sample text" is pretty handy too

Handy Links

  • Android Studio download… main tools:
    • SDK Manage
    • AVD Manager
    • Device Monitor – event log and GUI file explorer
  • Google Play APK Downloader
  • ChainFire’s “How To SU”
  • Windows AVD Folder where the runnable virtual machines sit: %UserProfile%.android\avd
    • HOWEVER Upon running Android Studio’s vs Visual Studio’s version of emulator.exe will manipulate the %UserProfile%.android\avd\hardware-qemu.ini to point the .img file paths to their folders
  • Android Studio puts everything here: %AppData%..\Local\Android\SDK
  • Visual Studio puts everything here: C:\Program Files (x86)\Android\android-sdk
    • \platform-tools\adb.exe
    • \tools\emulator.exe
    • \system-images\android-25\google_apis\x86_64\system.img, etc.
  • AStudio emulator.exe runs better NOT elevated
  • VStudio emulator.exe runs better ELEVATED
  • AStudio emulator.exe v2.5.2 looks like it creates “copy on write” system.img.qcow2 files instead of modifying system.img directly which means you can save that qcow2 file as backup or erase it to rollback to clean baseline
  • VStudio emulator.exe v2.5.5 looks like it modifies system.img directly
  • qemu-img.exe info file.qcow2 will show you what base .img it’s linked to (download qemu bundle)
  • Install Intel HAXM directly if SDK Manager is no cooperating

My full fidelity emulator launch script

(special TCC/LE batch syntax)

@echo off
SETLOCAL 

::call tk qemu-system-x86_64
start "Android Emulator" /inv /pgm "C:\Users\beej1\AppData\Local\Android\sdk\emulator\emulator.exe" -avd Nexus_9_API_25 -writable-system -selinux permissive
adb wait-for-device
adb root
adb remount
adb shell "su -ad &"

:pasteloop

echos Press any key when ready... to paste current clipboard to android^r
pause

set clipline=0
do forever
  set cliptxt=%@clip[%clipline%]%
  if "%cliptxt%" EQ "**EOC**" LEAVE
  adb shell input text '%cliptxt%'
  set clipline=%@inc[%clipline%]%
enddo 
goto pasteloop

[SOLVED] Xamarin Forms iOS build error: An inconsistency between the local app and the remote build has been detected for _____. Please rebuild the application and try again.

image

there’s tons of hits on this but for me it seems to somehow be a “corrupt” solution file…

solution == new solution ; )

i spun up a new xam cross platform project solution and simply readded my existing PCL and iOS projects from the broken solution and it built and deployed to simulator just fine

keeping the old solution around for a rainy day diff

notables:

  • i am running Visual Studio 2017 RTM (15.0.0-RTW+26228.4) but i’m pretty sure i ran into this on VS2015 a while back as well.
  • tried upgrading all Windows and Mac bits to latest Xamarin Alpha
  • tried upgrading to the latest XCode (8.2.1)
  • walked throught the majority of this connection troubleshooting opus at the ready (gee Xam dudes, problems here much?)…
  • tried Clearing the Mac Build cache
  • enabled verbose logs (c:\> devenv /log)
  • there’s just nothing logged out to any of the Mac or Windows log folders for that error
  • i had another solution lying around that i created about a month ago when i ran into this error (same projects)… i just loaded it up and got the “inconsistency” error on the first run attempt, but then it actually went thru and launched the simulator upon second try – go figure

ASP.Net Controller API nuggets

Write Directly to Response Stream

Stack-o basically covers this already but kinda danced around how minimal the code can really be for the basic scenario…

//ignore this...
//e.g. $.ajax(url, { procName: "", parms: {deliveryDate:"3/2/2016"}, returnParmName: "" }, ...)
public class GenericProcArgs
{
  public string procName { get; set; }
  //from: http://stackoverflow.com/questions/5022958/passing-dynamic-json-object-to-c-sharp-mvc-controller
  //super convenient way to receive JS object with arbitrary properties to be fed straight to proc parms
  public dynamic parms { get; set; }
  /// <summary>
  /// whether to titleCase the JSON property names (handy for feeding auto built datagrids)
  /// </summary>
  public bool titleCase { get; set; } = false;
  public string returnParmName { get; set; }
}

//here's the beef...
public ActionResult GetProc(GenericProcArgs args)
{
  Response.ContentType = "application/json";

  using (var proc = new Proc(args.procName))
  {
    proc
      .AssignParms(args.parms as IDictionary<string, object>)
      .ExecuteJson(Response.OutputStream, args.titleCase);
  }
  return new EmptyResult();
}

  • in my experience, the ContentType wasn’t even necessary but it feels like good practice
  • here i’m using a database layer represented by my own custom Proc class… which is a bundle of convenient methods wrapped around SqlCommand … in this case, it’s firing SqlCommand.ExecuteReader() and writing the results directly to the response via Newtonsoft.Json StreamWriters… i honestly haven’t done a real profile on this call stack but it feels like a nice straight shot from sql streaming through web tier transform to client
  • another nifty nugget in play here is the usage of C# Dynamic to catch arbitrary JS objects posted from the ajax client, and that Dynamic is then inherently castable to a Dictionary

Kendo UI Nuggets

Grid doesn’t like spaces in dataSource field names

(I happen to be subscribing to KnockoutJS observable here to receive data feed but that naturally depends on your framework of choice.)
Typical Kendo JS error: invalid template
Particularly note the way the columns property is generated.
[crayon toolbar=”always” lang=”js”]
sigCapVm.packingSlips.subscribe(function (newval) {
var gridPackingSlips = $(“#gridPackingSlips”);
var kgrid = gridPackingSlips.data(“kendoGrid”);
if (kgrid && kgrid.columns.length) kgrid.dataSource.data(newval);
else {
if (kgrid) kgrid.destroy();
gridPackingSlips.kendoGrid({
//workaround for autogenerating columns with spaces
//from: http://www.telerik.com/forums/field-name-with-space-and-other-than-numeric-creating-issues-to-load-the-grid#23fk8zzWZkioYCn7Tr4xFg
columns: $.map(Object.keys(newval.length === 0 ? {} : newval[0]),
function (el) {
if (el.startsWith(““)) return; //by convention, don’t show fields starting with “
return { field: ‘[“‘ + el.replace(“#”, “\#”) + ‘”]’, title: el }
}), //hash aka pound (#) is special character in kendo template syntax
dataSource: { data: newval },
noRecords: { template: “no records found for those inputs” },
height: “20em”,
change: function (e) {
//good to remember that we’re not doing a true knockout binding here vs setting the grid’s dataSource.data property above
//so we have to “manually” connect the selected row back to the viewmodel here
var selectedPackingSlip = e.sender.dataItem(e.sender.select());
var vm = ko.contextFor(gridPackingSlips[0]).$root;
vm.selectPackingSlipId(selectedPackingSlip._PackingSlipId);
},
resizable: true,
//scrollable: false,
sortable: true,
filterable: false,
selectable: true
});
};
});
[/crayon]