The Granite State Hacker

Microsoft.Graph and Appointment Management

It’s been a minute since I’ve felt like there was some content to share of a coding variety, and ironically, I don’t have a minute to do it. So without further ado, I’ll dig right in.

In the management of Granite State Code Camp, I devised a way to connect with all the folks who had ever been a part of one of the events I’ve hosted in Teams. I sent a calendar invite as a 1:1 meeting initiation from myself to each of all the guests in the tenant, using Graph.

This goes back to 2020, when Granite State Code Camp rode out the pandemic as an online-only event, hosted entirely in Teams. Having hosted both GSCC and the Manchester Community College’s New Hampshire CyberSecurity Symposium in the same tenant every year since, there’s a good number of guests in the tenant that all represent a decent targeted mailing list for such events.

In the meantime, while Microsoft has done a fantastic job of touting CoPilot for Visual Studio, I found that Copilot had no understanding of the latest Graph libraries. How ironic that the immense greatness of Copilot stumbles on the immense greatness of new library updates, but that’s something to explore in another post.

While the invitation automation code is messy, and not clean enough for publishing, I was then in a situation where I had a bunch of calendar invitations, and it was really hard to figure out who had accepted, who had declined, and who had ignored.

So, I wrote a console utility to find and filter all the invitations, so that I could then follow up appropriately. This code will eventually become the basis of a re-write for the invitation itself, because I like the updates to the Graph API (which I didn’t use in the part that sends the invitations). Anyway, here’s the GitHub hosted Gist including the project file that shows the package/versions I used to arrive here.

Tech in the 603, The Granite State Hacker

Microsoft Most Valuable Professional (MVP)

Jim Wilcox – 2019-2020 Microsoft MVP – Developer Technologies

This showed up in the mail today! Despite the April 1st date, it’s not an April Fools’ gag after all! I’ve only ever seen one of these trophies in person before this one. I’ve been trying to stay chill about it…. but heck, here it is…

I’m profoundly honored and thankful to say that Microsoft has chosen to award me with this 2019-2020 “Most Valuable Professional” (MVP) award, in the category of Developer Technologies!

If you’re not familiar with this award program, check out the program’s official web site: https://mvp.microsoft.com

Tech in the 603, The Granite State Hacker

Intro to Natural Language Processing with LUIS

Here’s the slides for the presentation I’m doing 11/16/2017 at the Granite State Windows Platform Developers (@WPDevNH) meeting in Salem, NH (at the Microsoft Store)

The group is primarily about Windows 10 app development (implying Universal Windows Platform, UWP).  That said, the group’s been begging for sessions on AI and related services for some time.

Since I’ve been helping a client navigate LUIS lately, I figured an into to the LUIS service would be a nice way to break into this very useful service.

I reserve the right to tweak these slides up until I present them on Thursday, November 16th, 2017.

[office src=”https://onedrive.live.com/embed?cid=90A564D76FC99F8F&resid=90A564D76FC99F8F%211282855&authkey=APp8wuFX2hkqevw&em=2″ width=”402″ height=”327″]Please Join Us! RSVP HERE:
https://www.meetup.com/Granite-State-NH-WPDev/events/243099117/

Tech in the 603, The Granite State Hacker

UWP Equivalent for HttpUtility.ParseQueryString

Getting ready for my LUIS presentation at the Granite State Windows 10 Platform Devs Users Group (@WPDevNH), it made sense to demo LUIS using UWP rather than .NET classic.  (Join us, 11/16 at the Microsoft Store in Salem, NH…  https://www.meetup.com/Granite-State-NH-WPDev/events/243099117/ )

For a demo related to LUIS querying, I needed an alternative to System.Web.HttpUtility.ParseQueryString.  (based on this demo:  https://docs.microsoft.com/en-us/azure/cognitive-services/LUIS/luis-get-started-cs-get-intent )

I did a simple decorator of a Dictionary, adding a constructor to parse using WwwFormUrlDecoder, and overriding the ToString() to put it back together…

I whipped one up relatively quickly, but decided this would be a decent quick post.  Here’s my alt code:

usingSystem.Collections;
usingSystem.Collections.Generic;
using System.Net;
using System.Text;
usingWindows.Foundation;
namespaceLUIS_Examples
{
    public class ParseQueryString : IDictionary<string, string>
    {
        private IDictionary<string, string> _internalDictionary = new Dictionary<string, string>();
        public ParseQueryString(string queryString) :
            base()
        {
            var decoder = new WwwFormUrlDecoder(queryString);
            foreach (var item in decoder)
            {
                _internalDictionary.Add(item.Name, item.Value);
            }
        }
        public override string ToString()
        {
            var sb = new StringBuilder();
            foreach (var aPair in _internalDictionary)
            {
                sb.AppendFormat(“{0}={1}”, WebUtility.UrlEncode(aPair.Key), WebUtility.UrlEncode(aPair.Value));
            }
            return sb.ToString();
        }
        public string this[string key] { get => _internalDictionary[key]; set { _internalDictionary[key] = value; } }
        public ICollection<string> Keys => _internalDictionary.Keys;
        public ICollection<string> Values => _internalDictionary.Values;
        public int Count => _internalDictionary.Count;
        public bool IsReadOnly => _internalDictionary.IsReadOnly;
        public void Add(string key, string value)
        {
            _internalDictionary.Add(key, value);
        }
        public void Add(KeyValuePair<string, string> item)
        {
            _internalDictionary.Add(item);
        }
        public void Clear()
        {
            _internalDictionary.Clear();
        }
        public bool Contains(KeyValuePair<string, string> item)
        {
            return _internalDictionary.Contains(item);
        }
        public bool ContainsKey(string key)
        {
            return _internalDictionary.ContainsKey(key);
        }
        public void CopyTo(KeyValuePair<string, string>[] array, int arrayIndex)
        {
            _internalDictionary.CopyTo(array, arrayIndex);
        }
        public IEnumeratorstring, string>> GetEnumerator()
        {
            return _internalDictionary.GetEnumerator();
        }
        public bool Remove(string key)
        {
            return _internalDictionary.Remove(key);
        }
        public bool Remove(KeyValuePair<string, string> item)
        {
            return _internalDictionary.Remove(item);
        }
        public bool TryGetValue(string key, out string value)
        {
            return _internalDictionary.TryGetValue(key, out value);
        }
        IEnumerator IEnumerable.GetEnumerator()
        {
            return ((IEnumerable)_internalDictionary).GetEnumerator();
        }
    }
}

Tech in the 603, The Granite State Hacker

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.

[office src=”https://onedrive.live.com/embed?cid=90A564D76FC99F8F&resid=90A564D76FC99F8F%211258505&authkey=AH4O2F_Cu16yiaE&em=2″ width=”402″ height=”327″]

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!

Tech in the 603, The Granite State Hacker

Apache Cordova and Windows Universal (8.1)

Thanks to everyone who made it out to the Granite State Windows Platform Users Group last night (April 16, 2015) to see my presentation on using Apache Cordova to create Windows Universal (8.1) “store apps”. 

I walked away feeling like I’d helped inspire everyone who attended…  even as an “intro” level presentation, the demos seemed to keep everyone engaged, asking questions, and prompting me to go “off-roading” to check out various features. 

We really had fun with it!

So while the best part of the presentation was the demos, the slides do have some great links in them.

[office src=”https://onedrive.live.com/embed?cid=90A564D76FC99F8F&resid=90A564D76FC99F8F%21370273&authkey=AKm8AYTLUY1iyG8&em=2&wdAr=1.7777777777777776″ width=”350″ height=”221″]
 
 

If you missed it, don’t worry too much…  I’ll keep this presentation dusted off & ready for upcoming events, as well…  I could imagine it fitting well into a Code Camp event or something akin to it in the coming year.  

Heck, feel free to reach out to me if you think this is something you’d like to know more about… I’m happy to have a chat about it.

Next month’s meeting is already scheduled…  we’re looking forward to Jim O’Neil coming to reprise his Boston Code Camp 23 presentation on Themes in Windows Universal (8.1).   Please join us!

Meetup:  http://www.meetup.com/Granite-State-NH-WPDev 



Tech in the 603, The Granite State Hacker

Aggregating Windows Phone Store Apps into RSS

Naturally, there’s an app for the Granite State NH Windows Phone Users Group.   🙂

I recently added the ability to aggregate listings from the Windows Phone app store to create a list of apps published by our members.  RSS seemed the natural way to present the info, since it was consumed easily by an App Studio app.

I showed it off a bit at the users group, and got a few requests for some of the code.

Once published, you should be able to go to http://{yourserver}/{optional}/GSWPUGServices.svc/GetData to load the RSS feed.

It’s currently published at http://www.kataire.com/GSWPUG/GSWPUGServices.svc/GetData

Here’s the project.

http://sdrv.ms/1cNYO9T

Tech in the 603, The Granite State Hacker

Virtual Gambit

What a pain.

A few weeks ago I posted a bit about how Windows 8 is not killing the PC market.

I’ll now take that a step further and argue about the one thing in Windows 8 that is really making me regret not having new hardware…  an actual compelling reason to really think about a new PC, for me.

Around the time I wrote the original post, I was looking at taking advantage of Windows 8 Pro / Hyper-V on my home PC…  mostly because emulators for devices such as Surface and Windows Phone 8 make use of it.  I have Hyper-V on my work system, and it’s fantastic for a variety of reasons.

I’d all but forgotten that my home PC didn’t have a processor that supported VT-x technology, meaning no Virtual Machines… so when I went to add the Hyper-V role, I was somewhat disappointed to discover it was a no-go.  

“Maybe it’s time to upgrade something,” I thought.   I could get a new machine… but it’s pretty hard to justify the chunk of change based on this one feature.  (Never mind that it’s not so easy to liberate that kind of money from the budget.)  “I’ll order a new processor that supports Virtual Machines.”  VT-x.

So I dropped the $200, instead…. placed an order for a dated, but still more feature-rich chip.  I waited for the thing to arrive, and finally sat down, lifted the old CPU out, and dropped in the new one.

After the successful screw-top surgery, I pulled up the dialog to add Hyper-V only to discover that…  the new CPU doesn’t have the guts to run Hyper-V on Windows 8 either.

Seriously miffed, (because I know VM technology is older than Hyper-V, and I just burned $200 for 2-3 more FPS in WoW) I started looking into what the deal was.  Turns out Hyper-V on Windows 8 requires an additional virtualization technology in the processor called SLAT.  

None of the processors that fit my home PC support SLAT. 

If I want Hyper-V, (which is highly desirable for coders like myself who want to use Microsoft tools for the latest MS platforms) I *must* replace the vast majority of my PC’s components… but, really… economically speaking…. I need a new PC.

So it’s an interesting conundrum that I can’t help think was designed around boosting hardware sales….  Seriously…  I can do a lot with Virtual Box and VMware Player in terms of running VMs.  I could even install Windows Server 2012 and run Hyper-V from the server OS (without SLAT) on the very same hardware.  (Only Windows 8 Pro Hyper-V requires it.)

I can’t buy a new PC for less than $2k that will outperform my current system…  so, when it comes down to it, the ONLY reason I can think of to upgrade would be for Hyper-V… what a pain.

Here’s a comparison between my PC (Hyper-V no-workey) and a much more modern i7 (Hyper-V workey)…  note that the i7 is an Intel i7-720M, but it’s processor score (6.9) in the Windows Experience Index is less than the experience index of my older Yorkfield Core 2 Quad-Q9400 (7.2).   (both systems are hobbled by their disk platters).

Tech in the 603, The Granite State Hacker

Keeping in the Code

At the end of the day, the business solution is always the most important part of the equation, but it’s not the only part.  While I’m working on a solution, I’m also looking at tools, scaffolding, and framework.  This is especially true if others are going to be working on the project, and that accounts for nearly every non-trivial project.

How easy is it to set up?  How easy is it to work with?  Do the expressions make sense?  Can I hand it off to my least experienced teammate, get them to pick this up, and expect reasonable results?  (For that matter, can I hand it off to my most experienced teammate and expect them to respect the design decisions I made? )

Keeping my head in the code is critical.  Loosing touch with tools means shooting in the dark on the above questions.  It doesn’t matter what their experience is, if you ask someone to push a tack into a corkboard, hand them the wrong tools for the job, they won’t be able to push the thumbtack into the corkboard… or you’ll nuke your budget paying for tools that are overpowered for the job.  (But that thumbtack will be SO IN THERE!)

In any case, in most projects, after the architecture & technical designs have been sorted out, frameworks, built, automations put in place, I’ll take on the coding, too.

Of course, I’ve said this before…  if you can really simplify the work, what’s to stop you from taking the extra step and automating it?   I’m always eyeing code, especially “formulaic”, repetititive stuff, looking for opportunities to simplify, abstract, and/or automate.

Tech in the 603, The Granite State Hacker

Custom Guid’s

Caught a question from Stacy Draper, @StacyDraper this morning about custom guids, to make them more recognizable.

It reminded me of a post I saw recently about Facebook using hex characters to make IPv6 addresses more recognizable.

Here’s what I was thinking… create a guid that has an embedded word.

For example, the following code creates a Guid that always starts with FACEB00C:

using System;
usingSystem.Collections.Generic;
using System.Linq;
usingSystem.Text;
 
namespaceCustomGuidTest
{
    class Program
    {
        static void Main(string[] args)
        {
            GuidcustomGuid = GenerateCustomGuid();
            Console.WriteLine(customGuid.ToString(“B”));
            Console.ReadKey();
        }
 
        static Guid GenerateCustomGuid()
        {
            Guidresult;
 
            //0xFACEB00C
            //backwards, but required this to achieve desired result
            //Likely due to some standard with respect to bit order.
            byte[] custom = new byte[] { 0x0C, 0xB0, 0xCE, 0xFA  };

            byte[] random = Guid.NewGuid().ToByteArray();
            byte[] final = new byte[16];
            for(int idx = 0; idx <16; idx++)
            {
                if(idx >= custom.Length)
                {
                    final[idx] = random[idx];
                }
                else
                {
                    final[idx] = custom[idx];
                }
            }
            result = newGuid(final);
            returnresult;
        }
    }
}

Example output:
{faceb00c-7828-4e99-8cf5-280e33202670}