OpenForce '07 - For the community, By the community

Oct29

I have seen a few posts recently about other conferences (Adobe Max and Community Server Developer Conference) that made me think hard about how we have positioned the OpenForce conferences this year.  I remember in past years that events like JavaOne developed a reputation for being nothing more than giant sales and marketing event put on by Sun.  This is a trap that I hope we never fall into with the OpenForce conference.  Our goal from the very beginning has been to create an event where the community could come together and share our experiences and learn from other experts in the community. 

While I know that the community is interested in where we are going with the DotNetNuke and how DotNetNuke Corp plays into the big picture, I also know that few people want to spend their hard-earned cash just so they can sit through a marketing pitch.  Our challenge this year and beyond is to make sure we keep the focus where it belongs - on you - the community.  We worked very hard this year to attract some of the superstars in the community to come and speak at the conference.  Our goal was not only to get great speakers (which I think we have done), but also to make sure that we covered topics that would be relevant to our entire community - not just developers and not just people from North America.

If we ever lose sight of where our focus should be, I hope that someone from the community reminds us of why we created this conference in the first place.  This doesn't mean that we won't tell the community about some of the features we have planned or about some of the community support services that DotNetNuke Corp. offers, but we do not want that to become the focus of the event.

Our OpenForce events would not have been possible without the support and backing of both SDN and DevConnections.  They have allowed us to focus on getting the content right, while they did the heavy lifting on the logistics side of the house.  Even though a lot of effort has gone into preparing for both of these conferences, we know that we can do better.  Next year we look forward to streamlining our processes to identify speakers earlier, to expand the number of sessions and tracks that we offer, and to attract even more attendees and sponsors.

If you are attending OpenForce '07 next week, feel free to stop by the DotNetNuke Corp booth (booth #736), we would love to meet you and chat.  Yes, we may actually show you some of what we are planning for DotNetNuke 5.0, but we know you won't mind.



Why not just use Add-Member

Oct17

In my last post Getting a Username/Password in PowerShell (cross posted to PowerShellCommunity.org), I was asked why not just use the Add-Member cmdlet.  Having been doing software development for my entire adult life, this is not the first time this question has come up.  Ok.  Maybe not those exact words, but something very similar - why use code X when code Y does the same thing.  Where I come from there is really only one response to this - look at both code alternatives and determine which one is the most efficient at doing the job without also becoming a maintenance problem.  So lets take a peek under the hood a bit so we can see why I chose PSObject.Members.Add over using the Add-Member cmdlet.

Scripting is code - except on the command line

When working in PowerShell I try to keep a clear understanding of my usage scenario.  If I am writing something intended to be typed on the command line then I tend to favor a more script oriented approach where I make heavy use of piping one command into another and where cmdlets provide all of the heavy lifting.  However, when I sit down to write a function, I am coding and I tend to favor a much more expanded and explicit coding style using variables and objects.  This makes it easier to maintain the code and to understand what exactly I am trying to accomplish.

Know what is happening under the cover

Once I know what coding style I will be using then I need to evaluate the effectiveness and efficiency of the coding alternatives.  Often this means you will need to understand what is happening inside the framework.  One of the reasons that I am excited about the announcement that .Net is going to provide Source code is that I will finally be able to look at the source code with full commenting.  Until that happens though, I still have Reflector and I use it very heavily.

In this case the question is:  Why use Members.Add instead of using Add-Member?  Lets look at what is going on in Add-Member and you'll see why.

Microsoft.PowerShell.Commands.AddMemberCommand.ProcessRecord() is the relevant method that gets executed when we run the Add-Member cmdlet.  There is some basic error checking to make sure that certain cmdlet parameters were set - like membertype.

Next we have a giant case statement: 

Select Case Me.memberType
    Case PSMemberTypes.AliasProperty
        member = Me.GetAliasProperty
    Case PSMemberTypes.CodeProperty
        member = Me.GetCodeProperty
    Case PSMemberTypes.NoteProperty
        member = Me.GetNoteProperty
    Case PSMemberTypes.ScriptProperty
        member = Me.GetScriptProperty
    Case PSMemberTypes.ScriptMethod
        member = Me.GetScriptMethod
    Case PSMemberTypes.MemberSet
        member = Me.GetMemberSet
    Case PSMemberTypes.PropertySet
        member = Me.GetPropertySet
    Case PSMemberTypes.CodeMethod
        member = Me.GetCodeMethod
    Case Else
        'Deal with error...
End Select


This case statement doesn't provide any real value to our function since I already know what type of members I wish to add, I don't need the cmdlet to make a conversion from my "string" to a root class type.  Even once the membertype is determined, the cmdlet calls another function (GetNoteProperty in our case) which we see below: 

Private Function GetNoteProperty() As PSMemberInfo
    Me.EnsureValue1HasBeenSpecified
    Me.EnsureValue2HasNotBeenSpecified
    Return New PSNoteProperty(Me.memberName, Me.value1)
End Function
 

So in essence, this big case statement is doing exactly the same thing as my code, except with a lot more overhead.  It is creating a new PSNoteProperty.  Now lets look at the next part of the ProcessRecord method.

Dim info2 As PSMemberInfo = Me.inputObject.Members.Item(member.Name)
If (Not info2 Is Nothing) Then
    If Not Me.force Then
        MyBase.WriteError("...")
    Else
        If info2.IsInstance Then
            Me.inputObject.Members.Remove(member.Name)
            goto Label_0201
        End If
        MyBase.WriteError("...")
    End If
    Return
End If
Me.inputObject.Members.Add(member)

So we see that beyond a bunch of extra error handling to deal with members that already exist, this code just calls Members.Add().

At this point I think it is safe to say that my original code and the Add-Member cmdlet are performing exactly the same function.  However, with the cmdlet there is a performance penalty to be paid for parsing all of the strings passed to the cmdlet and converting them to types.  Determining how to act based on some of the parameters (like -force).  Also, I think that my code is just as readable as using the cmdlet.  Ultimately though, Add-Member is just sugar coating for adding a PSMemberInfo object to a PSObject.Members collection.

So, the next time you have a question about whether to use a cmdlet or whether to use "code", pull out reflector and see what is really happening under the hood.



Getting a username/password in PowerShell

Oct16

As part of getting ready for my PowerShell session at OpenForce '07, I am creating a set of helper functions for working with SMO to manipulate and query the database server.  A common need when working with the database is to pass the username and password to various SMO methods.  When I first started coding my examples, I just passed a username and password as parameters into my functions.  This works, but does not exactly look professional when you are sitting in a presentation and typing out passwords in plaintext.

I decided that it would be better to use Get-Credential in this case since it would provide a professional dialog and keep the password hidden throughout the process.  Since I wanted to support both scenarios, I came up with the below function. 

function global:get-sqluser($username="", $password="") {
    # We are creating an object to which we'll add custom properties
    $user = New-Object Management.Automation.PSObject
    
    if ($username -eq "") {
        # No username was specified, so we should use Get-Credential to prompt for a user
        # We also define a default username in order to suppress console output
        # The results are added as synthetic properties to the PSObject we created above
        $cred = Get-Credential "SqlUser"
        $user.psobject.members.add( (New-Object System.Management.Automation.PsNoteProperty UserName, $cred.username.split("\")[1]) )
        $user.psobject.members.add( (New-Object System.Management.Automation.PsNoteProperty Password, $Cred.Password) )
    } Else {
        # In this case we can just create synthetic properties using the values passed to the function
        $user.psobject.members.add( (New-Object System.Management.Automation.PsNoteProperty UserName, $username) )
        $user.psobject.members.add( (New-Object System.Management.Automation.PsNoteProperty Password, $password) )
    }
 
    # Return our synthetic object
    $user
}

It is not perfect as the two cases return the password as either a cleartext string or a securestring.   Also, I don't like the hack with the Get-Credential since I don't really need a domain qualified name (notice the ugly split("\")[1] that is needed to get just the username without a domain qualifier).  My next version will resolve both of these issues, but for now this will have to suffice.



PowerShell for DotNetNuke

Oct14

For the past couple of months I have been playing with PowerShell and it has been a real pleasure to dig-in and get my hands dirty in a command-line interface again.  Not since my early days with the Amiga and ARexx have I enjoyed learning about a new CLI and an associated scripting language.  The PowerShell team has done a great job of bringing windows scripting and the CLI into the 21st century.  Not only has Microsoft been putting in a lot of effort into PowerShell, but you are also seeing an explosion of third-parties who have also jumped onboard to push the new language and hosting environment.  Companies like Sapien, Quest, /n Software, and ShellTools are creating great tools and sponsoring community sites like PowerShellCommunity.org.

With all of this excitement and passion in the PowerShell community, how could I not look to see how I could use PowerShell with DotNetNuke.  Thus was born my session idea:  PowerShell for DotNetNuke which I will be presenting in Las Vegas at OpenForce '07.  During my session I will be showing how you can use PowerShell to enhance managing DotNetNuke, both for installing new sites and for sites that are already up and running. 

One of the early ideas I had was that I might even be able to create a DotNetNuke module that would let a user execute PowerShell commands and scripts on the server.  Since DotNetNuke allows you to lock down access to any module it is fairly secure.  The initial code for this module is based off earlier examples by Scott Hanselman and Dominick Baier.  Here is a sample video of my work so far.

 

I still have some enhancements that I will be making before the conference, but you can download the latest code here.

 



DotNetNuke 4.6.2 is now available

Oct01

rubiks-cube Nothing is ever easy in life.  The release of 4.6.0 and the subsequent release of 4.6.1 proved that.  4.6.1 was primarily concerned with fixing a couple of very nasty bugs from the 4.6.0 build.  The two worst bugs included a breaking change to the behavior of ModuleSettingsBase and a defect in the UserSettings page that caused the system to overwrite your usersettings whenever someone logged in.  Unfortunately, when we attempted to roll back the changes to ModuleSettingsBase to the pre-4.6.0 code, we did not get all of the relevant code rolled back.  This only made the breaking change worse.  This prompted us to take the unusual step of completely removing the 4.6.1 download until we could get a new version coded, tested and built to put back online.  Last night we posted the new 4.6.2 version which fixed the breaking change.

One of the lessons learned as we went through this exercise is that when building an API you must be constantly evaluating how your audience might use that API.  Often your customers may do things you never intended, but which you should have anticipated.  We need to strive to develop our APIs, not for how we intend to use them, but for how we anticipate our customers will want to use them.  Maybe I only need an add and an update method for some entity.  Should I create a delete method as well since it is likely that customers will need that feature?  This analysis affects not just what methods or properties I make available, but also how I architect the class hierarchy.  Finally, we need to be very careful and deliberate whenever a decision is made to remove a public member of an API.  It doesn't matter if we never use that portion of the API.  If it is public, then there is a good likelihood that someone will have found it and started using it in their code.  One of our overriding goals from day one has been to avoid breaking changes wherever possible.  We try to batch up breaking changes that are needed to evolve the platform and only introduce those changes in a single large release every 2 to 3 years.

The decision to remove the properties from ModuleSettingsBase was wrong.  Unfortunately, the architecture was not as clean as it should have been which meant rolling back the change was not straightforward as it impacted other parts of the system.  This also meant that a clean fix was also not possible.  The system has been patched to correct the initial bug which precipitated the change and to correct the rolled back code so that it works as expected.  We will likely revisit this portion of code in the future to clean up the inheritance chain so that this portion of code is not so brittle.




TwitterCounter for @jbrinkman

"The Accidental Geek"

Joe Brinkman

Joe Brinkman

I am a long-time geek who is lucky enough to work on DotNetNuke full-time. You will also see the occassional post on my other passion - woodworking.

Calendar

<<  March 2010  >>
MoTuWeThFrSaSu
22232425262728
1234567
891011121314
15161718192021
22232425262728
2930311234

View posts in large calendar