<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>The SharePointer</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/tehnoonr/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/tehnoonr/feed.xml</link>
    <description>A place of sharing pointers!</description>
    <lastBuildDate>Sat, 27 Jan 2018 00:31:19 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Retrieving Office 365 Audit Data using PowerShell</title>
      <link>https://docs.microsoft.com/archive/blogs/tehnoonr/retrieving-office-365-audit-data-using-powershell</link>
      <pubDate>Fri, 26 Jan 2018 19:31:18 GMT</pubDate>
      <dc:creator><![CDATA[Tehnoon Raza [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/tehnoonr/?p=335</guid>
      <description><![CDATA[Introduction
In today's world, security, compliance and auditing have become a top priority for...]]></description>
      <content:encoded><![CDATA[<h1>Introduction</h1>
In today's world, security, compliance and auditing have become a top priority for I.T. admins. Office 365 has several built-in capabilities when it comes to auditing and compliance. If you have enabled auditing for your tenant, you can easily retrieve audit logs using the following methods:
<ul>
 	<li><a href="https://support.office.com/en-us/article/Search-the-audit-log-in-the-Office-365-Security-Compliance-Center-0d4d0f35-390b-4518-800e-0c7ec95e946c?ui=en-US&amp;rs=en-US&amp;ad=US">Office 365 Security and Compliance Center Portal</a></li>
 	<li>Using <a href="https://msdn.microsoft.com/en-us/office-365/office-365-management-activity-api-reference">Office 365 Management Activity API </a>in your custom application/service/script.</li>
 	<li>Using the PowerShell command <a href="https://technet.microsoft.com/en-us/library/mt238501(v=exchg.160).aspx">Search-UnifiedAuditLog </a></li>
</ul>
If you need to retrieve audit logs on a regular basis, you should consider implementing a solution using the Office 365 Management Activity API as that is the method that can provide you scalability and performance that you will need if you need to pull millions of audit records on a regular basis. However, there may be certain situations where you need to manually retrieve audit data using PowerShell and Search-UnifiedAuditLog has been designed for exactly that purpose. This is what I am going to focus on for this post.
<h1>Using Search-UnifiedAuditLog - The Challenges</h1>
The <a href="https://technet.microsoft.com/en-us/library/mt238501(v=exchg.160).aspx">documentation for Search-UnifitAuditLog </a>provides a good overview of the various different parameters and their use. There are a number of challenges when using this command to retrieve a large number of audit records:
<ul>
 	<li>You cannot guarantee how many records the command will return in a single call even when you have specified the ResultSize. You should repeatedly call Search-UnifiedAuditLog in a loop using the same value for SessionId parameter until records stop getting returned.</li>
 	<li>The maximum number of records that you can retrieve for a given criteria and SessionId is 50,000. That too when you use the ReturnLargeSet option for the SessionCommand parameter. If you find that the value for ResultCount in the returned data is greater than 50,000, that means you're not going to be able to retrieve all records in the current session and you should narrow your search to ensure the ResultCount stays below 50,000.  Remember that you have to issue multiple calls to Search-UnifiedAuditLog in a loop using the same SessionId to retrieve all 50,000 records.</li>
 	<li>If you have a slow connection, and it's taking a long time to retrieve the data, your session may time out on the server and in that case, you will see that the value for ResultIndex is getting reset to 1 before you could retrieve all data that matched the criteria specified.</li>
 	<li>When you are using repeated calls to Search-UnifiedAuditLog to retrieve data, you may get a few calls that return 0 results due to a network glitch, and your script may be "fooled" into believing that all data has been retrieved.</li>
</ul>
As you can see from the above, it can be quite a challenge to retrieve a large audit data set using PowerShell. But wait, I have a solution!
<h1>The Solution - An Intelligent Script</h1>
I have written a script that attempts to mitigate the challenges mentioned above in an automated fashion. The basic premise of the script is this: Let's say you are trying to retrieve 24 hours worth of audit data, the script will break that into several smaller intervals (15 minutes by default, but configurable). The smaller intervals will ensure that you are not hitting the max limit of how many records can be retrieved in a single session. For each smaller interval, the script will use a new session Id. Smaller intervals will also mean there will be a lesser chance of the session timing out on the server side. There is also retry mechanism built into the script (3 by default and configurable) that should address the problem of intermittent connectivity failures. I am providing the script below. Don't forget to change the configurable values to match your requirements. A few other things to note regarding the script:
<ul>
 	<li>The script will log it's progress in a log file</li>
 	<li>The output will be saved in a CSV file</li>
 	<li>if you see the following message in the log file, that would indicate you need to adjust the configurable variables to ensure each interval is not returning more than the maximum limit:
<em>"WARNING: x total records match the search criteria. Some records may get missed. Consider reducing the time interval!"</em></li>
</ul>
Let me know if this proves useful for you!

[code lang="ps"]

$UserCredential = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection
Import-PSSession $Session
#################################### Configuration Section ###################################################
$logFile = &quot;C:\Users\username\Desktop\MyLog.txt&quot;
$outputFile = &quot;C:\Users\username\Desktop\AuditRecords.csv&quot;
[DateTime]$start = &quot;1/22/18 03:59&quot;
[DateTime]$end = &quot;1/23/18 03:59&quot;
$record = &quot;SharePointFileOperation&quot;
$resultSize = 1000
$intervalMinutes = 15
$retryCount = 3
#################################### End Configuration Section ###################################################
[DateTime]$currentStart = $start
[DateTime]$currentEnd = $start
$currentTries = 0

Function Write-LogFile ([String]$Message)
{
$final = [DateTime]::Now.ToString() + &quot;:&quot; + $Message
$final | Out-File $logFile -Append
}

while ($true)
{
$currentEnd = $currentStart.AddMinutes($intervalMinutes)
if ($currentEnd -gt $end)
{
break
}
$currentTries = 0
$sessionID = [DateTime]::Now.ToString().Replace('/', '_')
Write-LogFile &quot;INFO: Retrieving audit logs between $($currentStart) and $($currentEnd)&quot;
$currentCount = 0
while ($true)
{
[Array]$results = Search-UnifiedAuditLog -StartDate $currentStart -EndDate $currentEnd -RecordType $record -SessionId $sessionID -SessionCommand ReturnNextPreviewPage -ResultSize $resultSize
if ($results -eq $null -or $results.Count -eq 0)
{
#Retry if needed. This may be due to a temporary network glitch
if ($currentTries -lt $retryCount)
{
$currentTries = $currentTries + 1
continue
}
else
{
Write-LogFile &quot;WARNING: Empty data set returned between $($currentStart) and $($currentEnd). Retry count reached. Moving forward!&quot;
break
}
}
$currentTotal = $results[0].ResultCount
if ($currentTotal -gt 5000)
{
Write-LogFile &quot;WARNING: $($currentTotal) total records match the search criteria. Some records may get missed. Consider reducing the time interval!&quot;
}
$currentCount = $currentCount + $results.Count
Write-LogFile &quot;INFO: Retrieved $($currentCount) records out of the total $($currentTotal)&quot;
$results | epcsv $outputFile -NoTypeInformation -Append
if ($currentTotal -eq $results[$results.Count - 1].ResultIndex)
{
$message = &quot;INFO: Successfully retrieved $($currentTotal) records for the current time range. Moving on!&quot;
Write-LogFile $message
break
}
}
$currentStart = $currentEnd
}
Remove-PSSession $Session
[/code]
]]></content:encoded>
    </item>
    <item>
      <title>Creating Communication Sites in SharePoint Online Programatically</title>
      <link>https://docs.microsoft.com/archive/blogs/tehnoonr/creating-communication-sites-in-sharepoint-online-programatically</link>
      <pubDate>Fri, 20 Oct 2017 22:47:24 GMT</pubDate>
      <dc:creator><![CDATA[Tehnoon Raza [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/tehnoonr/?p=305</guid>
      <description><![CDATA[Back in August 2017, a brand new template for SharePoint sites called "Communication Sites" was...]]></description>
      <content:encoded><![CDATA[Back in August 2017, a brand new template for SharePoint sites called "Communication Sites" was rolled out to SharePoint Online. You can read more about communication sites <a href="https://support.office.com/en-us/article/What-is-a-SharePoint-communication-site-94A33429-E580-45C3-A090-5512A8070732">here</a>. Communication sites are a significant step forward for SharePoint sites, as they have a very modern look and feel right out of the box, and can easily serve a number of different business needs with very few customizations.

Ever since the communication sites were rolled out, I've seen that a lot of customers have been looking for a way to create/provision communication sites programmatically (PowerShell or CSOM). Earlier this month, Microsoft officially released guidance around how communication sites can be created using REST. For more information, see <a href="https://docs.microsoft.com/en-us/sharepoint/dev/apis/communication-site-creation-rest">Creating SharePoint Communication Site using REST</a>.

As you can see from the official documentation of the REST API that can be used to create communication sites, it lacks a working demonstration of how you can use the REST API to actually create a communication site. I've put together the following PowerShell script that can be used to provision a new Communication Site in SharePoint Online. The one thing to note is that you need a user's security context to create the communication site and that user will become the owner of the site. You cannot use an "App-Only" access token to create a site. You can easily convert the PowerShell script into any other programming language.
<blockquote>Note: You will need the <a href="https://www.microsoft.com/en-us/download/details.aspx?id=42038">SharePoint Online Client Components SDK </a>to run the script.</blockquote>
Here is the script, enjoy!

[code lang="ps"]

Add-Type -Path &quot;C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll&quot;
################################## Config Section Start ############################################
#The Url of the root SharePoint site for your tenant. Ensure there is no trailing slash at the end!
$rootUri = &quot;https://yourtenant.sharepoint.com&quot;
#The REST endpoint to create the communication site
$restEndPoint = $rootUri + &quot;/_api/sitepages/communicationsite/create&quot;
#Let's set the classification that we want to assign to the site.
$siteClass = &quot;Contoso Confidential&quot;
#There are 3 possible designs for communication sites. Use &quot;null&quot; for &quot;Topic&quot;, &quot;6142d2a0-63a5-4ba0-aede-d9fefca2c767&quot; for Showcase and &quot;f6cc5403-0d63-442e-96c0-285923709ffc&quot; for a blank site
$designId = &quot;6142d2a0-63a5-4ba0-aede-d9fefca2c767&quot;
$siteTitle = &quot;My Comm Site PowerShell2&quot;
$siteDesc = &quot;This is the description of my communications site&quot;
$siteUrl = &quot;https://yourtenant.sharepoint.com/sites/mycomm55&quot;
$siteLCID = &quot;1033&quot;
############################### Config Section End ################################################
#Get the credentials from the user
if ($creds -eq $null)
{
$creds = Get-Credential
}
#Get the user context
$context = New-Object Microsoft.SharePoint.Client.ClientContext($rootUri)
$context.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($creds.UserName, $creds.Password)
$context.ExecuteQuery()
#Get the Auth cookie
$authCookie = $context.Credentials.GetAuthenticationCookie($rootUri, $true)
#Get the Form Digest
$digest = $context.GetFormDigestDirect()
#Now let's build the REST web request
$contentType = 'application/json;odata=verbose'
$headers = @{}
$headers[&quot;Accept&quot;] = &quot;application/json;odata=verbose&quot;
$headers[&quot;X-RequestDigest&quot;] = $digest.DigestValue
$session = New-Object Microsoft.PowerShell.Commands.WebRequestSession
$session.Cookies.SetCookies($rootUri, $authCookie)
$body = @{
request = @{
__metadata = @{type =&quot;SP.Publishing.CommunicationSiteCreationRequest&quot;}
AllowFileSharingForGuestUsers = 'false'
Classification = $siteClass
Description = $siteDesc
SiteDesignId = $designId
Title = $siteTitle
Url = $siteUrl
lcid = $siteLCID
}
}
$jsonBody = ConvertTo-Json $body
$result = $null
#Shoot the request to the cloud!
$result = Invoke-RestMethod -Method Post -ContentType $contentType -Headers $headers -Uri $restEndPoint -Body $jsonBody -WebSession $session
if ($result -ne $null -and $result.d.Create.SiteStatus -eq 2)
{
Write-Output &quot;Site created successfully at &quot;$result.d.Create.SiteUrl
}
else
{
Write-Host &quot;Failed to create site! Grab a fiddler trace while reproducing the failure to learn more about the failure!&quot;
}

[/code]
]]></content:encoded>
    </item>
    <item>
      <title>New InfoPath Calculation Timeout in SharePoint 2016</title>
      <link>https://docs.microsoft.com/archive/blogs/tehnoonr/new-infopath-calculation-timeout-in-sharepoint-2016</link>
      <pubDate>Fri, 13 Oct 2017 20:50:23 GMT</pubDate>
      <dc:creator><![CDATA[Tehnoon Raza [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/tehnoonr/?p=285</guid>
      <description><![CDATA[SharePoint 2016 was born from the cloud - that is SharePoint Online in Office 365. In SharePoint...]]></description>
      <content:encoded><![CDATA[SharePoint 2016 was born from the cloud - that is SharePoint Online in Office 365. In SharePoint Online, we added a performance throttling mechanism so that complex InfoPath forms do not cause performance issues for the web servers. The same code base was shipped with SharePoint Server 2016 (On Premise), and you may notice that the InfoPath forms that you used to be able to publish successfully in SharePoint 2013 are failing to be published with the following error:

<em>Expression evaluation timeout (&lt;timeout&gt; ms) exceeded, closing form urn:schemas-microsoft-com:office:infopath:list.</em>

You can set the timeout to the largest possible value which is equivalent of removing the timeout check. Just know that this can have a negative performance impact on your SharePoint Web Front Ends.

Here is the PowerShell script that you can use to change the timeout:

[code lang="PowerShell"]
$farm = Get-SPFarm
$service = $farm.Services | where {$_.TypeName -eq &quot;Forms Service&quot;}
$service.Properties[&quot;CalculationTimeoutMs&quot;] = [Int32]::MaxValue
$service.Update()
[/code]

Happy SharePointing!</pre>
<pre></pre>]]></content:encoded>
    </item>
    <item>
      <title>SharePoint 2013: "Check Permissions" and "DoesUserHavePermissions" Internals</title>
      <link>https://docs.microsoft.com/archive/blogs/tehnoonr/sharepoint-2013-check-permissions-and-doesuserhavepermissions-internals</link>
      <pubDate>Sun, 02 Jul 2017 23:24:33 GMT</pubDate>
      <dc:creator><![CDATA[Tehnoon Raza [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/tehnoonr/?p=247</guid>
      <description><![CDATA[Overview
If you're a SharePoint administrator, you've probably wondered how the "Check Permissions"...]]></description>
      <content:encoded><![CDATA[<h1>Overview</h1>
If you're a SharePoint administrator, you've probably wondered how the "Check Permissions" tool in SharePoint works, and more importantly, why does it happens sometimes that the users have been granted permissions via an Active Directory security group and can access SharePoint without a problem yet "Check Permissions" reports that those users do not have permissions to the site. This post should hopefully help clarify some of those confusions and will also help you troubleshoot and address issues related to "Check Permissions". This post primarily applies to SharePoint 2013, but the concepts are applicable to all versions of SharePoint starting SharePoint 2007.

First off, it's important to understand that the "Check Permission" tool <i>should</i> provide an accurate reflection of a particular user's access to the site, but in some cases, especially when the users have been granted permissions via Active Directory security groups, it does not function correctly and incorrectly reports permissions. In most cases, that does not prevent users from accessing the site as long as they have been granted the correct permissions even though "Check Permissions" reports otherwise. Most parts of SharePoint do not rely on "Check Permissions" to determine whether or not the user has access to a particular resource.  However, there is a function in the SharePoint object model <a href="https://msdn.microsoft.com/en-us/library/office/microsoft.sharepoint.spweb.doesuserhavepermissions.aspx">SPWeb.DoesUserHavePermissions</a> that a developer may be using in a custom WebPart/control and this API uses the same mechanism as "Check Permissions" and could therefore be affected if "Check Permissions" tool is not reporting permissions correctly. Now you could argue why doesn't "Check Permissions" use the same underlying mechanism to verify the user's permissions as SharePoint's core permission management process, and that's a valid argument. User authentication in SharePoint has evolved over the years (classic to claims), however, "Check Permissions" tool and the DoesUserHavePermissions API have worked the same way since the MOSS 2007 days. Sure there is room for improvement, and we will get there one day :).
<h1>How does it work?</h1>
So how does "Check Permissions" work? In a nutshell, every single user that ever accesses a SharePoint site gets a record created for themselves in the UserInfo table of the content database for that site. The user's record gets created regardless of whether they have been granted permissions directly in SharePoint or whether they have been granted permissions via an Active Directory security group. The only difference is that if a user has been granted permissions via an Active Directory security group, the record in UserInfo table only gets created when the user accesses the site for the first time or when <a href="https://msdn.microsoft.com/en-us/library/office/microsoft.sharepoint.spweb.ensureuser.aspx">SPWeb.EnsureUser </a>function is called for that particular user. For users that have been granted permissions via AD Security Groups, SharePoint stores a token in the tp_ExternalToken column of the UserInfo table that contains information about all the Active Directory security groups that the user is a member of. "Check Permissions" reads this token to determine whether or not the user is a member of a group that has permissions to the site. "Check Permissions" reports incorrect permissions when the information in tp_ExternalToken is either outdated or incorrect. So how does SharePoint populate information in tp_ExternalToken?
<h1>tp_ExternalToken Explained</h1>
By default, SharePoint updates the tp_ExternalToken for users once every 24 hours. You can easily tell exactly when the user's token was last updated by examining the tp_ExternalTokenLastUpdated column which contains the last update time in GMT time zone. The token may get refreshed after 8 (24/3) hours if the user logs into SharePoint themselves, and SharePoint takes the opportunity to update the User's token to avoid permission problems that the farm/application pool account may run into when updating the user's token (permission problems are discussed later). This default 24 hour token timeout is configurable, but I would strongly recommend against changing this default timeout as that can lead to other problems (too much traffic going to your domain controllers and users intermittently getting the "the context has expired and can no longer be used" error message). Here is how you can change the timeout for tp_ExternalToken using PowerShell. Notice that this is a farm wide setting and applies to all sites. In this example, we are just setting the timeout to it's default value of 1440 minutes (24 hours):
<div style="color: #000000">
<pre><span style="color: #ff4500">$cs</span> <span style="color: #808080">=</span> <span style="color: #808080">[</span><span style="color: #008080">Microsoft.Sharepoint.Administration.SPWebService</span><span style="color: #808080">]</span><span style="color: #808080">::</span>ContentService 
<span style="color: #ff4500">$cs</span>.TokenTimeout <span style="color: #808080">=</span> (New<span style="color: #808080">-</span>TimeSpan <span style="color: #808080">-</span>minutes 1440) 
<span style="color: #ff4500">$cs</span>.Update() 
</pre>
</div>
The same effect can also be achieved by adjusting the token-timeout property using <a href="https://technet.microsoft.com/en-us/library/cc287917(v=office.12).aspx">stsadm</a>.

<i>Note: If Active Directory security groups have been given permissions on the site and newly added users to the groups are receiving access denied while accessing the site, you can adjust the WindowsTokenLifetime</i> <i>and LogonTokenCacheExpirationWindow</i> <i>properties of STSConfig object for the farm as needed. This is assuming your site is using Windows Claims Authentication. This is outside the scope of this post as we are discussing "Check Permissions" and "DoesUserHavePermissions".</i>

Each time SharePoint needs to read the user's external token (e.g. "Check Permissions" is being used), the following sequence of events occurs:

1) The freshness of the token is evaluated based on the currently configured token timeout. If the token is valid, it is simply returned from the database and SharePoint does not try to connect to the Active Directory to get a new token.

2) If the token has timed out, SharePoint attempts to refresh the token by reading the user's tokenGroupsGlobalAndUniversal attribute from Active Directory.

3) If SharePoint is able to read the tokenGroupsGlobalAndUniversal, SharePoint essentially has a list of SIDs (Security Ids) with each SID representing a group.

4) SharePoint then tries to resolve each SID to a group name and eventually updates the token in the database.
<h1>Common Problems with tp_ExternalToken Refresh</h1>
Here are some of the common problems that can occur with tp_ExternalToken fresh and possible resolutions. All of these problems do not result in any error message to the user. We just get a bad token that gets cached in the database for the duration of the timeout. As a result, "Check Permissions" and "DoesUserHavePermisions" simply returns incorrect information. This makes troubleshooting particularly challenging.

<b>Problem #1: </b>SharePoint cannot read the user's tokenGroupsGlobalAndUniversal attribute because the user is in a domain that does not trust SharePoint domain (one-way trust).

<b>Resolution: </b>Adjust the people picker settings to specify a username and password for each domain from which the users can be added to SharePoint. Be sure to run the setapppassword command on each server in the farm before you configure people picker. You have to list every domain from which the users can be added or that domain will not be searched. Here is a sample PowerShell command:

<i>stsadm -o setproperty -pn peoplepicker-searchadforests -pv "domain:domain1.fqdn.com,account,Password;domain:domain2.fqdn.com,account,Password" -url http://webapp</i>

<b>Problem #2: </b>SharePoint timer service account or application pool account does not have permission to read the user's tokenGroupsGlobalAndUniversal attribute.

<b>Resolution: </b>Add the SharePoint accounts to the <b>Windows Authorization Access</b> group by using the Active Directory Users and Computers snap-in.

<b>Problem #3: </b>SharePoint cannot resolve the SID to group name because the group does not exist in the same domain as SharePoint. You may see the following error in ULS logs:

<i>03/29/2017 23:17:01.98 w3wp.exe (0x9DAC) 0x9578 SharePoint Foundation Claims Authentication ame5l Medium SPClaimsAuthRoleProvider.GetTokenGroupsForUser() unable to resolve group SID S-1-5-21-682003330-1957994488-839522115-553146</i>

This problem occurs because SharePoint does not use the Global Catalog to resolve the SID to a group name.

<b>Resolution: </b>A new property of the <b>SPPeoplePickerSettings</b> object named <b>ClaimsAuthRoleProviderUsesGlobalCatalog</b> was introduced with the December 2015 CU for SharePoint. By setting this property, you essentially tell SharePoint to use the Global Catalog when resolving group SIDs. Here is how you can set the property:
<div style="color: #000000">
<pre><span style="color: #ff4500">$w</span> <span style="color: #808080">=</span> Get<span style="color: #808080">-</span>SPWebApplication <span style="color: #ff4500">$url</span> 
<span style="color: #ff4500">$w</span>.PeoplePickerSettings.ClaimsAuthRoleProviderUsesGlobalCatalog <span style="color: #808080">=</span> <span style="color: #ff4500">$true</span> 
<span style="color: #ff4500">$w</span>.Update()</pre>
</div>
<p style="color: #000000"><b>Problem #4: </b>SharePoint tries to enumerate user groups using the Windows API GetAuthorizationGroups. This API has known issues including one that results in this API call to fail if one of the groups that the user is a member of has SID history attached to it. You may see the following errors in the ULS logs:</p>
<p style="color: #000000"><i>System.InvalidOperationException: The server is unwilling to process the request. </i></p>
<p style="color: #000000"><i>System.DirectoryServices.DirectoryServicesCOMException: There is no such object on the server</i></p>
<p style="color: #000000"><b>Resolution: </b>We can force SharePoint to use the "soft" SID resolution method which does not involve a call to GetAuthorizationGroups. This can be done by identifying an account in each domain that is a member of <b>Windows Authorization Access</b> group in that domain. Once the accounts have been identified, we need to set ClaimsAuthRoleProviderUsesGlobalCatalog property to $true as mentioned in Resolution #3 and then configure the people picker settings with a username and password for each domain. Every single domain from which users can be added to SharePoint must be specified or that domain will not be searched.</p>
<p style="color: #000000"><i>stsadm -o setproperty -pn peoplepicker-searchadforests -pv "domain:domain1.fqdn.com,account,Password;domain:domain2.fqdn.com,account,Password" -url http://webapp</i></p>
<p style="color: #000000"><i></i>Be sure to run setapppassword on each server in the farm so that password can be encrypted.</p>
<p style="color: #000000">Happy SharePointing!</p>]]></content:encoded>
    </item>
    <item>
      <title>Automate Preservation/Retention for OneDrive for Business sites using Office 365 Complaince Center PowerShell</title>
      <link>https://docs.microsoft.com/archive/blogs/tehnoonr/automate-preservationretention-for-onedrive-for-business-sites-using-office-365-complaince-center-powershell</link>
      <pubDate>Sun, 02 Jul 2017 00:41:00 GMT</pubDate>
      <dc:creator><![CDATA[Tehnoon Raza [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/tehnoonr/?p=225</guid>
      <description><![CDATA[I worked on a small project a few months back where we had to automate retention/preservation for...]]></description>
      <content:encoded><![CDATA[I worked on a small project a few months back where we had to automate retention/preservation for OneDrive for Business sites in Office 365. Here is what the high level requirements were for the automation:
<ol>
 	<li>An attribute of the user object in the On-premise Active Directory will determine whether the user’s OneDrive site should be placed on an indefinite hold . The attribute being used in this case was “extensionAttribute13”.</li>
 	<li>The “extensionAttribute13” for each user in the On-Premise Active Directory can either be empty/null or it can have a value “DONOTPURGE”. A value of “DONOTPURGE” indicates that the user’s OneDrive for Business site has to be put on legal hold. An empty/null value for the attribute means that the user’s OneDrive for Business site should NOT be put on hold, and the hold should be released if the site was previously on hold.</li>
</ol>
I decided to use <a href="https://technet.microsoft.com/en-us/library/mt587091(v=exchg.160).aspx">Office 365 Compliance Center PowerShell</a> to implement the automation. However, there were two major challenges in this implementation:
<ol>
 	<li>We had to use a “specific-location” retention policy instead of an org-wide policy. As documented <a href="https://support.office.com/en-us/article/Overview-of-retention-policies-5e377752-700d-4870-9b6d-12bfc12d2423">here</a>, a location-specific policy can only contain 100 SharePoint/OneDrive sites. The number of users with retention hold could be several hundred so a single policy wouldn’t be enough to hold all the sites. The script had to be intelligent enough to dynamically create new policies if no empty “slots” were found in the existing policies. I mention “slots” here since we could have a situation where a policy was previously full which could have resulted in creation of new policies, however, some users in that policy had their hold released afterwards and now the policy has empty “slots” which should be reused.</li>
 	<li>We had to dynamically determine the user’s OneDrive for Business site Url in Office 365 based on the user object in Active Directory. One approach that we could have used is documented <a href="https://technet.microsoft.com/en-us/library/dn911464.aspx">here</a>. However, this approach wouldn’t work if let’s say the script was run after the user’s profile had been marked for deletion because they have left the company, but the user’s OneDrive site was still not deleted as there is a default 30-day retention period, and there was a requirement to place an indefinite retention hold on that site. See <a href="https://support.microsoft.com/en-us/help/3042522/onedrive-for-business-retention-and-deletion">this</a> article to learn more about the default preservation/retention for OneDrive for Business sites. To address this challenge, I decided to use the user’s UPN which is also stored in the on-premise Active Directory to determine their OneDrive site dynamically. This is not the best approach, as it’s not very reliable, but this was the best one we could use.</li>
</ol>
The first part of the script is to initialize all the configuration variables which would need to be adjusted for every environment. The script also assumes that the initial retention policy (“test” in this example) has already been created. Here is the initialization section of the script:
<pre class="brush: powershell; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">############################## Begin Configuration #####################################################
#The logFileLocation is a folder where logs will be created and it must already exist
$logFileLocation = "C:\RetentionLogs" 
#The Url of the SPO Service for this tenant
$spoTenant = "https://therazas-admin.sharepoint.com"
#OneDrive site root
$odbSiteRoot = "https://therazas-my.sharepoint.com/personal"
#The UPN of the tenant admin
$tenantAdmin = "admin@therazas.onmicrosoft.com"
#The encrypted password will be stored here. If we don't find the file, we will simply prompt for password and save it here
$passwordFile = [System.Environment]::GetFolderPath('ApplicationData') + "\AdminPassword.txt"
#The Complaince center connection Uri. This won't need to be changed in most cases and its global
$complainceCenterUri = "https://ps.compliance.protection.outlook.com/powershell-liveid/"
#Name of the preservation policy
$policyName = "test"
#Maximum sites per policy
$MaxSitesPerPolicy = 100
#The AD search root for users
$searchRoot = "LDAP://dc=tmr,dc=com"
#Attribute Name that we will query AD for
$attributeName = "extensionAttribute13"
#Value of attributeName that will put the ODB Site on hold
$litigationHoldValue = "DONOTPURGE"
############################## End Configuration #####################################################
</pre>
Here are some of the functions in the script:
<ol>
 	<li>Write-LogFile: A function that simply logs messages in a log file for troubleshooting and understanding of what the script is doing.</li>
 	<li>Retrieve-Credentials: Saves/retrieves the password for the $tenantAdmin account to/from an encrypted file on the local computer. The file is stored at the $passwordFile path.</li>
 	<li>Ensure-Policies: This function is responsible for creating additional retention policies if needed to ensure that one policy does not contain more than 100 sites. The new policies will be based on on the initial policy name defined in $policyName variable. The new policies will have a number attached to them (1, 2, 3… and so on).</li>
 	<li>Get-SitesInPolicy: Returns all sites that are added to one of the preservation policies. We have to retrieve this information to determine which users should have their retention hold released if the attribute has been cleared.</li>
 	<li>Add-SiteToPolicy: Finds an open “slot” in the policies that exist and adds the site to the first available slot.</li>
 	<li>Remove-SiteFromPolicy: Removes the specified site from the policy. There could be multiple policies to check so we loop through each policy until we find the site.</li>
</ol>
The complete script is provided below. Don’t forget to update the configuration section and install the latest version of SharePoint Online management shell before running the script.
<pre class="brush: powershell; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: false; light: false; ruler: false; smart-tabs: true; tab-size: 4; toolbar: true;">Import-Module Microsoft.Online.SharePoint.PowerShell -DisableNameChecking

############################## Begin Configuration #####################################################
#The logFileLocation is a folder where logs will be created and it must already exist
$logFileLocation = "C:\RetentionLogs" 
#The Url of the SPO Service for this tenant
$spoTenant = "https://therazas-admin.sharepoint.com"
#OneDrive site root
$odbSiteRoot = "https://therazas-my.sharepoint.com/personal"
#The UPN of the tenant admin
$tenantAdmin = "admin@therazas.onmicrosoft.com"
#The encrypted password will be stored here. If we don't find the file, we will simply prompt for password and save it here
$passwordFile = [System.Environment]::GetFolderPath('ApplicationData') + "\AdminPassword.txt"
#The Complaince center connection Uri. This won't need to be changed in most cases and its global
$complainceCenterUri = "https://ps.compliance.protection.outlook.com/powershell-liveid/"
#Name of the preservation policy
$policyName = "test"
#Maximum sites per policy
$MaxSitesPerPolicy = 100
#The AD search root for users
$searchRoot = "LDAP://dc=tmr,dc=com"
#Attribute Name that we will query AD for
$attributeName = "extensionAttribute13"
#Value of attributeName that will put the ODB Site on hold
$litigationHoldValue = "DONOTPURGE"
############################## End Configuration #####################################################
$Session = $null
#Logs the desired message to the log file location
Function Write-LogFile ([String]$Message)
{
	$Message = "[" + [DateTime]::Now.ToString() + "] " + $Message
	if (Test-Path $logFileLocation)
	{
		$fileName = $logFileLocation + "\" +  [DateTime]::Now.ToShortDateString().Replace("/", "_") + ".txt"
		$Message | Out-File $fileName -Append -Force
	}
	else
	{
		$errorM = "Log File Location " + $logFileLocation + " not found..."
		Write-Output $errorM
		Write-Output $Message
	}
}

Function Retrieve-Credentials ([Boolean]$SPO=$false)
{
	   if (Test-Path $passwordFile)
      {
            $securePassword = Get-Content -Path $passwordFile | ConvertTo-SecureString
      }
      else
      {
            $securePassword = Read-Host -Prompt "Enter password" -AsSecureString
            $securePassword | ConvertFrom-SecureString | Out-File -FilePath $passwordFile -Force
      }
	  if ($SPO -eq $true)
	  {
	  	$creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($tenantAdmin, $securePassword)
	  }
	  else
	  {
	  	$creds = New-Object System.Management.Automation.PSCredential($tenantAdmin, $securePassword)
	  }
	  return $creds
}

#This function accepts $TotalSites as a parameter which is the total number of sites in the environment that have a preservation hold for ODB sites
Function Ensure-Policies ([Int]$TotalSites)
{
	$currentPolicyName = $policyName
	[Int]$reqNumber = $TotalSites/$MaxSitesPerPolicy
	if ($TotalSites%$MaxSitesPerPolicy -eq 0)
	{
		$reqNumber = $reqNumber - 1
	}
	#Let's make sure the "base" policy exists to avoid unintentional policy creation. This will throw an exception if policy does not exist
	$policy = $null
	try
	{
		$policy = Get-RetentionCompliancePolicy -Identity $policyName
	}
	catch
	{
		$policy = $null
	}
	if ($policy -eq $null)
	{
		throw [System.InvalidOperationException] "Complaince policy $policyName does not exist. Please check the name and try again."
	}
	#We need to ensure that we have $reqNumber of polcies created with the naming format $policyName1, $policyName2 and so on...
	for($i = 1; $i -le $reqNumber; $i++)
	{
		$currentPolicyName = $policyName + $i
		$policy = $null
		try
		{
			$policy = Get-RetentionCompliancePolicy -Identity $currentPolicyName
		}
		catch
		{
			$policy = $null
		}
		if ($policy -eq $null)
		{
			#This means the policy does not exist. We need to create it
			$message = "Creating preservation policy $currentPolicyName with indefinite hold..."
			Write-LogFile $message
			$policy = New-RetentionCompliancePolicy -Name $currentPolicyName
			$rule = New-RetentionComplianceRule -Name "Indefinite Hold for $currentPolicyName" -Policy $currentPolicyName -PreservationDuration Unlimited
		}
	}
}

#Returns an ArrayList of all sites in preservation policies)
Function Get-SitesInPolicy
{
	$sitesList = New-Object System.Collections.ArrayList
	$currentPolicyName = $policyName
	$i = 0
	while ($true)
	{
		$policy = $null
		try
		{
			$policy = Get-RetentionCompliancePolicy -Identity $currentPolicyName
		}
		catch
		{
			$policy = $null
		}
		if ($policy -eq $null)
		{
			break
		}
		foreach ($location in $policy.SharePointLocation)
		{
			$x = $sitesList.Add($location.Name)
		}
		$i = $i + 1
		$currentPolicyName = $policyName + $i
	}
	return ,$sitesList
}

#Adds the specified site to an availalbe "slot" in the policies. 
Function Add-SiteToPolicy ([String]$SiteUrl)
{
	$currentPolicyName = $policyName
	$i = 0
	while ($true)
	{
		$policy = Get-RetentionCompliancePolicy -Identity $currentPolicyName
		if ($policy.SharePointLocation.Count -lt $MaxSitesPerPolicy)
		{
			$message = "Adding site " + $SiteUrl + " to the preservation policy " + $currentPolicyName
			Write-LogFile $message
			Set-RetentionCompliancePolicy -Identity $currentPolicyName -AddSharePointLocation $SiteUrl
			break
		}
		$i = $i + 1
		$currentPolicyName = $policyName + $i
	}
}

#Removes the specified site from the list of policies
Function Remove-SiteFromPolicy ([String]$SiteUrl)
{
	$currentPolicyName = $policyName
	$i = 0
	while ($true)
	{
		$policy = Get-RetentionCompliancePolicy -Identity $currentPolicyName
		foreach ($location in $policy.SharePointLocation)
		{
			if ($location.Name.Equals($SiteUrl))
			{
				$message = "Removing site " + $SiteUrl + " from the policy " + $currentPolicyName
				Write-LogFile $message
				Set-RetentionCompliancePolicy -Identity $currentPolicyName -RemoveSharePointLocation $SiteUrl
				return
			}
		}
		$i = $i + 1
		$currentPolicyName = $policyName + $i
	}
}
#Query the AD
try
{
	$old_ErrorActionPreference = $ErrorActionPreference
	$ErrorActionPreference = 'Stop'
	Write-LogFile "******************************Starting Script Execution******************************"
	$message = "Querying Active Directory for accounts on legal hold at path " + $searchRoot
	Write-LogFile $message
	$objOU = New-Object System.DirectoryServices.DirectoryEntry($searchRoot)
	$strFilter = "(&amp;(objectCategory=User)("+$attributeName+"=" + $litigationHoldValue + "))"
	$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
	$objSearcher.SearchRoot = $objOU
	$objSearcher.PageSize = 1000
	$objSearcher.Filter = $strFilter
	$objSearcher.SearchScope = "Subtree"
	$colProplist = "userPrincipalName"
	foreach ($i in $colPropList){$x = $objSearcher.PropertiesToLoad.Add($i)}
	$colResults = $objSearcher.FindAll()
	$message = "Found " + $colResults.Count + " result(s) from the AD search query"
	Write-LogFile $message
	$message = "Connecting to SPO service at url " + $spoTenant + " for validating ODB Sites" 
	Write-LogFile $message
	$creds = Retrieve-Credentials
	Connect-SPOService -Url $spoTenant -Credential $creds
	$userTable = New-Object System.Collections.Hashtable($colResults.Count)
	foreach ($objResult in $colResults)
	{
		#Updated 4/15 to handle the null UPN scenario
		$upnValue = $objResult.Properties["userPrincipalName"][0]
		if ($upnValue -eq $null)
		{
			#User does not have UPN Set. Continue
			Write-LogFile "Found user without UPN set. Skipping..."
			continue
		}
		$upn = $upnValue.ToString() 
		#Calculate the ODB Site Url
		$odbSite = $upn.Replace("@", "_")
		$odbSite = $odbSite.Replace(".", "_")
		$odbSite = $odbSite.Replace("-", "_")
		$odbSite = $odbSiteRoot + "/" + $odbSite
		$message = "Checking if ODB site for user " + $upn + " exists at " + $odbSite
		Write-LogFile $message
		try
		{
			$site = Get-SPOSite $odbSite
		}
		catch
		{
			$site = $null
		}
		if ($site -eq $null)
		{
			Write-LogFile "Site Not Found, Skipping this user..."
			continue
		}
		Write-LogFile "Site Found!"
		$userTable.Add($upn, $odbSite)
	}
	#$userTable now contains all users with valid ODB Sites. 
	#Let's make sure we have the required number of policies created (1 Policy = 100 sites)
	#Connect to the complaince center
	$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $complainceCenterUri -Credential $creds -Authentication Basic -AllowRedirection -WarningAction Ignore
	$x = Import-PSSession $Session
	Ensure-Policies -TotalSites $userTable.Count 
	#Next, we need to remove all ODB Sites that are already in the preservation policy
	$sitesList = Get-SitesInPolicy
	#Now lets determine which sites we need to add to policy
	$allUsers = $userTable.Keys.GetEnumerator()
	$addCount = 0
	while ($allUsers.MoveNext())
	{
		$currentUser = $allusers.Current
		$currentSite = $userTable[$currentUser]
		#Check if this site is already in the policy
		if ($sitesList.Contains($currentSite))
		{
			$message = "ODB Site for user " + $currentUser + " is already in the preservation policy. Skipping"
			Write-LogFile $message
			#Remove this site from the list so we can release the hold on the remaining sites
			$sitesList.Remove($currentSite)
		}
		else
		{
			try
			{
				Add-SiteToPolicy -SiteUrl $currentSite
				#Set-RetentionCompliancePolicy -Identity $policyName -AddSharePointLocation $currentSite
				$addCount = $addCount + 1
			}
			catch
			{
				Write-LogFile "Error Ocurred while adding site to policy." 
				Write-LogFile $_.Exception.Message
			}
		}
	}
	$message = "Sucessfully Added " + $addCount + " site(s) to the preservation policy"
	Write-LogFile $message
	#Now let's remove the sites from the hold. Everything left in $sitesList needs to be removed. The user either does not exist in AD or does not has $litigationHoldValue set.
	$removeCount = 0
	foreach ($siteUrl in $sitesList)
	{
		try
		{
			#Set-RetentionCompliancePolicy -Identity $policyName -RemoveSharePointLocation $siteUrl
			Remove-SiteFromPolicy -SiteUrl $siteUrl
			$removeCount = $removeCount + 1
		}
		catch
		{
			Write-LogFile "Error Ocurred while removing site from policy." 
			Write-LogFile $_.Exception.Message
		}
	}
	$message = "Sucessfully Removed " + $removeCount + " site(s) from the preservation policy"
	Write-LogFile $message
	Write-LogFile "******************************Ending Script Execution******************************"
}
catch 
{
	Write-LogFile "Error Ocurred." 
	Write-LogFile $_.Exception.Message
	#Updated 4/15 to handle the null UPN scenario
	Write-LogFile $_.ScriptStackTrace

}
finally
{
	#Clear the complaince center session
	if ($Session -ne $null)
	{
		Remove-PSSession $Session
	}
	$ErrorActionPreference = $old_ErrorActionPreference
}
</pre>
Happy SharePointing!]]></content:encoded>
    </item>
    <item>
      <title>SharePoint 2013: August 2015 Cumulative Update Package Fails to Install</title>
      <link>https://docs.microsoft.com/archive/blogs/tehnoonr/sharepoint-2013-august-2015-cumulative-update-package-fails-to-install</link>
      <pubDate>Fri, 28 Aug 2015 08:41:17 GMT</pubDate>
      <dc:creator><![CDATA[Tehnoon Raza [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/tehnoonr/2015/08/28/sharepoint-2013-august-2015-cumulative-update-package-fails-to-install/</guid>
      <description><![CDATA[Update 9/17/2015: The issue has been fixed. See Solution for details  The Problem  The August 2015...]]></description>
      <content:encoded><![CDATA[<p><em><font size="3"><strong>Update 9/17/2015: The issue has been fixed. See Solution for details</strong></font></em></p>  <p><strong><font size="4">The Problem</font></strong></p>  <p><font size="2">The August 2015 Cumulative Update for SharePoint 2013 was released earlier this month as mentioned in Stefan’s Goßner’s blog post </font><a href="http://blogs.technet.com/b/stefan_gossner/archive/2015/08/11/august-2015-cu-for-sharepoint-2013-is-available-for-download.aspx"><font size="2">here</font></a><font size="2">. The installation of the August 2015 Cumulative Update server package may fail with the following error:</font></p>  <p><font size="2">“The installation of this package failed”</font></p>  <p><font size="2">The error above is a generic error and can occur due to a variety of different reasons such as low disk space, incorrect package download etc. However, for the August 2015 Public Update we have received several reports over the past few days of this issue occurring on multiple machines. In all these occurrences, the root cause of the package installation failure was found to be the following messages in the latest modified MSP log file (e.g. wssmui-en-us_MSPLOG.LOG, but the actual file name in your case could be different depending on which package failed to install) located in the temp folder of the server where you are installing the package (by default, it is C:\Users\username\AppData\Local\Temp\2):</font></p>  <p><font color="#ff0000" size="2"><strong>CAQuietExec:&#160; Error 0x8007000d: CAQuietExec Failed</strong></font></p>  <p><font color="#ff0000" size="2"><strong>CustomAction RegisterPerfmonManifest returned actual error code 1603 (note this may not be 100% accurate if translation happened inside sandbox)</strong></font></p>  <p><strong><font size="4">The Workaround</font></strong></p>  <p><font size="2">The best workaround for this issue is to simply run the installation package 3 times. The package will fail to install with the above error on the first two attempts, but should be successful on the third attempt.&#160; The installation will not be corrupt and there are no other known issues once you have the update package successfully installed. </font></p>  <p><font size="2"><strong>Note</strong>: A previous version of this blog post mentioned a registry key workaround which is not as effective as originally thought. If the installation package continues to fail with the error mentioned above even after the 3rd attempt, please let me know. </font></p>  <p><strong><font size="4">The Root Cause</font></strong></p>  <p><font size="3"><font size="2">The issue was being caused due to an error while registering a new Performance Counter within the SharePoint Search sub-system. </font></font></p>  <p><strong><font size="4">The Solution</font></strong></p>  <p><font size="3"><font size="2">The issue has been fixed with the September 2015 Server/Uber packages for SharePoint 2013 which were released last night (9/16/2015). If you haven’t already installed the August 2015 Server/Uber package, you may install the September 2015 Uber/Server package in your farm which includes all updates since SP1 and also has the package installation issue fixed. Please note that you must already have <a href="http://blogs.technet.com/b/stefan_gossner/archive/2014/04/22/sp1-for-sharepoint-2013-has-been-rereleased.aspx">SharePoint Server 2013 Service Pack 1</a> installed before installing this package. The relevant full server packages (aka Uber packages) can be downloaded at the links below:</font></font></p>  <ul>   <li><font size="2"><a href="http://www.microsoft.com/en-us/download/details.aspx?id=49097">Download SharePoint Foundation 2013 September 2015 CU</a></font></li>    <li><font size="2"><a href="http://www.microsoft.com/en-us/download/details.aspx?id=49098">Download SharePoint Server 2013 September 2015 CU</a></font></li>    <li><font size="2"><a href="http://www.microsoft.com/en-us/download/details.aspx?id=49099">Download Project Server 2013 September 2015 CU</a></font></li> </ul>]]></content:encoded>
    </item>
    <item>
      <title>Safari 7.1 on MAC Computers causes multiple Issues with SharePoint</title>
      <link>https://docs.microsoft.com/archive/blogs/tehnoonr/safari-7-1-on-mac-computers-causes-multiple-issues-with-sharepoint</link>
      <pubDate>Mon, 27 Oct 2014 15:20:08 GMT</pubDate>
      <dc:creator><![CDATA[Tehnoon Raza [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/tehnoonr/2014/10/27/safari-7-1-on-mac-computers-causes-multiple-issues-with-sharepoint/</guid>
      <description><![CDATA[The Issue  Apple recently released a new version of Safari for MAC computers. The browser version is...]]></description>
      <content:encoded><![CDATA[<p><strong><font size="4">The Issue</font></strong></p>  <p>Apple recently released a new version of Safari for MAC computers. The browser version is 7.1. The browser might be great, but SharePoint 2010 as well as MOSS 2007 all of a sudden have a number of User Interface issues including but not limited to:</p>  <ol>   <li>SharePoint navigation menus not functioning correctly </li>    <li>SharePoint ribbon menu options being disabled for all users </li>    <li>SharePoint People picker appears to hang when searching for a user </li> </ol>  <p><strong><font size="4">The Cause</font></strong></p>  <p>I have to be honest, there is nothing wrong with the new browser. As you may already know, SharePoint 2010 and MOSS 2007 are just web applications that are based on ASP.NET 2.0. The root cause of this issue lies at the ASP.NET layer and can affect any ASP.NET 2.0 web application. The issue does not exist in ASP.NET 4.0 and as a result, SharePoint 2013 is not impacted by this problem. </p>  <p>ASP.NET reads the user agent of the incoming request, and using regular expressions, assigns a Browser ID to the incoming request. ASP.NET uses browser definition files to assign browser IDs. The browser IDs are then used to enable or disable “capabilities” such as AJAX, certain types of controls etc. Applications such as SharePoint also use the browser ID to change the way they render content to achieve the best user experience.&#160; These browser definition files are located by default at <em>Drive:</em>\Windows\Microsoft.NET\Framework64\v2.0.50727\CONFIG\Browsers. The user agent for Safari 6.0 contained <strong>AppleWebKit/536.26 </strong>and ASP.NET was assigning the browser ID &quot;Safari1Plus&quot; to this and other recent Safari browsers based on the following entry in Mozilla.browser:</p>  <div id="codeSnippetWrapper" style="font-size: 8pt; overflow: auto; cursor: text; border-top: silver 1px solid; font-family: &#39;Courier New&#39;, courier, monospace; border-right: silver 1px solid; width: 97.5%; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; border-left: silver 1px solid; margin: 20px 0px 10px; line-height: 12pt; padding-right: 4px; max-height: 200px; background-color: #f4f4f4">   <div id="codeSnippet" style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4">     <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white"><span id="lnum1" style="color: #606060">   1:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">browser</span> <span style="color: #ff0000">id</span><span style="color: #0000ff">=&quot;Safari1Plus&quot;</span> <span style="color: #ff0000">parentID</span><span style="color: #0000ff">=&quot;Safari&quot;</span><span style="color: #0000ff">&gt;</span></pre>
<!--CRLF-->

    <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span id="lnum2" style="color: #606060">   2:</span>        <span style="color: #0000ff">&lt;</span><span style="color: #800000">identification</span><span style="color: #0000ff">&gt;</span></pre>
<!--CRLF-->

    <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white"><span id="lnum3" style="color: #606060">   3:</span>            <span style="color: #0000ff">&lt;</span><span style="color: #800000">capability</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;appleWebTechnologyVersion&quot;</span> <span style="color: #ff0000">match</span><span style="color: #0000ff">=&quot;\d\d\d&quot;</span> <span style="color: #0000ff">/&gt;</span></pre>
<!--CRLF-->

    <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span id="lnum4" style="color: #606060">   4:</span>        <span style="color: #0000ff">&lt;/</span><span style="color: #800000">identification</span><span style="color: #0000ff">&gt;</span></pre>
<!--CRLF-->

    <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white"><span id="lnum5" style="color: #606060">   5:</span>        <span style="color: #0000ff">&lt;</span><span style="color: #800000">capture</span><span style="color: #0000ff">&gt;</span></pre>
<!--CRLF-->

    <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span id="lnum6" style="color: #606060">   6:</span>        <span style="color: #0000ff">&lt;/</span><span style="color: #800000">capture</span><span style="color: #0000ff">&gt;</span></pre>
<!--CRLF-->

    <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white"><span id="lnum7" style="color: #606060">   7:</span>        <span style="color: #0000ff">&lt;</span><span style="color: #800000">capabilities</span><span style="color: #0000ff">&gt;</span></pre>
<!--CRLF-->

    <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span id="lnum8" style="color: #606060">   8:</span>            <span style="color: #0000ff">&lt;</span><span style="color: #800000">capability</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;ecmascriptversion&quot;</span>       <span style="color: #ff0000">value</span><span style="color: #0000ff">=&quot;1.4&quot;</span> <span style="color: #0000ff">/&gt;</span></pre>
<!--CRLF-->

    <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white"><span id="lnum9" style="color: #606060">   9:</span>            <span style="color: #0000ff">&lt;</span><span style="color: #800000">capability</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;w3cdomversion&quot;</span>           <span style="color: #ff0000">value</span><span style="color: #0000ff">=&quot;1.0&quot;</span> <span style="color: #0000ff">/&gt;</span></pre>
<!--CRLF-->

    <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span id="lnum10" style="color: #606060">  10:</span>            <span style="color: #0000ff">&lt;</span><span style="color: #800000">capability</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;supportsCallback&quot;</span>        <span style="color: #ff0000">value</span><span style="color: #0000ff">=&quot;true&quot;</span> <span style="color: #0000ff">/&gt;</span></pre>
<!--CRLF-->

    <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white"><span id="lnum11" style="color: #606060">  11:</span>        <span style="color: #0000ff">&lt;/</span><span style="color: #800000">capabilities</span><span style="color: #0000ff">&gt;</span></pre>
<!--CRLF-->

    <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span id="lnum12" style="color: #606060">  12:</span> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">browser</span><span style="color: #0000ff">&gt;</span></pre>
<!--CRLF--></div>
</div>

<p>Notice how the regular expression “\d\d\d” on line 3 results in a match for 536.26 and as a result, a browser ID of “Safari1Plus” gets assigned to requests with this user agent. SharePoint 2010, rightly so, assumes that the latest version of Safari would have the ID “Safari1Plus”. </p>

<p>Several years ago, there used to be a Safari browser that had <strong>AppleWebKit/60 </strong>in the user agent string. ASP.NET uses the browser ID “Safari60” for these browsers and does not enable AJAX since the browser is so old. Here is the entry in Mozilla.browser that was added for these old Safari browsers:</p>

<div id="codeSnippetWrapper" style="font-size: 8pt; overflow: auto; cursor: text; border-top: silver 1px solid; font-family: &#39;Courier New&#39;, courier, monospace; border-right: silver 1px solid; width: 97.5%; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; border-left: silver 1px solid; margin: 20px 0px 10px; line-height: 12pt; padding-right: 4px; max-height: 200px; background-color: #f4f4f4">
  <div id="codeSnippet" style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4">
    <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white"><span id="lnum1" style="color: #606060">   1:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">browser</span> <span style="color: #ff0000">id</span><span style="color: #0000ff">=&quot;Safari60&quot;</span> <span style="color: #ff0000">parentID</span><span style="color: #0000ff">=&quot;Safari&quot;</span><span style="color: #0000ff">&gt;</span></pre>
<!--CRLF-->

    <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span id="lnum2" style="color: #606060">   2:</span>        <span style="color: #0000ff">&lt;</span><span style="color: #800000">identification</span><span style="color: #0000ff">&gt;</span></pre>
<!--CRLF-->

    <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white"><span id="lnum3" style="color: #606060">   3:</span>            <span style="color: #0000ff">&lt;</span><span style="color: #800000">capability</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;appleWebTechnologyVersion&quot;</span> <span style="color: #ff0000">match</span><span style="color: #0000ff">=&quot;60&quot;</span> <span style="color: #0000ff">/&gt;</span></pre>
<!--CRLF-->

    <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span id="lnum4" style="color: #606060">   4:</span>        <span style="color: #0000ff">&lt;/</span><span style="color: #800000">identification</span><span style="color: #0000ff">&gt;</span></pre>
<!--CRLF-->

    <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white"><span id="lnum5" style="color: #606060">   5:</span>        <span style="color: #0000ff">&lt;</span><span style="color: #800000">capture</span><span style="color: #0000ff">&gt;</span></pre>
<!--CRLF-->

    <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span id="lnum6" style="color: #606060">   6:</span>        <span style="color: #0000ff">&lt;/</span><span style="color: #800000">capture</span><span style="color: #0000ff">&gt;</span></pre>
<!--CRLF-->

    <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white"><span id="lnum7" style="color: #606060">   7:</span>        <span style="color: #0000ff">&lt;</span><span style="color: #800000">capabilities</span><span style="color: #0000ff">&gt;</span></pre>
<!--CRLF-->

    <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span id="lnum8" style="color: #606060">   8:</span>            <span style="color: #0000ff">&lt;</span><span style="color: #800000">capability</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;ecmascriptversion&quot;</span>       <span style="color: #ff0000">value</span><span style="color: #0000ff">=&quot;1.0&quot;</span> <span style="color: #0000ff">/&gt;</span></pre>
<!--CRLF-->

    <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white"><span id="lnum9" style="color: #606060">   9:</span>        <span style="color: #0000ff">&lt;/</span><span style="color: #800000">capabilities</span><span style="color: #0000ff">&gt;</span></pre>
<!--CRLF-->

    <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span id="lnum10" style="color: #606060">  10:</span>  <span style="color: #0000ff">&lt;/</span><span style="color: #800000">browser</span><span style="color: #0000ff">&gt;</span></pre>
<!--CRLF--></div>
</div>

<p>The problem is that Safari 7.1 has <strong>AppleWebKit/600.1.17 </strong>in the user agent string and as a result, it ends up getting matched with the <strong>Safari60 </strong>definition. The regular expression here (line 3 in the snippet above) should have been ^60$ to avoid a match for 600. Because the BrowserId is incorrectly detected as Safari60, SharePoint does not enable the Menu controls for this browser Id. Also, due to a missing <strong>supportsCallback </strong>attribute in the browser definition file, AJAX calls do not function correctly which SharePoint uses when working with Ribbons and the people picker. </p>

<p><strong><font size="4">The Solution</font></strong></p>

<p><strong>Update : A permanent fix for this issue was released with the March 2015 Public Update for SharePoint 2010. If you install this or a later update, you will not need to apply the workaround mentioned below. I highly recommend upgrading your environment to the latest version instead of relying on the manual workaround. However, if you cannot immediately upgrade, you may use the workaround temporarily. </strong></p>

<p>The ideal solution would be to update the Mozilla.browser file located at <em>Drive:</em>\Windows\Microsoft.NET\Framework64\v2.0.50727\CONFIG\Browsers with correct regular expressions (<strong>^60$ </strong>for Safari60 and <strong>^85$</strong> for Safari85) and then run <strong>aspnet_regbrowsers.exe –i</strong> to re-deploy the browser definitions to all applications. However, strictly speaking, Mozilla.browser file is a system file that may get updated by a future Microsoft update and overwrite your changes. Keeping that in mind, the best solution would be to create a new browser definition file in the local IIS virtual directory for the affected SharePoint web applications. Here are the steps that you can use to apply this solution:</p>

<ol>
  <li>Inside the App_Browsers folder for your SharePoint web application (usually located at <em>Drive</em>:\inetpub\wwwroot\wss\VirtualDirectories\<em>port</em>\App_Browsers), create a new text file named <b>safari.browser </b>(Please ensure it is not safari.browser.txt, <b>.browser</b> must be the extension of the file) </li>

  <li>Add the following text to the file: 
    <div id="codeSnippetWrapper" style="font-size: 8pt; overflow: auto; cursor: text; border-top: silver 1px solid; font-family: &#39;Courier New&#39;, courier, monospace; border-right: silver 1px solid; width: 97.5%; border-bottom: silver 1px solid; padding-bottom: 4px; direction: ltr; text-align: left; padding-top: 4px; padding-left: 4px; border-left: silver 1px solid; margin: 20px 0px 10px; line-height: 12pt; padding-right: 4px; max-height: 200px; background-color: #f4f4f4">
      <div id="codeSnippet" style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4">
        <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white"><span id="lnum1" style="color: #606060">   1:</span> <span style="color: #0000ff">&lt;?</span><span style="color: #800000">xml</span> <span style="color: #ff0000">version</span><span style="color: #0000ff">=&quot;1.0&quot;</span> <span style="color: #ff0000">encoding</span><span style="color: #0000ff">=&quot;utf-8&quot;</span> ?<span style="color: #0000ff">&gt;</span></pre>
<!--CRLF-->

        <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span id="lnum2" style="color: #606060">   2:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">browsers</span><span style="color: #0000ff">&gt;</span></pre>
<!--CRLF-->

        <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white"><span id="lnum3" style="color: #606060">   3:</span>   <span style="color: #0000ff">&lt;</span><span style="color: #800000">browser</span> <span style="color: #ff0000">id</span><span style="color: #0000ff">=&quot;Safari6xxFix&quot;</span> <span style="color: #ff0000">parentID</span><span style="color: #0000ff">=&quot;Safari60&quot;</span><span style="color: #0000ff">&gt;</span></pre>
<!--CRLF-->

        <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span id="lnum4" style="color: #606060">   4:</span>     <span style="color: #0000ff">&lt;</span><span style="color: #800000">identification</span><span style="color: #0000ff">&gt;</span></pre>
<!--CRLF-->

        <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white"><span id="lnum5" style="color: #606060">   5:</span>       <span style="color: #0000ff">&lt;</span><span style="color: #800000">capability</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;appleWebTechnologyVersion&quot;</span> <span style="color: #ff0000">match</span><span style="color: #0000ff">=&quot;60\d&quot;</span> <span style="color: #0000ff">/&gt;</span></pre>
<!--CRLF-->

        <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span id="lnum6" style="color: #606060">   6:</span>     <span style="color: #0000ff">&lt;/</span><span style="color: #800000">identification</span><span style="color: #0000ff">&gt;</span></pre>
<!--CRLF-->

        <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white"><span id="lnum7" style="color: #606060">   7:</span>     <span style="color: #0000ff">&lt;</span><span style="color: #800000">capture</span><span style="color: #0000ff">&gt;</span></pre>
<!--CRLF-->

        <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span id="lnum8" style="color: #606060">   8:</span>     <span style="color: #0000ff">&lt;/</span><span style="color: #800000">capture</span><span style="color: #0000ff">&gt;</span></pre>
<!--CRLF-->

        <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white"><span id="lnum9" style="color: #606060">   9:</span>     <span style="color: #0000ff">&lt;</span><span style="color: #800000">capabilities</span><span style="color: #0000ff">&gt;</span></pre>
<!--CRLF-->

        <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span id="lnum10" style="color: #606060">  10:</span>        <span style="color: #0000ff">&lt;</span><span style="color: #800000">capability</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;ecmascriptversion&quot;</span>       <span style="color: #ff0000">value</span><span style="color: #0000ff">=&quot;1.4&quot;</span> <span style="color: #0000ff">/&gt;</span></pre>
<!--CRLF-->

        <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white"><span id="lnum11" style="color: #606060">  11:</span>        <span style="color: #0000ff">&lt;</span><span style="color: #800000">capability</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;w3cdomversion&quot;</span>           <span style="color: #ff0000">value</span><span style="color: #0000ff">=&quot;1.0&quot;</span> <span style="color: #0000ff">/&gt;</span></pre>
<!--CRLF-->

        <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span id="lnum12" style="color: #606060">  12:</span>        <span style="color: #0000ff">&lt;</span><span style="color: #800000">capability</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">=&quot;supportsCallback&quot;</span>        <span style="color: #ff0000">value</span><span style="color: #0000ff">=&quot;true&quot;</span> <span style="color: #0000ff">/&gt;</span></pre>
<!--CRLF-->

        <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white"><span id="lnum13" style="color: #606060">  13:</span>     <span style="color: #0000ff">&lt;/</span><span style="color: #800000">capabilities</span><span style="color: #0000ff">&gt;</span></pre>
<!--CRLF-->

        <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span id="lnum14" style="color: #606060">  14:</span>     <span style="color: #0000ff">&lt;</span><span style="color: #800000">controlAdapters</span><span style="color: #0000ff">&gt;</span></pre>
<!--CRLF-->

        <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white"><span id="lnum15" style="color: #606060">  15:</span>       <span style="color: #0000ff">&lt;</span><span style="color: #800000">adapter</span> <span style="color: #ff0000">controlType</span><span style="color: #0000ff">=&quot;System.Web.UI.WebControls.Menu&quot;</span></pre>
<!--CRLF-->

        <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span id="lnum16" style="color: #606060">  16:</span>                <span style="color: #ff0000">adapterType</span><span style="color: #0000ff">=&quot;&quot;</span> <span style="color: #0000ff">/&gt;</span></pre>
<!--CRLF-->

        <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white"><span id="lnum17" style="color: #606060">  17:</span>     <span style="color: #0000ff">&lt;/</span><span style="color: #800000">controlAdapters</span><span style="color: #0000ff">&gt;</span></pre>
<!--CRLF-->

        <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: #f4f4f4"><span id="lnum18" style="color: #606060">  18:</span>   <span style="color: #0000ff">&lt;/</span><span style="color: #800000">browser</span><span style="color: #0000ff">&gt;</span></pre>
<!--CRLF-->

        <pre style="border-top-style: none; font-size: 8pt; overflow: visible; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; background-color: white"><span id="lnum19" style="color: #606060">  19:</span> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">browsers</span><span style="color: #0000ff">&gt;</span></pre>
<!--CRLF--></div>
    </div>
  </li>

  <li>Save and close the file </li>

  <li>Verify that the issues are now resolved. </li>
</ol>

<p><strong><u>IMPORTANT</u></strong>: You must do a “dummy edit” on the compat.browser file located in the App_Browsers folder of your web application to force a recompilation of the browser definition files and for the solution to take effect. Simply open the compat.browser file and add a space at the very end of the file and save it back. You can remove the space and save it again if you wish, but an edit to compat.browser should force the recompilation. </p>

<p>Hope this helps. Happy SharePointing!!!</p>]]></content:encoded>
    </item>
    <item>
      <title>SharePoint: Document Information Panel fails to load when office documents are opened in a library that contains lookup columns</title>
      <link>https://docs.microsoft.com/archive/blogs/tehnoonr/sharepoint-document-information-panel-fails-to-load-when-office-documents-are-opened-in-a-library-that-contains-lookup-columns</link>
      <pubDate>Thu, 17 May 2012 17:23:27 GMT</pubDate>
      <dc:creator><![CDATA[Tehnoon Raza [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/tehnoonr/2012/05/17/sharepoint-document-information-panel-fails-to-load-when-office-documents-are-opened-in-a-library-that-contains-lookup-columns/</guid>
      <description><![CDATA[Overview  In SharePoint 2007/2010, if you have a document library that contains lookup columns that...]]></description>
      <content:encoded><![CDATA[<p><font size="3"><strong>Overview</strong></font></p>  <p><font size="2">In SharePoint 2007/2010, if you have a document library that contains lookup columns that were programmatically created or created via a custom feature, you may run into a problem where when a user clicks on a document to open the document, the document gets opened in Office Client (MS Word or MS Excel) but the Document Information Panel (DIP) that shows the document metadata fails to load and the following error is displayed on the user’s screen:</font></p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/17/19/metablogapi/0285.image_63713106.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-17-19-metablogapi/0285.image_5F00_63713106.png"><img style="margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/17/19/metablogapi/3022.image_thumb_50BC374F.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-17-19-metablogapi/3022.image_5F00_thumb_5F00_50BC374F.png" width="592" height="198" /></a></p>  <p align="center"> DIP Error when opening a word document from a document library in SharePoint</p>  <p align="left"><font size="2">Error Message: The Document Information Panel was unable to load. The document will continue to open . For more information, contact your system administrator.</font></p>  <p align="left"><font size="2">Error Details: The form cannot be opened. To fix this problem, contact the form designer.     <br />Form template: http://servername/sites/dip/proppanel.xsn&#160; <br />The following DataObject either cannot be created or cannot be initialized: list_5433DC30-D758-4B56-A4CA-9CCD98716342      <br />Document Information Panel cannot add the following object to the DataObjects collection: list_5433DC30-D758-4B56-A4CA-9CCD98716342      <br />list_5433DC30-D758-4B56-A4CA-9CCD98716342 could not be added to the DataObjects collection.      <br />The following item already exists in the collection: list_5433DC30-D758-4B56-A4CA-9CCD98716342</font></p>  <p align="left"><strong><font size="3">The Cause       <br /></font></strong><font size="2">This problem is caused if your list contains lookup columns that were created programmatically or using custom features. If the GUIDs of the list and column being referenced are not enclosed in curly brackets “{ }“ in the schema of the columns/fields, you will have this problem when opening the documents in Office Client applications. </font></p>  <p align="left"><strong><font size="3">The Solution</font></strong></p>  <p><font size="2">There was a forum discussion on one of the MSDN forums <a href="http://social.msdn.microsoft.com/Forums/en-US/sharepointdevelopment/thread/2a4d6d10-d1d5-4d6a-a22b-62dfb6b60685/" target="_blank">here</a> where someone had found the problem and posted some code to fix it. I figured the code is not the easiest to use, especially since you have to compile it to run and make some changes depending on the environment. I have created a PowerShell equivalent of the code and have modified it to make it more generic. All you need to do is change the Url to the url of the site/sub-site where the document library having the problem is located and the name of the document library (variables $siteUrl and $listName). Once you run this script against the library having the problem, you should be able to open documents from the library and have the DIP loaded without any issues. </font></p>  <p><em><font size="2">Disclaimer: The following script is a sample only and has not been tested fully. Please test this script in a test environment before applying on a production system. Provided “as is” without warranties</font></em></p>  <p><font size="2">Add-PSSnapin Microsoft.SharePoint.PowerShell     <br />$siteUrl = </font><font size="2">http://servername/sites/dip</font>    <br /><font size="2">$listName = &quot;Documents&quot;     <br />$web = Get-SPWeb $siteUrl      <br />$list = $web.Lists | where {$_.Title -eq $listName}      <br />$fields = $list.Fields | where {$_.Type -eq &quot;Lookup&quot;}       <br />foreach ($field in $fields)      <br />{      <br /> Write-Host &quot;Fixing Field &quot;$field.Title      <br /> #Fix the Lookup WebId first      <br /> $lookupWeb = $field.LookupWebId      <br /> $tempSchema = $field.SchemaXml      <br /> $toFind = &quot;WebId=`&quot;$($lookupWeb)`&quot;&quot;      <br /> $toReplace = &quot;WebId=`&quot;{$($lookupWeb)}`&quot;&quot;      <br /> $tempSchema = $tempSchema.Replace($toFind, $toReplace)      <br />&#160; #Check if we need to fix the Lookup List Id too      <br /> if ($field.LookupList.Length -gt 0)      <br /> {      <br />&#160; $lookupList = $field.LookupList      <br />&#160; #Need to make sure we don't do a double fix      <br />&#160; if ($lookupList.Contains(&quot;{&quot;) -eq $false)      <br />&#160; {      <br />&#160;&#160; $toFind = &quot;List=`&quot;$($lookupList)`&quot;&quot;      <br />&#160;&#160; $toReplace = &quot;List=`&quot;{$($lookupList)}`&quot;&quot;      <br />&#160;&#160; $tempSchema = $tempSchema.Replace($toFind, $toReplace)       <br />&#160; }      <br /> }      <br /> #Schema updates complete at this point. Replace the field schema      <br /> $field.SchemaXml = $tempSchema      <br /> $field.Update()      <br /> Write-Host &quot;Done Fixing &quot;$field.Title      <br />}</font></p>  <p><font size="2"></font></p>  <p><font size="2">Hope this helps! Happy SharePointing!</font></p>]]></content:encoded>
    </item>
    <item>
      <title>SharePoint Central Administration Web site takes a long time to load after an IIS Reset</title>
      <link>https://docs.microsoft.com/archive/blogs/tehnoonr/sharepoint-central-administration-web-site-takes-a-long-time-to-load-after-an-iis-reset</link>
      <pubDate>Thu, 17 May 2012 13:06:00 GMT</pubDate>
      <dc:creator><![CDATA[Tehnoon Raza [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/tehnoonr/2012/05/17/sharepoint-central-administration-web-site-takes-a-long-time-to-load-after-an-iis-reset/</guid>
      <description><![CDATA[Update 9/13/2012: The problem has been fixed in the August 2012 Cumulative update for SharePoint...]]></description>
      <content:encoded><![CDATA[<p><font size="3"><font size="2"><em>Update 9/13/2012: The problem has been fixed in the August 2012 Cumulative update for SharePoint Foundation. </em></font>&#160;</font></p>  <p><strong><font size="3">Overview</font></strong></p>  <p><font size="2">I have recently come across an annoying problem, and I have seen it often enough that I decided to blog about it. Consider the following scenario:</font></p>  <p><font size="2">You open your SharePoint Central Administration Website and it takes a long time to load the first time. After the initial load, the site is responsive and pages load and open fast. If you are experiencing these symptoms, you have come to the right place. Continue reading!</font></p>  <p><font size="3"><strong>Why is it Slow?</strong></font></p>  <p><font size="2">In the process of initializing the SharePoint Central Administration website, SharePoint tries to find the security group <strong>IIS_WPG</strong>. It first checks the local computer for the group, if the group is not a local security group, SharePoint tries to find the group on the domain. If you have a lot of two-way trusts, this search can go on for several minutes, which is what causes the slowness when loading the site. </font></p>  <p><strong><font size="3">IIS_WPG: Do I really need it?</font></strong></p>  <p><font size="2">Why does SharePoint need IIS_WPG – that’s a different topic. This group used to be a local security group on the default installation of IIS 6 (Windows Server 2003) and SharePoint 2007 (MOSS) would add the SharePoint application pool accounts to this group. I don’t know what problems you will run into if you delete the IIS_WPG group in MOSS 2007/WSS 3.0, but you should definitely not delete it.</font> </p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/17/19/metablogapi/8764.image_00EFB890.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-17-19-metablogapi/8764.image_5F00_00EFB890.png"><img style="margin-right: auto; margin-left: auto; float: none; display: block; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/17/19/metablogapi/1884.image_thumb_3FE1392B.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-17-19-metablogapi/1884.image_5F00_thumb_5F00_3FE1392B.png" width="538" height="345" /></a></p>  <p align="center"><em>The IIS_WPG local security group in Windows Server 2003</em></p>  <p><font size="2">The group went away with IIS7/Windows Server 2008, but SharePoint still tries to find it, which is what creates the slowness. This behavior is same for both MOSS 2007/WSS 3.0 and SharePoint 2010</font></p>  <p><font size="3"><strong>The Solution</strong></font></p>  <p><font size="2">The solution in this case is simple. All you need to do is create a local security group named “IIS_WPG” on each SharePoint server in the farm, and after that, central administration web site should load without any delays. </font></p>  <p><font size="2">Happy SharePointing!</font></p>  <p align="center"><strong><font size="4">&#160;</font></strong></p>]]></content:encoded>
    </item>
    <item>
      <title>Using WinDbg to extract the I.P. Address from a System.Net.IPAddress Object</title>
      <link>https://docs.microsoft.com/archive/blogs/tehnoonr/using-windbg-to-extract-the-i-p-address-from-a-system-net-ipaddress-object</link>
      <pubDate>Mon, 20 Feb 2012 13:25:49 GMT</pubDate>
      <dc:creator><![CDATA[Tehnoon Raza [MSFT]]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/tehnoonr/2012/02/20/using-windbg-to-extract-the-i-p-address-from-a-system-net-ipaddress-object/</guid>
      <description><![CDATA[Introduction  If you are looking at a System.Net.IPAddress object in a memory dump in WinDbg and are...]]></description>
      <content:encoded><![CDATA[<p><strong><u>Introduction</u></strong></p>  <p>If you are looking at a System.Net.IPAddress object in a memory dump in WinDbg and are wondering what I.P. address it actually represents, this post explains how you can get that information nice and quick. </p>  <p><strong><u>The Details</u></strong></p>  <p>I was looking at a hang dump today where a custom HTTP module was trying to connect to a remote server and was timing out. I found the System.Net.IPAddress on the stack using !dso and here is what the object looks like :</p>  <p>0:024&gt; !do 0ae055a8    <br />Name: System.Net.IPAddress    <br />MethodTable: 7a77385c    <br />EEClass: 7a773750    <br />Size: 40(0x28) bytes    <br />GC Generation: 0    <br /> (C:\WINDOWS\assembly\GAC_MSIL\System\2.0.0.0__b77a5c561934e089\System.dll)    <br />Fields:    <br />&#160;&#160;&#160;&#160;&#160; MT&#160;&#160;&#160; Field&#160;&#160; Offset&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Type VT&#160;&#160;&#160;&#160; Attr&#160;&#160;&#160; Value Name    <br />790fc054&#160; 40020d7&#160;&#160;&#160;&#160;&#160;&#160;&#160; 4&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; System.Int64&#160; 1 instance 552882186 m_Address    <br />790f97f0&#160; 40020d8&#160;&#160;&#160;&#160;&#160;&#160; 14&#160;&#160;&#160;&#160;&#160;&#160;&#160; System.String&#160; 0 instance 00000000 m_ToString    <br />7a7740c0&#160; 40020dc&#160;&#160;&#160;&#160;&#160;&#160; 1c&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; System.Int32&#160; 1 instance&#160;&#160;&#160;&#160;&#160;&#160;&#160; 2 m_Family    <br />7912b058&#160; 40020dd&#160;&#160;&#160;&#160;&#160;&#160; 18&#160;&#160;&#160;&#160;&#160; System.UInt16[]&#160; 0 instance 0ae055d0 m_Numbers    <br />790fc054&#160; 40020de&#160;&#160;&#160;&#160;&#160;&#160;&#160; c&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; System.Int64&#160; 1 instance 0 m_ScopeId    <br />790fe200&#160; 40020df&#160;&#160;&#160;&#160;&#160;&#160; 20&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; System.Int32&#160; 1 instance&#160;&#160;&#160;&#160;&#160;&#160;&#160; 0 m_HashCode    <br />7a77385c&#160; 40020d3&#160;&#160;&#160;&#160;&#160; 7bc System.Net.IPAddress&#160; 0&#160;&#160; shared&#160;&#160; static Any    <br />&#160;&#160;&#160; &gt;&gt; Domain:Value&#160; 000d0548:NotInit&#160; 1bea0890:06daefc8 &lt;&lt;    <br />7a77385c&#160; 40020d4&#160;&#160;&#160;&#160;&#160; 7c0 System.Net.IPAddress&#160; 0&#160;&#160; shared&#160;&#160; static Loopback    <br />&#160;&#160;&#160; &gt;&gt; Domain:Value&#160; 000d0548:NotInit&#160; 1bea0890:06daf00c &lt;&lt;    <br />7a77385c&#160; 40020d5&#160;&#160;&#160;&#160;&#160; 7c4 System.Net.IPAddress&#160; 0&#160;&#160; shared&#160;&#160; static Broadcast    <br />&#160;&#160;&#160; &gt;&gt; Domain:Value&#160; 000d0548:NotInit&#160; 1bea0890:06daf050 &lt;&lt;    <br />7a77385c&#160; 40020d6&#160;&#160;&#160;&#160;&#160; 7c8 System.Net.IPAddress&#160; 0&#160;&#160; shared&#160;&#160; static None    <br />&#160;&#160;&#160; &gt;&gt; Domain:Value&#160; 000d0548:NotInit&#160; 1bea0890:06daf050 &lt;&lt;    <br />7a77385c&#160; 40020d9&#160;&#160;&#160;&#160;&#160; 7cc System.Net.IPAddress&#160; 0&#160;&#160; shared&#160;&#160; static IPv6Any    <br />&#160;&#160;&#160; &gt;&gt; Domain:Value&#160; 000d0548:NotInit&#160; 1bea0890:06daf0b0 &lt;&lt;    <br />7a77385c&#160; 40020da&#160;&#160;&#160;&#160;&#160; 7d0 System.Net.IPAddress&#160; 0&#160;&#160; shared&#160;&#160; static IPv6Loopback    <br />&#160;&#160;&#160; &gt;&gt; Domain:Value&#160; 000d0548:NotInit&#160; 1bea0890:06daf110 &lt;&lt;    <br />7a77385c&#160; 40020db&#160;&#160;&#160;&#160;&#160; 7d4 System.Net.IPAddress&#160; 0&#160;&#160; shared&#160;&#160; static IPv6None    <br />&#160;&#160;&#160; &gt;&gt; Domain:Value&#160; 000d0548:NotInit&#160; 1bea0890:06daf170 &lt;&lt;</p>  <p>&#160;</p>  <p>Out I.P address is in the m_Address property whose value is 552882186. As you can see, it is not easy to convert 552882186 into a readable I.P. address. In order to identify the I.P. address represented by this value, we’ll have to examine raw memory. As you can see, the address of the object is 0ae055a8 and m_Address property is at the offset 4. This means, that m_Address is at the memory location 0ae055a8 +4 = 0ae055ac. An I.P. address has four parts, and each part is 1 byte (e.g. 192.168.10.50). Let’s examine the memory location 0ae055ac using the db command (dump bytes). Here is the output:</p>  <p>0:024&gt; db 0ae055ac   <br />0ae055ac&#160; <strong><font color="#ff0000">0a 50 f4 20</font></strong> 00 00 00 00-00 00 00 00 00 00 00 00&#160; .P. ............    <br />0ae055bc&#160; 00 00 00 00 d0 55 e0 0a-02 00 00 00 00 00 00 00&#160; .....U..........    <br />0ae055cc&#160; 00 00 00 00 58 b0 12 79-08 00 00 00 00 00 00 00&#160; ....X..y........    <br />0ae055dc&#160; 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00&#160; ................    <br />0ae055ec&#160; 58 2d 12 79 04 00 00 00-2c 90 0f 79 00 00 00 00&#160; X-.y....,..y....    <br />0ae055fc&#160; 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00&#160; ................    <br />0ae0560c&#160; 58 2d 12 79 01 00 00 00-5c 38 77 7a a8 55 e0 0a&#160; X-.y....\8wz.U..    <br />0ae0561c&#160; 00 00 00 00 58 2d 12 79-00 00 00 00 f0 97 0f 79&#160; ....X-.y.......y</p>  <p>In the above output, 0a 50 f4 20 is out I.P. Address. As this output is HEX, let’s convert this to decimal:</p>  <p>0a = 10 </p>  <p>50 = 80 </p>  <p>f4 = 244 </p>  <p>20 = 32</p>  <p>As you can see, the I.P. address represented by the System.Net.IPAddress object in this case is <strong>10.80.244.32</strong></p>  <p>Hope you find this helpful!</p>  <p>Tehnoon</p>]]></content:encoded>
    </item>
  </channel>
</rss>