IT Ramblings

Ramblings from an IT manager and long time developer.

NAVIGATION - SEARCH

Interested in SharePoint Certification?

A good place to start from would be here http://www.microsoft.com/learning/mcp/mcts/default.mspx. From there it all depends upon what certification you are planning to take: You can get certified either on MOSS or in Windows SharePoint Services 3.0.

Keep in mind that practical knowledge is essential for all these exams and if you have done couple of implementation, you will find these exams a lot easier.  An easy way to get hands on experience is to download the MOSS trials or even preconfigured VHD's from Microsoft: http://www.microsoft.com/downloads/details.aspx?familyid=67F93DCB-ADA8-4DB5-A47B-DF17E14B2C74&displaylang=en

The Best Cheat Sheet (that have found so far) is  go to these URL's and Check the Skills Measured Sections and start implementing these concepts in your project and keep practicing.   

Check these URLs for Skills measured, Reference Books, and Practice Tests:

The certification path and preparation guides are available at the following URL's:

MCTS: Windows SharePoint Services 3.0, configuring http://www.microsoft.com/learning/en/us/exams/70-631.mspx
MCTS: Microsoft Windows SharePoint Services 3.0 – Application Development http://www.microsoft.com/learning/en/us/exams/70-541.mspx
MCTS: Microsoft Office SharePoint Server 2007 – Configuration http://www.microsoft.com/learning/en/us/exams/70-630.mspx
MCTS: Microsoft Office SharePoint Server 2007 ― Application Development http://www.microsoft.com/learning/en/us/exams/70-542.mspx

Another thing to note is that Microsoft announced SharePoint Master Certification. This Certification path would get you SharePoint Architect or SharePoint Certified Master Credentials.

More details can be found here:

http://blogs.msdn.com/sharepoint/archive/2008/11/10/introducing-the-microsoft-certified-master-and-certified-architect-for-sharepoint.aspx

http://www.microsoft.com/learning/mcp/master/SharePoint/default.mspx

Plus, I think currently you can receive up to a 50% discount.

A for a few SharePoint 2007 Exams tips check out this site:http://www.sharepointforum.com/en-US/Blog/archive/2007/11/20/the-sharepoint-2007-exams-tips.aspx

Windows 7 to support Aero via Remote Desktop

Looks like Microsoft has been hard at work with Windows 7 and some of the new features are turning out to be real winners.  One of the ones that I am really looking forward to (besides the new UI) is the support for Aero via Remote Desktop.

Check out this post for more details and screen shots

http://www.neowin.net/news/main/09/03/16/windows-7-rdp-changes-improve-virtual-desktop-performance

A fantastic set of articles on creating a Silverlight web part for WSS and SharePoint

I was about to write up a set of posts on my recent experience on working with Silverlight in SharePoint, however when I ran across these posts from Ton Stegeman I decided that I couldn't have done a better job.

Take a look at his articles as he has written up a set of 4 articles that do an incredible job of outlining how to create a Silverlight webpart and application for Sharepoint

Windows Vista and batch files: UAC changes the rules (Part 1 of 2)

This is a reprint of the article from: http://www.romhack.net/index.php?post/2008/08/18/Windows-Vista-and-batch-files%3A-UAC-changes-the-rules-Part-1-of-2 

Windows Vista… whenever I hear this name, the first I think about is the polemic and only then about the Operating System. Vista has been the target of many criticisms, some justified, some simple matters of personal taste, and some only created to put gasoline on the fire. As such, many IT professionals expressed a great dislike of UAC (User Account Control), one of the main new security features of Vista, especially because they felt it was getting in their ways too often and that they knew their job well enough to not be bugged by it. Even if they are of course able to disable it on the computers they use, they would still have to bear with it on the other computers of their networks or on their customer’s machines: they simply can’t disregard UAC’s existence and have to cope with it and make sure their software and products get along nicely with it.

Personally, I don’t dislike UAC as it is helps reducing the risks of malware infection and of an user doing something dangerous rather than having it all the time running as admin (to be honest, in corporate environment, I even prefer to have users run as real users rather than as pseudo-administrators behind the UAC safeguard, which has been possible way before Vista but that’s another topic…)

For various reasons, I’m still running on Windows XP but have a Windows Vista virtual machine that I fire up whenever I need to check if one of my programs or scripts run properly on it. Today, I wrote a batch file as a test/prototype to include it in a bigger script written in the AutoIT scripting language (good scripting language that I’m going to talk about someday). Batch files may be outdated, lack features (try to do some nested conditions/branching without the script becoming a mess…) but they have the advantage to work relatively the same way on all the NT-based operating systems (or so I thought), do not need any compilation or runtime to install on the machines and provided you do not try to do anything overly complex, they have the most straightforward syntax of any scripting language you may find, all of which makes it great to quickly test ideas involving more externals programs than complex language features.

So my little batch file had several independent executables residing in the same directory as its own’s (very classic approach), which means that they were referenced in the script by base file name, without path. Everything worked fine under XP so I decided to unpack a pristine Vista virtual machine and do the test on this operating system. This script was adding a network adapter using an external executable, which is obviously an action requiring administrative privileges. In Vista, I got into the directory containing my script, right clicked on it and selected the “Run as Administrator” option… and then the problems started…

Several message boxes were complaining that the executables files referenced by my script could not be found. A bit surprised, I looked again and they were all  there. Suspecting a Path issue, I then added a “Echo %CD%” at the start of my script, which quickly confirmed the problem.

The “Echo %CD%” command reveals that the current directory was changed to system32 instead of remaining in the script’s directory
The “Echo %CD%” command reveals that the current directory was changed to system32 instead of remaining in the script’s directory

When running the script in elevated mode, the current directory was changed to C:\Windows\System32 directory (since it is where the cmd.exe command interpreter lies) and as a result, the executables that were residing in the script’s directory could not be found. It is the difference between the current directory and the application’s directory. I knew I wouldn’t have this problem with the AutoIt version as it provides easy ways to retrieve the path name the script resides in, but it is more complex with batch files and I was curious on how to fix the problem.

The surprising thing is that launching the script from the directory by double-clicking on it always worked in previous versions of the operating system, even the 16-bits ones as far as I can remember, so it isn’t really an expected change. While this feature was maybe not documented anywhere, it had become a given among scripters and I wonder how many batch files this change broke (although the problem only impacts those launched by clicking on them from the shell). I decided to check the differences between the ways the script was launched in non-elevated and elevated mode using Regedit and debuggers/monitors.

The command string used to run a batch file in normal, non-elevated, mode
The command string used to run a batch file in normal, non-elevated, mode

OllyDBG reveals the API call corresponding to a double click on the batch file from Explorer in non-elevated mode 
OllyDBG reveals the API call corresponding to a double click on the batch file from Explorer in non-elevated mode

The command string used to run a batch file in elevated mode  
The command string used to run a batch file in elevated mode

Process Monitor reveals that the API called when running the batch file from the “Run as Administrator” option is CreateProcessAsUser
Process Monitor reveals that the API called when running the batch file from the “Run as Administrator” option is CreateProcessAsUser

As we can see, the non-elevated command simply references the script’s file name as an argument (%1), which gets executed by CreateProcess (with the lpCurrentDirectory parameter correctly set to the batch file’s directory), while the command used by the “Run As Administrator” option also includes the full path to the command-line interpreter (%SystemRoot%\System32\cmd.exe). The API function launching the process in this case seems to be CreateProcessAsUser. Unfortunately, in the latter case, I didn’t manage to view the parameters passed to the function as I didn’t manage to hook the function: the API Spy I use needs to run elevated to successfully register its hooks and then start the program I want to inspect, but which would in this case run elevated as well because being a child of the API Spy application, which is itself elevated. Unfortunately, even clicking on “Run as Administrator” ends up calling CreateProcess instead of CreateProcessAsUser in this case (because UAC doesn’t trigger since Explorer is running elevated because the API Spy itself was running elevated… sorry, still following me?). Nevertheless, my theory, even though I couldn’t confirm it is that the problem lies in the lpCurrentDirectory parameter being set to %SystemRoot%\System32 instead than the batch’s file directory.

Now, even if we try modifying the batch’s runas registry entry to work around the issue (which doesn’t work anyway), it would only impact our machine and not the other ones, so, beyond any academic curiosity, what is actually needed is to find a fix to this behaviour that can be implemented at the beginning of the batch file, by running a command changing the current directory from whatever its current value is to the directory of our script. Here is a command sequence that did the trick for me:

@Echo off
pushd "%CD%"
CD /D "%~dp0"
REM Insert your code herepopd

pushd pushes the current directory value to the stack (similar to the push assembly instruction). In other words, it backups the current directory’s path (%SystemRoot%\System32\cmd.exe in our case of the elevated script) that we will restore a bit later. It is always nice to leave things as we found them in the first place to avoid further compatibility problems. Besides, other scripts calling this particular script may not expect this behaviour of changing the current directory and may break as the result, so it is better be safe than sorry and clean up after we are done.

CD /D "%~dp0" is going to change the current directory to the directory containing the running batch file. The /D switch is required in case our script resides in a different drive than %systemdrive% (aka C: in most cases). %~dp0 is a rather weird syntax and I have no idea of what it stands for, nor did I find a reference to any other ~dpX commands (%~dp1 doesn’t do anything for example) and even my favorite book on Command-Line scripting has nothing to say about it. As I was saying earlier, batch files have a very straightforward syntax for simple things but an incredibly obscure and strict one when you try to do something a little bit advanced (I’m thinking about this very %~dp0 variable and the for constructs).

Finally, popd restores the current directory that we previously backed up using pushd. Note that popd doesn’t require any argument and will automatically restore the path at the top of its stack.

With this, our batch file behaves the same way on Vista in elevated mode than it does on XP, but the risk to forget to add these 3 lines every time is real so in the next article I will show a little trick to make sure they get added every time automatically so they are never accidentally forgotten and to save the trouble and frustration of adding them manually every time.

Ever wondered how to write code against the BDC?

SharePoint 2007: BDC - The Business Data Catalog  (this is from http://blah.winsmarts.com/2007-4-SharePoint_2007__BDC_-_Writing_Custom_Code_against_the_runtime_object_model.aspx)

This post is in continuation to a series of blogposts I put up on BDC - the Business Data Catalog.

Table of Contents:

  • Introduction
  • In-built Webparts
  • Lists with Business data type columns.
  • Search
  • User Profiles
  • Other custom applications targeting a common runtime object model.  <--- You are here.
  • Making it easier to author XML Applications: BDCMetaMan

    Whew!

    My long series on BDC is coming to an end. What a bitch it has been to type so much LOL. So first of all, if I missed something, please ping me, so I can blog about it.

    In this last post, I am going to target the application we wrote here, using custom code.

    Here is a quick sample application targeting literally any BDC app.

    Sniffing your BDC App.

    static void Main(string[] args)
    {
    	string ssp = "SharedServices1";
    	
    	SqlSessionProvider.Instance().SetSharedResourceProviderToUse(ssp);
    	NamedLobSystemDictionary lobSystems = ApplicationRegistry.GetLobSystems();
    	
    	foreach (LobSystem system in lobSystems.Values)
    	{
    		Console.WriteLine("Application: " + system.Name);
    		
    		NamedDataClassDictionary lobClasses = system.GetDataClasses();
    		
    		foreach (DataClass dataClass in lobClasses.Values)
    		{
    			Console.WriteLine("  Entities: " + dataClass.Name);
    		}
    	}
    }
    
  • If I run the above, I get this output -

    Application: NorthWindApp
      Entities: Order
      Entities: Customer

    If you are wondering, I am using namespaces

        Microsoft.Office.Server.ApplicationRegistry.MetaDataModel
        Microsoft.Office.Server.ApplicationRegistry.Infrastructure.

    The references are

        Microsoft.Office.Server.dll
        Microsoft.SharePoint.dll
        Microsooft.SharePoint.Portal.dll

    Now, Let us slice and dice the above code step by step.

    The first thing you see in the above code is SqlSessionProvider. SqlSessionProvider represents a way to connect to the SSP. It immediately sticks out that the BDC runtime can target only the local farm. So, if you wish to allow BDC access over the network, you will need to write a webservice and deploy it on the farm, and access it via the web service.

    Once you get a hold of an instance using SqlSessionprovider.Instance(), you can then start querying it for various stuff. For instance, the first thing I wanted to find out were all the LobSystems (i.e. applications) registered in the SSP. And once I have the applications found, I can find the individual entities in each one of those classes.

    Once I have the individual entities, I can easily find the methods that entity has using the code below -

    DataClass customers = lobClasses["Customer"];
    NamedMethodDictionary methods = customers.GetMethods();
    
    foreach (Method meth in methods.Values)
    {
    	Console.WriteLine("Method: " + meth.Name);
    }
    

    You can continue to sniff around, and you will see that you can find methods, method instances, properties, heck if you snooped around enough, you could literally smell the entire metadata for the BDC app.

    So now that I have information about the BDC app, the next question is "How to use it".

    Using your BDC App.

    In order to actually use your BDC App, you need to first get a hold of the LobSystemInstances. Check the code out below -

    static void Main(string[] args)
    {
    	string ssp = "SharedServices1" ;
    	
    	SqlSessionProvider.Instance().SetSharedResourceProviderToUse(ssp);
    	
    	NamedLobSystemDictionary lobSystems = ApplicationRegistry.GetLobSystems();
    	
    	foreach (LobSystem system in lobSystems.Values)
    	{
    		Console.WriteLine("Application: " + system.Name);
    
    		NamedLobSystemInstanceDictionary instances = 
    		
    		lobSystem.GetLobSystemInstances();
    		
    		foreach (LobSystemInstance instance in instances.Values)
    		{
    			Console.WriteLine(instance.Name);
    		}
    	}
    }
    

    You might ask, what is the difference between a LobSystem and a LobSystemInstance? BDC in MOSS 2007 lets you put upto two instances on each LobSystem. This means, you get different authentication settings for the two instances, for the same application. This is incredibly useful, say when you are setting up search on BDC, because you would typically want search to work under different credentials than regular BDC usage by a user.

    Once you have the specific instance, you can then find the entity, the filters, set filter values, and finally execute the Finder method using the following code -

    Entity customerEntity = instance.GetEntities()["Customer"];
    FilterCollection filterColl = customerEntity.GetFinderFilters();
    
    (filterColl[0] as WildcardFilter).Value = "London";
    
    IEntityInstanceEnumerator customerEnum = customerEntity.FindFiltered(filterColl, instance);
    
    while(customerEnum.MoveNext())
    {
    	DataTable dt = (customerEnum.Current as DbEntityInstance).EntityAsDataTable;
    	PrintDataRow(dt.Rows[0]);
    }
    

    PrintDataRow is simply a method that prints out the values of the DataRow in a single line.

    The full final code looks like this.

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Data;
    using Microsoft.Office.Server.ApplicationRegistry.MetadataModel;
    using Microsoft.Office.Server.ApplicationRegistry.Infrastructure;
    using Microsoft.Office.Server.ApplicationRegistry.Runtime;
    using Microsoft.Office.Server.ApplicationRegistry.SystemSpecific.Db;
    
    namespace SampleBDCApp
    {
    	class Program
    	{
    		static void Main(string[] args)
    		{
    			string ssp = "SharedServices1";
    			SqlSessionProvider.Instance().SetSharedResourceProviderToUse(ssp);
    
                NamedLobSystemDictionary lobSystems = ApplicationRegistry.GetLobSystems();
    			
                foreach (LobSystem system in lobSystems.Values)
                {
    				Console.WriteLine("Application: " + system.Name);
                    NamedLobSystemInstanceDictionary instances =                     system.GetLobSystemInstances();
    				
                    foreach (LobSystemInstance instance in instances.Values)
                    {
    					Console.WriteLine(instance.Name);
    					
    					Entity customerEntity = instance.GetEntities()["Customer"];
    					FilterCollection filterColl = customerEntity.GetFinderFilters() ;
    					
                        (filterColl[0] as WildcardFilter).Value = "London";
                        IEntityInstanceEnumerator customerEnum =  customerEntity.FindFiltered(filterColl, instance);
    					
                        while(customerEnum.MoveNext())
                        {
    						DataTable dt = (customerEnum.Current as DbEntityInstance).EntityAsDataTable;
    					PrintDataRow(dt.Rows[0]);
                        }
    				}
    			}
    		}
    		
            private static void PrintDataRow(DataRow dr)
            {
    			foreach (DataColumn dataColumn in dr.Table.Columns)
                {
    				Console.Write(dr[dataColumn] + "\t");
    			}
    			Console.WriteLine();
    		}
    	}
    } 			
    

    .. and when you execute this, you get the following output -

    Congratulations - you've just written your first application using BDC. You can now implement the above in a web service, and expose any underlying LOB using a consistent BDC API.

    Here is an interesting exercise for you to try - Try using Office SSO + WindowsCredentials, so the end application's identity matters when calling the web service, and that same identity goes all the way to the web service.

    Have fun!