Welcome to MSDN Blogs Sign in | Join | Help

Copying files from Desktop to a CE device

 

So I have this problem, where I need to create a tool that creates a folder with a bunch of files on the PC and then copies all these files over to a CE device. The method of choice here was via ActiveSync over USB.  One of the design goals was to be able to copy these files to a number of devices simultaneously. However, research revealed that this is not really possible since, activesync only supports one active connection at a time. So much for the great idea.

So now we are faced with this problem of copying files over to the device over ActiveSync. Since the app had a lot of GUI, I created that in C#. The .NET framework exposes excellent API for file manipulation based on paths. The problem with ActiveSync connections is when the device is cradled, there is no drive letter associated with the connection. So all device paths are then \My Documents\ or \Program Files\ etc.

This creates a problem as far as the File manipulation API in System.IO. Since these methods accept relative as well as fully qualified paths, any path like the above, would be treated as a relative path and not a fully qualified path, thereby causing a lot of grief.

The only way to get past this so far has been to use RAPI.

RAPI stands for Remote Application Programming Interface, and was created ages ago with the first wave of activesync and windows mobile products.

RAPI has some documentation on MSDN at: http://msdn.microsoft.com/en-us/library/aa458022.aspx

However since RAPI is a native API, almost all the documentation is geared towards native implementation.

After searching the intertubes for a suitable solution, I couldn’t find one that was recent, and that was guaranteed to work.

Below is the solution:

 

 

using System;
using 
System.Threading;
using 
System.Runtime.InteropServices;
using 
COMTYPES System.Runtime.InteropServices.ComTypes;
using 
System.Collections.Generic;
using 
System.Text;
using 
System.IO;
using 
Logger Microsoft.MobileDevices.Tools.Utilities.Logger;


namespace 
Microsoft.MobileDevices.Tools.RAPILibrary
{
    
public class RAPILibrary
    {
        
# region RAPI EXTERN
        
// -------------------------------------------------------
        // RAPI.DLL Definitions
        // -------------------------------------------------------

        
public const int MAX_PATH 260;
        public const uint 
MAXDWORD 0xFFFFFFFF;
        public const uint 
S_OK 0;

        public struct 
RAPIINIT
        {
            
public int cbSize;
            public 
IntPtr heRapiInit;
            public int 
hrRapiInit;
        
};

        
// From WINBASE.H -- for CeCreateFile
        
public enum ACCESS : uint
        
{
            READ 
0x80000000,
            WRITE 
0x40000000,
        }
        
// From WINBASE.H -- for CeCreateFile
        
public enum SHARE
        {
            READ 
0x00000001,
            WRITE 
0x00000002,
        }
        
// From WINBASE.H -- for CeCreateFile
        
public enum ACTION
        {
            CREATE_NEW 
1,
            CREATE_ALWAYS 
2,
            OPEN_EXISTING 
3,
            OPEN_ALWAYS 
4,
            TRUNCATE_EXISTING 
5
        
}

         
// From WINBASE.H -- for CeCreateFile
        
public enum FILEFLAGATT : uint
        
{
            ATTRIBUTE_READONLY 
0x00000001,
            ATTRIBUTE_HIDDEN 
0x00000002,
            ATTRIBUTE_SYSTEM 
0x00000004,
            ATTRIBUTE_DIRECTORY 
0x00000010,
            ATTRIBUTE_ARCHIVE 
0x00000020,
            ATTRIBUTE_INROM 
0x00000040,
            ATTRIBUTE_ENCRYPTED 
0x00000040,
            ATTRIBUTE_NORMAL 
0x00000080,
            ATTRIBUTE_TEMPORARY 
0x00000100,
            ATTRIBUTE_SPARSE_FILE 
0x00000200,
            ATTRIBUTE_REPARSE_POINT 
0x00000400,
            ATTRIBUTE_COMPRESSED 
0x00000800,
            ATTRIBUTE_OFFLINE 
0x00001000,
            ATTRIBUTE_ROMSTATICREF 
0x00001000,
            ATTRIBUTE_NOT_CONTENT_INDEXED 
0x00002000,
            ATTRIBUTE_ROMMODULE 
0x00002000,
            FLAG_WRITE_THROUGH 
0x80000000,
            FLAG_OVERLAPPED 
0x40000000,
            FLAG_NO_BUFFERING 
0x20000000,
            FLAG_RANDOM_ACCESS 
0x10000000,
            FLAG_SEQUENTIAL_SCAN 
0x08000000,
            FLAG_DELETE_ON_CLOSE 
0x04000000,
            FLAG_BACKUP_SEMANTICS 
0x02000000,
            FLAG_POSIX_SEMANTICS 
0x01000000,
        }


        
/// <summary>
        /// Closes handle passed in
        /// </summary>
        /// <param name="hObject">handle to be closed</param>
        /// <returns></returns>
        
[DllImport("rapi.DLL", CharSet CharSet.Unicode)]
        
public static extern int CeCloseHandle(IntPtr hObject);

        
/// <summary>
        /// Creates file on device
        /// </summary>
        /// <param name="lpFileName">path of file</param>
        /// <param name="dwDesiredAccess">Read/Write</param>
        /// <param name="dwShareMode">Share mode</param>
        /// <param name="Res1"></param>
        /// <param name="dwCreationDisposition">File creation options</param>
        /// <param name="dwFlagsAndAttributes">Flags and attributes</param>
        /// <param name="Res2"></param>
        /// <returns>pointer to the created file</returns>
        
[DllImport("rapi.DLL", CharSet CharSet.Unicode)]
        
public static extern IntPtr CeCreateFile(string lpFileName, ACCESS dwDesiredAccess, SHARE dwShareMode, int Res1, ACTION dwCreationDisposition, FILEFLAGATT dwFlagsAndAttributes, int Res2);

        
/// <summary>
        /// Reads the file
        /// </summary>
        /// <param name="hFile">handle to the file</param>
        /// <param name="lpBuffer">buffer to copy data to</param>
        /// <param name="nNumberOfBytesToRead">file size to read</param>
        /// <param name="lpNumberOfBytesRead">file size read</param>
        /// <param name="Reserved"></param>
        /// <returns></returns>
        
[DllImport("rapi.DLL", CharSet CharSet.Unicode)]
        
public static extern int CeReadFile(IntPtr hFile, IntPtr lpBuffer, int nNumberOfBytesToRead, ref int lpNumberOfBytesRead, int Reserved);

        
/// <summary>
        /// Writes file to device
        /// </summary>
        /// <param name="hFile">handle of file to write to</param>
        /// <param name="lpBuffer">data to write</param>
        /// <param name="nNumberOfBytesToWrite">length of buffer</param>
        /// <param name="lpNumberOfBytesWritten">length of file on device</param>
        /// <param name="Reserved"></param>
        /// <returns></returns>
        
[DllImport("rapi.DLL", CharSet CharSet.Unicode)]
        
public static extern int CeWriteFile(IntPtr hFile, IntPtr lpBuffer, int nNumberOfBytesToWrite, ref int lpNumberOfBytesWritten, int Reserved);

        
/// <summary>
        /// Copies file from desktop to device
        /// </summary>
        /// <param name="deskFile">Full path of file on the desktop including filename</param>
        /// <param name="devFilePath">Path of file name on the device. '\' denotes root </param>
        
public static void CopyFiletoDevice(string deskFile, string devFilePath)
        {
            
try
            
{
                
int numTries=0;
                
// Verify file exists on desktop
                
FileInfo fInfo = new FileInfo(deskFile);
                if 
(fInfo.Exists)
                {
                    IntPtr devFileHandle
;
                    
// create a file on the device
                    
do // force valid handle in the loop
                    
{
                        devFileHandle 
CeCreateFile(devFilePath, ACCESS.READ | ACCESS.WRITE, SHARE.READ | SHARE.WRITE, 0, ACTION.CREATE_ALWAYS, FILEFLAGATT.ATTRIBUTE_NORMAL, 0);
                        if 
(devFileHandle.ToInt32() < 0)
                        {
                            CeCloseHandle(devFileHandle)
;
                         
}
                    } 
while (devFileHandle.ToInt32() < 0);


                    
// read file from desktop into a byte buffer
                    
Byte[] buffer;
                    
ReadFileAsBinary(deskFile, out buffer);

                    int 
numBytesWritten 0;
                    unsafe
                    
{
                        
fixed(byte* bufferPtr buffer)
                        {   
                            
int retVal CeWriteFile(devFileHandle, (IntPtr)(bufferPtr), (int)fInfo.Length, ref numBytesWritten, 0);
                            if 
(retVal == 0)
                            {
                                 
throw new IOException("RAPILibrary:CopyFileToDevice() Error Writing file on device. " + CeGetLastError().ToString());
                            
}
                        }
                    }

                    
// close handles
                    
CeCloseHandle(devFileHandle);
                
}
                
else
                
{
                    Logger.WriteLog(
"RAPILibrary:CopyFileToDevice() File does not exist on desktop: " + deskFile);
                
}

            }
            
catch (IOException ioEx)
            {
                Logger.WriteLog(ioEx.Message)
;
            
}
            
catch (Exception ex)
            {
                Logger.WriteLog(ex.ToString())
;
            
}
        }

        
/// <summary>
        /// Reads file and returns byte[]
        /// </summary>
        /// <param name="path">Full path of file</param>
        /// <param name="buffer">byte array for file data</param>
        
private static void ReadFileAsBinary(string path, out Byte[] buffer)
        {
            Logger.WriteLog(
"RAPILibrary:ReadFileAsBinary() Reading the file " + path);
            
FileInfo fInfo = new FileInfo(path);
            long 
fileLength fInfo.Length;
            
buffer = new Byte[fileLength];
            
FileStream fs fInfo.OpenRead();
            
fs.Read(buffer, 0, (int)fileLength);
            
fs.Close();
            
Logger.WriteLog("RAPILibrary:ReadFileAsBinary() Exit");
        
}
    }
}

Shifting Gears

Last year I moved over from supporting developers on SharePoint to testing software for Windows Mobile. This was the driver for my move from India over to Redmond last July. There have been a lot of developments in both the Office Server space as well as the Windows Mobile space. For reasons of my sanity, I will be blogging more on Windows Mobile starting now.
Windows Mobile 6.0 was the last release more than a year ago. Over the last year, there were a lot of developments and some interesting releases. Microsoft has a partnership with several operators and several OEMS. These two terms are very important to how Microsoft does business in the Windows Mobile space. From this perspective, operators are network service providers who maintain and operate cellular networks. In the US, the ones that we work with are T-Mobile, Verizon, AT&T and Sprint. Across the pond, in Europe, it is Vodaphone, Softphone etc.
OEM's on the other hand, are the companies that actually build the phones themselves. For instance, we work closely with HTC, Samsung, Motorola, Toshiba, etc. These are the companies that build the phone and its hardware. The question then is, what does Microsoft do in terms of having the phone in the hands of the end consumer?
There are two major groups within the Mobile division. One group is the OS team, and the other is the commercialization team. The OS team, works over a long cycle, that would involve market prediction, product planning etc, and chalk out and architect a strong platform, which for the purpose of this post, is analogous to cookie dough. These guys would work off of the latest Windows CE platform and create a extendible platform on top of that. Each of their releases is generally a major architectural change from the previous release. However, since the release is analogous to cookie dough, this is not what gets to the market. Of course, no one would want dough if they were shopping around for a cookie would they?
The commercialization team on the other hand is responsible for ensuring that the cookie dough gets baked into a delicious cookie that can get to the market. So this team works with OEM's and operators in a triad to figure out the combination of the network and hardware that a particular release would be shipped on. For instance, the team could work with HTC and T-Mobile to chalk out the requirements that they have for T-Mobile to sell the device. This would generally require understanding the new hardware features the OEM has introduced, such as say GPS capabilities, touch capabilities, or 3G network capability etc and then plug that in with new services that the operator might be planning. This generally translates into a new feature set which actually makes into the store.
On a time line scale, there is a lag of 2-6 months between the OS team releasing a new platform to the device being in the store. Of course, the operators and OEM's keep coming back with more and more improvements or changes to their feature set, or with questions or report some problems that need to be fixed. These get fixed in incremental fixes that are then commercialized in varying timelines. This is a very iterative process. For instance if a version x.0 is released, then there would be some devices that would ship with x.0, there would be some that would ship with x.0.1, some with x.0.2, etc. These are generally minor fixes or tune ups that certain operators or OEM's need. Then there would be a major holiday/summer push with say a x.1.0, and so on. The process would then repeat, till the OS team would release the next major release.
So as you see, there is a major emphasis on ensuring that we enable the OEM's and the operators to build and market their devices and services (enable being the keyword here). This is very easy considering that a lot of effort and planning is done to ensure that the platform is extensible and takes into account a variety of requirements that can be made at a later stage. For instance, the extensibility of the platform allowed HTC to convert the standard Windows Mobile 6.0 pocket PC interface and expand it to add Touch and gesture support via the HTC Touch that is available on Sprint networks. This extension was created by HTC and is now part of the new HTC Touchflo platform that is being targeted for a line of devices (www.htctouch.com ).
More recently a targeted experience was created for T-Mobile with the Shadow device. This required creating a new Home screen, specifically targeted for T-Mobile, which had the T-Mobile branding and colors etc. Of course, this kind of work, exposes new requirements, and enables us to create application platforms that can be extended. As with the Shadow work, we were able to create a application platform, that could help us create better user experiences in the future.

When one looks at the process above, it is obvious that the drivers for improvements are based off the direct customer feedback that the operators receive from the users. This feedback is then channeled back to us via product bugs that are prioritized and then actioned. Of course, since the feedback we receive from the Operators is weighted by their urgency in commercial viability of future devices, some actual user scenarios or pain points get overlooked. I am hoping to make this blog a place where I can have some interaction on what scenarios are causing you pain.

There is a lot of great work happening in the Windows Mobile space and with the recent announcements at the Mobile World Congress there is definitely a lot of interesting stuff lined up for this year.

~Harsh



GlobeTrotter

It's been quite a while since I have posted here. There have been lots of things going around. As some of you know, I was working in the SharePoint Developer Support team, and some amongst you, who have called in might know that there were huge volumes due to the never-before numbers of MOSS deployments. My team was completely swamped with what was happening due to this. In the midst of all of that, I was interviewing within Microsoft for a position in Redmond. There are a number of articles and discussions out there on the internet that talk about various experiences of people interviewing with Microsoft. Suffice to say that, being already an employee did not put me on a pedestal and I was put through the same rigors as anyone else while I was interviewing. This experience was something that I really liked about the company. It does not matter whether you are an existing employee or not, unless you have the required skills needed for the job you are applying for, there is no way they will let you in.
During this process I interviewed with all the teams in the Office Server space as well as with some other teams and the experience was really an eye-opener. There is a standard format to these interviews. You (as in the candidate) searches for a job opening, looks at something that fits what he/she is looking for, and then sends out an email to the recruiter or the hiring manager with a resume and asking for an informational interview. An informational interview at this stage is a staging talk between the candidate and the hiring manager wherein the candidate gets a deep look at what exactly the job description said. Also, at this point, the hiring manager would generally schedule a technical screening, to take a look at whether or not it's worth the effort to schedule a full round of interviews. Of course once this is done, you are looking at the real deal - which is the actual interview process. Typically for the programming position that I was applying for, there would be anywhere between 4-8 different individual interviews in a full "loop" as they call it. Each interview is at least an hour long and has a set pattern too. There are a lot of instances when potential candidates are flown to Redmond for the interviews, however in my case, since I was already at a Microsoft site, we utilized the power of technology to work through the interviews. I would book a video conference room at my end and the recruiters would book a video conference room in Redmond. Once the connection would be established, each of the interviewers would walk-in and grill me over the course of the next hour and a half. One thing that really worked in my favor was having a conference room that had a white board facing the screen/camera. It really eased out a lot since, I could write out code or explain my thought process using figures/diagrams and they could actually see what I was writing compared to using a pen and notepad. The interviews would generally go over as, the first 15 minutes walking through my resume, then a programming problem which would take up about 40 minutes or so followed by more questions on why I did something or why I chose not to do something in the code. This would be followed up about 5-10 minutes for me to ask them questions on what they do and what potentially I would be doing.
After about two or three months of interviewing I finally found a "mutual perfect fit" team that I was excited to work with. Then started the tedious process of paper work, going back and forth over the offer, working through the visa issues, the travel itinerary and then the actual relocation. It was quite enlightening to understand during this period that each of the individual verticals within Microsoft operated as independent organizations all being part of one parent company. So, while I was in India, I rolled up into Microsoft India R&D which encompassed Services, R&D, Engineering, Sales and Evangelism. However, once I accepted the offer, I realized that I would now be rolling into Microsoft Corp which kind of encompassed almost everything. However, since Microsoft India R&D was a independent subsidiary, all finances, accounts and in general everything was separate and apart from email address and employee number nothing was being transferred. So when I was making the move, the India organization treated this as an employee resigning and leaving, and the US organization treated this as a new employee joining. This definitely was a very interesting process.
Back in March just after I had got back from my TechReady trip me and my wife Ketaki had found out that we were expecting our first child. So this was definitely something that we would have to factor in when we were relocating. There were obviously travel restrictions on how late into the pregnancy she would be allowed to travel and I wanted to make sure that we moved over to Redmond well in time to get ourselves settled in and with some time on our hands till the baby was due. She was working with HP at the time and decided to take time off from work to lend a hand with the whole relocation thingy.
Going through the visa process was a fun experience since the legal had taken care of practically everything and all we had to do was to show up and answer some questions. Of course, with me, nothing can be smooth sailing for long. We landed in New Delhi on the morning of the visa interview and proceeded to the US consulate. The US consulate in New Delhi is heavily barricaded with a number of security checks before you actually enter the visa processing centre. On the outside they have this huge queue to check if all documents are in order. Most of the people are sent back from here. Once this is done you go through a huge security gate that makes airport security checks seem like a joke. Inside, there is another line for finger printing and then the last long wait for the actual interview at the window. When we got there at around 11:45 for a 12:00 PM interview, there was this huge line on the outside for the document check. I had just resigned to the fact of a long wait when out of nowhere, I tripped and fell while getting off the sidewalk. There was a small trench like gap between where the side walk ended and the road began, and I had somehow managed to get my foot trapped in that gap, twisted it violently and crashed on the tar in full view of everyone there. For a moment I was writhing with pain, and had no sense of what was happening around me. From amongst the crowd this lady came up to us, and offered me some water, and actually ran back to her car parked some distance back to get me a pain reliever gel and a crepe bandage. Before we could ask her who she was, she had disappeared just as suddenly as she had appeared. Both me and Ketaki were just left wondering who she was – and also thinking there are indeed some kind hearted souls in this world. Thank you Mysterious Lady for helping us out during that brief moment.
I was visibly limping after I got up, with my ankle looking like a soccer ball. The guards saw this and just let us through to the finger printing. Some good did come off the pain that I was in. Instead of waiting in line for an hour and a half we were just ushered in to the fingerprinting and then onward to the interview. We were out in a flat 30 minutes. We took a flight back the same evening. In a couple of days I had received my passport at my office and Ketaki had received hers at the home. We were all set, now we only needed the plane tickets. All of this was June. During the same period both of us were running about getting everything else done, we needed to close the rental agreement that we had for the place we were living in, sell the Opel Corsa we had, and get all our belongings packed and shipped. The relocation guys were tremendously helpful in arranging for a packing and moving company to just come over one day pack everything into neat boxes and send it out. After the packing was done, and the apartment was practically just four walls standing, we took the next flight out to Mumbai where we planned to spend a couple of days meeting our friends and family. The relocation specialist I was dealing with did an excellent job of getting us the flight itinerary that worked for us as well as getting us the temporary accommodation at such short notice. On the 19th of July at about 3:00 AM we boarded a BA flight from Mumbai to Heathrow. A eight hour really taxing and boring halt at Heathrow and we were onward for our direct connection to Sea-Tac. We arrived at about 5:30 local time, completely exhausted. The total trip time from boarding to alighting was close to 26 hours. Under normal circumstances that would have been bearable, but with a 7 ½ months pregnant wife, it was really taxing. A friend had come over to receive us and take us to the temp housing. We just crashed on getting there.
We had arrived in Bellevue/Redmond on the 20th of July.

 

~Harsh

SharePoint 2007 Maximum Limitations

Following is a list of names and other parameters with the maximum allowable size on each.

Entity                        Max Permissible Size
Site Name                    128 characters
Site URL                 255 characters
Display name                 128 characters
Connection string                 384 characters
Email address                    128 characters
Version numbers                064 characters
Virtual Server Friendly Name            064 characters
SQL Database Name                123 characters
SQL Database Column                128 characters
SQL Database Table Name            128 characters
SQL Role Name                    128 characters
Server Name                    128 characters
Windows User Name                300 characters
Windows Password                300 characters
Dependencies per object            032 objects
Zone enumeration value            004 zones
Default SQL command timeout             300 seconds
Number of simultaneous
workflows that can be run*             015

If during your course of using the product, you inadvertently cross these limits, then you would end up with errors. These are hard limits.

 

* This is the maximum number of simultaneous workflows that can be in memory executing code. (NOTE: there is no limit to the number of workflow instances in progress in the database)

~harsh

 

Single SignOn Error codes and what they mean

Error Code

Meaning

When Thrown

Bubbled Behavior

How To Overcome

-2140993974

SSO is not configured

Failure when SSO has not been setup via Central Administration

Critical error logged in ULS with error code.

If SSO is not configured then configure from Central Admin.

-2140993973

SSO Wrong Version

SSO config setting or master secret has changed and change has not reflected.

Critical error logged in ULS with error code.

Not applicable. Self healing error.

-2140995575

Failed to connect to SQL Server

Creation of the SSO database fails.

Critical error logged in ULS with error code.
Error logged in application event log.

Check SQL connectivity.
Check permissions for the account running the MS SSO service.

-2140995576

SharePoint Central administration virtual root not found

The SSO folder under 12\Template\Admin\SSO does not exist. This check performed while configuring master secret server. Either a call into Configuration.ConfigureSecretServer via OM or the UI page to configure SSO can throw this error.

Error logged in ULS with error code.

Or error returned to calling function

Repair the product installation.
Most likely the files were not copied properly

-2140995588

Web application not running with windows authentication.

When a custom webpart is placed on a page in a non-windows auth web app.
SSO CANNOT WORK WITH FORMS AUTHENTICATION.

Error logged in ULS with error code.

Or error returned to calling function.

Check authentication providers for the web application. If you have a requirement to have the web app behind FBA, then SSO cannot work.

-2140995589

SQL Server not supported.

If the SQL server specified to host the SSO db is not greater than or equal to SQL Server 2000 SP3.

Error logged in ULS with error code.

Or error returned to calling function.

Check SQL Server patching and version numbers.
http://support.microsoft.com/kb/321185
Minimum required is SQL Server 2000 SP3

-2147023143

Failure to connect to the Microsoft Single-SignOn Service.

Failure to connect to the MS SingleSign On Service. Either when the service is not started or the service has a logon failure.

Error logged in ULS with error code

-


The above information is indicative of the errors that you may encounter while working with Single SignOn on MOSS 2007. This is only for troubleshooting purposes.

~harsh

Posted by Harshawardhan Chiplonkar | 2 Comments
Filed under: , ,

MOSS, SSO, FBA

Single Sign On does not work with Forms Based Authentication

SingleSignonException caught.
Exception Code: 0x8062fffc
Source: Microsoft.SharePoint.Portal.SingleSignon
StackTrace: at Microsoft.SharePoint.Portal.SingleSignon.Credentials.SetUserCredentials(String strApplicationName, String strUserAccount, Object[] Args) at MethodName: SetUserCredentials
Message: A call into SPS Single Sign-on failed. The error code returned was '-2140995588'.

 

R.I.P

Posted by Harshawardhan Chiplonkar | 0 Comments
Filed under: , ,

IRM and the Object Model

A couple of weeks earlier, I saw an interesting issue. It was a normal day as far as days go in support and in comes this issue, where the person in question wants to investigate or rather should I say automate the process of creating IRM settings on document libraries. I wasn't working on this issue and a colleague took this over. But then somewhere it was lurking, how the hell do you do that? The natural starting point is getting a site/web context and going down to the list and then getting dirty with the properties exposed by the particular SPList object. So after finishing what I had on my plate, I dug into figuring out how exactly to set the IRM settings for a list using the object model. So here goes:

Step 1 Enable IRM on the farm

SPWebService svc SPFarm.Local.Services.GetValue<SPWebService>();
SPIrmSettings irmSettings    svc.IrmSettings;
irmSettings.IrmRMSEnabled    = true;
//set true or false based on the situation
irmSettings.IrmRMSUseAD      = true;
irmSettings.IrmRMSCertServer "certificate server here";
irmSettings.IrmChanges       irmSettings.IrmChanges + 1;
svc.Update();



Step2 Set the IRM properties for a document library

SPSite site = new SPSite("http:////");
SPList spList site.OpenWeb().Lists["list_name"];
SPFolder folder spList.RootFolder;
spList.IrmEnabled = true; //corresponds to "Restrict permission to documents in this library on download"
// BELOW SET=2, RESET=0
folder.Properties["vti_irm_IrmPrint"      2// Allow users to print documents
folder.Properties["vti_irm_IrmVBA"        2// Allow users to access content programmatically
folder.Properties["vti_irm_IrmOffline"    2// Users must verify their credentials every nOfflineDays
spList.IrmReject = true; // do not allow users to upload documents that do not support IRM
spList.IrmExpire = true; //sto[ restricting permissions to documents in this library on expiry date
folder.Properties["vti_irm_IrmOfflineDays"nOfflineDays
// integer representing number of days after which user needs to verify credentials
folder.Properties["vti_irm_IrmExpireDate" dtExpire.ToString("r", CultureInfo.InvariantCulture)
// date on which to stop restricting IRM permissions to documents
folder.Properties["vti_irm_IrmTitle"      "Permission Policy Title";
folder.Properties["vti_irm_IrmDescription""Permission Policy Description";
folder.Update();
spList.Update();

Phew! 

~harsh

TechReady4

I am attending TechReady 4 at the moment. If you are there as well, I would really like meeting up with you.

Reaching Seattle from India, was one heck of a journey. With more than 30 hours spent looking at the insides of a plane, we were lucky we didn't lose it, by the time we landed in Sea-Tac at midnight on Friday. Sessions started today morning, with some great enthusiastic pitches by Norm Judah and Steve Balmer on where Microsoft is heading in the near future.
As one would expect, the focus is on the new wave of products that's just been rolled out. With Vista and Office 2007 System, hitting retail a week ago, everyone's pretty excited about whats happening in the connected application platform space.
Again, given that we are looking at LongHorn server just round the corner, the objective as such is pretty much geared up towards making sure, that we as an organization are well oiled and the machinery is all smooth, in order to ensure that we can get amazing next-gen solutions out the door to our customers. All these products that just went retail are so well created, to fit together like, pieces of a giant jigsaw, the amount of solutions that can be created out of this jigsaw is phenomenally enormous to say the least.
TechReady by itself is a unique Microsoft platform, that brings together the entire gamut of people in customer facing environments together from sales, premier field engineers, MCS, product support, everyone is in here right now in Seattle.
As we said a week ago, the 'WOW' starts now!

Updates, updates, updates...

Right of the bat! All SKU's of Office 2007 client and server have shipped. Also, at the same time, the greatest and bestest OS ever has been shipped as well. This is aptly enabled with the "WOW" campaign for both the Office2007 suite as well as Vista.
Yaaayyyyy!


On another note, people with MSDN subscriptions can still download everything above from the downloads section.

Servers + SharePoint + SharePoint Server 2007 (617MB)

  • Office SharePoint Server 2007 Standard and Enterprise Editions (Arabic)
  • Office SharePoint Server 2007 Standard and Enterprise Editions (Dutch)
  • Office SharePoint Server 2007 Standard and Enterprise Editions (English)
  • Office SharePoint Server 2007 Standard and Enterprise Editions (French)
  • Office SharePoint Server 2007 Standard and Enterprise Editions (German)
  • Office SharePoint Server 2007 Standard and Enterprise Editions (Hebrew)
  • Office SharePoint Server 2007 Standard and Enterprise Editions (Italian)
  • Office SharePoint Server 2007 Standard and Enterprise Editions (Japanese)
  • Office SharePoint Server 2007 Standard and Enterprise Editions (Korean)
  • Office SharePoint Server 2007 Standard and Enterprise Editions (Polish)
  • Office SharePoint Server 2007 Standard and Enterprise Editions (Portuguese-Brazil)
  • Office SharePoint Server 2007 Standard and Enterprise Editions (Simplified Chinese)
  • Office SharePoint Server 2007 Standard and Enterprise Editions (Spanish)
  • Office SharePoint Server 2007 Standard and Enterprise Editions (Swedish)
  • Office SharePoint Server 2007 Standard and Enterprise Editions (Traditional Chinese)
  • Office SharePoint Server 2007 Standard and Enterprise Editions (Thai)

The English 180 day trial of Office SharePoint Server 2007 from download center is available here.

Office Forms Server 2007 (in Server)

  • Office Forms Server 2007 (Arabic)
  • Office Forms Server 2007 (Dutch)
  • Office Forms Server 2007 (English)
  • Office Forms Server 2007 (French)
  • Office Forms Server 2007 (German)
  • Office Forms Server 2007 (Hebrew)
  • Office Forms Server 2007 (Japanese)
  • Office Forms Server 2007 (Korean)
  • Office Forms Server 2007 (Italian)
  • Office Forms Server 2007 (Polish)
  • Office Forms Server 2007 (Portuguese-Brazil)
  • Office Forms Server 2007 (Swedish)
  • Office Forms Server 2007 (Thai)
  • Office Forms Server 2007 (Simplified Chinese)
  • Office Forms Server 2007 (Spanish)
  • Office Forms Server 2007 (Traditional Chinese)

No trial is available.  Download SharePoint Server Enterprise Trial here to evaluate Forms functionality.

Office SharePoint Designer (in Applications)

  • Office SharePoint Designer 2007 (Arabic)
  • Office SharePoint Designer 2007 (Dutch)
  • Office SharePoint Designer 2007 (English)
  • Office SharePoint Designer 2007 (French)
  • Office SharePoint Designer 2007 (German)
  • Office SharePoint Designer 2007 (Hebrew)
  • Office SharePoint Designer 2007 (Japanese)
  • Office SharePoint Designer 2007 (Korean)
  • Office SharePoint Designer 2007 (Italian)
  • Office SharePoint Designer 2007 (Polish)
  • Office SharePoint Designer 2007 (Portuguese-Brazil)
  • Office SharePoint Designer 2007 (Swedish)
  • Office SharePoint Designer 2007 (Simplified Chinese)
  • Office SharePoint Designer 2007 (Spanish)
  • Office SharePoint Designer 2007 (Thai)
  • Office SharePoint Designer 2007 (Traditional Chinese-Taiwan)
  • Office SharePoint Designer 2007 - DVD (Traditional Chinese-Hong Kong SAR)

The 180 day English trial of Office SharePoint Designer 2007 is available from download center here.


Servers + SharePoint + SharePoint Server 2007 for Search

  • Office SharePoint Server 2007 for Search Standard and Enterprise Editions (German)
  • Office SharePoint Server 2007 for Search Standard and Enterprise Editions (English)
  • Office SharePoint Server 2007 for Search Standard and Enterprise Editions (Japanese)

No trial is available.  Download SharePoint Server Standard or Enterprise trial here to evaluate Search functionality. 

ISO Instructions 
An ISO-9660 image file is an exact representation of the original installation media, including the content and the logical format. The most common use of an image file is to write it to a blank DVD Recordable disc resulting in an identical copy of the original DVD including file name and volume label information. ISO Images can also be extracted directly to a file location by many Recordable DVD utilities. For more information about image files, please visit the
MSDN FAQ.

MOSS AND MOM

Also we have released MOM packs for Office 2007

The MOSS 2007 MOM Pack is now RTM and you can download it here.  If you don't have it, we highly recommend the WSS 3.0 MOM Pack as well.

Overview

This Management Pack quickly brings any failures or configuration problems to your attention, which increases the availability and performance of Office SharePoint Server 2007. This Management Pack also provides the knowledge and expertise you need to leverage MOM 2005 and get an immediate return on your investment.


Feature Summary:
This Management Pack alerts you about the following critical conditions:
• Shared Services Provider (SSP) provisioning failed
• Site Directory scan job failed
• Enabling features failed on some sites
• Administration site for the SSP is missing
• Enabling features on existing sites failed
• The Office SharePoint Server Search service is not running
• The Microsoft Single Sign-On service is not running
• The Office Document Conversions Launcher service is not running
• Failed to connect to parent server farm
• SSP synchronization failed
• The Office Document Conversions Load Balancer service is not running
• Failures in content deployment jobs
• Poor cache performance
• Error during document copy or move operations
• Errors with the Information Rights Management (IRM) features
• Failures in the Document Conversion feature
• Out of Memory exceptions coming from form business logic
• Denial of Service scenarios
• Failures during form processing or while loading business logic assemblies

TELERIK R.A.D Cross Browser Rich Text Editor for SharePoint 2007 – public beta now available

Microsoft had earlier announced by way of the SharePoint product team blog that Telerik's cross browser rich text editor is the official r.a.d editor for SharePoint 2007 . this Web-based rich text editor extends the web content authoring environment of Office SharePoint Server 2007 by providing cross-browser compatibility (i.e. with Netscape 7.1+ and Mozilla 1.3 browsers) and support for the Macintosh platform (i.e. Safari browser). This special edition of Telerik's market leading editor offers the same functionality as SharePoint's native rich text editor and is provided by Telerik at no cost to all registered customers of Office SharePoint Server 2007.
This r.a.d.editor can be used in the following scenarios:

·         Rich text field control in a SharePoint List

·         Rich text editor Web Part

·         Web Content Management page

To get the public beta, go to
http://www.telerik.com/sharepoint.
For online Q&A and discussion, go to
http://www.sharepointcontrols.com/support/forums/forum/b3041S-btc.aspx.

Upgrade ToolKit for WSS2.0 Sites and Templates final release is now available

The upgrade toolkit for WSS2.0 Sites and Templates is finally out the door, and can be found here. This solution accelerator combines three components that will help you effectively plan and upgrade your custom sites and templates to function in a Windows SharePoint Services 3.0 environment. The first is a prescriptive guide that will walk you through the common steps of the upgrade process; the second, a set of scripts that will help you perform common Stsadm tasks in batch and sequential manner; and the third, a set of 63 upgraded 2.0 application templates for Windows SharePoint Services 3.0.

SharePoint Test Data Load tool

The SharePoint product team has just sanitized and posted a tool to help push sample data into SharePoint 2007 for load testing scenarios.
You can get it here : http://technet2.microsoft.com/Office/en-us/library/301ed832-95da-4251-b266-7be6288f7ea01033.mspx?mfr=true or
here: http://www.codeplex.com/sptdatapop or
here: http://www.codeplex.com/sptdatapop/Project/FileDownload.aspx?DownloadId=4702

Bear in mind that this is not an officially Microsoft released product and is a community supported tool. Please don't contact product support with any issues you may experience using the tool. 
This is the tool referred to on TechNet as the tool that was used for load testing by the SharePoint Performance test team at Microsoft.
From Codeplex workspace:
"The SharePoint test data population tool (WSSDW.exe) is a capacity planning and performance testing tool that populates data for testing SharePoint deployments. The SharePoint test data population tool is available as a command-line executable program that extracts information about how to populate the server from an XML configuration file, and calls Microsoft .NET assembly: WSSDWLib.dll. "

More updates as and when I receive them. Keep watching this space.

~Harsh


 

Custom Search and URL zones

It's a very common task with SharePoint to create a custom Search web part. The objective ranges from the very intuitive – need to change the search results display - to the very complex perform some complex queries that are not possible Out of the Box. For a large part, customizing the search behavior in Microsoft Office SharePoint Server 2007 is very similar to how it was done in SharePoint Portal Server 2003. The major difference however is how the Search behaves. Since a great deal of time and energy has been spent in completely rewriting the underlying search engine, the results are very obvious. If you have not yet seen the MOSS search behavior, I will suffice it to say that it's pretty close to SharePoint 2003 search on steroids.
For a large part, here's how a typical custom search would look like:

referencing Microsoft.Office.Server.Search and Microsoft.SharePoint.Search depending on whether its OSS or WSS.

//typical initalisation
Microsoft.Office.Server.Search.Query.Query query;
query = new Microsoft.Office.Server.Search.Query.FullTextSqlQuery(ServerContext.Current);
Microsoft.Office.Server.Search.Query.ResultTableCollection rsltTableColl;

//set some properties for the FullTextSqlQuery instance
query.ResultTypes |= Microsoft.Office.Server.Search.Query.ResultType.RelevantResultsl;
query.QueryText = "some query";
//and then execute the query
query.Execute();

This is a typical lab scenario. But something interesting happens when you execute this on an actual farm deployment. Consider a deployment architecture as follows:
You have web application on port 80 as contoso.com. So the root site collection on that web application will be http://contoso.com. Contoso decides that they want to expose the same web application on the intranet, extranet as well as internet zones. So the admin goes ahead and creates extended web applications on port 80 for different URL zones.
So now you have
contoso.com on the default zone
contoso-intra.com on the intranet zone
contoso-extra.com on the extranet zone.

Note that the root site collections will now be identified as
http://contoso.com
http://contoso-intra.com
http://contoso-extra.com
respectively.
Since it's an extended web application, the content is the same across all URL's though the URL's accessed would be different for each. The implicit advantage this offers is the ability to expose the same content to different sets of users that are authenticated using different authentication mechanisms. Now consider say that the custom search web part that you created earlier is deployed in such a scenario.
When a user fires a query on this custom query part, the query executes etc. No problems at all there. But look closer. If you hover over the hyperlinks for the individual items in the search results the URL's will actually be pointing to the URL corresponding to the default URL zone. This is not such a cool thing, since the user on the extranet does not need to know, what the actual content URL is.
Now, just to cover all bases, execute a similar query from the Search box that ships with SharePoint. Irrespective of the zone you are browsing from, the URL's for the search result items are properly structured. What is it that SharePoint is doing but we are not in our code?
PSS actually received a couple of calls on how to get past this seeming bug. For one, there are no articles online or even in the SDK at the moment that explain how this can be done. The answer popped up from a relatively uncanny place – how, SharePoint implements Search.

Solution: Internally, there is a seemingly incongruous property that's being set to get past this weird problem. Now, for the record, the SDK does not glorify this property at all and if you use your favorite web search engine, there would be just a couple of lines describing what this does.

//typical initalisation
Microsoft.Office.Server.Search.Query.Query query;
query = new Microsoft.Office.Server.Search.Query.FullTextSqlQuery(ServerContext.Current);
Microsoft.Office.Server.Search.Query.ResultTableCollection rsltTableColl;

//set some properties for the FullTextSqlQuery instance
query.ResultTypes |= Microsoft.Office.Server.Search.Query.ResultType.RelevantResultsl;
query.QueryText = "some query";
SPSite site = SPControl.GetContextSite(HTTPContext.Current);
query.SiteContext = new Uri(site.Url);

//and then execute the query
query.Execute();

What is this doing? In essence it fetches the current site context from the HTTPContext and then specifies that the query executes under that specific context.

Solution delivered and issue resolved.

~harsh

 

Posted by Harshawardhan Chiplonkar | 0 Comments
Filed under:

Forms Based Authentication in MOSS

There have been a lot of great posts in the blogosphere on how to setup forms based authentication. Some of them:
SharePoint Product Group Blog by Steve Peschka
Nick Swan [non-MS]

What I want to put forth in this post, is a reference on the web.config changes that are required for various types of providers plus some tips on how to troubleshoot failures.

ASPNET SQL PROVIDER

- Connection String for local SQL
<membership defaultProvider="AspNetSqlMembershipProvider" />
<connectionStrings>
<remove name="LocalSqlServer" />
<add name="LocalSqlServer" connectionString="data source=127.0.0.1;Integrated Security=SSPI;Initial Catalog=aspnetdb" />
</connectionStrings>

- Connection String for Remote SQL
<connectionStrings>
<add name="SqlProviderConnection" connectionString="server=SQLSERVERMACHINE;database=aspnetdb;Trusted_Connection=True" />
</connectionStrings>

- Role Provider XML
<roleManager enabled="true" defaultProvider="AspNetSqlRoleProvider">
<providers>
<remove name="AspNetSqlRoleProvider" />
<add connectionStringName="LocalSqlServer" applicationName="/"
description="Stores and retrieves roles data from the local Microsoft SQL Server database" name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider, System.Web, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</providers>
</roleManager>

- Membership Provider XML
<membership defaultProvider="AspNetSqlMembershipProvider">
<providers>
<remove name="AspNetSqlMembershipProvider" />
<add connectionStringName="SqlProviderConnection" passwordAttemptWindow="10" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="true" applicationName="/" requiresUniqueEmail="false" passwordFormat="Hashed" description="Stores and retrieves membership data from the Microsoft SQL Server database" name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</providers>
</membership>

Office Server LDAP

Membershipprovider XML

<membership defaultProvider="PeopleDCLDAPMembership">
<providers>
<add name="PeopleDCLDAPMembership" type="Microsoft.Office.Server.Security.LDAPMembershipProvider, Microsoft.Office.Server.LDAPProvider, Version=12.0.0.0, Culture=neutral, PublicKeyToken=94de0004b6e3fcc5" server=[server name as string] port="389" useSSL="false" userDNAttribute="distinguishedName" userNameAttribute="sAMAccountName" userContainer="OU=UserAccounts,DC=[fqdnstringpart],DC=[fqdnstringpart],DC=[fqdnstringpart],DC=com" userObjectClass="person" userFilter="(&amp;(ObjectClass=person))" scope="Subtree" otherRequiredUserAttributes="sn,givenname,cn" />
</providers>
</membership>

Roleprovider XML

<roleManager defaultProvider="PeopleDCLDAPRole" enabled="true" cacheRolesInCookie="true" cookieName=".PeopleDCRole">
<providers>
<add name="PeopleDCLDAPRole" type="Microsoft.SharePoint.Security.LDAPRoleProvider, Microsoft.SharePoint.LDAPProvider, Version=12.0.0.0, Culture=neutral, PublicKeyToken=94de0004b6e3fcc5" server=[server name as string] port="389" useSSL="false" groupContainer="OU=UserAccounts, DC=[fqdnstringpart],DC=[fqdnstringpart],DC=[fqdnstringpart],DC=com" groupNameAttribute="sAMAccountName" groupMemberAttribute="uniquemember" userNameAttribute="sAMAccountName" dnAttribute="CN" groupFilter="(&amp;(ObjectClass=group))" scope="Subtree" />
</providers>
</roleManager>

WebSSO (ADFS)
- Modification to the Web Application Web.config

<sectionGroup name="system.web">
<section name="websso" type="System.Web.Security.SingleSignOn.WebSsoConfigurationHandler, System.Web.Security.SingleSignOn, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, Custom=null" />
</sectionGroup>

<add key="SingleSignOnMembershipProvider" value="" />

<add name="Identity Federation Services Application Authentication Module" type="System.Web.Security.SingleSignOn.WebSsoAuthenticationModule, System.Web.Security.SingleSignOn, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, Custom=null" />

<trust level="Full" originUrl="" />

Membership provider

<membership defaultProvider="SingleSignOnMembershipProvider">
<providers>
<add name="SingleSignOnMembershipProvider" type="System.Web.Security.SingleSignOn.SingleSignOnMembershipProvider, System.Web.Security.SingleSignOn, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" fs="https://fs-server/adfs/fs/federationserverservice.asmx" />
</providers>
</membership>

Role provider

<roleManager enabled="true" defaultProvider="SingleSignOnRoleProvider">
<providers>
<add name="SingleSignOnRoleProvider" type="System.Web.Security.SingleSignOn.SingleSignOnRoleProvider, System.Web.Security.SingleSignOn, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" fs="https://fs-server/adfs/fs/federationserverservice.asmx" />
</providers>
</roleManager>

<websso>
<authenticationrequired />
<auditlevel>55</auditlevel>
<urls>
<returnurl>https://servername</returnurl>
</urls>

<cookies Persistent="True">
<path>/</path>
</cookies>

<fs>https://fs-server/adfs/fs/federationserverservice.asmx</fs>
<!-- usettp / -->
<isSharePoint />
</websso>

- Modification to the Central Administration web application web.config

Membership Provider
<membership>
<providers>
<add name="SingleSignOnMembershipProvider" type="System.Web.Security.SingleSignOn.SingleSignOnMembershipProvider, System.Web.Security.SingleSignOn, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" fs="https://fs-server/adfs/fs/federationserverservice.asmx" />
</providers>
</membership>


Role Provider
<roleManager enabled="true" defaultProvider="AspNetWindowsTokenRoleProvider" >
<providers>
<remove name="AspNetSqlRoleProvider"/>
<add name="SingleSignOnRoleProvider" type="System.Web.Security.SingleSignOn.SingleSignOnRoleProvider, System.Web.Security.SingleSignOn, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" fs="https://fs-server/adfs/fs/federationserverservice.asmx" />
</providers>
</roleManager>

ASPNET Active Directory Provider

Connection string
<connectionStrings>
<add name="ADConnectionString" connectionString="LDAP://[domainname]/OU=UserAccounts, DC=[fqdnstringpart],DC=[fqdnstringpart],DC=com" />
</connectionStrings>

Membership Provider
<membership defaultProvider="AspNetActiveDirectoryMembershipProvider">
<providers>
<add name="AspNetActiveDirectoryMembershipProvider" type="System.Web.Security.ActiveDirectoryMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="ADConnectionString" enableSearchMethods="true" attributeMapUsername="sAMAccountName" />
</providers>
</membership>

Thanks to DW for compiling this list

OVERVIEW AND TROUBLESHOOTING


A lot of us who have played with Forms based Authentication with Microsoft Office SharePoint Server 2007 would know, that the steps for setting it up are fairly simple, however, if and when something does go wrong, finding it out is really a mess. Here's something that can help do so some basic troubleshooting:
A thumb rule to look for is, when you browse to the Login page, and the page loads without the CSS, then definitely something has gone amiss. That's the first clue. After this, it is many a times a mind game. The question that comes up is why is it so difficult to figure it out? A lot of people have asked me as to why there wasn't any logging or error handling implemented from within SharePoint to make it easier to troubleshoot Forms Based Authentication? The answer lies in understanding how SharePoint implements FBA.

As you can see from the flow diagram above, the bulk of the action happens within .NET Framework. From a SharePoint perspective the request to login (when you click the Login button) just sends the user credentials entered in the Login web control (yeah, we use that on the default login page!) to the Provider. Obviously, prior to this, the framework has already swung into action and prepped the environment by loading the Provider assembly based on the entries made in the web.config file. There are a whole bunch of problems that you can run into at this level. Let's take them one by one:

1. The assembly does not get loaded. The page displays File Not Found.
This is a classic in itself. There are multiple reasons for this to occur. The manifestation of this problem is a simple "File Not Found" string displayed in the browser window. By itself this does not tell much. If you do venture out and enable call stacks and turn on the debug flags in the web.config (refer the debugging explanation @ http://msdn2.microsoft.com/en-us/library/ms916837.aspx ), then you will see the error being generally thrown from a System.Reflection call on the provider assembly.
One solution that works is to check the name of the provider that is registered in the web.config. If you are using OOB providers, then obviously this does not apply. This solution works for custom providers. Why this causes a problem, is the reflection makes a call to the provider for loading. There is a overridden property within the provider called Name. If this has not been implemented properly to get/set the value specified in the web.config, then the framework keeps looking for the provider with a different name than the one that is actually returned from within the assembly.
Another solution that works, is running the Fusion Log Viewer, to make a note of the location the framework is looking for the provider assembly.
http://msdn2.microsoft.com/en-us/library/e74a18c4(VS.80).aspx
Closely looking at the log, generally reveals the location of the ASP.NET cache. Clearing this cache, will most likely solve the problem.

2. The browser displays the message "Default membership provider could not be found"
To solve this, check the web.config, for the value of the defaultProvider there. Then browse to the IIS manager, and open the property sheet for the web site corresponding to the web application throwing the error. Crack open the ASP.NET configuration settings. Under Authentication, take a look at the default provider. Due to some weird framework calls, the default provider gets reset to AspNetSqlMembershipProvider. Change it back to the correct one.

If you have seen these errors and have a solution that you vouch by, then I would like to hear about it. More interestingly, if you have seen errors other than these, I would like to hear about those too.
For others, if these don't solve the problem, contact your friendly neighborhood MS support guy.

~harsh

Posted by Harshawardhan Chiplonkar | 17 Comments
Filed under: ,

Some random issues with Beta 2 Technical Refresh of MOSS 2007

Its been quite some time since the B2TR builds for Microsoft Office SharePoint Server 2007 were released. The builds have been released as patches and the general upgrade experience has been something that has helped us learn a lot about upgrades and patching scenarios. Amongst all the scenarios that we have seen there have been some that have been dominant in nature and affected a large number of users while there were some that are the on-off types and occurring in an essentially random manner. In this post I would be talking about some that have been very erratic and have had a significant impact:

 

------------
ISSUE: Beta2 to Beta2 TR upgrade fails with a MSI error.
ERROR: The installation of this package failed. Please see for more information." with the error code 1603
EVIDENCE: Navigate to the %temp% directory, the Windows Installer logs would show a error as follows:

Product: Microsoft Windows SharePoint Services 3.0 -- Error 1406. Setup cannot write the value QMEnable to the registry key \Software\Microsoft\Shared Tools\Web Server Extensions\12.0\WSS\Diagnostics. Verify that you have sufficient permissions to access the registry or contact Microsoft Product Support Services (PSS) for assistance. For information about how to contact PSS, seePSS10R.CHM.

 

RESOLUTION:

- Open the Registry Editor [Start->Run->regedit].

- Navigate to HKLM\Software\Microsoft\Shared Tools\Web Server Extensions\12.0\WSS\Diagnostics

- Right Click, select New ->DWORD Value. Change the name to 'QMEnable' without the quotes.

- Change the value to 0

 

ROOT CAUSE:

This error is misleading to say the least. The error reported in the log files is about permissions, however, the patch installer searches the registry for the key QMEnable and does not seem to find it. However, it will also find that the component requiring this registry key is installed and hence will try to repair the installation. But in order to do so, it will try to use the value for this key from the registry which in the first place was not there. And hence the failure.

 

-------------

-------------

-------------

 

 

 

ISSUE: Errors in the application event log.

ERROR:

ProblemDescription:    Event Type:    Error

Event Source:        DCOM

Event Category:        None

Event ID:        10016

Date:     <somedate>

Time:        <sometime>

User:        <domain\username>

Computer:        <computername>

Description:

The application-specific permission settings do not grant Local Activation permission for the COM Server application with CLSID

{61738644-F196-11D0-9953-00C04FD919C1}

to the user <domain\username> SID (X-X-X-XX-XXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX-XXXXX). This security permission can be modified using the Component Services administrative tool.

For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.

 

RESOLUTION:

  • Navigate to Start->Control Panel->Administrative Tools->Component Services
  • Under Console Root, navigate to Component Services->Computers->My Computer->DCOM Config.
  • Right click IIS WAMREG Admin service and select properties
  • In the Property pane, switch to the Security tab.
  • Click Edit on the Launch and Activation Permissions section and you should see that only administrators and service have rights here. Add your service account in here as well to match the admin rights and those errors should go away.

     

-------------

-------------

-------------

 

 

 

ISSUE: Enabling BDC with SSO authentication, throws the following error.

ERROR:

Exception thrown while performing the BDC query in Entity Picker Microsoft.Office.Server.ApplicationRegistry.MetadataModel.InvalidMetadataPropertyException: The Type name for the single sign-on provider is not valid. ---> System.TypeLoadException: Could not load type 'Microsoft.SharePoint.Portal.SingleSignOn.SpsSsoProvider' from assembly 'Microsoft.SharePoint.Portal.SingleSignOn, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c'.     at System.RuntimeTypeHandle._GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark, Boolean loadTypeFromPartialName)     at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark)     at Sys...

 

RESOLUTION:

The xml tags in the BDC xml file are case sensitive and there was a recent update to the assembly type names. So you would need to replace the tag

<Property Name ="SsoProviderImplementation" Type="System.String">Microsoft.SharePoint.Portal.SingleSignOn.SpsSsoProvider, Microsoft.SharePoint.Portal.SingleSignOn, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Property>

To read as:

<Property Name ="SsoProviderImplementation" Type="System.String">Microsoft.SharePoint.Portal.SingleSignon.SpsSsoProvider, Microsoft.SharePoint.Portal.SingleSignon, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Property>

 

 

~Harsh

Blogged with Microsoft® Office® Word 2007 Beta2 TR

 

 

 

Adding a List Item inside a folder

As with v2, v3 also has seen its fair share of requests on how you can add an item to a folder in a list. Now, there are two types of lists that we are dealing with, lists that store documents and lists that store items. Internally they are identified by the list type which can be a DocumentLibrary or a GenericList. Actually the enumeration is quite huge, but these are the two values that we are concerned with. Both these types of lists can have folders and these folders can have items in them. Adding items to the folders though the UI is pretty straight forward. On the other hand, doing the same through code is a bit tricky. The SDK documents it to an extent but that is not very clear.

Adding a document to a folder in a document library is the simplest

 

SPSite site = new SPSite("http://blr3r01-13:10000");

SPWeb web = site.OpenWeb();

SPList list = web.Lists["Documents"];

SPListItemCollection folderColl = list.Folders;

foreach (SPFolder folder in folderColl)

{

if (folder.Name == "TestFolder")

{

SPFileCollection fileColl = folder.Files;

// Use fileColl.Add() to upload the file

}

}

 

Adding an item to a folder for a generic list took me some time to figure out. The point where I got mislead was believe it or not a missing '/' character. There were a number of things I tried in getting to the SPListItemCollection representing the items inside a folder. However, all attempts at getting there ended up in recurrent loops [sic]. The simplest approach was of course using the SPListItemCollection.Add(). The moment I finally obtained that collection, from there on it took me several tries to get the actual syntax right. So here's the polished up code.

 

SPSite site = new SPSite("http://blr3r01-13:10000");

SPWeb web = site.OpenWeb();

SPList list = web.Lists["Tasks"];

SPListItemCollection folderColl = list.Folders;

for (int i = 0; i < folderColl.Count; i++)

{

if (folderColl[i].Folder.Exists)

{

SPFolder folder = folderColl[i].Folder;

SPListItemCollection itemColl = list.Items;

SPListItem item = itemColl.Add("/Lists/Tasks/TestFolder", SPFileSystemObjectType.File, null);

item["Title"] = "AddedFromOM";

item.Update();

}

}

 

All in a day's work.

 

Cheerio

/Harsh

 

 

Blogged using Microsoft Office Word 2007 running on Microsoft Vista

        

Copying publishing site pages

Publishing sites are just WSS sites with a special template. Though there is a separate namespace to help with the feature light-up specific to publishing sites. A very trivial scenario would be copying a page from a library, say the Pages library in a publishing site to say a Pages library in another Publishing site. For the sake of theory, let's consider that both the sites are part of the same site collection.

Looking at the SDK the obvious choice would have been churning out a piece of code that looked like:

 

SPSite site = new SPSite("http://MOSS");

PublishingSite psite = new PublishingSite(site);

PublishingWeb pweb = PublishingWeb.GetPublishingWeb(site.RootWeb);

PublishingPageCollection ppages = pweb.GetPublishingPages();

foreach (PublishingPage ppage in ppages)

{

if (ppage.Name == "Default.aspx")

{

ppage.ListItem.CopyTo("http://MOSS/PressReleases/Pages/" + ppage.Name);

pweb.Update();

}

}

 

This is what I would have agreed to as well. Until a very interesting behavior was brought to my attention. When the above code is executed, the file gets copied over as one would expect, however, what does not get copied over is the associated details such as the master page, the content types etc. In order to get a deep-copy so to speak one would need to get to the underlying SPFile objects and the code would in general look like:

 

SPSite site1 = new SPSite("http://blr3r01-13:20000");

SPSite site2 = new SPSite("http://blr3r01-13:20000/subsite1");

SPWeb web1 = site1.OpenWeb();

SPWeb web2 = site2.OpenWeb();

 

PublishingWeb pubWeb = PublishingWeb.GetPublishingWeb(site1.RootWeb);

PublishingPageCollection pubpageCollection = pubWeb.GetPublishingPages();

foreach(PublishingPage pubPage in pubPageCollection)

{

if(pubPage.Name == "SomePage.aspx"

{

SPFile file = web1.GetFile(pubPage.Url);

Byte[] binFile = file.OpenBinary();

string filename = file.Name;

 

SPFolder destFolder = web2.GetFolder("Pages");

if(destFolder != null)

{

file.CheckOut();

destFolder.Files.Add(filename, binFile, true);

file.CheckIn("temp");

file.Approve("temp");

}

foreach(SPFile destFile in destFolder.Files)

{

if(destFile.Name == filename)

{

destFile.Approve("temp");

}

}

}

}

 

With this you are all set to go.

 

-Harsh

Lists Web Service - I

As with SPS 2003, MOSS ships with some default web services as well. Most of them have been carried over from SPS 2003, whereas there are some that are newly introduced.
The Lists webservice offers some interesting functions to perform remote operations on the lists in a site collection. Some of the web methods that are exposed are:

  • AddAttachment ( listName As string , listItemID As string , fileName As string , attachment As base64Binary ) As string
  • AddDiscussionBoardItem ( listName As string , message As base64Binary )
  • AddList ( listName As string , description As string , templateID As int )
  • AddListFromFeature ( listName As string , description As string , featureID As guid , templateID As int )
  • ApplyContentTypeToList ( webUrl As string , contentTypeId As string , listName As string )
  • CheckInFile ( pageUrl As string , comment As string , CheckinType As string ) As boolean
  • CheckOutFile ( pageUrl As string , checkoutToLocal As string , lastmodified As string ) As boolean
  • CreateContentType ( listName As string , displayName As string , parentType As string , fields As , contentTypeProperties As , addToView As string ) As string
  • DeleteAttachment ( listName As string , listItemID As string , url As string )
  • DeleteContentType ( listName As string , contentTypeId As string )
  • DeleteContentTypeXmlDocument ( listName As string , contentTypeId As string , documentUri As string )
  • DeleteList ( listName As string )
  • GetAttachmentCollection ( listName As string , listItemID As string )
  • GetList ( listName As string )
  • GetListAndView ( listName As string , viewName As string )
  • GetListCollection ( )
  • GetListContentType ( listName As string , contentTypeId As string )
  • GetListContentTypes ( listName As string , contentTypeId As string )
  • GetListItemChanges ( listName As string , viewFields As , since As string , contains As string )
  • GetListItemChangesSinceToken ( listName As string , viewName As string , query As , viewFields As , rowLimit As string , queryOptions As , changeToken As string , contains As string )
  • GetListItems ( listName As string , viewName As string , query As , viewFields As , rowLimit As string , queryOptions As , webID As string )
  • GetVersionCollection ( strlistID As string , strlistItemID As string , strFieldName As string )
  • UndoCheckOut ( pageUrl As string ) As boolean
  • UpdateContentType ( listName As string , contentTypeId As string , contentTypeProperties As , newFields As , updateFields As , deleteFields As , addToView As string )
  • UpdateContentTypesXmlDocument ( listName As string , newDocument As string )
  • UpdateContentTypeXmlDocument ( listName As string , contentTypeId As string , newDocument As string )
  • UpdateList ( listName As string , listProperties As , newFields As , updateFields As , deleteFields As , listVersion As string )
  • UpdateListItems ( listName As string , updates As string )

Of these the last two might be the ones seeing the most usage. UpdateList and UpdateListItems, both are extremely handy when adding, modifying or deleting columns (in the case of the former) and list items (in the case of the latter). The SDK documents the usage of both but it does seem that there can be quite a few pitfalls while actually implementing these. Here are some examples:
I am using the UpdateListItems here as this is the easiest 
Creating the lists web service reference and initializing all data required for making the actual call.

PostLists.Lists lst = new TESTBED.PostLists.Lists();

lst.Credentials = System.Net.CredentialCache.DefaultCredentials;

// Adding a new Item in this case a folder
string strBatch = "<method id='1' Cmd='New'>" +
                  "<Field Name='ID'>New</Field>" +
                  "<Field Name='FSObjType'>1</Field>" +
                  "<Field Name='BaseName'>testFolder</Field>" +
                  "</Method>";
XmlDocument doc =
new XmlDocument();
XmlElement el = doc.CreateElement("Batch");
XmlElement properties = doc.CreateElement("listproperties");
properties.InnerXml = "";
XmlElement newFields = doc.CreateElement("newFields");

XmlElement updateFields = doc.CreateElement("updateFields");
updateFields.InnerXml = "";
XmlElement deleteFields = doc.CreateElement("deleteFields");
deleteFields.InnerXml = "";

el.SetAttribute("OnError", "Continue");
el.SetAttribute("ListVersion", "0");
el.SetAttribute("PreCalc", "TRUE");
el.SetAttribute("ViewName", "{4A163CCB-3CE7-40B1-9EB5-A9568F355E3D}");
el.InnerXml = strBatch;

// the actual call
System.Xml.XmlNode node = lst.UpdateListItems("Documents", el);
MessageBox.Show(node.OuterXml);

Now let's look at the UpdateList webmethod. This is a bit complicated. So if you dont get it right the first time try try till you get it working! Hell no, just kidding.

Setting the environment:

 

PostLists.Lists lst = new TESTBED.PostLists.Lists();
lst.Credentials = System.Net.CredentialCache.DefaultCredentials;

XmlNode ndList = lst.GetList("ASampleList");
XmlNode ndVersion = ndList.Attributes["Version"];

XmlDocument xmlDoc = new System.Xml.XmlDocument();
XmlNode ndDeleteFields = xmlDoc.CreateNode(XmlNodeType.Element,"Fields", "");
XmlNode ndProperties = xmlDoc.CreateNode(XmlNodeType.Element, "List","");
XmlAttribute ndTitleAttrib = (XmlAttribute)xmlDoc.CreateNode(XmlNodeType.Attribute,"Title", "");
XmlAttribute ndDescriptionAttrib =(XmlAttribute)xmlDoc.CreateNode(XmlNodeType.Attribute,"Description", "");
XmlNode ndNewFields = xmlDoc.CreateNode(XmlNodeType.Element,"Fields", "");
XmlNode ndUpdateFields = xmlDoc.CreateNode(XmlNodeType.Element,"Fields", "");

ndTitleAttrib.Value = "RobinSannerList";
ndDescriptionAttrib.Value = "New_Description";

ndProperties.Attributes.Append(ndTitleAttrib);
ndProperties.Attributes.Append(ndDescriptionAttrib);

Creating a new field:

ndNewFields.InnerXml = "<Method ID='1'>" +
                       "<Field Type='DateTime' DateOnly='TRUE' DisplayName='A_New_Test_Field' FromBaseType='TRUE' Required='TRUE' Description='sometextdescription'/>" +
                       "</Method>";

Making the call:

try
{
           XmlNode ndReturn =
           lst.UpdateList("{18D0E90B-20B9-4931-96EB-5435D08532DC}",
                           ndProperties, ndNewFields, null , null,
                           ndVersion.Value);
           MessageBox.Show(ndReturn.OuterXml);
}

catch (Exception ex)
{
           MessageBox.Show("Message:\n" + ex.Message + "\nStackTrace:\n" + ex.StackTrace);

}

Updating the field:

ndUpdateFields.InnerXml = "<Method ID='2'>" +
                          "<Field Type='DateTime' Name='A_New_Test_Field' DisplayName='SomeNewName'/>" +
                          "</Method>";

Making the call:

try
{
           XmlNode ndReturn =
           lst.UpdateList("{18D0E90B-20B9-4931-96EB-5435D08532DC}",
                           ndProperties, null, ndUpdateFields, null,
                           ndVersion.Value);
           MessageBox.Show(ndReturn.OuterXml);
}

catch (Exception ex)
{
           MessageBox.Show("Message:\n" + ex.Message + "\nStackTrace:\n" + ex.StackTrace);
}

Deleting the Field:

ndDeleteFields.InnerXml = "<Method ID='3'>" +
                          "<Field Name='SomeNewName'/></Method>";

Making the call:

try
{
           XmlNode ndReturn =
           lst.UpdateList("{18D0E90B-20B9-4931-96EB-5435D08532DC}",
                           ndProperties, null, null, ndDeleteFields,
                           ndVersion.Value);
           MessageBox.Show(ndReturn.OuterXml);
}

catch (Exception ex)
{
           MessageBox.Show("Message:\n" + ex.Message + "\nStackTrace:\n" + ex.StackTrace);
}

Of course all is not so rosy while you are doing this and there are some issues that have been trudging along since SPS2003. More on this in the next post.

-Harsh

More Posts Next page »
 
Page view tracker