Tome's Land of IT

IT Notes from the Powertoe – Tome Tanasovski

Linux folks meet piped objects, Microsoft folks meet sed!

The world is a buzz around the announcement that Microsoft has open sourced PowerShell and released a working version of the language for Mac and Linux.

2000px-tux-svgpowershell_5-0_icon

Personally, I’ve been looking forward to this for a long time.  While I believe that PowerShell is a great language for development, I’m NOT excited about that aspect of it on Linux.  I think it will be a long time before the core dotnet becomes tuned to a point where it would perform comparably to Python as an interpreted language, but I do have hope.  No, the reason I have wanted this is because it is a super booster to bash!

Bash Booster – Objects in the pipe

I cannot tell you how many times I’ve tinkered in a Linux shell over the last few years and cursed the fact that I didn’t simply have objects.  Sure I can represent objects in CSVs or JSON, but to truly interact with them on a non-text level is frustrating in a shell after you’ve used PowerShell for so long.  In PowerShell, this is the way the world works:

Invoke-Webrequest http://blah.blah.blah |
ConvertFrom-Json|where {size -gt 100} |select name, size |export-csv output.csv

It’s all about data manipulation.  Grab data, filter, select properties to create new data sets, and output that data.  Additionally, you often process that data inline, for example:

...| ConvertFrom-Json| select @{name=SizeMB;expression={size/1MB}}| ...

And because everything is objects, you can easily write your own parsers, manipulators, or outputters that are duck-typed to work with the objects coming in.  It’s truly a game changer in the shell.

Native Linux Commands to PowerShell? – Hello sed!

For those unfamiliar with Linux or those who use Linux who are looking for the quickest way to convert your text into PowerShell objects, I’m here to tell you that sed is your friend.  Basically, the process is to turn your Linux output into CSV with sed and then use ConvertFrom-CSV to turn the CSV into PowerShell objects.  Of course, this assumes there isn’t a built-in way to switch the output of the command to CSV or JSON.  If there is a switch that exists to do so, it is always the best way to go.  For this article we’re talking about pure text output to objects.

We’re going to use the -r format of sed so that the regexes are more robust as far as what you can use in the regex.  We’re also going to use the form s/regex/replace/g which basically says (s)earch for regex and swap the contents with replace (g)lobally in the input string.

For this example, we’ll look at the output of ps -f:

10:06:04 PS /> ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
tome     22528  4516  0 09:42 pts/2    00:00:00 -bash
tome     22689 22528  0 09:45 pts/2    00:00:04 powershell
tome     22760 22689  0 10:06 pts/2    00:00:00 /bin/ps -f

As you can see there are some spaces or tabs between each record. We can easily parse the contents of this and replace those spaces with a comma. To do this with sed, we do the following:

10:08:12 PS /> ps -f |sed -r 's/\s+/,/g'
UID,PID,PPID,C,STIME,TTY,TIME,CMD
tome,22528,4516,0,09:42,pts/2,00:00:00,-bash
tome,22689,22528,0,09:45,pts/2,00:00:04,powershell
tome,22774,22689,0,10:08,pts/2,00:00:00,/bin/ps,-f

For now, let’s just ignore the fact that the -f is showing up with a comma in the last line. There is a fix to that which I will give an example of, but for now, let’s just convert this to PowerShell:

10:27:24 PS /> ps -f |sed -r 's/\s+/,/g' |ConvertFrom-Csv |select uid, cmd

UID  CMD
---  ---
tome -bash
tome powershell
tome /bin/ps


10:27:49 PS /> ps -f |sed -r 's/\s+/,/g' |ConvertFrom-Csv |Format-Table

UID  PID   PPID  C STIME TTY   TIME     CMD
---  ---   ----  - ----- ---   ----     ---
tome 22528 4516  0 09:42 pts/2 00:00:00 -bash
tome 22689 22528 0 09:45 pts/2 00:00:09 powershell
tome 23058 22689 0 10:28 pts/2 00:00:00 /bin/ps

If you really need to ensure that the spaces in cmd are preserved, there is a good stack overflow discussion about it here, but the shortcut outcome would be to do something like this:

10:29:55 PS /> ps -f |sed -r 's/\s+/XXX/8' |sed -r 's/\s+/,/g' |
sed -r 's/XXX/ /g' |ConvertFrom-Csv |Format-Table

UID  PID   PPID  C STIME TTY   TIME     CMD
---  ---   ----  - ----- ---   ----     ---
tome 22528 4516  0 09:42 pts/2 00:00:00 -bash
tome 22689 22528 0 09:45 pts/2 00:00:09 powershell
tome 23084 22689 0 10:30 pts/2 00:00:00 /bin/ps -f

One final note: if you are new to PowerShell from Linux, the format commands always go at the end of an object chain. They are designed to change the display output to the screen. Otherwise, you should not use them. They will change your objects and is likely not what you want to do if you have a pipe after the format command.

What about headerless commands such as ls -l?

If you look at the output of ls -l and the corresponding output of the CSV file from a sed, it looks like this:

10:35:05 PS /home/tome> ls -l
total 4
-rw-rw-r--  1 tome tome    0 Aug 19 10:33 file1
-rw-rw-r--  1 tome tome    0 Aug 19 10:34 file2
drwxrwxr-x 11 tome tome 4096 Aug 17 10:36 PowerShell
10:35:08 PS /home/tome> ls -l |sed -r 's/\s+/,/g'
total,4
-rw-rw-r--,1,tome,tome,0,Aug,19,10:33,file1
-rw-rw-r--,1,tome,tome,0,Aug,19,10:34,file2
drwxrwxr-x,11,tome,tome,4096,Aug,17,10:36,PowerShell

There are two problems with the above.  First, there is an extra line that has no relevant info.  Second, there is no header to tell PowerShell what the property names are for the objects.

Skipping a line with Select

Skipping the total line is easy using the skip argument to Select-Object:

10:35:10 PS /home/tome> ls -l |sed -r 's/\s+/,/g' |select -Skip 1
-rw-rw-r--,1,tome,tome,0,Aug,19,10:33,file1
-rw-rw-r--,1,tome,tome,0,Aug,19,10:34,file2
drwxrwxr-x,11,tome,tome,4096,Aug,17,10:36,PowerShell

Adding a custom header

ConvertFrom-CSV has a specific argument called header that allows you to supply a list that makes up what would be the header found in a CSV if one does not exist.  Here is how you can use it to convert the output of ls -l to actual PowerShell objects:

10:43:33 PS /home/tome> ls -l |sed -r 's/\s+/,/g' |select -Skip 1 |
ConvertFrom-Csv -Header @('mode','count','user','group','size','month','day','time','name') |Format-Table

mode       count user group size month day time  name
----       ----- ---- ----- ---- ----- --- ----  ----
-rw-rw-r-- 1     tome tome  0    Aug   19  10:33 file1
-rw-rw-r-- 1     tome tome  0    Aug   19  10:34 file2
drwxrwxr-x 11    tome tome  4096 Aug   17  10:36 PowerShell

 

Alternative to sed

Alternatively, you can use PowerShell in place of sed for replacing string contents. The pattern is generally like this:

10:43:55 PS /home/tome> ls -l |select -Skip 1 |%{$_ -replace '\s+', ','}
-rw-rw-r--,1,tome,tome,0,Aug,19,10:33,file1
-rw-rw-r--,1,tome,tome,0,Aug,19,10:34,file2
drwxrwxr-x,11,tome,tome,4096,Aug,17,10:36,PowerShell

Summary

PowerShell adds a lot more tools into your belt.  When it comes to data manipulation, the paradigm shift to objects over text is a game changer.  I’m personally really happy to have this flexibility and I can’t wait to take advantage of it!

 

Announcing WinArduino – A PowerShell Module that helps you dev an Arduino from a Windows box

I recently starting taking the Arduino course on Coursera entitled “The Arduino Platform and C Programming” from the University of California, Irvine.  I was having a blast with the course, but I really wanted PowerShell interfaces while working on code.  For those that know me, they know that I like my standard interface while developing: conemu: with a split window for each thing I’m developing with vim in the top and powershell on the bottom or a putty session (also in conemu) with two tmux panes with vim on the top and bash on the bottom.

conemu_env.png

I wanted this same setup for Arduino while developing on Windows.  Hence I created the WinArduino project to provide the tools I needed to program the Arduino that can run in my bottom PowerShell pane.

Features

Here’s a list of the two major features in WinArduino:

Compile and Verify

Currently this requires ArduinoIDE to be installed on your system, but I may go deeper and eventually compile/upload directly without it.  For now, it suits my needs by providing a wrapper to the Arudino IDE debug commandline interfaces to compile or compile and upload to my Arduino over USB.

Compiling is done with Invoke-ArduinoVerify and compiling with upload is done with Invoke-ArduinoUpload.

Invoke-ArduinoUpload c:\sketches\Blink\Blink.ino

Serial Input/Output

In the examples folder on the project are some robust examples which include some Arduino sketches to show how you can use PowerShell to either read/debug from serial messages in your Arduino code or how you can use PowerShell as an interface to directly control your Arduino board.  The latter is pretty fun – the example simply lets you write a 0 or 1 to turn off or on an LED, but it really opens the door to a lot of really fun things you can control with PowerShell in the IOT-Arduino world.

Get Started Now!

So what are you waiting for?  Sign up for the coursera course, download the WinArduino module, buy yourself an Arduino kit, and start hacking the electrons in your circuits!

 

Powerbits 10.5 History Revisited hg & he

Not too long ago, I posted a powerbit for a function that I was using called hgrep.  This is the evolution of that function and how I use it ALL the time in Windows PowerShell.

Here are the two functions, hg (history grep) and he (history execute).  Note: hg is also used by mercurial so feel free to change the alias to suit your needs – you can get the gist with a license to use/modify it off of github.

function Get-HistoryGrep {
    param(
        [Parameter(Mandatory=$false, Position=0)]
        [string]$Regex
    )
    get-history |?{$_.commandline -match $regex}
}

function Invoke-History {
    param(
        [Parameter(Mandatory=$true, Position=0)]
        [int]$Id
    )
    get-history $Id |%{& ([scriptblock]::create($_.commandline))}
}

new-alias hg Get-HistoryGrep
new-alias he Invoke-History

Basically, the functions are used like this:

“Oh man, I need to re-execute that function again – it was an invoke-pester command, but it had a bunch of switches that I got wrong, and then finally got right”

PS C:\test> hg pester

  Id CommandLine
  -- -----------
   5 Invoke-Pester -TestName 'test1' -OutputXml out.xml
   6 Invoke-Pester -TestName 'test1' -OutputFile out.xml
   7 Invoke-Pester -TestName 'test1' -OutputFile out.xml -OutputFormat nunitxml

“Oh, that’s the one, number 7! Let me run that again”

PS C:\test> he 7

Now, you can reuse the above over and over without having to look it up. This is exactly how you code in Linux in the shell. The equivalent in Linux is this:

history |grep pester
!7

Unfortunately, we can’t use the “!” special character in PowerShell because it is reserved to inverse boolean values. However, the general workflow is the same.  If you develop, live, and probably one day die in the shell, then these two functions are essential to your daily life.

One final note, if you run over 4096 commands in the shell, by default “he” won’t work with the earliest commands.  You can modify the special variable, $MaximumHistoryCount, if you want to change this behavior

Interprocess Communication (IPC) Between Asynchronous Events Triggered in C# to PowerShell

I played with Apache Zookeeper and PowerShell all weekend.  While I won’t dig into what I’ve been doing deeply in this article, I will tell you that the .NET interface requires a lot of asynch callbacks (event triggering).  Fortunately, I worked out a way to not only receive an event from C# (easy Bruce Payette taught us that years ago), but I also found a way to communicate variables into the runsapce of the action that gets executed when an event is triggered.

We’ll start with a simple C# class with an event to subscribe to.  In this case, I’m going to subscribe to the Changed event of my TestEvent.Watcher class.  This class has a single method which I can use to invoke the event with a string message attached to it.  This code should be invoked prior to running anything else in this post:

$code = @"
namespace TestEvent
{
    using System;

    public class Watcher
    {
        public delegate void ChangedEvent(object sender, WatcherEventArgs e);
        public event ChangedEvent Changed;

        public virtual void InvokeEvent(string message)
        {
            if (Changed != null) {
                Changed(this, new WatcherEventArgs(message));
            }
        }
    }
    public class WatcherEventArgs : EventArgs
    {
        public string message;
        public WatcherEventArgs(string message) {
            this.message = message;
        }
    }
}
"@
add-type -typedefinition $code

Here is the code to create the subscription and invoke the event. Register-ObjectEvent creates a job to run the event actions:

$watcher = new-object testevent.watcher

$job = Register-ObjectEvent -InputObject $watcher -EventName Changed -Action {
    $eventargs.message
}

$watcher.InvokeEvent('Triggering this message')

sleep 1 # just to ensure that the trigger happens
$job |receive-job

When we invoke, it looks like this:

PS C:\> .\test.ps1
Triggering this message

In Zookeeper, I needed to pass the current and valid connection object I had to the watcher so that when the event was triggered it would be sure to use the live object. Unfortunately, I didn’t see a way to pass arguments to the scriptblock, but I realized that I had full access to the $sender variable. In the above example,$sender is the testevent.watcher object I created and stored in the $watcher variable. Therefore, I figured I could just use add-member on $watcher to attach whatever objects I need to the action scriptblock.  These could then be accessed via $sender,

$watcher = new-object testevent.watcher
$watcher |add-member -NotePropertyName 'object' -NotePropertyValue 'value at watcher creation'

$job = Register-ObjectEvent -InputObject $watcher -EventName Changed -Action {
    $eventargs.message
    $sender.object
}

$watcher.InvokeEvent('Triggering this message')

sleep 1 # just to ensure that the trigger happens
$job |receive-job

The results of the above show that $sender.object indeed has the value I set when I registered the event.

PS C:\> .\test.ps1
Triggering this message
value at watcher creation

With that accomplished, I had to test whether or not the parent script could modify the $watcher object prior to the trigger and still set the value. This would enable me to pass live objects if they ever changed or needed to be updated by the parent script.

$watcher = new-object testevent.watcher
$watcher |add-member -NotePropertyName 'object' -NotePropertyValue 'value at watcher creation'

$job = Register-ObjectEvent -InputObject $watcher -EventName Changed -Action {
    $eventargs.message
    $sender.object
}

$watcher.object = 'value at watcher invokation'
$watcher.InvokeEvent('Triggering this message')

sleep 1 # just to ensure that the trigger happens
$job |receive-job

As you can see, success! The object is updated and passed at the time of the trigger rather than at the time of registration.

C:\> .\test.ps1
Triggering this message
value at watcher invokation

In case your interested, communication from the triggered job to the parent (the other half of IPC) is very easy. Simply use the messages/objects from the output of the scriptblock itself. In other words, your parent script will need to call receive-job and deal with the messages/output accordingly.

UPDATE

The above technique is sound and still useful for controlling messages to an event trigger.  It’s a very clean technique to use the $sender object.  However, I realized further in my testing and playing that it’s not always necessary.  Actions have access to GLOBAL and SCRIPT scope variable.  Not only can they access those variables on demand, but they can set them too.  This winds up being an even easier medium for transferring state because it’s actually just updating the live state.

Invoking the GetDiskSpaceInformation method of the IOfflineFilesCache COM interface with C# and PowerShell

This article could also be entitled, “Using an Inproc COM server in C# and PowerShell”.

Part I of this series shows how to invoke the GetDiskSpaceInformation method of the IOfflineFilesCache COM interface via C++. This was accomplished after failing miserably at trying to get it to work with C# and PowerShell. However, after I solved the problem in C++ I understood exactly how it worked and was able to ask better questions in Google to find out how to do the same in C#.

The challenge

First, to explain why it’s hard. When I first looked at the docs, I thought this would be easy. In PowerShell, a COM object can be invoked by instantiating a com object with new-object.  For example:

$app = new-object -comobject excel.application

Even if that didn’t work, I knew that often times C++ code could be Marshaled to and from the world of C# and managed code with a bit of tinkering. This is usually where you see pinvoke.net and code that leverages add-type.  However, in this case, the libraries do not exist in pinvoke.  Basically, because this is really COM, you cannot do this.  Also, because there are no tlb files associated, you cannot easily just use the interfaces like they are COM.

Just to be clear as to why this is the case:  This is a new interface.  It was plugged in by the Windows developers into the latest versions of Windows.  It’s implemented in COM so that other languages can get access to it.  However, it’s not fully at the point where it needs to be flushed into general use.  I expect that in the years to come, we’ll see these interfaces exposed with a tlb and eventually there may even be a PowerShell module that is used to manage the offline files cache directly.  However, if you want access before that day comes, you need to get crafty.

Finding GUIDs OLE/COM Object Viewer

The key to invoking this code from C# is to know the GUIDs that were used for both the CLSID and the interface we are trying to get access to.  This can be accomplished by running the OLE/COM Object Viewer.  For me, this was installed with my Visual Studio 2013 and can be found here: C:\Program Files (x86)\Windows Kits\8.1\bin\x86\oleview.exe.

Once in the GUI, you can browse to Object Classes->All Objects->Offline Files Cache Control

olecomviewer1

We’re looking for the GUID: 48C6BE7C-3871-43CC-B46F-1449A1BB2FF3

Next, if you double-click on that you’ll see the interfaces.  In our case, we want the IOfflineFilesCache interface.

olecomviewer2The GUID is 855D6203-7914-48B9-8D40-4C56F5ACFFC5

It should be noted that these GUIDs are static.  You do not need to run the COM viewer on your desktop if you are invoking the exact same interface that I am demonstrating.  The GUIDs are the same on ever computer.  However, this is here to show the generic steps that are needed to invoke the methods on one of these no-TLB COM interfaces.

CreateInstance

The first step is to create an instance of the CLSID using the GUID we found above.

Guid ID = new Guid("48C6BE7C-3871-43cc-B46F-1449A1BB2FF3");
Type idtype = Type.GetTypeFromCLSID(ID);
IOfflineFilesCache obj = (IOfflineFilesCache) Activator.CreateInstance(idtype, true);

It should be noted that the code we are using requires:

using System.Runtime.InteropServices;

Unfortunately, in the above bit of code, we are referencing the IOfflineFilesCache type, but it does not yet exist anywhere.  Therefore, we have to help C# know what this is by creating an interface with the ComImport attribute

Interface Attributes

I should note that everything I’m demonstrating is documented here.  However, it’s a bit cludgy to get through.  Also, there are a few key elements it leaves out.  Specifically, it neglects to inform you that when you create the interface, you must implement all of the methods that exist in the interface in exact order leading up to the method you care about using.  The best way to get the methods and the order they are implemented is to read the C++ header file.  This was one of the #include files I showed in part I of this article.  Specifically, you need to view cscobj.h.  A quick search of your hard drive should find it in an SDK folder.  Once you have read through this, you can create the interface in the proper order:

    [ComImport]
    [Guid("855D6203-7914-48B9-8D40-4C56F5ACFFC5"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    interface IOfflineFilesCache
    {
        [PreserveSig()]
        int Synchronize();

        [PreserveSig()]
        int DeleteItems();

        [PreserveSig()]
        int DeleteItemsForUser();

        [PreserveSig()]
        int Pin();

        [PreserveSig()]
        int UnPin();

        [PreserveSig()]
        int GetEncryptionStatus();

        [PreserveSig()]
        int Encrypt();

        [PreserveSig()]
        int FindItem();

        [PreserveSig()]
        int FindItemEx();

        [PreserveSig()]
        int RenameItem();

        [PreserveSig()]
        int GetLocation();

        [PreserveSig()]
        int GetDiskSpaceInformation(ref ulong pcbVolumeTotal, ref ulong pcbLimit, ref ulong pcbUsed, ref ulong pcbUnpinnedLimit, ref ulong pcbUnpinnedUsed);

        // only need to go as far as the function you need, but rest here for completeness

        [PreserveSig()]
        int SetDiskSpaceLimits();

        [PreserveSig()]
        int ProcessAdminPinPolicy();

        [PreserveSig()]
        int GetSettingObject();

        [PreserveSig()]
        int EnumSettiingObjects();

        [PreserveSig()]
        int IsPathCacheable();
    }

You’ll notice that in the above, the GUID is the GUID we found when looking at the interface in the OLE/COM viewer.

Finished code, but let’s do it in PowerShell

So, now that we have the interface and an instance of it, the rest is easy.  The following final bit of code injects the C# into PowerShell via add-type.  I simply return the results as a collection and then convert it into an object in PowerShell, but you could just as easily modify the code to have the object returned directly from C#.

$code = @'
using System;
using System.Runtime.InteropServices;

public class offlinecache {
    public static ulong[] GetOfflineCache() {
        ulong pcbVolumeTotal=0, pcbLimit=0, pcbUsed=0, pcbUnpinnedLimit=0, pcbUnpinnedUsed=0;
        Guid ID = new Guid("48C6BE7C-3871-43cc-B46F-1449A1BB2FF3");
        Type idtype = Type.GetTypeFromCLSID(ID);
        IOfflineFilesCache obj = (IOfflineFilesCache) Activator.CreateInstance(idtype, true);
        int i = obj.GetDiskSpaceInformation(ref pcbVolumeTotal, ref pcbLimit, ref pcbUsed, ref pcbUnpinnedLimit, ref pcbUnpinnedUsed);
        ulong[] output = new ulong[5];
        output[0] = pcbVolumeTotal;
        output[1] = pcbLimit;
        output[2] = pcbUsed;
        output[3] = pcbUnpinnedLimit;
        output[4] = pcbUnpinnedUsed;
        return output;
    }

    [ComImport]
    [Guid("855D6203-7914-48B9-8D40-4C56F5ACFFC5"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    interface IOfflineFilesCache
    {
        [PreserveSig()]
        int Synchronize();

        [PreserveSig()]
        int DeleteItems();

        [PreserveSig()]
        int DeleteItemsForUser();

        [PreserveSig()]
        int Pin();

        [PreserveSig()]
        int UnPin();

        [PreserveSig()]
        int GetEncryptionStatus();

        [PreserveSig()]
        int Encrypt();

        [PreserveSig()]
        int FindItem();

        [PreserveSig()]
        int FindItemEx();

        [PreserveSig()]
        int RenameItem();

        [PreserveSig()]
        int GetLocation();

        [PreserveSig()]
        int GetDiskSpaceInformation(ref ulong pcbVolumeTotal, ref ulong pcbLimit, ref ulong pcbUsed, ref ulong pcbUnpinnedLimit, ref ulong pcbUnpinnedUsed);

        // only need to go as far as the function you need, but rest here for completeness

        [PreserveSig()]
        int SetDiskSpaceLimits();

        [PreserveSig()]
        int ProcessAdminPinPolicy();

        [PreserveSig()]
        int GetSettingObject();

        [PreserveSig()]
        int EnumSettiingObjects();

        [PreserveSig()]
        int IsPathCacheable();
    }
}
'@

add-type -TypeDefinition $code

$output = ([offlinecache]::GetOfflineCache()) 
new-object psobject -Property ([ordered] @{
    VolumeTotal = $output[0]
    Limit = $output[1]
    Used = $output[2]
    UnpinnedLimit = $output[3]
    UnpinnedUsed = $output[4]
})

Here’s a trail of it running:

06:50:06 PS C:\Dropbox\scripts> .\GetOfflineCacheDiskInfo.ps1


VolumeTotal   : 469636214784
Limit         : 109076041728
Used          : 0
UnpinnedLimit : 109076041728
UnpinnedUsed  : 0

Invoking the GetDiskSpaceInformation method of the IOfflineFilesCache COM interface with C++

This is a two-part post.  If you only care about solving this problem in C# and PowerShell, feel free to skip this and move to Part II.

My friend at work came to me with a problem.  There are some functions for offline files that only exist in the API.  Knowing my affinity for taking on bizarre pinvoke API calls, he came to me and asked whether or not I could get this function to work in PowerShell.  We’ll go into PowerShell and C# in Part II of this post, but to put it simply, this was an extremely difficult puzzle to figure out.  It was something I have never done and it is something I have never read anyone else do (I did a lot of googling and some begging on twitter – so if anyone does have a first post, please post it in the comments).  After failing at C# and PowerShell, I decided to try failing at implementing this in C++.

GetDiskSpaceInformation

The method in question is GetDiskSpaceInformation.  When looking at the documentation, you get a few clues through the two DLLs listed and the one Header, i.e., CscSvc.dll, CscObj.dll, and CscObj.h.  As you can see, there are no examples.  After some poking, I was able to find an example for another function, GetEncryptionStatus.  However, this is the easy part.  To me, this is just C++ and I could figure this out.  The hard part is called out in the code example for GetEncryptionStatus with an assumption on the first line of comments.  It says that we “Assume we already have a cache ptr”, referring to the IOfflineFilesCache *pCache interface.

IOfflineFilesCache Interface

The documentation for this also has no examples nor do any of the additional interfaces.  Sigh – this I think is why fewer people do C++ at all in the Microsoft world.  It’s a very frustrating web of documentation.  Regardless, the clue to figuring out how to implement this interface is in a single line in the IOfflineFilesCache interface documentation underneath the “When to use” section of the doc:

Create this object as an in-proc COM server using the class ID CLSID_OfflineFilesCache.

So this is COM – but not your C#-managed-code COM.  No, that would be too easy.

In-proc COM server client

I will spare you the hours of searching and tinkering to get this right.  The end result is that you must use a specific function called CoCreateInstance.  Of course, you will find zero posts that show exactly how to do this.  So finally, here it is:

IOfflineFilesCache *pCache;
HRESULT hr;
CoInitialize(nullptr);
hr = CoCreateInstance(CLSID_OfflineFilesCache, NULL, CLSCTX_INPROC_SERVER, IID_IOfflineFilesCache, (void**)&pCache);
if (FAILED(hr)) {
    std::cerr << "ERROR: " << hr << "\n";
    return 0;
}

I have the following includes in my code when invoking the above:

#include “stdafx.h”
#include
#include

The final code and ultimate solution

Without further ado, here is the full C++ code to invoke this function.  It displays the 5 values returned to stdout.

#include "stdafx.h"
#include <cscobj.h>
#include <iostream>
int _tmain()
{
    IOfflineFilesCache *pCache;
    HRESULT hr;
    CoInitialize(nullptr);
    hr = CoCreateInstance(CLSID_OfflineFilesCache, NULL, CLSCTX_INPROC_SERVER, IID_IOfflineFilesCache, (void**)&pCache);
    if (FAILED(hr)) {
        std::cerr << "ERROR: " << hr << "\n";
        return 0;
    }
    ULONGLONG pcbVolumeTotal;
    ULONGLONG pcbLimit;
    ULONGLONG pcbUsed;
    ULONGLONG pcbUnpinnedLimit;
    ULONGLONG pcbUnpinnedUsed;
    hr = pCache->GetDiskSpaceInformation(&pcbVolumeTotal, &pcbLimit, &pcbUsed, &pcbUnpinnedLimit, &pcbUnpinnedUsed);
    if (FAILED(hr)) {
        std::cerr << "ERROR: " << hr << "\n";
        return 0;
    }
    std::cout << "VolumeTotal:\t"    << pcbVolumeTotal    << "\n";
    std::cout << "Limit:\t\t"        << pcbLimit            << "\n";
    std::cout << "Used:\t\t"        << pcbUsed            << "\n";
    std::cout << "UnpinnedLimit:\t" << pcbUnpinnedLimit << "\n";
    std::cout << "UnpinnedUsed:\t"    << pcbUnpinnedUsed    << "\n";
    return 1;
}

The code can also be found on github.
Note: This was done on a windows 8.1 box using Visual Studio 2013 (important, because the libs are not in all versions of windows).

Tada

Once compiled, you have a nice utility that wraps this function:

offlinefilescachexe

In part II of this article, I will show you how the above is done in C#.  Once in C#, it’s just a copy/paste to get it to work in PowerShell via Add-Type.

Look back at 2014 and look forward to 2015

A look back at 2014

2014 was the year of containers for me.  I spent a lot of time looking at Docker, Kubernetes, Mesos with Marathon and Aurora, and working (and using) tooling around the core Linux Kernel components that make these platforms possible.

shipping2

Additionally, this was the year that I fully embraced and understood Apache Zookeeper and played with etcd.  For me, Zookeeper becomes the foundation of nearly any distributed system I write.  It’s easy and it works.  Etcd has a place when zookeeper is overkill, but I have yet to use it in anything real.

Elasticsearch – I finally got dirty with elasticsearch.  I have a lot of positive things to say about it.  I’m interested in seeing how far the software can be taken.  Specifically to see whether the datastore (that can now be backed up) will become an actual data tier rather than just an efficient layer on top of a data tier.

In the Perl world, I learned Moose which make Perl actually usable in modern day programming.  It provides objects and types to Perl.

I was really happy to have the opportunity to implement ZeroMQ into something I was working on.  I am really excited by this library and I hope 2015 gives me a chance to write something about PowerShell and ZeroMQ.  There are very few platform and language agnostic libraries out there.  Additionally, the perfect abstraction with robust patterns and documentation make it a lot of fun to tinker with new communication topologies with just a few minor changes to code.  I have not been so inspired or zealously passionate about something like this since PowerShell 2.0 took my brain.

I played with AngularJS a bit.  It was fun.  However, every time I sit down to do UI work, I feel defeated.  It’s just something I’m not amazing at nor do I think I really want to be.  I’m glad to understand the framework and how it works, but I’ll save the meaty part of that work for others.

Pester Pester Pester!!! Test-driven development took over my PowerShell life (as well as all other languages).  My coding takes longer, but I have much more faith in it.  Pester is the greatest thing to happen to PowerShell from the community ever!  I was really happy to work with my internal corporate teams to build SDLC best-practices for PowerShell that involve Continous Integration (CI) and a Pester as the testing framework.

In 2014 I was introduced by my mentor to some time management techniques outlined in Eat that Frog.  Basically it’s about turning your life into Agile.  That sounds strange and the book doesn’t mention agile once – it is my interpretation of it.  It’s really about prioritizing daily and choosing the items that are most impactful to your company and yourself while deprioritizing everything else.  Additionally, I have adopted the more and more common practice of ignoring most e-mails and checking them less frequently throughout the day.  If it’s important, they will get back to you in a way that you cannot ignore.  Otherwise, it’s just getting in the way of the things you prioritized for the day.  If you start to follow this advice, I would add that you should also set up some alerts to ensure that certain people are never ignored.

An unhealthy obsession with gaming returned to my life in 2014.  However, I was successful in squashing it at the end of 2014 – well all of it except for the updates to candy crush I have to do when a new level comes out :)  Hopefully the squash will return some valuable time I need in order to blog a bit more and round myself in the wee hours of the night.

The 2015 Hitlist

New-Year-Baby-2

Golang

Use golang in an actual project.  I really like golang.  It feels like an interpretive language (PowerShell, Python, Perl), but it is compiled and has the potential to automagically make things more efficient as the engine matures.  I have played with golang a bit, but I want to find a project to use it with that will prove/disprove my initial thoughts about the language.

Openstack

Learn Openstack.  I’m sick of being in conversations where I cannot speak with authority about what open stack can and can’t do.  I need to understand all of the components and how they work.  This is pure lab time that I should have done last year.

Public cloud

Re-evaluate the cloud providers.  It’s been about two years since I last looked at AWS and Azure.  I’d like to get a handle on the current offerings and take a closer look at the Google compute engine stuff.

PowerShell Talks and Blogs

Put some new talks together about PowerShell 5.0 and the ZeroMQ library.  Perhaps finally blog or do a talk about the heuristic and deterministic algorithm implementations I have done with PowerShell.

Publish my unpublished article around running a PowerShell script as any user in AD without credentials:) (it’s possible, but requires a configuration you will likely never want to do – but hey, from a research perspective, it’s fun to try).

Podcast

Revisit the cmdlet of the day podcast (no link because the storage is currently not working).  Of all of the things I have ever been involved with, this is the one that I get the most positive feedback from.  I have been thinking it would be fun to kick off the year giving 5-minute discussions about enterprise scripting best practices. There’s so much potential in the short-form podcast format for something highly technical.  I’d love to do this right and perhaps inspire others to pick up the torch in similar technologies that I could benefit from listening to.

The 2015 Watchlist

baby-with-glasses

 

PowerShell

PowerShell as a development language – I still firmly believe that PowerShell is one of the best languages ever written.  In my opinion it is a better interpreted development language than Python and Perl.  I would love to see it used the way it should be.  This is probably a losing battle as Microsoft’s focus is on making it feel like a development language strictly to get providers written for DSC, but I constantly hold my breath waiting for something more.  My hope is that the open sourcing of .NET along with the new language mode in 5.0 may open that door a bit more.  However, my face is slowly turning blue and I may not see the sweet release of air any time soon.  Additionally, I just don’t work on anything that would allow me to prove this outside of little pet projects here and there.  I suppose this is more of a crylist entry than a watchlist entry.

Microsoft open source

.NET being open sourced.  What does it mean?  What’s going to happen with it next?

Windows containers

Containers on Windows – What in the world does it all mean?  How will it manifest to IT shops, and how can I exploit it for the benefit of cheap, secure, and flexible compute where I work?

Checkpoint/Restore

In early 2013, I ran a successfull POC that leveraged CRIU to migrate an app including all of its state from one Linux server to another and have it start running again as if nothing happened.  Why is this not being exploited or am I missing projects that are leveraging it?  Either way, it’s still the most cutting-edge bit of magic out there.  I can’t wait to see where it goes.

Happy New Year!

Announcing PshOdata – Cmdlets that make Odata easy

I’m sitting in the PowerShell summit and just left the stage where I presented how the Odata extensions work and shared my new project (contributors welcome) to bring PowerShell-driven Odata endpoints to the masses

To make it clear just how easy it is to use, here is the code required to create a web service around get-process and stop-process.

$class = New-PshOdataClass Process -PK ID -Properties 'Name','ID'
$class |Set-PshOdataMethod -verb get -cmdlet get-process -Params Name, ID -FilterParams Name
$class |Set-PshOdataMethod -verb delete -cmdlet stop-process -FilterParams ID
$class |New-PshOdataEndpoint

This will generate three files in a folder called odata that can be copied up to your IIS server. After an IISReset, the Process endpoint will be available via the following URLs:

I hope you enjoy, and please post issues on GitHub if you encounter any.

Github Project

You Know PowerShell is an Object-Oriented Language, Right?

I was recently reading an article that I’ll refrain from linking to for fear of a flame war. It infuriated me because it referred to PowerShell as a procedural/functional language that is antiquated and more like shell scripting.  I reflected on this for a while and I came to the realization that if I were to look at 99.99999% of the code out there I may think the same thing.  I also realized that there are reasons that PowerShell code appears procedural instead of object oriented.

This post will do a few things

  1. Show you how to do object-oriented programming with PowerShell using a traditional approach
  2. Show you the alternative (still object-based) so you can see why it’s generally used

A Class

Let’s describe a dog.

Properties

A dog has a name, color, and is some size.

$dogclass = new-object psobject -Property @{
   color = $null
   name = $null
   size = $null
}

A Constructor

While it may not be needed because you can instantiate the object without doing so (via psobject.copy()), object-oriented developers love their constructors. It’s also a good place to add some validation for your class. For example, in the below constructor we’ll restrict the size to either small, medium, or large.

function DogClass {
    param(
          [Parameter(Mandatory=$true)]
          [String]$name,
          [Parameter(Mandatory=$false)]
          [string]$color,
          [Parameter(Mandatory=$false)]
          [ValidateSet('Small','Medium','Large')]
          [String]$size
    )
    $dog = $DogClass.psobject.copy()
    $dog.name = $name
    $dog.color = $color
    $dog.size = $size
    $dog
}

Now you can start using your class

08:31:50 PS C:\> $lucy = DogClass -name Lucy -color brown -size large
08:45:07 PS C:\> $lucy

color                                       name                                        size
-----                                       ----                                        ----
brown                                       Lucy                                        large


A Method

A dog performs certain functions. For example, a dog is known to pee. We can modify our dog class with a method by using Add-Member. Also note that you can use the $this special variable to access the object that is invoking the method.

$DogClass |Add-Member -MemberType ScriptMethod -Name "Pee" -Value {
    "A warm refreshing pee trickles out of {0}" -f $this.name
}

With the method created, you can instantiate Lucy again from the modified class and access her new method.

08:50:50 PS C:\> $lucy = DogClass -name Lucy -color brown -size large
08:52:30 PS C:\> $lucy.Pee()
A warm refreshing pee trickles out of Lucy

Accessor Functions

Accessor functions help you protect the properties of an object. As in Perl and Python, there is no real protected or private property available to you. Therefore, you can use the same convention that these other languages use to supply an underscore prefix to any private methods or properties. It doesn’t actually prevent people from using it, but it’s a clear sign that they shouldn’t use it. For example, if we wanted to make the size property private, we would modify the class to look like this. Note: I’m adding the scriptmethod we created in one step using the -PassThru parameter of Add-Member.

$DogClass = new-object psobject -Property @{
   color = $null
   name = $null
   _size = $null
} |Add-Member -PassThru -MemberType ScriptMethod -Name "Pee" -Value {
    "A warm refreshing pee trickles out of {0}" -f $this.name
}

ScriptMethod

With the new _size property, it’s easy enough to modify our constructor to use the new property, but what if you want to control how people set or get the property of size. You can create an accessor function to do this. Basically, this is just a method that will set or return the data from _size.

$dogclass |Add-Member -PassThru -MemberType ScriptMethod -Name Size -Value {
    param(
        [Parameter(Mandatory=$false, Position=0)]
        $Size
    )
    if ($size) {
        $this._size = $size
    } else {
        $this._size
    }
}

Now, we can access the data in _size by using the accessor.

$lucy = DogClass -name Lucy -color brown -size large
"The dog is {0}" -f $lucy.Size()

We can also set the _size using the same function.

$lucy.Size('medium')

It’s important to note that I lost the property validator I have in the constructor. ScriptMethods break if you have an optional parameter that also has a validator. There are two ways to handle this. Either you add validation to the Size() method or you create two accessor functions, SetSize() and GetSize(). Both are acceptable and both are very easy to implement. Here’s an example of implementing your own validatior

ScriptProperty

A nice way to allow access to the pseudo private properties is to use the ScriptProperty member instead. This provides you with a way to perform a scripted action for a get, but it also allows you to do validation on a set. The difference is that it allows you to use the equal sign instead of a method to set the property.

Here’s what a ScriptProperty looks like. The first ScriptBlock is the get function and the second ScriptBlock is the set function.

$dogclass |Add-Member -MemberType ScriptProperty -name Size -Force -Value {
    $this._size
} {
    param(
        $Size
    )
    if (@('small','medium','large') -contains $size) {
        $this._size = $size
    } else {
        throw "This is not a valid size.  A size must be small, medium, or large"
    }
}

I’m using Force above to override the Size member I already created. In order to use the new property

In order to use this property, I can now do the following with my instantiated instance of Lucy.

PS C:\> $lucy.Size = 'blah'
Exception setting "Size": "This is not a valid size.  A size must be small, medium, or large"
At line:1 char:1
+ $lucy.Size = 'blah'
+ ~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], SetValueInvocationException
    + FullyQualifiedErrorId : ScriptSetValueRuntimeException

PS C:\> $lucy.Size = 'medium'
PS C:\> $lucy.Size
medium

A nice thing about this technique is that your custom formatters will be able to see the property. In other words, it can be used in Select, Format-Table, Format-List, etc.

Class Inheritance

PowerShell doesn’t have real inheritance. However, the functionality of inheritance is very easily achieved. If you’re not familiar with inheritance, it’s pretty straightforward. Many times a class will have subclasses. For instance, a Scottish Terrier is a subclass of dog that is always small, black, and prefers to chase rats (rather than hunt like a beagle or keep your feet warm like a pug). Therefore, we can create a Scotty class that is based on the dog class, but has these properties set by default and has a method for hunting vermin.

Inherited Class

Because the definition of our class is simply an object, we can copy and modify it to create a new class that can be used later by other things.

$ScottyClass = $DogClass.psobject.copy()
$ScottyClass.color = 'black'
$ScottyClass._size = 'small'

One thing to note when creating an inherited class in PowerShell using this technique is that you need to recreate your constructors. This is probably the only unfortunate part of the pseudo-class inheritance that PowerShell offers. It basically forces override whether you want it or not on the constructor.

function New-Scotty {
    param(
          [Parameter(Mandatory=$true)]
          [String]$name
    )
    $dog = $ScottyClass.psobject.copy()
    $dog.name = $name
    $dog
}

Now we can use our new class:

$George = New-Scotty George

Overriding Methods

In the case of the Scotty class where we want to add a new method for catching rats, there’s nothing special that needs to be done. New methods are treated the same as on the base class. However, if you want to override a method that exists on the parent class, the technique is identical, but you’ll need to supply the force parameter to Add-Member. For example, if we want to override the Pee() method for the dog, we could do the following.

$ScottyClass|Add-Member -Force -MemberType ScriptMethod -Name "Pee" -Value {
    "The Scotty sniffs the tree.  A warm refreshing pee trickles out of {0}" -f $this.name
}

Note about PIA 2.0

Bruce Payette has a great set of code in PowerShell in Action 2.0 about extending PowerShell to wrap the OO-ability of the language in something that looks cleaner. The end result is you can define a class like this:

DogClass {
    property name 
    property size
    method Pee { "Oh yeah"}
}
$dog = new DogClass

While doing research for this post, I realized that I had never noticed this section of the book. We really need to make this a publicly available extension. It’s pretty simple to do, but I don’t want to paste his code due to copyright reasons. Actually, if you’re the kind of person who has been looking for OO in PowerShell and have never read Bruce’s book, you probably should because it will answer a whole lot more about PowerShell than just this for you.

Objects from New-Module

The PowerShell team added a shortcut way to do all of the above. Modules exist in their own closure. Because of this, they may contain their own scoped variables that can be stored within the module itself. There is a parameter on New-Module called -AsCustomObject that will convert your defined scriptblock module into a PowerShell object with note properties and script methods. Here’s an example of the Dog class using this technique.

function New-Dog {
    param(
        [Parameter(Mandatory=$true)]
        [string]$Name,
        [Parameter(Mandatory=$false)]
        [ValidateSet('small', 'medium','large', $null)]
        [string]$size,
        [Parameter(Mandatory=$false)]
        [string]$color
    )
    New-Module -Argumentlist @($name,$size,$color) -AsCustomObject {
        param(
            [Parameter(Mandatory=$true)]
            [string]$Name,
            [Parameter(Mandatory=$false)]
            [ValidateSet('small', 'medium','large', $null)]
            [string]$size,
            [Parameter(Mandatory=$false)]
            [string]$color
        )
        function Pee {
            "A warm refreshing pee trickles out of {0}" -f $Name
        }
        Export-ModuleMember -Function Pee -Variable Name, Size, Color
    }
}

If we look at the members that this creates, you’ll see it looks very similar to what we’ve been doing up until now.

$Lucy = New-Dog -Name Lucy
$Lucy |Get-Member

   TypeName: System.Management.Automation.PSCustomObject

Name        MemberType   Definition
----        ----------   ----------
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()
GetType     Method       type GetType()
ToString    Method       string ToString()
color       NoteProperty System.String color=
Name        NoteProperty System.String Name=blah
size        NoteProperty System.String size=
Pee         ScriptMethod System.Object Pee();

The PowerShell Way

So what we’ve been looking at is modern object oriented programming. However, it’s rarely seen in the wild with PowerShell even though it’s very simple to implement. Why is that exactly? Sure, there are plenty of beginners out there who weren’t even developers until now, but I believe it’s deeper than that. I personally know that this exists. However, I’ve only used it on one project.

The reality is that PowerShell lives and breaths objects through everything. Also, these objects are very flexible because they can be extended or modified on the fly. Functions can take objects as input and the type of Input provided by strongly typed objects can more easily be achieved with strongly type parameters. I see the param() block of a function as something that describes the properties of an object that I expect to see.

Now this is PowerShell to me. This is a paradigm shift in the way we do object-oriented programming. To me, when my peers ask me why I’m so PowerShell crazy, this is the answer. It looks like it’s functional, but it is far from that.

function New-Dog {
    param(
        [Parameter(Mandatory=$true)]
        [string]$Name,
        [Parameter(Mandatory=$false)]
        [ValidateSet('small', 'medium','large', $null)]
        [string]$size,
        [Parameter(Mandatory=$false)]
        [string]$color
    )
    New-Object psobject -property @{
        Name = $Name
        Size = $Size
        Color = $color
    }
}

function Invoke-Pee {
    param(
        [Parameter(Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)]
        [String]$Name
    )
    PROCESS {
        "A warm refreshing pee trickles out of {0}" -f $Name
    }
}

New-Dog -Name Lucy |Invoke-Pee
A warm refreshing pee trickles out of Lucy

Not only do I have a dog that can pee, but I also can use the same Invoke-Pee function for anything that has a name property. It can also invoke-pee on a number of dogs without having to create a loop.  If I really needed to be sure it was a dog, I could take the entire psobject as a parameter and validate that it had the properties that make it a dog.  Perhaps even write the Test-Dog function to do that.

Finally, I would personally wrap the above in a module named Dog and use a prefix more like New-Dog and Invoke-DogPee. Then it’s easy to import the module and inspect what methods are available using Get-Command -Module Dog. Again, this looks and smells like it’s functional, but it’s all objects and encapsulation, and it’s amazing!

Powerbits #10 – history |grep or hgrep in PowerShell

I’ve been working a bit more in Linux. Besides it inspiring me to write a lexical parser in python for PowerShell (don’t get your hopes up – it’s too much work, and I can’t do it), I keep getting little inspirations for cool projects. For example, someone needs to create tmux for PowerShell; I digress. This powerbit is from that inspiration. Recently, my laptop’s up and down arrows stopped working. Because of this, I have been relying on history |grep something in Linux so that I can quickly copy and paste that something back into the commandline. Context Swtich! Yesterday I was in PowerShell, and I got frustrated by the output of get-history (I really only want the commandline property) and the complexity it takes to filter for what I want using Where-Object.   As I was discussing this with a colleague, I said, let me just wrap this already and never worry about it again. So here it is, hgrep:

function hgrep {
    param(
        [Parameter(Mandatory=$false, Position=0)]
        [string]$Regex,
        [Parameter(Mandatory=$false)]
        [switch]$Full
    )
    $commands = get-history |?{$_.commandline -match $regex}
    if ($full) {
        $commands |ft *
    }
    else {
        foreach ($command in ($commands |select -ExpandProperty commandline)) {
            # This ensures that only the first line is shown of a multiline command
            if ($command -match '\r\n') {
                ($command -split '\r\n')[0] + " ..."
            }
            else {
                $command
            }
        }
    }
}

you can use it like this:

hgrep something

While, it’s bad practice to add the |ft command to the function, I find it useful so that I can use the -full switch to get everything I want in the format I want to see it:

11:17:22 PS D:\Dropbox\scripts> hgrep longfunction -full

   Id CommandLine                  ExecutionStatus StartExecutionTime              EndExecutionTime               
   -- -----------                  --------------- ------------------              ----------------               
   9 longfunction                        Completed 9/26/2013 11:00:00 AM           9/26/2013 11:14:41 AM

You can fork or clone this gist off of github here, or just run the following:

git clone https://gist.github.com/6715170.git
Follow

Get every new post delivered to your Inbox.

Join 44 other followers

%d bloggers like this: