Thursday, April 27, 2017

I Taught My Kids How To Hack

My family and I enjoy gaming together... and I mean, really... together. We're geeks. Our favorite "family time" game is World of Warcraft... nothing says quality family time like developing character abilities and gear together, working out optimal ability usage ("rotation") and team interaction, in preparation to mob up & go kill demons and monsters.   It's cheaper than a night at the movies, generally, and often more thought-inducing. ("For the Alliance!   For Azeroth!")

Other games pop up from time to time.   Recently the kids started playing some Steam title...  some cute little 8-bit thing.  One thing that was unique about it was that, unlike almost everything out there, this game was entirely local...  it's a true single player game.

As they got into the finer points of this new game, they started to agonize over its limitations. It's no Kobayashi Maru, but it's designed to engage users and drag out their engagement over long periods of time.

Now I get that games have their points and lessons to learn, and it's generally best to let kids work through and past them naturally.   These guys are like most kids nowadays, solid gamer geeks, familiar with the gamut of games across phone, PC and Xbox, among others.   They've been there.  Done that.  When they tell me they're bored, I tell them to go outside and play, and they look at me as if I have two heads.

In today's modern computing technology, "apps" (which most games qualify as being) are too secure and/or too distributed to consider operating outside of the original intent of the program.  The save-file of the game is either stored in a "sandbox" that's fully isolated from the user...  OR the "save file" is not even stored on the device, it's actually downloaded as needed from some cloud-based host somewhere in the inter-webs.

This game is just like dozens of others they've worked through "naturally"...  I found myself thinking they might benefit from thinking outside the box a bit.   Given this is a classic "low-tech" local PC game, no other players would be impacted, and... there's access to the file system.

Frankly, it was easier than I expected.  Initially, we started scanning the registry for clues, and found a silly ROT13 encoded string related to it that we decoded together, but not what we wanted. Eventually, we stepped back to the flat simplest solution. We found the game save files in c:\users\{userid}\AppData\Roaming\{Game}\  (how convenient!).   Opening the files within that folder, we found good old NOTEPAD.EXE did the trick...  the save file was an XML document, but that made for a nice, easy to grok (and search) structure...  within minutes we'd multiplied their in-game gold amounts by 1000x (by just tacking a few 0's on the end of their configured amount).

The full game save file was a long list of name-value pairs that were easy to identify.  They could have easily added to their on-hand materials counts or any number of other hacks that would have been beneficial.  In this case, everything they needed in game could be acquired with gold, so it didn't make sense to dig much deeper.

Cheating?   Well...  Yes.   And they definitely took advantage. 

My two kids are into game design, and often say they want to build games when they grow up.  This was an interesting opportunity to show them in concrete terms that data is data, and they can think much further outside the box than the average kid...  this is especially important for them to understand the mechanics of app (and game) construction and architecture, peeling back the illusion of the game world. 

In mechanical terms, it's not much different than cracking the hood on a car and showing them how to beef up the engine.

What say you?  Do the ends justify the means?

Friday, April 21, 2017

What's New in C# 7 (CSharp)

Thanks again to folks who joined in for the presentation at the Granite State Windows Platform App Devs  (@WPDevNH) at the Microsoft Store in Salem, NH last night.

Meetup:
https://www.meetup.com/Granite-State-NH-WPDev/events/238684720/

The site most of the content came from was MSDN:



Here's the slide deck:


and example code on GitHub:
https://github.com/GraniteStateHacker/WPDevNH_CSharp7



Tuesday, April 4, 2017

Back To Where We Belong

Big changes for me lately, so more of a narrative personal post than a technical presentation...  and with apologies. I've been too wrapped up with the finer details of finishing up my project with Fidelity to get any blog posts out at all since November last year (yikes). 

I'll get back to the regularly scheduled broadcast shortly.

About this time two years ago, I started a project with a financial firm out in Back Bay, in the John Hancock tower.  We rolled out SharePoint 2013 on-prem, and migrated it from multiple legacy farms... both of which were WSS3.0.   So between the build out and migration, I ended up on that project for a solid three months or so.  Not a bad gig, but... Boston commute (thank God for the Boston Express Bus), and no C# (not even ASP.NET).  It was really more of an IT Pro gig than development.  I was able to do some really fancy powershell stuff to manage the migration, but definitely not my first choice.

That fall, I landed a role on Fidelity's new order management/trading desktop build-out. I have to say, that was roughly the kind of project I've been angling for, for years.  

Technology-wise, the only thing that could have made it any better was to be Windows 10/UWP based, maybe with mobile tendencies.  Alas, building rich clients of any sort is relatively rare, so .NET 4.6 is better than... not .NET at all. 

Still... All C#/WPF, desktop client...   

A good number of my most recent technical posts and presentations were heavily influenced by this project.   Sure, Boston again... for a good portion of it... but they let me work at Fidelity's Merrimack location for a good chunk of the latter half of the project, too.

And it was maybe the longest running single version project I've been on in my life.  I was on it for 18 months...  a full three times longer than a "big" six month project.

All that to say I haven't spent a full, regular day at a desk at BlueMetal Boston's Watertown office in just about two full years. 

In that time, I've seen too many great teammates move on, and about as many new teammates join us.  We were employee owned back then, and I rode out the entire Insight purchase while "living" at the clients' site.

Still, one thing that bothered me is a pattern I don't intend to continue repeating.  When I took my position at Jornata that became BlueMetal, I accepted the title of Senior Developer, even though it appeared to be a step down from my Systems Architect title at Edgewater. 

My reason for accepting that was primarily that I was joining Jornata as a SharePoint make/break, and I needed to get a little more SharePoint experience under my belt before I was comfortable calling myself a SharePoint Solutions Architect.   By the time the BlueMetal merger worked itself around, I realized my options had opened broadly.  I got the SharePoint experience I needed, but it became very apparent that it wasn't the experience I wanted.  Unfortunately, I was stuck with the "Senior Developer" title even on projects where my depth of experience went much deeper. 

SharePoint is cool for using, and even integrating, and IT Pros get a lot of mileage out of it, but as for software developers... well...  let's just say I let SharePoint fuck up my career enough that I had to re-earn my "Architect" title.  (pardon my language, there's no better word for it.)  I always deliver a win, but I'm a Visual Studio kinda guy.  I'm still happy to develop integrations with SharePoint, and support the SharePoint community... but while there've been major improvements in the past few months alone, Microsoft has been muddling it's SharePoint developer story for years, and I let myself fall victim to it.

Thankfully, the Fidelity project did the trick...  it was just the level of high-touch, real Enterprise application development that I needed to earn my self respect back, and prove out my abilities in the context of BlueMetal. 

I'll admit, while I feel this is restoring my title, it is certainly not lost on me that "Architect" at BlueMetal is a class (or two) above "Architect" in any of my previous companies.  I always felt I was there, even if I felt discouraged and unsupported by my former teams.  I am truly honored to be among those who've earned this title in this company, and very appreciative of the recognition.

At BlueMetal, I'm supported and inspired by my team, and really seeing this as validation that my career vector is now fully recalibrated.

I've said this before: meteorologists are very well educated with lots of fancy tools to help them be more accurate, but reality is that unless you're standing in it, you don't really have much hope of getting it truly right.  I have no intention of becoming a weatherman architect.  Hands-on the code is where my strength (and value) is, so that's where I'll always shoot to be.



Saturday, November 19, 2016

Intro to IoT with C#, Windows 10 on Raspberry PI 3a, a la #BOSCC26

Despite the time crunch, I had expected to be able to dig in on more of the example code I'd prepared (heck, wouldn't have spent so much time pulling that together if I'd thought I wasn't going to get to it.)

I'll also admit, my slides were more of a discussion guide than details, but there are a few good url's in there to get you going with a PI or other IoT starter kit.



GIT repository for the demo code
https://github.com/GraniteStateHacker/BOSCC-GPIO

Feel free to reach out to me with questions, I'm happy to help!

Wednesday, April 13, 2016

Need to Synchronize Columns of a Master/Detail Grid in DevEx WPF?

I generally prefer Telerik controls, but I've got a client that uses Developer Express.  I recently had a need to synchronize columns in a Developer Express WPF Master/Detail grid.   It's a bit of an unusual circumstance, where we have Master / Detail records that use the same view interface, but found the TreeListControl unable to scale up to the demands of our use cases.  The client still wanted the detail grid's columns to appear to functionally be the same column as the master record's (with the ability to show/hide the detail).

Thankfully, the Dev Express GridColumn class is a DependencyObject, and all the needed properties are exposed as DependencyProperty's.

Since the detail grid has the same data interface as the master grid, I was even able to clone the column definitions. 

Finally, since this was an MVVM project, I didn't want the functionality in code-behind, so I abstracted the code for this into a Behavior.

The approach was to bind the Width, Visibility, and VisibleIndex properties of each master grid column to a cloned detail grid column, giving the two entities the appearance of being one functional entity.
Here's the snippet representing the detail grid definition....




        <dxg:GridControl>


<!-- Master grid defined here, not shown.  Detail grid below   -->



          <dxg:GridControl.DetailDescriptor>


                <dxg:DataControlDetailDescriptor ItemsSourceBinding="{Binding Details}">


                    <dxg:GridControl x:Name="DetailsGrid" AutoGenerateColumns="None" ColumnsSource="{StaticResource ColumnsCollection}" >


                        <dxg:GridControl.View    >





                            <dxg:TableView  AutoWidth="False"


                            AllowCascadeUpdate="False"

                            AllowFixedGroups="True"

                            ShowGroupPanel="False"

                            CellStyle="{StaticResource DefaultCellStyle}"

                            NavigationStyle="Row"

                            ShowGroupedColumns="True"

                            AllowGrouping="True"

                            AllowEditing="False"

                            AllowScrollAnimation="False"

                            ShowFixedTotalSummary="False"

                            AllowHorizontalScrollingVirtualization="True"

                            HorizontalScrollbarVisibility="Auto"

                            RowStyle="{StaticResource RowStyle}"

                            AlternateRowBackground="{x:Static dxRes:DevExpressResources.AlternateRowBackgroundBrush}"

                            UseLightweightTemplates="None"

                            ShowColumnHeaders="False"

                               />

                        </dxg:GridControl.View>

                        <i:Interaction.Behaviors>


                            <local:SyncDetailGridColumnsBehavior/>


                        </i:Interaction.Behaviors>

                    </dxg:GridControl>

                </dxg:DataControlDetailDescriptor>

            </dxg:GridControl.DetailDescriptor>

        </dxg:GridControl>


Note the highlighted part above that introduces a local class called SyncDetailGridColumsBehavior, shown in its entirety below:




using System.Windows.Data;


using System.Windows.Interactivity;


using DevExpress.Xpf.Grid;


namespace Local
{
    public class SyncDetailGridColumnsBehavior : Behavior<GridControl>
    {
        private GridColumnCollection _parentGridColumns;
        private GridColumnCollection _detailsGridColumns;

        protected override void OnAttached()
        {
            _detailsGridColumns = AssociatedObject.Columns;
            _parentGridColumns = AssociatedObject.ResolveParentColumnCollection();
            InitializeMasterDetailGrid();
        }
       
        private void InitializeMasterDetailGrid()
        {
            _detailsGridColumns.CloneColumnsAndBindWidthsFrom(_parentGridColumns);
        }
    }

    internal static class ColumnHelpers
    {

        public static GridColumnCollection ResolveParentColumnCollection(this GridControl associatedObject)
        {
            var result =
                ((DevExpress.Xpf.Grid.GridControl)
                    ((System.Windows.FrameworkContentElement) associatedObject.Parent).Parent).Columns;
            return result;
        }

        public static void CloneColumnsAndBindWidthsFrom(this GridColumnCollection targetGridColumns,
            GridColumnCollection sourceGrid)
        {
            targetGridColumns.Clear();
            foreach (var aSourceColumn in sourceGrid)
            {
                var aClonedColumn = aSourceColumn.Clone();
                aSourceColumn.BindWidths(aClonedColumn);
                aSourceColumn.BindPositions(aClonedColumn);
                targetGridColumns.Add(aClonedColumn);
            }
        }

        public static GridColumn Clone(this GridColumn source)
        {
            return new GridColumn()
            {
                Name = source.Name,
                Width = source.Width,
                Binding = source.Binding,
                Header = source.Header,
                Style = source.Style,
                CellStyle = source.CellStyle,
                CellTemplateSelector = source.CellTemplateSelector,
                CellTemplate = source.CellTemplate,
               
            };
        }

        public static void BindWidths(this GridColumn source, GridColumn bindingPartner)
        {
            source.SetBinding(BaseColumn.WidthProperty,
                new Binding("ActualWidth")
                {
                    Source = bindingPartner,
                    Mode = BindingMode.OneWay,
                    UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
                });
            bindingPartner.SetBinding(BaseColumn.WidthProperty,
                new Binding("ActualWidth")
                {
                    Source = source,
                    Mode = BindingMode.OneWay,
                    UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
                });
        }

        public static void BindPositions(this GridColumn source, GridColumn bindingPartner)
        {
            source.SetBinding(BaseColumn.VisibleIndexProperty,
                new Binding("VisibleIndex")
                {
                    Source = bindingPartner,
                    Mode = BindingMode.TwoWay,
                    UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
                });
           
        }

        public static void BindVisibility(this GridColumn source, GridColumn bindingPartner)
        {
            source.SetBinding(BaseColumn.VisibleProperty,
                new Binding("Visible")
                {
                    Source = bindingPartner,
                    Mode = BindingMode.TwoWay,
                    UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
                });

        }
    }
}

       
I expect this to cover 90% of our needs, the other 10% has to do with row selection across master/detail boundaries, but that's a story for another day.

In the meantime, let me know how this makes ya feel...  leave a comment, below.

Thanks!

Sunday, April 10, 2016

Rise of the Smart App

Microsoft didn't talk much about the Windows Phone at Build 2016.  If you think that's news, you're missing the point.

As Microsoft re-defines "Mobile First, Cloud First" they declare shenanigans on the idea that the tech world revolves around phone and tablet.  Yes, tablet and smartphone are mature, first-class citizens, now, but they're not above laptops, PCs, or other computing devices, as Apple (and perhaps even Samsung) might have you believe.

There's no denying that Microsoft lost the battle for smartphone market share.  RIM's Blackberry, considered a relic of the primordial smartphone market, is all but forgotten. Microsoft was pushing Windows Phone as significant competitor, yet, with about the same market share as Blackberry, no one really took their smartphone offering seriously. 

Until Windows Phone's recent convergence with the PC on the universal Windows 10 OS, Windows Phone had no more competitive edge than Blackberry, either.  Sadly, this new competitive edge comes too little, too late. Or has it?

Several years ago, in a very sly move, Apple narrowed and laser-focused the global technology mindset on a much smaller battle... one that it was well positioned in. Apple then equated the battle to the war... They made it all about the smartphone/tablet market.  (I don't think Apple counted on Android, but it didn't matter... in terms of market share, Android won, but in terms of profitability, Apple won.)  Billions of dollars can't be wrong, so Microsoft tried to position itself in Apple's vision, and let itself get dragged around for years... 

Until now.

By connecting Mobility with Portability, Microsoft is driving the scope of technology mindshare again, and are driving it back out to a scale Apple will have to struggle to position itself in. Apple made good smartphones.  Cool beans.

With its converged "Universal" Windows 10 platform, Xamarin portability, and mature cloud offerings replete with machine learning, Microsoft is targeting a much broader "smart app" market... Smart Apps are apps that make any device (keyboard, mouse, display/touchscreen, microphone, pen, scanner, camera, video recorder/editor, audio mixer, cell phone, media player, whiteboard, virtual/augmented reality, what have you) into a smart device.  (Notice anything missing here?  perhaps cars...  but it's hard to imagine that won't change in the next few years...  after all, cars (e.g. BMW) did get mentioned at Build.) 

The smartphone isn't irrelevant, it's just not the whole pie. The reality is that Microsoft is not going to exclude phones from Windows 10 now or any time soon. 

Smartphone prominence is not innovation superiority.

So, how does this make you feel?

Thursday, March 31, 2016

Mobile First, Cloud First as Redefined in Build 2016

There were a number of very cool announcements made at Microsoft Build's 2016 kickoff today, Wednesday, March 30th.  On first brush, one might not notice the common theme across the announcements, however.
These things may seem disconnected, but if you look again, they're not... nor are the other less obviously connected major announcements such as:
Microsoft has been promising Mobile First, Cloud First for a long time. Until today, there's been a consensus that Mobile First meant Tablet and Phone...  as in those hardware form factors get updates and features before classic alternatives.  Today Satya Nadella, CEO of Microsoft, addressed the developer crowd and clarified (or perhaps more accurately "redefined") what "Mobile First" really means.

Mobile First, Cloud First has morphed to mean something more like "Portable First, Cloud First", with portable referring directly to the Universal Windows Platform...  write your code once, and the user can take it to any device (desktop, laptop, phone, IoT) and use it as naturally as possible with the whatever human interface device is available (keyboard, mouse, touch, ink, voice, text, etc)...

And there is, indeed, how all the announcements fit together. 

All of the announcements made today talk about how Microsoft is diversifying the human interface, yet keeping the context of all your work and play available across all devices.  Your apps are there, and they work just as naturally with voice commands as they do with ink. 

Note that keyboard and mouse are relatively unnatural compromises in human interface paradigm, and their use will be diminished in the future. 

If pen and paper is the natural choice, Ink will replace it. 

If voice makes sense, it will be available.

If an intelligent actor might assist you, Cortana and your trusted "Network of Experts" (Apps and BotFX bots) are there. If a virtual or augmented reality makes sense, your apps will join you on Hololens. 

If an Xbox controller is the right choice, no problem. 

All of these things can be enhanced significantly with DirectX 12, even for non-games.

And the Cloud will interlink them naturally so that you can flip from tablet to Hololens without skipping a beat. (in some ways, live process migration is really becoming a reality;  when the apps are the same across every deployed device, the only thing that needs to transfer from device to device is user data, and that's happening via cloud.)

One segment that didn't see much love today:  the Web.  Or did it?  Bash for Windows 10 is a bit of a stretch to connect to the coming shift, but really, it is meant to make it easier for developers to deliver web-based, cloud-hosted solutions using Visual Studio to non-Windows hosts.  Indirectly this will aid in the creation of services that might support Bots made with the BotFX, for example.  All of this is based predominantly on JSON over REST / HTTP.

Some would point out that Windows 10 Mobile (formerly Windows Phone) didn't get any stage time, either, but the reality is that Microsoft no longer sees the smartphone edition of Windows to be a separate thing.   Windows 10 is converging on "The Best Windows Ever", Windows 10... smartphone or not.