Sladescross's Blog

Blogging about Sharepoint related stuff

Non-Compliant CLS Types In Powershell March 1, 2010

Filed under: .NET,CLS,Non-Compliant,Overloading,Powershell — sladescross @ 3:49 pm

http://www.nivot.org/2007/10/24/NonCLSCompliantTypesInPowerShell.aspx

One of the rules of a so-called “CLS compliant type” (cls = common lanaguage specification) is that you should not expose any public members that only differ in casing. The SPContentDatabase type has two properties, “Id” and “ID.” This is perfectly legal in C# since case in important in that language and the compiler sees them as different as chalk and cheese. However, in VB.NET, case is not important and as such it [vb] has no native mechanism to differentiate between the two. The same goes for PowerShell’s grammar. So, how do we get around this?

First, you grab a handle to the method directly by asking for it from the Type itself:

PS> $idMethod1 = [Microsoft.SharePoint.Administration.SPContentDatabase].getmethod(“get_ID”)

and for the second version,

PS> $idMethod2 = [Microsoft.SharePoint.Administration.SPContentDatabase].getmethod(“get_Id”)

Note the differing case for get_Id and get_ID. Btw, Properties like ID in .NET are actually served by special accessor methods prefixed with get_ and set_, hence the prefixes. Next, you need a way to invoke those methods on the instance itself: this is done by using the Invoke method on the MethodInfo object representing the method itself. You pass the instance to the Invoke method telling it that the method is “instance” (e.g. not static/shared) and “public” and it will call that method for you on the instance, returning the value, if any.

PS> $result = $idMethod1.Invoke($site.ContentDatabase, “instance,public”, $null, $null, $null)

http://blogs.msdn.com/carloshm/archive/2009/06/05/how-to-programmatically-read-the-changelog-in-powershell.aspx

Call overloaded non-compliant method in Powershell. GetChanges.

function Display_ChangeTokens_For_ContentDatabase([string] $ServerName, [string] $SiteCollectionName, [string] $ChangeCSVFile)
{

 $spsite = new-object Microsoft.Sharepoint.SPSite($ServerName + $SiteCollectionName);

 $spcontentdatabaseidmethod =  [Microsoft.SharePoint.Administration.SPContentDatabase].getmethod(“get_ID”);
 $spcontentdatabaseguid = $spcontentdatabaseidmethod.Invoke($spsite.ContentDatabase, “instance,public”, $null, $null, $null);

 $spcontentdatabaseguid.ToString() | select;

 $spcontentdatabasemethods = [Microsoft.SharePoint.Administration.SPContentDatabase].GetMethods(“instance,public”);

 $spcontentdatabasemethods | foreach-object {

  if ($_.name -eq “GetChanges”)
  {

   $parameters = @($_.GetParameters())

   # Call Overloaded GetChanges Without Parameters

   if($parameters.Count -eq 0)
   {

    $spcontentdatabasechanges = $_.Invoke($spsite.ContentDatabase, “instance,public”, $null, $null, $null);
    #$spcontentdatabasechanges | select;

    $spcontentdatabasechanges | foreach-object {

     #$spcontentdatabasechanges.Id + ” ” + ” ” + $spcontentdatabasechanges.ChangeType + ” ” + $spcontentdatabasechanges.SiteId + ” ” + $spcontentdatabasechanges.Time.ToString() + ” ” + $spcontentdatabasechanges.ChangeToken.ToString() | add-content -encoding ascii  $ChangeCSVFile;
     $spcontentdatabasechanges.Id | add-content -encoding ascii  $ChangeCSVFile;

    }
    
   }
  
  }
 
 }

 # Dispose of Site
 $spsite.Dispose();

}

and to get all the changes back use this.

function Send_ChangeTokens_All__For_ContentDatabase([string] $ServerName, [string] $SiteCollectionName, [string] $ChangeCSVFile)
{

 $spsite = new-object Microsoft.Sharepoint.SPSite($ServerName + $SiteCollectionName);

 $spcontentdatabaseidmethod =  [Microsoft.SharePoint.Administration.SPContentDatabase].getmethod(“get_ID”);
 $spcontentdatabaseguid = $spcontentdatabaseidmethod.Invoke($spsite.ContentDatabase, “instance,public”, $null, $null, $null);

 “Content Database is ” + $spcontentdatabaseguid.ToString() | select;

 $spcontentdatabasegetchangesmethod =  [Microsoft.SharePoint.Administration.SPContentDatabase].getmethod(“GetChanges”,[Microsoft.SharePoint.SPChangeToken]);
 $targetparameters = @($null);
 $total = 0;

 do
        {

  $spcontentdatabasechanges = $spcontentdatabasegetchangesmethod.Invoke($spsite.ContentDatabase, “instance,public”, $null, $targetparameters, $null);
  $total += $spcontentdatabasechanges.Count;

  $spcontentdatabasechanges | foreach-object {

    $_.ChangeToken.ToString() + ” ” + $_.ChangeType.ToString() + ” ” + $_.SiteId.ToString() + ” ” + $_.Time.ToString()  | add-content -encoding ascii  $ChangeCSVFile;

  }

  $targetparameters[0] = $spcontentdatabasechanges.LastChangeToken;

  if($targetparameters[0] -ne $null) { 
   “Change Token ” + $targetparameters[0].ToString() | select; }

 } while ($spcontentdatabasechanges.Count -gt 0)

 “Total ” + $total | select;

 # Dispose of Site
 $spsite.Dispose();

}

http://santoshbenjamin.wordpress.com/category/powershell/

Notice that the “Invoke” is different in the PS and the C#. Also notice how convoluted the PS is when trying to do a simple object.GetType() , but i guess PS wasnt meant for this sort of thing anyway, so we cant complain.

http://www.mohundro.com/blog/2008/05/07/ReflectionByExampleWithPowershell.aspx

Powershell for Reflection.

About these ads
 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
Follow

Get every new post delivered to your Inbox.

Join 63 other followers