More servicesWindows Live
HomeHotmailSpacesOneCare
 
MSN
Sign in
 
 
Spaces home  Itay's spaceProfileFriendsBlogMore Tools Explore the Spaces community

Blog

June 01

Blog moved

I'm happy to announce that this blog has moved to a new location:
 
The move was done mainly because of the limitations of the Spaces environment - mainly, not having the option to add scripts to the blog. This limitation prevents using services such as web statistics, advertising, Digg (and family), etc.
 
You are also welcome to visit my new site at:
April 28

SharePoint 2007 Web Folders

I've been working with SharePoint 2007 for so long now on my office desktop and laptop, that it seems that I don't remember some of the SharePoint 2007 requirements. Working on a fresh virtual machine that has WSS 3.0 installed and running, I've tries to open a Pages Library as a Web Folder. The result was a nice error message telling me "Your client does not support opening this list with Windows Explorer." This seemed a bit strange, since I'm working on the SharePoint server itself, which is a fully updated Windows Server 2003 (all patch and updates installed), and I'm browsing using Internet Explorer 7 (again, fully updated).

After googling a bit, it seems the resolution was hidden in a forum with a link on page 2 of Google. The topic forwarded me to the following Microsoft page: Software Update for Web Folders (KB907306)

I'm not sure if I should say that this update should come as part of the Windows Update or not, but I'm sure glad I've found this!

February 01

User friendly file size

Based on a utility method found in the Microsoft.SharePoint.Utilities.SPUtility class, here's a method to get a user-friendly text for a file size:

public static string FormatSize(long cbSize)
{
    double num;
    if (cbSize <= 1024L)
    {
        if (cbSize <= 0L)
        {
            return string.Format("{0} KB", "0");
        }
        return string.Format("< 1 KB");
    }
    if (cbSize <= 1048576L)
    {
        num = Math.Round((double)(Convert.ToDouble(cbSize) / 1024.0), 1);
        return string.Format("{0} KB", num);
    }
    if (cbSize <= 1073741824L)
    {
        num = Math.Round((double)(Convert.ToDouble(cbSize) / 1048576.0), 1);
        return string.Format("{0} MB", num);
    }

    if (cbSize <= 1099511627776L)
    {
        num = Math.Round((double)(Convert.ToDouble(cbSize) / 1073741824.0), 1);
        return string.Format("{0} GB", num);
    }

    num = Math.Round((double)(Convert.ToDouble(cbSize) / 1099511627776.0), 1);
    return string.Format("{0} TB", num);
}
January 29

Utility classes: Negative arrays

Playing around with Lutz Roeder's .Net Reflector, I came across a very simple implementation of a "negative" array inside the Microsoft.SharePoint.Utilities namespace: NegativeArray. This class allows you to work with a "two-way" array: Creating a NegativeArray of size 10, you will have an array, with indices ranging from -10 to 10.

Where's the class implementation:

 

public class NegativeArray
{
    private int[] negative;
    private int[] positive;

    public NegativeArray(int maxIndex)
    {
        this.positive = new int[maxIndex + 1];
        this.negative = new int[maxIndex];
    }

    public NegativeArray(int maxIndex, NegativeArray source)
    {
        this.positive = new int[maxIndex + 1];
        this.negative = new int[maxIndex];
        for (int i = -source.MaxIndex; i <= source.MaxIndex; i++)
            this[i] = source[i];
    }

    public int this[int index]
    {
        get
        {
            if ((index >= 0) && (index <= this.MaxIndex))
                return this.positive[index];

            if (index < -this.MaxIndex)
                throw new ArgumentOutOfRangeException();

            return this.negative[-index - 1];
        }
        set
        {
            if ((index >= 0) && (index <= this.MaxIndex))
                this.positive[index] = value;
            else
            {
                if (index < -this.MaxIndex)
                    throw new ArgumentOutOfRangeException();

                this.negative[-index - 1] = value;
            }
        }
    }

    public int MaxIndex
    {
        get
        {
            return (this.positive.Length - 1);
        }
    }
}

MIME Types and File Extensions

Whenever working with content of files, it is often useful to have a way to find the MIME type based on a file extension, or the other way around - finding the file extension from a MIME type. Below are 2 useful methods for such requirements:

public static string GetExtensionFromMime(string mimeType)
{
    try
    {
        RegistryKey key = Registry.ClassesRoot.OpenSubKey(@"Mime\Database\Content Type\" + mimeType);
        if (key == null)
            return null;

        string str = key.GetValue("Extension") as string;
        if (string.IsNullOrEmpty(str))
            return string.Empty;
        
        return str;
    }
    catch
    {
        return string.Empty;
    }
}

public static string GetMimeFromExtension(string ext)
{
    if (!ext.StartsWith("."))
        ext = "." + ext;
    RegistryKey key = Registry.ClassesRoot.OpenSubKey(ext);
    if (key == null)
        return null;

    return key.GetValue("Content Type") as string;
}
November 19

Don't name the URL for a sub-site 'CON' in MOSS 2007 - mindykelly's blog

Now, I'm not the best person to speak about documentation and openness is code and products, but every now and then I find myself raising an eyebrow about someone else's behavior:

Don't name the URL for a sub-site 'CON' in MOSS 2007 - mindykelly's blog

I don't complain that Microsoft don't allow the "CON" as the URL of a WSS/MOSS site. But people, how about making this a public knowledge. How about putting up a one-stop repository for all SharePoint limitation and restrictions?

Among the many sites that Microsoft pops-up every other week, I'd love to see a site that centralize all the information about naming convention and limitations in SharePoint. Starting from the list of invalid characters for any type of items, list of "illegal" endings (_files, -files, etc), invalid names and so on...

October 02

SharePoint Associated groups

When you create a new sub-site in SharePoint, and choose the "Use Unique Permissions" option, three groups are created at the site-collection level: Owners, Members & Visitors. These groups are "associated" to the sub-site that you've just created.

But what does "associated" actually mean?

First, I misled you a bit - the names of the groups are actually SiteName Owners, SiteName Members & SiteName Visitors (where SiteName is the name of the sub-site you're creating). Next they all have a nice link in their description, directing you to the sub-site.

More interesting, those three groups get some permissions on the sub-site.

The less obvious "associations" are the fact that those groups will appear in the Quick Launch area when you go to the "People and Groups" section of the site. Also, if you delete the sub-site, the groups will be removed from the site-collection.

That's quite a lot of meaning for a single word.

Let look a bit deeper into each meaning:

Title & Description:

This is just some basic naming policy used by SharePoint. The SiteName is validated, the group type is appended, the description is generated with a link. Nothing fancy here.

Permissions:

The permissions are obtained by assigning permission levels to each group. Again, nothing too interesting.

Quick Launch:MOSS_SetUpGroups

The list of groups that appear in the Quick Launch is retained in the AssociatedGroups property of the SPWeb. This list can also be updated by modifying the vti_associategroups key in the AllProperties property of SPWeb.

Setting a group as the AssociatedMemberGroup, AssociatedVisitorGroup or AssociatedOwnerGroup automatically adds the group to the list of AssociatedGroups. These properties can be also updated by modifying the vti_associatemembergroup, vti_associatevisitorgroup & vti_associateownergroup keys in the AllProperties property of SPWeb.

These three properties are also reflected in the "Set up Groups" page of the sub-site.

Auto deletion:

This issue is a bit more complex. When using the SharePoint UI, or when calling CreateDefaultSharePointGroups methods of SPWeb, this behavior is implemented automatically. However, creating a group, and even associating it with a site, doesn't reproduce it. Only after using Lutz Roeder's .Net Reflector, and examining the CreateDefaultSharePointGroups method, I've found that you need to add the group's ID to the vti_createdassociategroups key in AllProperties.

October 01

SqlCE doesn't support TRUNCATE TABLE

Not long ago, I modified a piece of code to use SqlCE as a data store. The older code was using OleDb to access an MS Access file.

As part of the modifications, our team did a general overview of much of the data access code. We did many changes, more than I can even number. Here is a partial list:

  • Review of table keys, indices and restrictions.
  • Usage of IDbCommand instead of SQL string statements.
  • Removed legacy object model.
  • Replaced consecutive DELETE and INSERT statements with UPDATE.
  • and so on.

A few days ago, I noticed some delay in the data layer. This was nothing new - we process a huge amount of data - but since the many improvements, what used to be fast might now appear slow compared to the optimized code. After some search I've come up to a method that clears a many tables in the database. Something along the lines of:

using (IDbCommand cmd = DAL.GetClearTableCommand(tablename))
{
    // cmd.CommandText == "DELETE FROM " + tablename
    cmd.ExecuteNonQuery();
}

This of course, is nothing fancy or special. My thought was, instead of performing a DELETE statement, why not use the TRUNCATE TABLE statement, which is faster and more efficient. To my surprise, changing the GetClearTableCommand() method to return a TRUNCATE TABLE statement results in an parsing exception.

After some research, I've found that the TRUNCATE TABLE statement is not supported/implemented in SqlCE. Much to my disappointment, I will have to leave the DELETE statement in place, until I find a faster solution.

September 29

Allowing timeout on long-running operations - possible bug - Miscellaneous Debris

Avner Kashtan writes in his blog about an interesting problem, and solution, on how to run a long-running operation, with a timeout. The solution involves, obviously, running the code in a different thread. The possible bug is an unhandled exception in the different thread, which might kill the whole application process.

The suggested solution is to catch the exception in the running thread, and "passing the exception backward". This is possible thanks to the us of an anonymous delegate.

Although this is indeed, as mentioned in the post, an ugly solution, I find myself wondering what's the penalty of doing such a thing. Is the performance degraded so much? Is it such a horrible OOP crime?

Allowing timeout on long-running operations - possible bug - Miscellaneous Debris

August 23

Scot Hiller writes about the Tzunami Deployer

A couple of weeks ago Scot Hillier, Microsoft SharePoint MVP, wrote in his blog about our expected release of the Tzunami Deployer. Take a look at it here: Next Version of Tzunami Deployer

August 08

MOSS Documents Libraries naming policy

When you create a new Documents Library in MOSS, you are asked to provide a title for that Library. The provided title will be later used to define the internal name of the Library, as well as its URL. This is where the problems start.

It only makes sense that MOSS allows the user to enter any value for the Library's title. However, there are a lot of limitations on internal names, and even more on URLs. This result in MOSS doing some kind of encoding/validation on the title. The result might range from having the name exactly the same as the title, to the name being completely different and unrelated.

After some digging, I came up with the following logic:

For each char:
  if char is valid
    add it to URL
  if char is invalid
    if URL already ends with '_' (underscore)
      don't do anything
    else
      add '_' (underscore)

Strip '_' from beginning and end of URL

If URL is empty
  replace URL with a legal DocLibXXX value where XXX is a number

Invalid characters are the following:
1. Any character bellow 0x20
2. Any of the following characters: ~!@#$%^&*{}[]-=+\:"'|<>,?/.
3. Any character that takes more than 1 byte (Unicode and such)

 

Hopefully, this will save some other poor soul from losing his hair like I did.

August 02

Creating a user in Documentum

Here's 2 ways to create a user in Documentum:

Using the DQL:

create dm_cabinet object
set object_name = '%USERNAME%'
go

create dm_user object
set user_name = '%USER DISPLAY NAME%,
set default_folder = '/%USERNAME%',
set user_os_name = '%USERNAME%',
set user_privileges = %PRIVILEGES%',
set user_address = '%USER EMAIL%
go

Using the IAPI:

create,c,dm_user
set,c,l,user_name
set,c,l,user_os_name
set,c,l,user_address
save,c,l

ListViewGroup - only one item per group

As I was working on a new GUI part of the software I'm working on, I needed to allow the user to choose only a single item in each category. I overloaded the ListView control, and override the OnItemCheck method. Here's the result:

public class SingleItemPerGroupListView : ListView
{
    public SingleItemPerGroupListView()
    { }

    protected override void OnItemCheck(ItemCheckEventArgs ice)
    {
        // Always behave regulary when user uncheck an item
        if (ice.NewValue == CheckState.Unchecked)
        {
            base.OnItemCheck(ice);
            return;
        }

        // Get the checked item
        ListViewItem lvi = this.Items[ice.Index];

        // If no item has no group, handle regulary
        if (lvi.Group == null)
        {
            base.OnItemCheck(ice);
            return;
        }

        // If another item is checked, uncheck item
        foreach (ListViewItem otherLvi in lvi.Group.Items)
        {
            if (otherLvi == lvi)
                continue;

            if (otherLvi.Checked)
            {
                otherLvi.Checked = false;
            }
        }
    }
}

April 25

Comparison between the Deployer and another migration product

Jingmei Li, a Microsoft employee, did a comparison on her blog between the Tzunami Deployer 2.01, and DocAve 4.1 Migrator. 
February 15

Scot Hillier's "Microsoft SharePoint: Building Office 2007 Solutions in C# 2005"

Scot Hillier, on of the gurus of Microsoft SharePoint, just shipped his new book about Sharepoint solutions, entitles "Microsoft SharePoint: Building Office 2007 Solutions in C# 2005". As with the rest of Scot's book, this is definetly a must-read for all SharePoint administrators and developers. Scot is an independent consultant focused on SharePoint, the Microsoft Office System, and .NET technologies. Scot has authored eight books on Microsoft technologies over the last ten years, as well as numerous articles appearing in magazines and online.
January 02

Design Patterns Implementation in a Storage Explorer Application

Although a bit old, I found the well-written, interesting article by Breman Sinaga, Design Patterns Implementation in a Storage Explorer Application to be an excellente piece of work, explaining about several design patterns, such as Strategy, Observer, Adapter and Template Method, and showing how to corperate them all together. The result looks like a well designed, well thought-of, tool.
December 21

DebbugerDisplayAttribute

A little late, I know, but while watching the Channel 9: Scott Nonnenberg - Visualizers in VS 2005 webcast, I've learned the beauty of the DebuggerDisplayAttribute.
For those of you not familiar with this attribute, it allow you to choose how the tooltips inside the IDE while debugging will look like, and what values they will show you. Look at the following example:
 
[System.Diagnostics.DebuggerDisplay("Name={Name} ({Members.Count} members)")]
public class
Group
{
   
public string
Name;
   
public ArrayList Members = new ArrayList
();
}

Group
g = new Group();
g.Name =
"Administrators"
;
g.Members.Add(
"User1"
);
g.Members.Add(
"User2"
);
g.Members.Add(
"User3");
 
If you run your application, and have an instance of a Group, here's how it will look like when you'll place the mouse ove the instance:
 
Name="Aministrator" (3 members);
 
This is very usefull if you have instances of complex objects, and you'd like to shorten the time you spend understanding that's the data that you are currently debugging.
October 04

Tzunami at SharePoint Connections

The company that I work for, Tzunami Inc., which specialize in SharePoint migration, will exhibit in the SharePoint Connections conference at Las Vegas, on November 6-9 2006.
Be sure to visit us at booth #716 to see a live demonstration of our tool, the Tzunami Deployer.
September 16

Isolated storage

Although not a very technical, you should read the following article by Peter Aitken: Exploring .Net's Isolated Storage. The article doesn't go very deep, isn't very technical, and to tell the truth, I didn't find it a good read. However, it does provide a basic introduction to the very important subject of Isolated Storage.