Permission Reminder Script

This script is posted as part of our MSPress Book that will be released in 2013.

You can use this script to send site owners the list of permissions in each site that they must validate every set number of days:

function SendEmail($emailTo, $body)
{
$emailFrom = "sharepoint@contoso.com"
$subject = "60-Day SharePoint Permissions Review"
$smtpServer = "smtp.contoso.com"
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$smtp.Send($emailFrom, $emailTo, $subject, $body)

}

function GetPermissions($web)
{           
$permissions = new-object system.text.stringbuilder
[void]$permissions.appendline("Please review your site's, " + $web.url + ", permissions and remove anyone that no longer needs access")
[void]$permissions.appendline("")

[void]$permissions.appendline("Web Groups:")
[void]$permissions.appendline("")

            foreach($group in $web.groups)
            {

        if ($group.users.count -gt 0)
        {

[void]        $permissions.appendline("`tGroup Name: " + $group.name)
[void]        $permissions.appendline("`tGroup Owner: " + $group.Owner)
[void]        $permissions.appendline("`tGroup Members: ")

                foreach($user in $group.Users)
                {
[void]$permissions.appendline("`t`t" + $user.userlogin)
                }
        }

            }

[void]$permissions.appendline("")
[void]$permissions.appendline("Web Permissions:")
[void]$permissions.appendline("")
     

        foreach($ass in $web.roleassignments)
        {

[void]$permissions.appendline("`tUser/Group:" + $ass.member.tostring())

            foreach($def in $ass.roledefinitionbindings)
            {
[void]$permissions.appendline("`t`t" + $def.name)

            }
        }

[void]$permissions.appendline("")
[void]$permissions.appendline("Unique List Permissions:")
[void]$permissions.appendline("")
     
foreach($list in $web.lists)
{

if ($list.hasuniqueroleassignments)
{
[void]    $permissions.appendline("`tList (unique perms)" + $list.title)

        foreach($ass in $list.roleassignments)
        {

[void]$permissions.appendline("`tUser/Group:" + $ass.member.tostring())

            foreach($def in $ass.roledefinitionbindings)
            {
[void]$permissions.appendline("`t`t" + $def.name)

            }
        }
}
}

return $permissions

}

add-pssnapin microsoft.sharepoint.powershell
$webapps = get-spwebapplication

foreach($wa in $webapps)
{

    foreach($site in $wa.sites)
    {

        "Processing " + $site.url

if ($site.url.tolower().startswith("http://my.contoso.com"))
{
continue;
}

foreach($web in $site.allwebs)
{

"Processing " + $web.url

$date = $web.properties["PermissionReminderDate"]

if (!$date)
{
"Setting empty date"
$web.properties["PermissionReminderDate"] = [System.DateTime]::Now.toshortdatestring()
$web.properties.update()
$date = $web.properties["PermissionReminderDate"].tostring()
}

$remindDate = [System.DateTime]::Parse($date)
"Date is " + $reminddate

if ($remindDate -lt [System.DateTime]::Now)
{
"Sending permissions reminder to " + $web.author.userlogin + " for web " + $web.url

#generate the permissions info
$permissions = GetPermissions $web

SendEmail $web.author.email $permissions

$web.properties["PermissionReminderDate"] = [System.DateTime]::Now.adddays(60).toshortdatestring()
$web.properties.update()

}

#[system.console]::readline()

}
}
}

Enjoy!
CJG

Shredded Storage Whitepaper and Testing Framework

So…I haven't posted anything in a while…notice?  Yeah, you probably did.  Multiple reasons including two MSPress books, clients, courseware…and…the crazy shredded storage whitepaper.  This thing is EPIC.  There have been a few blog posts, but NOTHING that has gone as deep as we have and DEFINITELY nothing that will provide you the source code to test on your own!  So in coordination with AvePoint, NetApp and some Microsoft folks, the white paper is in its final stretch and again…the source code for the tool and its use cases is about ready to go!   When it is final…it will be posted here:

http://shreddedstorage.codeplex.com

Stay tuned!  The excitement is only just building!

CJG

Paused for:Backup/Restore

Ever had this happen to you?  No, probably you haven't, but then again…have you been a good Admin and tested your Search Backup and Restores?  No, didn't think so.  So if that fateful moment ever happens, here's what can cause it and what you have to do to clear this status code.

The issue arose when I was trying to backup and (unsuccessfully), restore using the Central Administration UI.  This I am afraid is a futile approach.  Things really only work when you use Windows PowerShell for backup and restore and I highly suggest you keep to that.

So what happened?  Well, somewhere in the process of restoring after I FULLY deleted the search service application, the status got corrupted.  The restore DID work successfully, but I was left with a status of "Paused for:Backup/restore" on the main admin page. 

Looking up the code for that page, their is a web part called  SearchApplicationSystemStatus.  It interrogates the search service application object and then makes a call to a method called GetStatusString.  GetStatusString runs the IsPaused method on the SearchServiceApplication which then makes call to the stored procedure called "dbo.proc_MSS_GetPauseCrawlsReasons".  This looks up some data in the search admin database table called "MSSStatusChange".  This table has some records in it (that you should not delete), but have a status code on them.  If the status is anything but zero, your search will be in some state other than "Running".  When this happens, you can pretty much guarantee that some items are going to effectively be OFF.  This includes things like no Crawling, no searching, no index replication…etc.

Of course, I needed to re-crawl my content, after trying to start the crawls, they just stayed in "Starting" state.

So how to you fix this?  I suppose an easy, yet long and wasteful approach would be to attempt to do a backup and then a restore.  But I hate waste.  So I changed the status codes to zero.  What happened? Didn't work…crap.  Then I did a restart on the "SharePoint Search Host Controller" just to re-initailize things.  Didn't work.

So, one last ditch effort, I manually paused the server (via the quick launch on the search admin page), then resumed it.  This kicked the crawl component back into action!  Sweet!  Solved!

Enjoy,
Chris

Latest SharePoint MVP Forum Stats

  1. As we are getting close to the finish of our 2012 Forum Jam, here is an update of the SharePoint MVP rankings. Previous results are here.
Name Points Posts Answers
Paul stork, MVP 31853 860 1873
Trevor Seward 27805 726 1585
Dave Hunter 20320 333 1474
Mike Smith MCT MVP 18735 420 1252
Serge Luca [MVP] 15055 233 1093
Marc D Anderson MVP 14975 299 1162
Ivan Sanders 14060 289 1035
Paul Galvin 13750 170 1156
Peter Holpar, MVP 11385 209 719
Waldek Mastykarz MVP 10839 148 586
Mike Oryszak 9570 162 747
Cornelius J. van Dyk 9010 113 682
John D. Ross 8615 217 623
Moonis Tahir 8510 97 665
Pratik Vyas [MVP] 7777 109 598
Scot Hillier 7677 134 515
Alberto Diaz Martin – MVP 6920 334 348
LauraRogers MVP 6680 171 451
John Timney MVP 6595 117 500
Dhirendra Yadav 5709 101 390
Fabian André Gehrke 5576 130 352
Mikael Svenson 5390 157 316
Ashutosh Singh 4743 109 295
Gary Lapointe (MVP) 4265 80 348
Wictor Wilen [MVP] 4170 76 275
Randy Drisgill MVP 3460 78 267
Giuseppe Marchi MVP 3340 164 209
Ishai Sagi[MOSS MVP] 3240 26 288
Jennifer Mason 3160 63 237
Kris Wagner – MVP 3155 81 238
Michael Nemtsev [MSFT] 2895 51 229
Ayman El-Hattab 2710 111 119
Becky Bertram 2695 55 201
Sohel Rana MVP 2625 43 200
Ivan Padabed MVP 2570 50 199
Spencer Harbar [MCM] 2536 83 140
Doug Ware 2405 63 168
Geoff Evelyn 2350 49 175
XVanneste [MVP] 2265 111 115
Arnault Nouvel 2200 56 138
Mirjam van Olst [MCM] 2170 60 148
Sangha Baek MVP 2105 57 147
Michal Pisarek MVP 1960 34 149
Liam Cleary [SharePoint MVP] 1930 49 136
Destin Joy MVP 1860 82 131
Matthew McDermott, MVP 1810 25 151
Gaetan Bouveret 1640 4 146
Gabriele Del Giovine 1595 90 97
stephane eyskens 1525 35 103
Jimy Cao 1510 0 122
Serge_Tremblay 1475 43 106
Steven Van de Craen 1335 28 85
Lionel Limozin 1290 99 66
Francesco Sodano 1280 27 87
Sean Wallbridge – SharePoint MVP 1225 28 90
Eric Shupps [MVP] 1165 26 91
Tobias Zimmergren [MVP] 1130 27 75
Kanwal Khipple 1100 20 84
Rob Windsor 1085 29 69
Romeo Pruno 1017 46 67
Andrew Woodward 990 12 89
Vince Rothwell 975 5 87
Gavin Barron 975 229 87
David Martos MVP 955 47 46
Natalya Voskresenskaya 935 24 66
Todd Klindt 920 38 61
Jan Tielens 880 4 80
Bandar Alsharfi 785 1 0
John Holliday 777 5 18
Darrin Bishop 770 16 59
Wes Preston 765 19 56
Philippe Sentenac 735 12 59
Andrew Connell [MVP] 630 11 50
Darko Milevski 585 11 45
James Milne 530 6 45
Asif Rehmani, MVP 485 19 35
Pierre Erol Giraudy 475 32 26
Paul Schaeflein – MVP 415 14 29
Nicolas Georgeault 380 6 26
Amanda Perran 360 10 26
Amanda Perran 360 10 26
Nick Swan 350 4 31
Marwan Tarek – MVP 340 7 25
Ben Robb 310 9 21
Thorsten Hans 310 8 25
Jeremy Thake 283 14 15
Jerry Yasir MVP 235 4 19
Cathy Dew 220 27 14
Panagiotis Kanavos 205 8 12
Salvatore Di Fazio 190 1 18
Sébastien Sougnez 165 1 12
Bil Simser [MVP] 165 11 8
Daniel Wessels MVP 160 14 7
Michael Greth 160 2 13
Ai Yamasaki 160 1 15
Kevin Laahs 155 4 13
Alain Lord – MVP 155 3 12
Christoph Müller 155 21 0
Agnes Molnar – old 130 0 12
Ivan Wilson 120 2 11
Bob Mixon – SharePoint MVP 115 0 9
Sharad K 110 4 6
Steve Sofian 105 4 8
Chris O_Brien 100 2 8
Adis Jugo 100 6 5
Andrey Markeev [MVP] 90 7 4
Becky Isserman 90 0 9
Kathy Hughes 90 7 4
Ton Stegeman [MVP] 85 0 7
Ed Musters, SharePoint MVP 85 2 5
Sahil Malik 80 0 8
Alan Richards 80 1 6
Toni Frankola 80 0 5
Shai Petel 65 5 3
Chandima [ MVP SharePoint ] 65 2 5
Alex Pearce 60 1 4
Sarbjit Singh Gill 55 1 4
Shane Young – MVP 50 1 4
Fabrice [MVP] 50 5 2
Ricardo Munoz 50 3 2
Igor Macori 50 2 4
Sampathperera 50 0 5
Andres Felipe Rojas Parra 50 2 2
Todd Bleeker 49 1 3
Benjamin Curry 45 1 3
Dan Holme 40 3 2
Matt Ranlett 40 2 2
Haaron Gonzalez 40 0 3
Reza Alirezaei – MVP 35 0 3
Didier P. Danse 30 0 3
Robert L. Bogue [MVP] 25 0 2
Muhammad Imran Khawar 25 0 2
Claudio Brotto 25 3 1
Yaroslav Pentsarskyy 25 11 2
Marat Bakirov 20 2 1
Eli Robillard 20 0 2
Shane Perran 20 0 2
Carsten Keutmann 15 1 1
Brian Farnhill [MCP] 10 0 1
Joseph_tu 10 0 1
Rehman Gul 10 0 1
Wouter van Vugt 10 0 1
Dave Coleman 10 0 1
Atsuo Yamasaki 10 0 1
John P White 10 0 1
Julien Chable 10 0 1
Thiago Soares 5 1 0
Aleksandr Chervyak 5 1 0
Alexander Romanov MVP 5 0 0
Valy Greavu 0 0 0
Randy Williams 0 0 0
Matt Smith 0 0 0
Dieudonne 0 0 0
Nguyen Ba Quang 0 0 0
Steve Curran 0 0 0
Arno Nel 0 0 0
Rouslan Grabar 0 0 0
Debbie Ireland 0 0 0
Riwut Libinuko 0 0 0
Bill Brockbank 0 0 0
kWazar 0 0 0
Shailaja Muthu Kumaran 0 0 0
Ed Richard SGC 0 0 0
Muhanad Omar 0 0 0
Todd Baginski 0 0 0
Mark Orange 0 0 0
Shady Khorshed – MVP 0 0 0
David Mann 0 0 0
Hiroaki Oikawa 0 0 0
Penny Coventry MVP 0 0 0
saifullah 0 0 0
Rob Foster 0 0 0
Pierre Vivier-Merle. 0 0 0
Dave McMahon 0 0 0
Steve Smith 0 0 0
Mohamed Zaki 0 0 0
Peter Yu 0 0 0
Brendon Schwartz 0 0 0
Bill English61 0 0 0
Daniel Seara 0 0 0
Stephen Cummins 0 0 0
Daniel Larson 0 0 0
Ted Pattison 0 0 0
Loke Kit Kai 0 0 0
Agusto Xaverius Sipahutar 0 0 0
Juan Larios 0 0 0
Sony Setiawan 0 0 0
Fabian Imaz 0 0 0
Wei Du 0 0 0
Hilton Giesenow 0 0 0
Kamil Jurik 0 0 0
Robin Meure 0 0 0
Zac Smith 0 0 0
Stephen Cawood 0 0 0
Elaine van Bergen 0 0 0
Dux Raymond Sy 0 0 0
Masatoshi Kondo 0 0 0
Ruven Gotz 0 0 0
Martin Harwar 0 0 0
Andre Lage 0 0 0
Michael Noel 0 0 0
Marianne van Wanrooij 0 0 0
Nick Kellett 0 0 0
Emre BALCI 0 0 0
Augusto Simoes 0 0 0
AMOL GHUGE 0 0 0
Jason Kaczor 0 0 0
Christian Stahl 0 0 0
Veronique 0 0 0
Peter Carson 0 1 0
Samuel Zuercher 0 0 0
Mark Rhodes 0 0 0
Dmitry Plotnikov 0 0 0
Rodrigo Pinto 0 0 0
Thuan Nguyen 0 0 0
Michal Bojko 0 0 0
Scott Jamison 0 0 0
Christian Buckley 0 0 0
Antonio Maio 0 0 0
Domyoung Kim 0 0 0
Gerardo Reyes 0 0 0
Jean 0 0 0
Nabil 0 0 0
Sezai Komur 0 0 0
Kevin Trelohan 0 0 0
Paul Olenick 0 0 0
Symon 0 0 0
Seung-Jin Kim -1 -1 -1
Saed Ahmad Shela -1 -1 -1
Sundararajan Narasiman -1 -1 -1
Lei Qin -1 -1 -1
Juan Pablo Pussacq Laborde -1 -1 -1
Stanislav Vyschepan -1 -1 -1
Noorez Khamis -1 -1 -1
Radi Atanassov -1 -1 -1
Martin Wilhelm Angler -1 -1 -1
Fernanda R Saraiva -1 -1 -1
Alexey Sadomov -1 -1 -1
Jeong Woo Choi -1 -1 -1
Christian Glessner -1 -1 -1
Yasir Attiq -1 -1 -1
Shuguang Tu -1 -1 -1
Susitha Prabath Fonseka -1 -1 -1
Hoyeon Kim -1 -1 -1
Patrick Guimonet -1 -1 -1
Panagiotis Kanav -1 -1 -1
Joris Poelmans -1 -1 -1
Adams Chao -1 -1 -1
Mohanad Omar -1 -1 -1
vivekthangswamy -1 -1 -1
Xizhang Chen -1 -1 -1
Elczar Peralta Adame -1 -1 -1
basquang Nguyen -1 -1 -1
Ricardo Jose Munoz -1 -1 -1
Jake Dan Attis -1 -1 -1
Renaud Comte -1 -1 -1
Goran Husman -1 -1 -1
Fumio Mizobata -1 -1 -1
Carlos Segura Sanz -1 -1 -1
Will Ho -1 -1 -1
Ruben Alonso Cebrian -1 -1 -1
Baowei Guo -1 -1 -1
JinHo Baek -1 -1 -1
Qifeng Zhao -1 -1 -1
Fabian Moritz -1 -1 -1
Juan Manuel (Manolo) Herrera -1 -1 -1
Juan Andres Valenzuela -1 -1 -1
Hector Insua -1 -1 -1
Yoshiaki Nishita -1 -1 -1
Gustavo Adolfo Velez Duque -1 -1 -1
Jakub Gutkowski -1 -1 -1
Joy Rathnayake -1 -1 -1
Mohammed A. Saleh -1 -1 -1
Juan Carlos Gonzalez Martin -1 -1 -1
Daniel William Brown -1 -1 -1
Chee Meng, Patrick Yong -1 -1 -1
Jing Ma -1 -1 -1
Fengbiao Liang -1 -1 -1
Majid Ardforoushan -1 -1 -1
Kazuhiko Nakamura -1 -1 -1
Qiuguang Zhao -1 -1 -1
Woodrow Windischman -1 -1 -1
G Vijai Kumar -1 -1 -1
Oksana Prostakova -1 -1 -1
Anton Lavrov -1 -1 -1
Vladimir Medina -1 -1 -1

CellStorage.svc – Intelligent Updating with Office Clients

In one of my previous posts, I came to an unlikely conclusion that Office Clients don't support delta updates as has been so widely marketed.  This was because on every single client I had tested it on, never did it make such an intelligent call.  Since I have two of four chapters done for our upcoming book, I had some time and decided to install windows 8 on a 120GB SSD drive on my laptop.  After doing so, I also decided to install Office 2013 to see what the experience would be like. Not bad, a lot of re-learning to do, but hey, I'm an MCT, we love learning new stuff.  Sooo, I thought, let's try my previous tests that have subsequently failed so many times on this freshly installed OS and Office Client. To my surprise, something different happened when saving and editing SharePoint stored Office XML documents. 

The reason the previous Office clients I was working didn't do the delta updates is because they failed to make the proper calls to cellstorage.svc.  The HTTP request headers appear to be correct, but it doesn't send a body, which is the most important part of the request.  When this happens, it falls back to "FULL" update mode and every time you make a change, the full file is sent using an HTTP PUT request (no call to cellstorage.svc is made after the first failure).  Delta updates only support Office XML documents. The reason they are only Office XML is that deep inside cellstorage it makes a call to create a pointer to an XmlReader object.  Obviously, the older files are not based on this file format and an attempt to read them is futile, therefore, you won't have any calls to cellstorage.svc, but simply the regular HTTP PUT calls.

Again, until today I was not able to get it to work. But now is a different story.  As far as what happens when it does work, this POST will help you.  I am working with several others to figure out why my other clients did not work (more to come later).

CellStorage supports various different command types (not sure the entire set, but this is a lot of them):

  • GetDocMetaInfo
  • WhoAmI
  • ServerTime
  • Cell (get and set)
  • Coauth
  • SchemaLock
  • ReleaseLock

There is a standard process to this:

  • First step is to send a request for the Document MetaInfo
  • Second step is to actually get the parts of the document that are being viewededited at that moment (cell get)
  • Third step is to request to start editing the document (requesting a schema lock)
  • Fourth step is send back any changes that a person makes (cell set)
  • Last step is to tell the server you are done (release the schema lock)

During this entire process, the client will ping the sharedaccess.asmx web service to ensure that it is the only one editing the document.  This is done about every 20 seconds.  As part of the request, it is looking for the ETag to change.  If it has changed, that means someone updated the document and the version you have is now old and you will need to refresh your copy, or overwrite what they did.  This scenario should never happen, but it looks like they attempt to check that it somehow does (it is MicrosoftSharePoint right?).

Some interesting facts:

  • When you press Ctrl-S and you haven't made any changes, it doesn't save the file, but it does do a call for GetDocMetaInfo.  So although it is not as expensive as previous versions were, there is still a cost to this (the DocProps are HUGE)
  • More to come…

The following APPENDIX is a series of CellStorage calls for each of the steps above:

APPENDIX: 

The first request (Doc MetaInfo) looks like this:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<RequestVersion Version="2" MinorVersion="2" xmlns="http://schemas.microsoft.com/sharepoint/soap/"/>
<RequestCollection CorrelationId="{5E1AF699-7B07-4FF3-ADCA-16E1E40201CC}" xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<Request Url="http://www.sanspug.org/Presentations/Safety%20Plan%20Template.docx" UserAgent="{1984108C-4B93-4EEB-B320-919432D6E593}" UserAgentClient="msword" UserAgentPlatform="win" Build="15.0.4420.1017" MetaData="1031" RequestToken="1">
<SubRequest Type="GetDocMetaInfo" SubRequestToken="1"/>
<SubRequest Type="WhoAmI" SubRequestToken="2"/>
</Request>
</RequestCollection>
</s:Body>
</s:Envelope>

The response is this:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<ResponseVersion Version="2" MinorVersion="2" xmlns="http://schemas.microsoft.com/sharepoint/soap/"/>
<ResponseCollection WebUrl="http://www.sanspug.org" xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<Response Url="http://www.sanspug.org/Presentations/Safety%20Plan%20Template.docx" RequestToken="1" HealthScore="0">
<SubResponse SubRequestToken="1" ErrorCode="Success" HResult="0">
<SubResponseData>
<DocProps>
<Property Key="vti_internalversion" Value="513"/>

</DocProps>
<FolderProps>
<Property Key="vti_hassubdirs" Value="true"/>
…</FolderProps>
</SubResponseData>
</SubResponse>
<SubResponse SubRequestToken="2" ErrorCode="Success" HResult="0">
<SubResponseData UserName="Chris Givens" UserLogin="i:0#.w|chrisgivensadministrator" UserEmailAddress="givenscj@hotmail.com" UserSIPAddress=""/>
</SubResponse>
</Response>
</ResponseCollection>
</s:Body>
</s:Envelope>

The second request (get doc parts) is like this:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<RequestVersion Version="2" MinorVersion="2" xmlns="http://schemas.microsoft.com/sharepoint/soap/"/>
<RequestCollection CorrelationId="{459EA7C7-7B07-4FF3-ADCA-16E1E40201CC}" xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<Request Url="http://www.sanspug.org/Presentations/Safety%20Plan%20Template.docx" UserAgent="{1984108C-4B93-4EEB-B320-919432D6E593}" UserAgentClient="msword" UserAgentPlatform="win" Build="15.0.4420.1017" MetaData="1031" RequestToken="1">
<SubRequest Type="ServerTime" SubRequestToken="1"/>
<SubRequest Type="Cell" SubRequestToken="2">
<SubRequestData PartitionID="383adc0b-e66e-4438-95e6-e39ef9720122" BinaryDataSize="103">DQALAJzPKfM5lAabBgIAAO4CAACqAiAAjBCEGZNL606zIJGUMtblk1oEFgANbXN3b3JkB3dpbnoCCABFFOUPdwEWAgYAAwUAigICAADaAgYAAwAAygIIAAgAgAOEAEELAawCAFUDAQ==</SubRequestData>
</SubRequest>
<SubRequest Type="Cell" SubRequestToken="3">
<SubRequestData GetFileProps="true" BinaryDataSize="103">DQALAJzPKfM5lAabBgIAAO4CAACqAiAAjBCEGZNL606zIJGUMtblk1oEFgANbXN3b3JkB3dpbnoCCABFFOUPdwEWAgYAAwUAigICAADaAgYAAwAAygIIAAgAgAOEAEELAawCAFUDAQ==</SubRequestData>
</SubRequest>
<SubRequest Type="Cell&quo
t; SubRequestToken="4">
<SubRequestData PartitionID="7808f4dd-2385-49d6-b7ce-37aca5e43602" BinaryDataSize="103">DQALAJzPKfM5lAabBgIAAO4CAACqAiAAjBCEGZNL606zIJGUMtblk1oEFgANbXN3b3JkB3dpbnoCCABFFOUPdwEWAgYAAwUAigICAADaAgYAAwAAygIIAAgAgAOEAEELAawCAFUDAQ==</SubRequestData>
</SubRequest>
<SubRequest Type="Cell" SubRequestToken="5">
<SubRequestData BinaryDataSize="88">DQALAJzPKfM5lAabBgIAAO4CAACqAiAAjBCEGZNL606zIJGUMtblk1oEFgANbXN3b3JkB3dpbnoCCABFFOUPdwEWAgYAAxcAAgQIAAQ1DAALAawCAFUDAQ==</SubRequestData>
</SubRequest>
<SubRequest Type="GetVersions" SubRequestToken="6"/>
</Request>
</RequestCollection>
</s:Body>
</s:Envelope>

The response is this (but also included the binary that was requested in the request after the XML part of the response):

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<ResponseVersion Version="2" MinorVersion="2" xmlns="http://schemas.microsoft.com/sharepoint/soap/"/>
<ResponseCollection WebUrl="http://www.sanspug.org" xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<Response Url="http://www.sanspug.org/Presentations/Safety%20Plan%20Template.docx" RequestToken="1" HealthScore="0">
<SubResponse SubRequestToken="1" ErrorCode="Success" HResult="0">
<SubResponseData ServerTime="634934067280000000"/>
</SubResponse>
<SubResponse SubRequestToken="2" ErrorCode="Success" HResult="0">
<SubResponseData>DAALAJ3PKfM5lAabFgMCAACsAgAMWkCfInndLk8SpahJoDsL3N5J72OAed0uTxKlqEmgOwvc3knvYz9FAAAAAAAAA4gEAAAFVQ4CBgADBQD6AigAQJ8ied0uTxKlqEmgOwvc3knvYwCEACYCIAATHwkQgsj7QJiGZTP5NMIdbAFwWQwcuPLQK0r+TVOn9MDyqn7BNTEAEFAFZRBVAGgpfUBUooP7XAJQAFAAUAAAcLkMWcPYYK6I7UOVZMRDNVJSnZUxADtQMYDEgGKDDF05g8hQM1MOXDSAwFADUwxcMHzIZDZmzFw4iMSEYoONXTF90Ggmc01bYYWEXdZSzWhico1lY1ZNaTh1wVAAALUTASYCIAAO6XY6MoAMTbnd88ZQKUM+TAEgJgwcuPLQK0r+TVOn9MDyqn7BAwClEwFBBwGLAQ==</SubResponseData></SubResponse><SubResponse SubRequestToken="3" ErrorCode="Success" HResult="0">
<SubResponseData Etag="&quot;{2EC13881-6761-4F26-A5AC-4CBBC5F4E8E0},2&quot;" CreateTime="129677043240000000" HaveOnlyDemotionChanges="False" LastModifiedTime="129677044800000000" ModifiedBy="System Account">
<xop:Include href="cid:http://tempuri.org/1/634933491321512406" xmlns:xop="http://www.w3.org/2004/08/xop/include"/>
</SubResponseData>
</SubResponse>
<SubResponse SubRequestToken="4" ErrorCode="Success" HResult="0">
<SubResponseData>DAALAJ3PKfM5lAabFgMCAACsAgAMWkCjInndLk8SpahJoDsL3N5J72OAed0uTxKlqEmgOwvc3knvY0dFAAAAAAAAA4gEAAAFVQ4CBgADBQD6AigAQKMied0uTxKlqEmgOwvc3knvYwCEACYCIAAO6XY6MoAMTbnd88ZQKUM+TAEgJgwcuPLQK0r+TVOn9MDyqn7BAwAgJgyZIgShWw0pQpGd0oV6Kr7gAAClEwEmAiAAEx8JEILI+0CYhmUz+TTCHWwBcFkMHLjy0CtK/k1Tp/TA8qp+wTUxABBQBWUQVQBoKX1AVKKD+1wCUABQAFAAAHC5DFnD2GCuiO1DlWTEQzVSUp2VMQA7UDGAxIBigwxdOYPIUDNTDlw0gMBQA1MMXDB8yGQ2ZsxcOIjEhGKDjV0xfdBoJnNNW2GFhF3WUs1oYnKNZWNWTWk4dcFQAAC1EwFBBwGLAQ==</SubResponseData></SubResponse><SubResponse SubRequestToken="5" ErrorCode="Success" HResult="0">
<SubResponseData HaveOnlyDemotionChanges="False">DAALAJ3PKfM5lAabFgMCAACsAgBVDgIGAAMXAAoEKgBUqbSHwoLARZ4MOEP3qCkZ6gQENQwHAYsB</SubResponseData></SubResponse><SubResponse SubRequestToken="6" ErrorCode="Success" HResult="0">
<GetVersionsResponse>
<GetVersionsResult>
<results>
<list id="{713BA73C-EFCD-49C9-B23D-8A2106868919}"/>
<versioning enabled="0"/>
<settings url="http://www.sanspug.org/_layouts/15/LstSetng.aspx?List={713BA73C-EFCD-49C9-B23D-8A2106868919}"/>
<result version="@1.0" url="http://www.sanspug.org/Presentations/Safety Plan Template.docx" created="12/6/2011 8:08 PM" createdRaw="2011-12-07T04:08:00Z" createdBy="SHAREPOINTsystem" createdByName="System Account" size="30106" comments=""/>
</results>
</GetVersionsResult>
</GetVersionsResponse>
</SubResponse>
</Response>
</ResponseCollection>
</s:Body>
</s:Envelope>

The request that drives the saving of a part back is (also included is a multi part binary that has the changes):

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<RequestVersion Version="2" MinorVersion="2" xmlns="http://schemas.microsoft.com/sharepoint/soap/"/>
<RequestCollection CorrelationId="{71E42242-7B07-4FF3-ADCA-16E1E40201CC}" xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<Request Url="http://www.sanspug.org/Presentations/Safety%20Plan%20Template.docx" UserAgent="{1984108C-4B93-4EEB-B320-919432D6E593}" UserAgentClient="msword" UserAgentPlatform="win" Build="15.0.4420.1017" MetaData="7" RequestToken="1">
<SubRequest Type="Coauth" SubRequestToken="1">
<SubRequestData CoauthRequestType="RefreshCoauthoring" SchemaLockID="29358EC1-E813-4793-8E70-ED0344E7B73C" ClientID="{7D99133D-52B2-44E4-BCFC-A56DBD9BE639}" Timeout="3600"/>
</SubRequest>
<SubRequest Type="SchemaLock" SubRequestToken="2" DependsOn="1" DependencyType="OnNotSupported">
<SubRequestData SchemaLockRequestType="RefreshLock" SchemaLockID="29358EC1-E813-4793-8E70-ED0344E7B73C" ClientID="{7D99133D-52B2-44E4-BCFC-A56DBD9BE639}" Timeout="3600"/>
</SubRequest>
<SubRequest Type="Cell" SubRequestToken="3" DependsOn="2" DependencyType="OnSuccessOrNotSupported">
<SubRequestData Coalesce="true" CoauthVersioning="true" GetFileProps="true" BypassLockID="29358EC1-E813-4793-8E70-ED0344E7B73C" SchemaLockID="29358EC1-E813-4793-8E70-ED0344E7B73C" BinaryDataSize="32021">
<i:Include xmlns:i="http://www.w3.org/2004/08/xop/include" href="cid:820fe252-7a34-4b40-802f-e666a88a8941-0@tempuri.org"/>
</SubRequestData>
</SubRequest>
</Request>
</RequestCollection>
</s:Body>
</s:Envelope>

The file update response is:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<ResponseVersion Version="2" MinorVersion="2" xmlns="http://schemas.microsoft.com/sharepoint/soap/"/>
<ResponseCollection WebUrl="http://www.sanspug.org" xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<Response Url="http://www.sanspug.org/Presentations/Safety%20Plan%20Template.docx" RequestToken="1" HealthScore="0">
<SubResponse SubRequestToken="1" ErrorCode="Success" HResult="0">
<SubResponseData LockType="SchemaLock" CoauthStatus="Alone"/>
</SubResponse>
<SubResponse SubRequestToken="2" ErrorCode="DependentOnlyOnNotSupportedRe
questGetSupported" HResult="2147500037">
<SubResponseData/>
</SubResponse>
<SubResponse SubRequestToken="3" ErrorCode="Success" HResult="0">
<SubResponseData Etag="&quot;{2EC13881-6761-4F26-A5AC-4CBBC5F4E8E0},3&quot;" HaveOnlyDemotionChanges="False">DAALAJ3PKfM5lAabFgMCAACsAgBVDgIGAAMLADoEBAAAAIQAJgIgAPY1ejJhBxREloZR6QBmek2kAHgmYSrmvvwoD0GvMdRy1rRs+wDyCHgmntUZQQPX8L5QziuNKUuTBADyCFETASYCIAAO6XY6MoAMTbnd88ZQKUM+TAEgKAx+xz7RnpjZsFpTs0Q6CxcfpgwAICgUfsc+0Z6Y2bBaU7NEOgsXH6YMAKUTASYCIAATHwkQgsj7QJiGZTP5NMIdbAFwSQykwL9CeUV1ACf0G+m6m5XCJTEACVAFdAJw13VWUwNQAFAAALUTAUFKBAIAAAcBiwE=
</SubResponseData>
</SubResponse>
</Response>
</ResponseCollection>
</s:Body>
</s:Envelope>

 Closing the session request is:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<RequestVersion Version="2" MinorVersion="2" xmlns="http://schemas.microsoft.com/sharepoint/soap/"/>
<RequestCollection CorrelationId="{C2ADFD14-7B07-4FF3-ADCA-16E1E40201CC}" xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<Request Url="http://www.sanspug.org/Presentations/Safety%20Plan%20Template.docx" UserAgent="{1984108C-4B93-4EEB-B320-919432D6E593}" UserAgentClient="msword" UserAgentPlatform="win" Build="15.0.4420.1017" MetaData="1031" RequestToken="1">
<SubRequest Type="Coauth" SubRequestToken="1">
<SubRequestData CoauthRequestType="ExitCoauthoring" SchemaLockID="29358EC1-E813-4793-8E70-ED0344E7B73C" ClientID="{7D99133D-52B2-44E4-BCFC-A56DBD9BE639}"/>
</SubRequest>
<SubRequest Type="SchemaLock" SubRequestToken="2" DependsOn="1" DependencyType="OnNotSupported">
<SubRequestData SchemaLockRequestType="ReleaseLock" SchemaLockID="29358EC1-E813-4793-8E70-ED0344E7B73C" ClientID="{7D99133D-52B2-44E4-BCFC-A56DBD9BE639}"/>
</SubRequest>
</Request>
</RequestCollection>
</s:Body>
</s:Envelope>

 The response is:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><ResponseVersion Version="2" MinorVersion="2" xmlns="http://schemas.microsoft.com/sharepoint/soap/"/>
<ResponseCollection WebUrl="http://www.sanspug.org" xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<Response Url="http://www.sanspug.org/Presentations/Safety%20Plan%20Template.docx" RequestToken="1" HealthScore="0">
<SubResponse SubRequestToken="1" ErrorCode="Success" HResult="0">
<SubResponseData/>
</SubResponse>
<SubResponse SubRequestToken="2" ErrorCode="DependentOnlyOnNotSupportedRequestGetSupported" HResult="2147500037">
<SubResponseData/>
</SubResponse>
</Response>
</ResponseCollection>
</s:Body>
</s:Envelope>

 

Office Web Apps and WOPI Binding at Site Collection Level

If you haven't made it too far into OWA land, then let me forewarn you about some things.  There are two version of Excel Services.  The one that comes with SharePoint and the one that comes with OWA.  The truth is:

You can have one and only one!  – (update:  I should have added here, "in certain areas" to get the point across)

UPDATE: Evidentally, some think it ok and acceptable, to view excel reports through the  excel services web part (with the limited viewing area) rather than the more straight forward way of just viewing it directly in the browser.  I'm not one of those people.

You must decide which one you want.  In our upcoming book, I point out the various difference between the two versions.  The net net is if you want advanced Business intelligence features, you must use Excel Services.  If you want advanced viewing and editing, you must use OWA.  You cannot target web apps, content databases or site collections for the decision.  It is a global farm setting decision.

I find this unacceptable to the community as a whole and I can see a service pack coming that enables us to configure this at least on a web application level and if possible on a site collection basis too.

That being said, it is true, as pointed out by Bryan Hart on my Facebook page, that you can disable the "Viewing" action to allow Excel Services to view the files, but allow editing to be done by OWA.  This is done with the New-SPWOPISupressionSetting cmdlet.

At some point, this will all change with new features and versions and hopefully work much better than it does now.

Chris

Installing Project Server 2013 – Previous version of product exists

This error is not very specific.  It could mean project server 2010 or sharepoint 2010 exists.  If your uninstall doens't complete successfully (or it does but you don't realize it left some residual), then you may run into this problem.  The key to figuring this out is to run ProcMon.exe on the server when you attempt to do the install, then work backwards on all the registry keys that it tries to access.

In my case, because the HKLMSoftwareMicrosoftShared ToolsWeb Server Extensions14.0 registry key still existed, it thought that SharePoint 2010 was installed.  However, I had removed it.  Yes this residual registry key was preventing the install from proceeding.  Simply delete this registry key and your install will continue as desired!

Enjoy!
Chris

How Request Management Works in SharePoint 2013

Spence Harbar has a great 3-part blog here on how to configure request management.  It however does not go into the deep level of what is occurring in the code.  This blog will take you a bit deeper into how Request Management works.

 What is Request Management?  It is a Reverse Proxy implemented in SharePoint 2013.  It is defined by the SPRoutingReverseProxy class.  As Spence points out, Request Management is implemented in the Http Module of SharePoint (Microsoft.SharePoint.ApplicationRuntime.SPRequestModule).  Internally it works like this:

  • An HTTP request is received by a SharePoint Web
    Application
  • As part of the ASP.NET pipeline, the SPRequestModule
    is passed the HTTP request for processing
  • The module will check if Request Management
    settings are present for the respective web application
  • If settings are present, the module will then
    check to see if Routing or Throttling has been enabled and if the request management
    service is started.  The module will also
    check to see if the request routing has already been cached as part of any previous requests for the client by
    an internal reverse proxy called the SPRoutingReverseProxy
  • Request Management will then check to see if the
    client has been assigned an affinity to a particular machine via the SPRoutingAffinity
    logic
  • If the request does have affinity, Request
    Management will check that the target server is available, if it doesn’t, then
    the next Routing Target will be selected
  • Once a target has been selected, the HTTP
    context will have a “SPRequestManagementRouted” item added to it for future
    routing
  • Lastly, the request will then be routed to the
    target, the response will be proxied back to the client as long as it responds
    before the Request Execution Timeout in the Request Management Settings
    • The request is sent using basic HttpRequest classes and it is basically copying the request from the SharePoint server to the target server, so as long as the target server is a part of the SharePoint farm, technically any applications running on the SharePoint server can be routed too (not just SharePoint ones).

I'm actually very excited about having this reverse proxy in SharePoint.  There have been a number of things I have been wanting to do on the ACS network but just couldn't do with both SharePoint and my other apps running.  This gives me the ability to route the http requests to other applications on my internal network, not just SharePoint ones!

Even though Request Management is implemented as a reverse
proxy, it is lacking some common features of a full reverse proxy such as:

  • URL Rewriting
  • Static and Dynamic Content Caching
  • Response manipulation (adding or removing JavaScript,
    etc)

The process of determining the final target host is as follows:

 

  • The request is passed to the SP Routing Rule
    Evaluator
  • The routing rules are evaluated and a pool of
    targets will be returned.  The first routing
    rule to have targets wins.
  • Each target is pinged to determine if they are
    available, only targets that are available are considered
  • For each available target, the throttling rules
    are applied, if a target fails it is removed from the routing list
  • The remaining targets, if more than one, are
    evaluated based on their weighting, the machine with the lowest weighting is
    returned
  • Lastly, and not performant-ly by the way, if there is an affinity machine, it is
    selected and returned (this should have been done first before analyzing the weighting, this is a design flaw in the code)

The last point about this new feature is the APIs are all set as internal.  This is LAME.  It keeps people like me and the real MVPs(the ones that could build these tools whether Microsoft MVP or not) from building GUI tools for it.  Maybe they will open it up in the future?

To learn even more about how Request management works, buy our book when it comes out!

Enjoy!
Chris

 

How Shredded Storage REALLY works in SP2013

So as some of you know, I'm on each of the MSPress IT Pro books that will be released on SharePoint 2013.  In one of the books, I'm talking about the architecture and how the content databases have changed.  One of those changes is Shredded Storage.  Yes, I have read Bill Baer's post here and he has a second one here, and I agree with everything he says (even though he doesn't really use the internal architecture's terminology in several cases), except for one point which I bring up at the end.  I have also read Dan Holme's blog here.  He pretty much comes to the same conclusions that I do.  He even nailed it with the max 64K chuck size as the default (but the files don't max at the 64K limit, they end up somewhere below it). 

So, even after reading all this technet and SPC12 mumbo jumbo.  I really wanted to see this stuff working for myself and that required digging in deep to learn how it really works given all the blogs that are incorrect.  In that exploration of the assemblies, classes, tables and stored procedures I have had a few ah ha moments.  Some facts:

  • Shredded Storage is document focused, and from a storage standpoint, only valuable with versioning turned on.  It is not content database or farm focused.  What does that mean?  It means that when a document is "shredded" (SPHostBlob), the shreds are specific to the document and there are no database wide hashes that is done of the shred.  What does this mean?  It means that if you upload the same file in two different places, the same shreds will be created and no optimization takes place.
    • This means that SharePoint does a "better" effort at managing blobs.  It is not what I would call "great" or "stellar" like the solution that StorSimple built.  You are still going to need an RBS solution that will aggregate the new "small shredded blobs" in a de-dupping fashion.  But BE VERY CAREFUL WITH THIS, as Jeremy points out here, the RBS performance hit for small shreds is not worth it! At this point, I'd say that using Shredded Storage is more of a performance hit than it is worth because you now have a table that will have anywhere from 10-4500 shreds for each file.  Multiply that times however many files you have…and that is a very large number of rows in a single table.  You must also take into account the CPU cycle it takes appending the shreds together to be sent back to the client (this is NOT done by coalese on the SQL Server).  All for the sake of reducing your storage by a marginal amount?
  • Shredded Storage works by creating what I am calling a "stream map". This map is stored in the "DocsToStreams" table. The first time you upload a file it is shredded into the smaller parts (except there were a few cases where it does not shred the document and just put a single blob).  When you upload a second updated file, the WFE will query for two non-file based shreds (that add about around 10K or more to each file).  These configuration shreds have shred information that the WFE will use to determine what shreds need to be saved back to the database.  As part of that, a new stream map is built that used any old shreds that didn't change, and the new shreds.  All shreds are in a specific order called the BSN.  Starting from the lowest BSN to the highest BSN for a "stream map".  These shreds are then put back together (minus the configuration shreds) to re-create the file and then passed back to the calling client
  • Some important classes to note in the object model:
    • SPFileStreamManager – Responsible for Computing the Streams (ComputeStreamsToWrite)
    • SPFileStreamStore – Saves the SPHostBlobs back to the database (PutBlobs), and gets blobs from the database (GetBlobs*)
  • When using full Office clients, the full files are sent to SharePoint (only if the first call to cellstorage.svc fails…keep reading below).  This is done by making an HTTP PUT to the url of the document. SharePoint via its Cobalt classes (CobaltStream which derives from the core Cobalt classes) is responsible for doing the actual shredding and comparisons.  I did NOT see the Office client (2010 or 2013), do any type of intelligent saving of documents based on PackageParts in Office files (again this does work if the first call succeeds). 
  • I did confirm that the shreds are generated no matter what the file type is.  This makes me think the shredding is somewhat random (upto the default 64K limit for a shred) and will not catch everything perfectly (ie half the change in one shred and half the change in another shred rather than one shredded component).  I tried to see if I could figure out how the shredding was working but things get really crazy when you get into the Cobalt classes because their are too many abstract classes laying around.

UPDATE:  See this blog post for my more recent experiences with editing with Office Clients and intelligent updating (it does work)

Back to one of the above points.  I was not able to get the Office clients (2010 or 2013) to do any type of smart updating as mentioned in Bill's post (with Word and PowerPoint with a particular client build).  In other wards, I only wanted to send the changes I had made to SharePoint.  I had never really tested this before and was looking forward to seeing it in action, but alas, it doesn't seem to do it at all.  I'm guessing only in a multi-user editing mode (OWA?) will you see this type of feature being utilized (UPDATE: and this guess was correct!  See below!).     Just as an FYI, here's what I did with Office and SharePoint OM calls:

  • Used our awesome friend Fiddler to monitor the traffic
  • Uploaded a PowerPoint file to SharePoint
  • Opened the PowerPoint in PowerPoint Client
  • Removed a slide from the powerpoint, saved it
  • Office sends the entire file to SharePoint (it is visible in the content-size header of the PUT request that this IS the case)
  • SharePoint does the shredding and creates any new shreds
  • Put the slide back in (Ctrl-Z), save the file, again the whole file is sent
  • A new version and similar shreds are created, but some are retained from the first uploadsecond update

If anyone knows how to get this working reliably with Office Clients and SharePoint OM, please let me know.  Otherwise, I'm going to have to say we are getting dupped on this whole "delta" changes from office client non-sense and there is no network optimization going on between Office Client and WFE.  In this scenario, Shredded storage is really just saving us a few bytes here and there (if versioning is turned on) which does reduce the number of writes, but at the cost of more "reads" and CPU to rebuild the files.

UPDATEOffice Web Apps and Shredded
Storage
– this is where you will see the wire optimization between the client (OWA) and the WFE.  It works like this.  When a request for a file is made from SharePoint, OWA will ask the WFE to give it the file.  The file will be built by the WFE from the shreds.  When two users open the file for editing, a new type of shred container is created called a "partition".  This partition contains shreds that each users is working on.  This is where the shreds get broken down to their smaller XML pieces.  As each part of a document is changed, new partitions are created.  When someone wants to see what another person has done, they will request this new partition and it (and only it) will get sent to the client.  Any changes that are made are also sent singly and the entire file is not.

So where does that put us?  Here is the reality and correct details about Shredded Storage (as every blog on Shredded Storage is wrong on the internet).  You have to test shredded storage with 3 things in mind to see if you really are getting any benefits (whether storage or network based).

  • With versioning turned on (you gain the storage benefit, without it, you don't gain any storage benefit)
  • With Office Web Apps (you gain the client to WFE network optimization and the "partitioning" effect in mutil-user editing)
  • When using Office or SharePoint clients, no matter what, you gain a WFE to SQL Server network optimization only when writing a document back (however there is not a wire benefit between Office and SharePoint clients and the WFE when the first call fails to cellstorage.svc)

If you want more information at a super deep level, buy our MS Press book in October!

Enjoy!
Chris

MSDN Forum Jam 2012 Updates

The MSDN Forum Jam is over!  The big winner is Maarten!  He blew away the competition with 2720 points!  Amit came in second and Ivan was 3rd (I don't count, but I am thrilled to have gain 47% more points than last time).  Final prize results are:

  • Maarten will win $100 gift card
  • Amit won a $75 gift card (but has chosen the courseware instead!)
  • Ivan wins a copy of ACS courseware!

NOTE:  Unfortunately, the way msdn forum does the posts now is not the way it worked before, so I had no real way to track the highest ratio of answers to posts this time around. But in looking at a few things, I can get it working for the next round later this year.  Sorry about that 🙁

Final Official Results – 2/14/2013

Name Points Posts Answers
MaartenSundman 2720 75 162
Amit V 2055 47 111
Chris Givens 1470 46 92
Ivan Sanders 1375 37 89
Marc D Anderson MVP 740 31 47
CoreyRoth [MVP] 590 13 21
Doug Hemminger 135 6 8
Fabian G Williams 130 7 8
Gavin Barron MVP 125 3 8
cimares 105 2 6
Nicholas Holloway 90 1 8
EricaToelle 60 1 5
Xenox 40 4 2

I thought tomorrow (12/7) was the day I was to do the Forum Jam start.  Didn't realize I put it in for last week (thursday).  See the original post here. Therefore, I am forced to change the dates of our little competition.  I'll be tweeting this all weekend long for people to sign up and I will then REALLY start the clock on Monday (12/10) and it will continue through till Feb 13th (the day BEFORE valentines so the winner can buy their hunny something nice).  I will be updating this blog post with the results of the people that are participating. 

So far, here is the list.  If I missed people…which I know I did because twitter sucks and removed the hashtag searching and only shows so many replies now, I need you to tweet or email (chris@architectingconnectedsystems.com) me to let me know you want to participate!!!

Remember, these people are competing for $150 top prize!

  • Nicholas Holloway (@nholloway4) – –
  • Amit Vasu (@amitvasu) – –
  • Erica Tolle (@EricaTolle) – –
  • Fabian Williams (@fabianwilliams) – –
  • Maarten Sundman () —
  • Xenox Garavito (@zenoxg)
  • Chris Givens (@givenscj)
  • Ivan Sanders (@iasanders)
  • Gavin Barron (@gavinBarron)
  • Corey Roth (@coreyroth)
  • Marc Anderson (@sympmarc)
  • Paul Hunt (@cimares)

CJG (@givenscj)