12/19/2010

SharePoint: PowerShell Script to List All Users in All Groups

 

 

Here's a quick little PowerShell script to list all groups and all users. Note that if an AD group is listed as a user, all the users in that group may not show up in this list until the user has visited SharePoint at least once.

 

For both SharePoint 2007 or 2010 in any PowerShell:

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")

$site = New-Object Microsoft.SharePoint.SPSite("http://yourservername/sites/yoursitecollection ")

$groups = $site.RootWeb.sitegroups

foreach ($grp in $groups) {"Group: " + $grp.name; foreach ($user in $grp.users) {"  User: " + $user.name} }

$site.Dispose()

 

or for SharePoint 2010 in the SharePoint 2010 Management Shell:

$site = Get-SPSite http://yourservername/sites/yoursitecollection 

$groups = $site.RootWeb.sitegroups

foreach ($grp in $groups) {"Group: " + $grp.name; foreach ($user in $grp.users) {"  User: " + $user.name} }

$site.Dispose()

 

.

12/17/2010

Content by Tag

.

SharePoint: Opening a 2010 Dialog Box from Quick Launch

 

Here’s how to open any page in a SharePoint 2010 popup dialog box from Quick Launch or anywhere else using JavaScript. The key code is from an MSDN article here, but it needed just a little tweaking to work from Quick Launch or an “<A>” tag’s HREF.

 

As a teaser… here’s this site displayed in a SharePoint 2010 dialog box:

image

 

The Code

The MSDN article had this JavaScript example:

var options = SP.UI.$create_DialogOptions();
options.url = url;
options.height = 300;
SP.UI.ModalDialog.showModalDialog(options);

I just needed to modify it so it would work in an HREF of an <A> hyperlink tag. Basically it needed to be in one line and return VOID when called. The following must be typed as all one line!

JavaScript:var options=SP.UI.$create_DialogOptions();
options.url='http://techtrainingnotes.blogspot.com';
options.height = 400;
void(SP.UI.ModalDialog.showModalDialog(options))

 

Now to use it in Quick Launch:

Just go to Site Actions, Site Settings and click Quick Launch. Then click New Navigation Link and add the JavaScript:

image

 

What kind of pages make sense for a dialog box?

It probably does not make much sense to use dialog boxes to display external sites like this one, although it’s better than a Page Viewer Web Part. A better use would be to display any SharePoint page or list/library view and an external report that fits in a popup window.

If you want to display a SharePoint page inside of a dialog box add “?IsDlg=1” to the page’s URL.

Here’s the a normal Shared Documents library page:

image

 

Here’s the same page with “?IsDlg=1” added to the URL:

           http://yourserver/sites/yoursite/Shared%20Documents/Forms/AllItems.aspx?IsDlg=1

image

 

So here’s Shared Documents in a dialog box… notice that you have the ribbon, but not the rest of the master page clutter!

image

 

And as a additional bonus, dialog boxes can be called from within dialog boxes. Here’s the Upload Multiple dialog box being used from the example above:

image

 

Or open a dialog box from a HyperLink

To use in an <A> hyperlink tag:  (again, this is all one line!)

<a
href="JavaScript:var options=SP.UI.$create_DialogOptions();
options.url='http://techtrainingnotes.blogspot.com';
options.height = 400;
void(SP.UI.ModalDialog.showModalDialog(options))"
>
Click here!
</a>

 

Links:

How to: Display a Page as a Modal Dialog Box

http://msdn.microsoft.com/en-us/library/ff798390.aspx

 

How to use JavaScript in Quick Launch

http://techtrainingnotes.blogspot.com/2010/10/sharepoint-javascript-in-quick-launch.html

 

More about the SharePoint JavaScript API

http://msdn.microsoft.com/en-us/library/ee538253.aspx

 

.

SharePoint: Modifying the “Respond to this Survey” Prompt

 

I had a recent request to change a survey’s “Respond to this Survey” text. Here’s two ways to do it, plus the “detective work” on how to do these kinds of changes.

 

If you just want the JavaScript solution then go ahead and scroll down to the end.

 

Solution 1: Don’t change it!

If your goal is to give the user a better way to start a survey, then just give them a direct link from Quick Launch, an Announcement or even an email. The “Respond to this Survey” button is just a link to the “Newform.aspx” for the survey and all you need to do is copy it. Here’s what the links look like:

SharePoint 2007 link:

  http://yourserver/sites/yoursite/Lists/Survey%201/NewForm.aspx?Source=http%3A%2F%2Fyourserver%2Fsites%2Fyoursite%2FLists%2FSurvey%25201%2Foverview%2Easpx

SharePoint 2010 link:

  http://yourserver/sites/yoursite/Lists/Test%20Survey/NewForm.aspx?IsDlg=1

 

Both of these give some interesting hints as to cool things you can do with these links:

  • Redirect to another page on completion: In both 2007 and 2010 you can add “?Source=” and specify a page to go to after the survey has been completed. The destination (Source) could be the survey home page, the site’s home page or a custom “Thank you” page.
     
  • Open the survey in a in a popup dialog box:  In SharePoint 2010 you can add “?IsDlg=1” to the URL to open the survey formatted for a dialog box (more info below). Without this, the survey will be displayed as a normal SharePoint page.
     
  • Note: You cannot use both “Source=” and “IsDlg” in the same URL as the user will just be redirected to a blank page.

To discover these links, just go to your survey and click “Respond to this Survey”. In SharePoint 2007 just copy the URL at the top of the browser. In SharePoint 2010, right-click inside of the dialog box and click Properties. From there you can copy the URL.

Now go to Quick Launch (Site Actions, Site Settings), a new Announcement, a new email, etc and paste the URL.

 

Adding to Quick Launch:

Here’s an example of using the link in Quick Launch. In the following example the URL will send them back to the home page after the survey has been completed:

http://yourserver/sites/yoursite/Lists/Survey%201/NewForm.aspx?Source=http://yourserver/sites/yoursite

image

As displayed in Quick Launch:

image

SharePoint 2010 and “IsDlg=1”

“IsDlg=1” alone is not enough to open a popup dialog box. “IsDlg=1” actually is an instruction to hide the master page content!  So if you want to display just the survey and only the survey, add “IsDlg=1” to the URL.

Without “IsDlg=1”

image

With “IsDlg=1”   (no Title, ribbon, Quick Launch, etc)

image

I’ll add an item to my “Blog To-Do” on show to actually display a page in a dialog box. (or you can just google/bing it!)

 

 

Solution 2: Change the “Respond to this Survey” text

Now for some detective work… Go to your survey page (overview.aspx). Right-click the page and select your browser’s “View Source” option. Search the displayed text for “Respond to this Survey”.

SharePoint 2010:  (I replaced parts of the JavaScript with “…”)

<a
id="ctl00_m_g_e2a6c7f0_8d5e_46a4_985f_8d175bfc5b24_ctl01_ctl00_toolBarTbl_RptControls_ctl00_diidIONewItem" 
accesskey="N" title="Respond to this Survey" 
onclick="javascript:NewItem2(event, ' ... ');return false;" 
href="javascript:__doPostBack('  ...  ','');">
  <img align='absmiddle' alt="Respond to this Survey" 
           src="/_layouts/images/NewItem.gif" style='border-width:0px;' />
   &#160;
  <span class="ms-splinkbutton-text">Respond to this Survey</span>
</a>

SharePoint 2007:

<a id="ctl00_m_g_bcf319ff_0b26_4f28_b8d3_70cbf4e8152a_ctl00_ctl00_toolBarTbl_RptControls_ctl00_diidIONewItem" 
accesskey="N" title="Respond to this Survey" 
onclick="javascript:NewItem(' ... ');return false;" 
href="javascript:__doPostBack(' ... ','');">
<img align='absmiddle' alt="Respond to this Survey" 
         src="/_layouts/images/NewItem.gif" style='border-width:0px;'>
  &nbsp;Respond to this Survey
</a>

 

Just enough difference to be a nuisance! But note that in both we have three copies of “Respond to this Survey” to change. One in the A tag, one in the IMG tag and one at the end of the A tag (and for 2010, inside a SPAN tag).

Now for some detective work:

So how do we find the one A tag out of all of the HTML on this page? I never depend on IDs with lots of strange characters (they tend to change from page to page) so that leaves out the normal best solution:  document.getElementById(“ctl00 ….. “). We could just loop through the A tags looking for one with a title of “Respond to this Survey”. And that will work fine, but as a best practice we may want this to work regardless of the language settings used to create the site.

So I see two other useful possibilities, find A tags with an ID that ends with “IONewItem” or find IMG tags that have ‘src="/_layouts/images/NewItem.gif"’. I’m going to use the first of these two.

 

So first let’s find the A tag: 

var atags = document.getElementsByTagName("A");
for (var i=0;i<atags.length;i++)
{
  if (atags[i].id.indexOf("IONewItem")>0)
  {
    // make text changes here...
  }
}

Now let’s change the text:

The first change is easy. As we already have found the “A” tag (atags[i]) all we need to is change the title property:

var newsurveytext = "Click here for the survey!";
atags[i].title = newsurveytext;

The second change is not too hard… The A tag contains two or three child nodes and the first one is the image. All we need to do to it is change the ALT attribute:

atags[i].childNodes[0].alt = newsurveytext;

We need to be careful with the next part as we want it to work in both 2007 and 2010. As 2007 has two nodes (IMG and the text) and 2010 has three nodes (the IMG, the “&#160;” text and the SPAN) we just need to check the count of nodes to make the correct edit for each version:

if (atags[i].childNodes.length == 2)
{
  // must be 2007  ("\u00A0" is to replace the &nbsp;)
  atags[i].childNodes[1].nodeValue = "\u00A0" + newsurveytext;
}
else
{
  // must be 2010 (and we hope the next version!)
  atags[i].childNodes[2].innerText = newsurveytext;
}

 

So here’s the final solution:

<script>

var atags = document.getElementsByTagName("A");
for (var i=0;i<atags.length;i++)
{
  if (atags[i].id.indexOf("IONewItem")>0)
  {
    var newsurveytext = "Click here for the survey!";
    atags[i].title = newsurveytext;
    atags[i].childNodes[0].alt = newsurveytext;
    if (atags[i].childNodes.length == 2)
    {
      // must be 2007  ("\u00A0" is to replace the &nbsp;)
      atags[i].childNodes[1].nodeValue = "\u00A0" + newsurveytext;
    }
    else
    {
      // must be 2010 (and we hope the next version!)
      atags[i].childNodes[2].innerText = newsurveytext;
    }
    break;  // no need to check the other A tags
  }
}

</script>

 

To add the JavaScript to SharePoint 2007

  1. Go to the survey page (overview.aspx)
  2. Click Site Actions and Edit Page
  3. Click Add a Web Part and select the Content Editor Web Part
  4. Move the Content Editor Web Part below the existing survey web part (important!)
  5. Edit the Content Editor Web Part and click the Source Editor button
  6. Copy and Paste the JavaScript above, changing the “newsurveytext” to your text
  7. Save and test

Or… edit the page (overview.aspx) in SharePoint Designer and add the JavaScript just be for the closing tag for the placeholder named “PlaceHolderMain”.

To add the JavaScript to SharePoint 2010

  1. Open Notepad, Copy and paste the JavaScript above, changing the “newsurveytext” to your text
  2. Save the file to a local drive
  3. Upload the file to a SharePoint library (while Shared Document will do, you may want a add a library just for these kinds of files)
  4. Go to the library where you just uploaded the file and copy the URL to the file (right-click the file and click Properties to find the URL)
  5. Go to the survey page (overview.aspx)
  6. Click Site Actions and Edit Page
  7. Click Add a Web Part and select the Content Editor Web Part
  8. Move the Content Editor Web Part below the existing survey web part (important!)
  9. Edit the Content Editor Web Part and paste the URL to the JavaScript file into the Content Link box
  10. Save and test

Or… edit the page (overview.aspx) in SharePoint Designer and add the JavaScript just be for the closing tag for the placeholder named “PlaceHolderMain”.

 

.

12/15/2010

Want to be a pilot? (Shameless book plug…)

 

Need a last minute gift?  Always wanted to be a pilot?  Want something to read on the plane?

 

Timothy O'Connor, a fellow trainer at MAX Technical Training, has just completed a book for the “sport pilot” titled:

You Can Afford To Be A Pilot: How To Become A Pilot And Fly For Fun On A Middle Income Budget 

The purpose of this book is not to teach ground school or flight training, but is intended to teach the reader how to shop for these services and, once purchased, how to keep them affordable, efficient and useful. Certified FAA Instructor Timothy O’Connor uses his twenty years of experience with technical subjects and adult training to bring flying to people on a middle-income budget. Learn about the new Sport Pilot Certificate license, Ultralights, Light Sport Aircraft, Experimental Aircraft, How to pass the FAA Exams, the steps involved in learning to fly, getting the best flying lessons, how to choose instructors ( a CFI ) and more on a budget.  Read more at the links below…

 

By the way, Tim is a pilot, a Certified Flight Instructor and in his spare time, a Microsoft Certified Trainer. Both he and his wife own airplanes (yes, plural). 

 

The hardcopy version is available from Amazon:

            

 

EBook versions are available from here for $8.99:

https://www.smashwords.com/books/view/31207

 

 

If you run into Tim, tell him he owes me a sales commission, or at least a cup of MAX coffee…

 

.

SharePoint: How to get the SharePoint version from JavaScript

 

Update: I found a JavaScript function that returns the version number. Content below has been updated.

 

Simple question:

I’m writing some JavaScript that will run almost identically in SharePoint 2007 and SharePoint 2010. How can I write an IF statement to test the version?

 

So far I have found no simple answer, but I have found a few that work. Each has an “if” or a “risk”, so pick one that works for you.  If you know a better way, please post a comment below.  I propose three methods:

  • Method 1: Check the “_fV4UI” variable
  • Method 2: Check for an element with “V4” or “s4” in its ID or style
  • Method 3: Get the EXACT (almost) version number
  • Method 4: Call a SharePoint 2010 ECMAScript Class Library Object Method

 

SharePoint Versions: (that I’m interested in…)

  • 2007, also called 3.0 or V3, also called version 12
  • 2010, also called 4.0 or V4, also called version 14
  • and one day 201x, called 5.0 or V5? also called version 15?
  • would also love to get WSS vs MOSS and Foundation vs Server

It would be nice if:

  • something in the page had the version number?  (14.xxx)  (I can’t find it)
  • there’s a JavaScript function in one of the core libraries somewhere? (I can’t find one)  (Update: actually there is in 2010)

Solution requirements:

  • Must be available in all site pages, and ideally in all application pages
  • Must be in all templates
  • Must still be there after major master page branding surgery
  • Should still be useful

A few quick ideas:

  • Look for one of the many controls with a tag with “V4” embedded or one of the CSS classes with “V4” embedded. (Risk? Minimal, but site branders who have really hacked the master page or the styles could mess this up.)
  • Look for a unique JavaScript variable (see _fV4UI below). (Risk? Minimal, but a web search for “_fV4UI” finds a number of articles that mention deleting this from the master pages.)

Method 1: Check the “_fV4UI” variable

 

SharePoint 2010 pages have a JavaScript variable named “_fV4UI” that indicates if the page is using the “V4” navigation (Ribbon).  After an upgrade from SP 2007 this variable will be set to “false”. When the user interface is upgraded to the ribbon this will be set to “true”.

So:

  • if _fV4UI does not exist we probably have SP 2007
  • if _fV4UI does exist we probably have SP 2010
  • will there be a _fV5UI in the next version?  (can only wait and see)

The code:

<script type="text/javascript">
  if ( typeof _fV4UI == "undefined" ) 
  {
    // 2007 code here
  }
  else
  {
    // 2010 code here
  }  
</script>

Pros:

  • Probably the easiest test to do
  • Very simple code
    Can even be reduced to one line:

         var SPversion = (typeof _fV4UI == "undefined") ? "12" : "14";

Cons:

  • Your code must be placed after where SharePoint initializes this variable. Be aware that a number of blog articles mention removing the first instance listed below.

    This is where I found it in a Team Site:
    • Line 13 in the <HEAD> section  (this is the only one you will see in the master page)
    • Line 100 in the <BODY> section  (auto generated by a control)
    • Line 1033 near the end of the page  (auto generated by a control)

 

Method 2: Check for an element with “V4” or “s4” in its ID or style

 

The challenge here is, which one? You will need to pick an element that will reliably exist in all branded and unbranded pages.  Just about everything in the master page is up for grabs when custom branded. (Yes, I have seen branded sites without a title, Quick Launch, Tabs, Search, View All Files and Recycle Bin!) 

The control you pick needs to be towards the top of the page and most likely left behind in a branded master page. So let’s pick one… (let me know if there is a better one)  Both SP 2007 and SP 2010 have a hidden <SPAN> or <DIV> named TurnOnAccessibility. In 2010 this DIV has a style named “s4-notdlg”, which SP 2007 will never have, so let’s test for that:

The code:

<script type="text/javascript">
  if ( document.getElementById("TurnOnAccessibility").className == ""  ) 
  {
    // 2007 code here
  }
  else
  {
    // 2010 code here
  }  
</script>

Pros:

  • Easy to test
  • The tag we are testing is at the very top of the page

Cons:

  • This will probably be one of the first things a brander will remove (mostly as they have no idea what it is for)

What is TurnOnAccessibility for? The dropdown menus in SharePoint, such as the Welcome menu or Site Actions, are dynamically generated and somewhat meaningless to a user with vision problems who is using a screen reading program. When “more accessible mode” is enabled, clicking what usually is a dropdown menu will open a popup window with all of the menu options listed.

 

Method 3: Getting the EXACT (almost) version number

 

Now this is what I really want, and it is sent by SharePoint for every page request, but as part of the HTTP Header.  But… most of what’s in that header is not available to JavaScript.

Here’s what’s sent from SharePoint 2010 in the header:

image

Is that version number right?
    14.0.0.4762  reported in the header
    14.0.4763.1000 reported in Central Admin for SharePoint
    14.0.4763.1000 also reported in CA as the database schema version

This number is what is found in IIS under HTTP Response Headers.

image

Anybody know why it does not match any other SP 2010 version number? 

 

Ok, the number is not the correct version, but it is close!

 

SharePoint 2007 reports:

image

At least this is the correct version!

 

So if JavaScript cannot read this header value, how do we get it? Depends on which browser you are using, so I’m using a routine from an MSDN article to deal with the browser version.

 

The code:

<script type="text/javascript">

  /*
    The following copied from:
    http://msdn.microsoft.com/en-us/library/ms537505(v=vs.85).aspx
  */
  var xmlHttp = null;
  if (window.XMLHttpRequest) {
    // If IE7, Mozilla, Safari, and so on: Use native object.
    xmlHttp = new XMLHttpRequest();
  }
  else
  {
    if (window.ActiveXObject) {
       // ...otherwise, use the ActiveX control for IE5.x and IE6.
       xmlHttp = new ActiveXObject('MSXML2.XMLHTTP.3.0');
    }
  }
  /*
    end copy
  */

  xmlHttp.open('HEAD', location.href, false);
  xmlHttp.send();
  var headers =  xmlHttp.getAllResponseHeaders();
  var SPVersion = xmlHttp.getResponseHeader("MicrosoftSharePointTeamServices");

  if ( SPVersion.substring(0,2) == "12"  ) 
  {
    // 2007 code here
  }
  else
  {
    // 2010 code here
  }  

</script>

Note: The XMLHttpRequest call is usually setup with an asynchronous callback as the URL called is usually not the same URL that contains the calling JavaScript.  The example above does not seem to need this as it appears the header is read from the current copy of the page (“location.href”). Test this in your environment!

 

It would be a good idea to wrap this code as a function and add this to a custom JavaScript library that you would load in the master page. You can then call it as needed from other routines.

function getSharePointMajorVersion()
{
 // The following copied from: http://msdn.microsoft.com/en-us/library/ms537505(v=vs.85).aspx
  var xmlHttp = null;
  if (window.XMLHttpRequest) {
    // If IE7, Mozilla, Safari, and so on: Use native object.
    xmlHttp = new XMLHttpRequest();
  }
  else  {
    if (window.ActiveXObject) {
       // ...otherwise, use the ActiveX control for IE5.x and IE6.
       xmlHttp = new ActiveXObject('MSXML2.XMLHTTP.3.0');
    }
  }
  //  end copy

  xmlHttp.open('HEAD', location.href, false);
  xmlHttp.send();
  var SPVersion = xmlHttp.getResponseHeader("MicrosoftSharePointTeamServices");

  return  SPVersion.substring(0,2) 
}  

 

Pros:

  • Gets the version number, so should also work with the “next version” of SharePoint (15?)
  • Should work regardless of “branded” master page changes
  • Works with the browsers I test with: IE6, IE7, IE8 and FireFox 3.5.10

Cons:

  • A lot of code for a just to see if we are in 2007 or 2010
  • The version number returned is stored in the IIS settings and could get changed independent of SharePoint (I don’t know if service packs update this)
  • The SharePoint 2010 version returned is not 100% correct (but the major version “14” is correct)

 

Method 4: Call a SharePoint 2010 ECMAScript Class Library Object Method

SharePoint 2010 supports a JavaScript client object model that can access lists, libraries and other content. Once of the classes is called SP.ClientSchemaVersions and it has a property called currentVersion that returns a version number. This number is not the version of SharePoint itself, but appears to be the version of the library as it returns “14.0.0.0” only.

So:

  • if “SP.ClientSchemaVersions.currentVersion”does not exist we probably have SP 2007
  • if “SP.ClientSchemaVersions.currentVersion” does exist and starts with “14” then we probably have SharePoint 2010
  • And… if we are lucky “SP.ClientSchemaVersions.currentVersion” will return “15.something” for the next version.

The Code:

<script type="text/javascript">

function SampleFunction()
{
  var SPversion = "12"; 

  try { SPversion = SP.ClientSchemaVersions.currentVersion.substring(0,2) } 
  catch (e) {}

  if (SPversion == "12")
  {
      // 2007 code here
  }
  else
  {
      // 2010 (and later) code here
  }
}

ExecuteOrDelayUntilScriptLoaded( SampleFunction, "sp.js" );

</script>

 

Pros:

  • Gets the version number, so should also work with the “next version” of SharePoint (15?)
  • Should work regardless of “branded” master page changes
  • Works with the browsers I test with: IE6, IE7, IE8 and FireFox 3.5.10

Cons:

  • A lot of code for a just to see if we are in 2007 or 2010
  • The version number returned is for the script library, not SharePoint (but that should be OK)
  • Our code can only be run after the page is fully loaded and the “sp.js” library has been loaded (that’s why we need the ExecuteOrDelayUntilScriptLoaded call)
  • Our code must be wrapped up in a JavaScript function  (SampleFunction in the example above)

 

My Preference?

Right now it is Method 1, Check the “_fV4UI” variable.  It’s simple and light weight. But just remember the variable initialization could get deleted by someone working on the master page.

 

 

 

 Know a better way?  Post a comment below!

 

.

12/12/2010

Visio Services: there are no addresses available for this application

 

While doing a demo for Visio Services in SharePoint 2010 I got the following “perfectly clear and obvious” error message.

image

 

The fix was quite simple… go start the Visio service in Central Administration! 

 

This error occurs for other services, such as the Document ID services and BCS, and the solution is generally the same: start the service and/or make sure the configuration is correct.

 

.

12/02/2010

Cincinnati SharePoint User Group

Reminder! The Cincinnati SharePoint User Group meeting is tonight!

http://www.cincinnatispug.org/

December's Presentation


SharePoint 2010 Disaster Recovery: New Capabilities, New Possibilities!

Disaster recovery planning for a SharePoint 2010 environment is something that must be performed to insure your data and the continuity of business operations. Microsoft made significant enhancements to the disaster recovery landscape with SharePoint 2010, and we'll be taking a good look at how the platform has evolved in this session. We'll dive inside the improvements to the native backup and restore capabilities that are present in the SharePoint 2007 platform to see what has been changed and enhanced. We'll also look at the array of exciting new capabilities that have been integrated into the SharePoint 2010 platform, such as unattended content database recovery, SQL Server snapshot integration, and configuration-only backup and restore. By the time we're done, you will possess a solid understanding of how the disaster recovery landscape has changed with SharePoint 2010.

Presenter: Sean P. McDonough

Sean is a Product Manager for SharePoint Products at Idera, a Microsoft gold certified partner and creator of tools for SharePoint, SQL Server, and PowerShell.

11/20/2010

SharePoint Changes Files as they are Uploaded

 

I love the questions in MSDN forums!  They lead me down new paths in SharePoint that I would have never tried.

Such a simple question: "if a document is uploaded to doc library, will the checksum of the document change". (http://social.msdn.microsoft.com/Forums/en-US/sharepointdevelopment/thread/4b184d0a-8fce-4ec7-a9d9-7badf205b85e)

Well, I know of a few cases where it can, but I'll come back to that. Here's the very weird thing I discovered... I uploaded the same file (a 2003 Word document) three different ways, and got two different file sizes in the library, and when downloaded they were all different from the the originally uploaded file.  SharePoint changed the files!

 

Test using a Word 2003 (.doc) document

(File size from right-clicking the file in Windows Explorer and selecting Properties)

  • Original file on disk (C:):
       139,264 bytes
     
  • File uploaded by clicking "Upload" in the library and then checking it's size from Open with Windows Explorer: 
       140,288 bytes
  • File uploaded with "Upload Multiple":
       139,776 bytes
  • File uploaded by dragging from C: (Windows Explorer) to Open with Windows Explorer:
       139,264 bytes  (but I think this is the original file size due to some caching – when I reopened the Open with Windows Explorer it changed to 139,776)

Now I downloaded the file using drag and drop from Open with Windows Explorer:

  • File uploaded by clicking "Upload"
      140,288  )
  • File uploaded by clicking "Upload Multiple"
      139,776 
  • File uploaded with dragging from C: (Windows Explorer) to Open with Windows Explorer:
      139,776 

Next I wrote some .Net code to access the documents via the API and the size reported from SPFileItem.File.Length is the same as the downloaded numbers (140,288, 139,776, 139,776).

Remember... the original file on C: was 139,264 bytes.

Now I opened each of the "uploaded and then downloaded" files in a HEX viewer:

  • The file uploaded by clicking "Upload Multiple" and and the file uploaded with dragging from C: (Windows Explorer) to Open with Windows Explorer:
      All bytes identical until the end of the file where there is what looks like random bytes (different in both files) and an incomplete fragment of an XML structure (same in both files).  (junk in the upload buffer???)
     
  • File uploaded by clicking "Upload"
      First byte changed from 00 to D0
      bytes/text added at the end of the file with metadata from the library columns!

So... I don't think you can rely on the check sum of the file!

 

Test using a TXT or PDF file

A simple text (.TXT) was unchanged by SharePoint and always reported the same file length no matter how I uploaded or downloaded it. The same for a PDF.

 

Test using an Excel 2003 file

Size on drive C:  22,528 bytes

Size inside of SharePoint: 30,208 bytes   (regardless of how it was uploaded or downloaded)

 

Test using an Excel 2007 file

Size on drive C:  16,501 bytes

Size inside of SharePoint: 19,076 bytes   (regardless of how it was uploaded or downloaded)

This one get even more interesting!  Office 2007 files are actually ZIP files. It looks like SharePoint unzipped the file, added some folders and some files and then rezipped the file. Here’s the before and after:

image

 

What’s changed?

  • New folder in the root of the zip file called “[trash]” that contains two tiny files “0001.dat” and “0002.dat”.
  • The file sizes in “_rels” have changed
  • The “docProps” folder has a new file named “custom.xml”
  • The “docProps\core.xml” file has been changed to include the SharePoint content type
  • and probably some other things I missed

 

Now back to how (I used to know) files can be different after upload...

  • If you are using Information Rights Management - the IRM wrapper is removed on upload (so files can be indexed for search) and reapplied on download.
  • If you have fields bound between an Office document (Word, etc) and the columns in the library, a user who edits the library columns will also be changing the content of the file.

 

Summary (or at least some guesses)

  • SharePoint modifies Office 2003 documents by appending to the end of “uploaded” files, but not for Upload Multiple or Explorer drag and drop.
     
  • SharePoint modifies Office 2007 documents by modifying the files in the “DOCX/XLSX” ZIP files, and for all ways they are uploaded.
     
  • SharePoint does not appear to modify non-Office files

 

If you know anything about this, please post a comment and share!

.

11/06/2010

SharePoint 2010: Don’t install the October Cumulative Updates for SharePoint Server 2010 and Project Server 2010

 

Update:

The SharePoint team has posted an update and some workarounds…

http://blogs.msdn.com/b/sharepoint/archive/2010/11/06/details-and-workaround.aspx

 

 

The SharePoint team has just released an announcement on their blog site about the October updates for SharePoint 2010 and Project Server 2010.

Microsoft has discovered a critical issue in the recently released October Cumulative Updates for SharePoint Server 2010 and Project Server 2010, and we have removed the files from download availability.  If you have already downloaded the CU, do not install it.  If you have installed the CU, please contact Microsoft Support for assistance. 

Monitor their blog for updates, what to if you have already installed it, and when a fix is coming…

http://blogs.msdn.com/b/sharepoint/archive/2010/11/05/critical-information-about-the-sharepoint-server-2010-october-cumulative-update.aspx

 

.

Note to spammers!

Spammers, don't waste your time... all posts are moderated. If your comment includes unrelated links, is advertising, or just pure spam, it will never be seen.