Peace For All

March 13, 2013

C# Feature Need: Lambdas having an implicit reference to themselves

Filed under: C#, Programming — Tags: , , , — Devlin Bentley @ 1:07 pm

I really want a “me” keyword in C# that gives a reference to the current lambda.

For event handling it is often useful to have a one time event that detaches itself after it has fired. Currently this isn’t too hard, you assign said event to a nice Func<T…> or Action<T…> (or actual event handler delegate type) and when you reference it in your lambda (while unassigning it) it gets captured in your closure.

An example of this is:

EventHandlerType handler = null;
handler = (string receivedString) =>
    {
        this._someString = receivedString;
        EventClass.Event -= handler;
    };
EventClass.Event += handler;

As you can see above, handler is my event handler, it takes in a lone string (because event args is for chumps), assigns said string to a class member variable, and then detaches itself.

This isn’t horrible, but it still is a fair pain in the arse. I’d presuming the lambda already has a reference to itself somewhere, so my creating an explicit one seems sort of redundant. Also it is an unneeded closure, quite frequently that is the only variable I am closing over, which means I have a fairly sizable overhead just to capture a reference to myself!

On a separate note, I wonder if declaring your handlers as class members optimizes this in any way. I am not 100% sure if they are captured over, I should read up on it to see if I can find clarification. Thinking about it some more, there may be times when there is a need to capture them, but if they are public members this might not be needed. I am now wondering if the C# compiler is smart enough to optimize this away.

Anyway, none of that would matter if C# had a keyword that said “give me a reference to the bloody function I am in right now!”

And hey, type inference means the syntax could be really nice! ūüôā

(And if there is already a way to do this, that doesn’t involve gobs of reflection code, please do tell!)

Now this really becomes a pain when you are trying to chain event handlers together. I have some annoying lock step code I need to write where I do a call-handle-call-handle over a network channel. Each message I get is of the same type (so it flows through the same event), but the handler has to be different each time.

Now obviously I could make one giant lambda that tracks its state and how many times it has responded to messages, but I much prefer simpler lambdas that do exactly one thing. Thus I am constantly unassigning and reassigning handlers to the same event. My code would be a lot cleaner if I didn’t have to predeclare all my handlers.

(Of course this code is dealing with an impedance mismatch between an non-OO system and my OO system, so the code is going to be somewhat ugly, but I prefer to minimize this as much as possible!)

Advertisements

September 22, 2011

Remotely Executing Commands in PowerShell using C#

Filed under: C#, PowerShell, Programming — Tags: , , — Devlin Bentley @ 4:02 pm

At first glance, this seems like it should be easy. After all: remoting using PowerShell is dirt easy! Once the server is configured you are a single Invoke-Command away from remoting bliss! So how hard could it be in C#? Surely there is some functional equivalent to Invoke-Command that gets exposed, right?

Well no, it is not that simple. It isn’t too bad, but the lack of any examples on MSDN makes some aspects of doing¬†this quite literally impossible to figure out if you are using MSDN documentation alone.

Thankfully by piecing together posts from the MSDN Forums it is possible to get something working. Having done just that, I figure I’d save you all the time and effort.

Precursor

Get a reference to System.Management.Automation into your project. The best way to do this is to manually edit the csproj file and add the line

<Reference Include=”System.Management.Automation” />

Yes this is ghetto. I am not sure why that library is not sitting with the rest of them in the proper location that would get it listed in the “Add References” dialog.

Goal

Calling in from C# code, execute PowerShell  code on a remote machine.

Tools

A bunch of poorly documented object constructors.

The key to getting this all working is to properly construct an instance of WSManConnectionInfo and pass that on to the RunspaceFactory.CreateRunspace(..) method.

Step 1: Constructing a PSCredential

This step is pretty straight forward. PSCredential has only one constructor, it takes in a username and a SecureString password. The only gotcha is that userName includes domain if applicable.

Good luck on the SecureString PW part. Doing it properly (e.g. never storing your PW in a string at any step) can take some planning ahead, depending on your situation of course.

PSCredential remoteMachineCredentials = new PSCredential(domainAndUserName, securePassword);

 Step 2: Constructing WSManConnectionInfo

This is the hard part. Mostly because the documentation on how to use this class is so poor, most of it consisting of how to establish a loopback connection to localhost.

With our particular goal in mind, we only really care about one of the overloads:

public WSManConnectionInfo (
bool useSsl,
string computerName,
 int port,
string appName,
string shellUri,
PSCredential credential
)

The documentation for this constructor (located at http://msdn.microsoft.com/en-us/library/dd978670(v=VS.9).aspx if you want to read it yourself) has such gems as

appName

The application end point to connect to.

Not very useful.

Lets go over these parameters one by one and look at what each one means.

useSsl – Pretty simple, a bool flag indicating if SSL should be used. Highly recommended for use, of course. Note that changing this changes what port number you will be using later on

computerName – The name of the machine you are connecting to. On local networks, this is just the machine name.

port РThanks to the blog post at http://blogs.msdn.com/b/wmi/archive/2009/07/22/new-default-ports-for-ws-management-and-powershell-remoting.aspx we know what port numbers PowerShell remoting uses. 5985 if you are not using SSL, and 5986 if you are using SSL.

appName – This should be “/wsman”. I don’t know what it is or what other values you can use here, but thanks to the Emeka¬†over on the MSDN forums (thread: http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/a0e5b23c-b605-431d-a32f-942d7c5fd843)¬†we know that “/wsman” will get it working.

shellUri – Again, thanks to Emeka we know that this needs to be http://schemas.microsoft.com/powershell/Microsoft.PowerShell&#8221;. I am not sure what other values are acceptable, but that value does indeed work.

credential – Finally we come back to the PSCredential object we constructed earlier. Simple enough.

Step 3: Creating a Runspace

We thankfully return back to documented things. After constructing the WSManConnectionInfo just pass that into RunspaceFactory.CreateRunspace(…) and be done with it.

Step 4: Putting it all together

string shellUri = "http://schemas.microsoft.com/powershell/Microsoft.PowerShell";
PSCredential remoteCredential = new PSCredential(domainAndUsername, securePW);
WSManConnectionInfo connectionInfo = new WSManConectionInfo(false, remoteMachineName, 5985, "/wsman", shellUri, remoteCredential)

using ( Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo) )

{

runspace.Open();

Pipeline pipeline = runspace.CreatePipeline("<COMMAND TO EXECUTE REMOTELY>");

var results = pipeline.Invoke();

}

All in all, not too bad. The sad part it, in terms of figuring out what to do it is easier to create a local runspace and use Invoke-Command on it, but once you know what you are doing, it is only one extra line of code to execute scripts remotely!

Blog at WordPress.com.