Document Property Promotion and Demotion Overview and Considerations

Overview

Document Property Promotion and Demotion is a Feature in versions of SharePoint designed to synchronize specific metadata across documents and its parent List columns and/or fields.

Property promotion refers to the process of extracting values from properties of a document and writing those values to corresponding columns on the list or document library where the document is stored.

Property demotion is the same process in reverse. Values are read from list columns and written to document properties.

Document Parser

SharePoint works together with a document parser to provide automation of the process of promoting and demoting properties so if the value of a one or more document properties changes, those changes are automatically synchronized to the parent List object or conversely when the values of the parent List columns or fields in a list item change, those changes are synchronized to the subordinate document associated with the item.

Document Parsers represent a significant advantage to managing metadata associated with one or more documents stored in a SharePoint List or Library, by providing a programmatic approach to managing the metadata associated with a document removing the need to manually synchronize important document characteristics across a document and its parent container.  By default SharePoint Server 2013 provides document parsers (pluggable) for the following types:

docx      SharePoint.SPDocumentParser.OfficeParser

docm      SharePoint.SPDocumentParser.OfficeParser

dotx      SharePoint.SPDocumentParser.OfficeParser

dotm      SharePoint.SPDocumentParser.OfficeParser

pptx      SharePoint.SPDocumentParser.OfficeParser

pptm      SharePoint.SPDocumentParser.OfficeParser

potm      SharePoint.SPDocumentParser.OfficeParser

potx      SharePoint.SPDocumentParser.OfficeParser

ppsx      SharePoint.SPDocumentParser.OfficeParser

ppsm      SharePoint.SPDocumentParser.OfficeParser

xlsx      SharePoint.SPDocumentParser.OfficeParser

xlsb      SharePoint.SPDocumentParser.OfficeParser

xlsm      SharePoint.SPDocumentParser.OfficeParser

xltx      SharePoint.SPDocumentParser.OfficeParser

xltm      SharePoint.SPDocumentParser.OfficeParser

gif       SharePoint.SPDocumentParser.ImageParser

jpeg      SharePoint.SPDocumentParser.ImageParser

jpg       SharePoint.SPDocumentParser.ImageParser

jpe       SharePoint.SPDocumentParser.ImageParser

jfif      SharePoint.SPDocumentParser.ImageParser

bmp       SharePoint.SPDocumentParser.ImageParser

dib       SharePoint.SPDocumentParser.ImageParser

png       SharePoint.SPDocumentParser.ImageParser

tif       SharePoint.SPDocumentParser.ImageParser

tiff      SharePoint.SPDocumentParser.ImageParser

ico       SharePoint.SPDocumentParser.ImageParser

wdp       SharePoint.SPDocumentParser.ImageParser

hdp       SharePoint.SPDocumentParser.ImageParser

In addition to the parsers provided out of the box, SharePoint Server 2013 also provides an extensible document parsing infrastructure that allows developers to install custom parsers for types not included out of the box to enable the process of property promotion and demotion for those types.

Architecture

Flow

Document Promotion and Demotion is applied when the following conditions are met:

  • A document is uploaded to a SharePoint Document Library
  • List item fields associated with a document are modified
  • SPFile object properties are programmatically modified
  • A document is downloaded after the list item schema is modified (first run experience only)

Picture1

 

In each scenario SharePoint will attempt to determine whether or not a parser is associated with the document type and in the event a parser is associated with the document type, SharePoint invokes the parser and sends the parser the document and property bag object.  If a promotion scenario, the document parser will fill the property bag with the values that need to be synchronized with the parent list or in a demotion scenario, extracts values from the property bag that need to be written to the document.

Content Types

Referencing the illustration above, when using the document parser interface, document parsers can access the Content Type assigned to a document and subsequently store the content type in the document in addition to updating the Content Type definition stored in the document to match the version of the definition used by a List or Document Library.

Picture1

Validating Input / Output

For content supportive of Document Parsing an XML namespace designation is added to the document metadata, in some cases, the document itself.

Example 1

Create a new HTML type document “PropValidation.html”.

Copy into the document the following HTML:

<html>
    <head>
</head>
        <body>
            <span>Hello World</span>
        </body>
    </head>
</html>

Save as something.html

Upload to a SharePoint Document Library and open the document.

The following html will be added to the document

<html xmlns:mso="urn:schemas-microsoft-com:office:office" xmlns:msdt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882">
    <head>
       
<!–[if gte mso 9]><xml>
<mso:CustomDocumentProperties>
<mso:IsMyDocuments msdt:dt="string">1</mso:IsMyDocuments>
</mso:CustomDocumentProperties>
</xml><![endif]–>

</head>
        <body>
            <span>Hello World</span>
        </body>
    </head>
</html>

Notice the UUID element.  The UUID is an XML namespace designation used as part of property demotion, everyone who saves an HTML-like file to a SharePoint document Library will have the same GUID inserted into the document.

Example 2

Create a new Microsoft Word Document (Document.docx).

Edit the document properties and specify a Title property of “Parse this field”.

image

Upload the document to a Document Library.  The Title column field associated with the document will reflect the document property (promotion).

image

Edit the Title property of Document.docx in the browser.

image

Download the document, the document property will be updated to reflect the value specified in the Title column field associated with the document (demotion).

image

 

Special Content Type Considerations

In some cases a document Content Type may not be associated with the Document Library where the document is uploaded (I.e. a user creates a document from a Document Template containing a Content Type or moved the document to a different Document Library.  In these scenarios, unlike the flow depicted in the image above, SharePoint will:

  • Invoke the Document Parser to demote the out of the box default List Content Type for the Document Library into the document if the document contains a property for a Content Type, but the document property is empty.  SharePoint will then promote the document properties to match columns in the out of the box List Content Type.
  • Leaves the document Content Type unchanged if the Document Library allows any Content Type and the document is assigned a Content Type not associated with the Document Library.  SharePoint will not promote the document Content Type, but will promote any document properties that match the Document Library columns.

NOTE

If a List is set to allow any Content Type, documents of any Content Type can be uploaded and their Content Types will not be overwritten which subsequently enables movement of documents between Libraries without the documents losing their metadata.

  • Invokes the Document Parser to demote the out of the box List Content Type for the Document Library into the document if the document is assigned a Content Type that is not associated with the Document Library and the Document Library does not allow any Content Types (see Note above).  SharePoint then promotes the document properties that match columns in the out of the box List Content Type and stores the document.

Enumerating Pluggable Parsers

Enumeration of Document Parsers lists all of the default (pluggable) parsers shipped with SharePoint.

To enumerate pluggable parsers refer to the following code sample.

C#

namespace EnumParsers
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Microsoft.SharePoint.Administration;

    public static class Program
    {
        private static void Main()
        {
            SPFarm objFarm = SPFarm.Local;
            SPWebService service = objFarm.Services.GetValue<SPWebService>(string.Empty);

            Dictionary<string, SPDocumentParser> objParser = service.PluggableParsers;
            Dictionary<string, SPDocumentParser>.KeyCollection keys = objParser.Keys;

            Console.WriteLine("Extension     Parser");
            Console.WriteLine("---------     -------");
            foreach (string key in keys)
            {
                Console.WriteLine(string.Format(CultureInfo.CurrentCulture, "{0, -7}       {1}", objParser[key].FileExtension, objParser[key].ProgId));
            }
        }
    }
}

Disabling the Document Parser

The Document Parser can be enabled and/or disabled on-premises by configuring the SPWeb.ParserEnabled value to True|False.

C#

namespace ParserEnabled
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.Administration;

    class Program
    {
        static void Main(string[] args)
        {
            SPFarm oFarm = SPFarm.Local;
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                SPWebApplication webApp = SPWebApplication.Lookup(new Uri("http://www.contoso.com"));

                foreach (SPSite site in webApp.Sites)
                {
                    foreach (SPWeb web in site.AllWebs)
                    {
                        if (web.ParserEnabled == true)
                        {
                            web.ParserEnabled = false;
                            web.Update();
                        }
                    }
                }
            });
        }
    }
}

Windows PowerShell

$web = Get-SPWeb www.contoso.com
$web.ParserEnabled = $false
$web.Update()

NOTE

Disabled Document Parsing should be carefully considered as it will also impact Features dependent on promotion and demotion.  For example, content type syndication and document information panels.

Disabling Document Parsing is effectively a one-way operation.  Disabling parsing disables the bidirectional synchronization of document properties, if disabled, and subsequently re-enabled and the properties are diverged while disabled, the original property values will be synchronized as contained within the property bag.

Similarly, Document Parsers also affect how content types are managed.  For example, when SharePoint invokes a parser to promote document properties (writes the properties to the parent List), the parser writes all document properties to an instance of the IParserPropertyBag interface and then determines which properties in the property bag match the columns on the parent List or Library.  If the property bag indicates that the document has an assigned content type, and the content type is supported by the document library, SharePoint promotes the document properties that match the columns that are included in the content type.

Associating Custom Parsers with File Types

In addition to enumeration and disabling document parsers, you can also add a document parser and associate with a specific parser.

The example below associates a custom document parser with an RTF extension.

C#

namespace AddParsers
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Microsoft.SharePoint.Administration;

    public static class Program
    {
        static void Main(string[] args)
        {
            SPWebService service = SPWebService.ContentService;
            Dictionary<string, SPDocumentParser> parsers = service.PluggableParsers;

            string extension = "rtf";
            string progID = parsers["docx"].ProgId;
            SPDocumentParser customParser = new SPDocumentParser(progID, extension);

            if (parsers.ContainsKey(extension))
            {
                parsers.Remove(extension);
                service.Update();
            }

            service.PluggableParsers.Add(extension, customParser);
            service.Update();
        }
    }
}

Purpose

Document parsing in SharePoint provides a number of benefits to the management of metadata around documents,

Metadata management is a powerful capability offered in SharePoint, document parsing simplifies the scenario of maintaining consistent metadata between documents and their parent libraries and parent libraries and their subordinate documents.

In SharePoint several Features leverage Document Parser logic to include:

Link Fixup

Link Fixup is used to indicate a Web Part property that contain one or more links to a document, if the document is moved or renamed, Link Fixup corrects the absolute Url to reflect the new location as a relative Url.  See also ManagedLinkAttribute.Fixup property.

Property Panels

Document Information Panels are forms that are displayed within the client application, and which contains fields for the document metadata. Document information panels enable users to enter important metadata about a file anytime they want, without having to leave the client application.  For example, a Document Information Panel may include custom properties to associated with a document, such as declaration information, specific terms, etc.

For files stored in document libraries, the document information is actually the columns of the content type assigned to that file. The document information panel displays a field for each content type property, or column, the user can edit.

For documents stored in SharePoint, these property values are promoted back to the document library, as column values, when the user updates them in the document. Similarly, if the user updates the content type column values in the SharePoint user interface, the new values are demoted into the document itself, as document properties.

Metadata Portability

See Special Content Type Considerations above.

Conclusion

Document Parsers in SharePoint provide an abstract method for users when managing metadata (document properties) across client and server.

ULS Viewer and SharePoint 2010

So you downloaded the ULS Viewer and fired up on your SharePoint 2010 environment only to see something like this?

—-

System.TypeInitializationException: The type initializer for 'UlsGump.AboutForm' threw an exception. —> System.TypeLoadException: Could not load type 'System.Reflection.CustomAttributeExtensions' from assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.

   at UlsGump.AboutForm..cctor()

   — End of inner exception stack trace —

   at UlsGump.MainForm.MainForm_Load(Object sender, EventArgs e)

   at System.Windows.Forms.Form.OnLoad(EventArgs e)

   at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)

   at System.Windows.Forms.Control.CreateControl()

   at System.Windows.Forms.Control.WmShowWindow(Message& m)

   at System.Windows.Forms.Control.WndProc(Message& m)

   at System.Windows.Forms.Form.WndProc(Message& m)

   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

The problem lies in that the ULS Viewer (well mscorlib) is looking for the .NET 4 version of mscorlib.  Installing Microsoft .NET Framework Version 4.5 should resolve the issue.

SharePoint 2010 installs Microsoft .NET Framework Version 3.5 SP1 whereas SharePoint 2013 installs Microsoft .NET Framework Version 4.5.

Implementing Azure Blob Storage (ABS) with SQL Server 2014 and SharePoint 2013 [Updated]

Overview

NOTE (8/26/2014)

With any solution that externalizes the unstructured content with SharePoint you need to understand the limitations and optimal use of those solutions as documented at http://technet.microsoft.com/en-us/library/ff628583(v=office.15).aspx to include related latency and performance requirements.

With any application organizations face consistent key challenges such as high efficiency and business value, complex configuration, and low total cost of ownership.  Extending applications to the cloud in hybrid scenarios addresses many of these challenges, whether distributing SharePoint content across on-premises and Office 365 while leveraging search as a service (hybrid search) or externalizing data, extending it to the cloud with Remote Blob Storage or related technologies.

SQL Server 2014 and Windows Azure Blob Storage provide a unique solution that balances the needs of IT with those of the business – SQL Server Data Files in Windows Azure which allows you to create a database in SQL Server running in on-premises or in a virtual machine in Windows Azure with a dedicated storage location for your data in Windows Azure Blob Storage.

Picture1

This enhancement especially simplifies to move databases between machines by using detach and attach operations. In addition, it provides an alternative storage location for your database backup files by allowing you to restore from or to Windows Azure Storage. Therefore, it enables several hybrid solutions by providing several benefits for data virtualization, data movement, security and availability, and any easy low costs and maintenance for high-availability and elastic scaling.

Prerequisites

SQL Server 2014 on-premises or as a Windows Azure Virtual Machine

Storage Account and Container in Windows Azure

When using SQL Server Data Files in Windows Azure feature, you need to create a storage account and a container in Windows Azure, create a SQL Server credential, which includes information on the policy of the container as well as a Shared Access Signature that is necessary to access the container.

Getting Started

Create a Storage Account

To store files and data in the Blob, Table, Queue, and File services in Azure, you must create a storage account in the geographic region where you want to store the data.

For step by step instructions on how to create a Storage Account using the Windows Azure Management Portal see http://azure.microsoft.com/en-us/documentation/articles/storage-create-storage-account/.

image

Create a Container

All storage blobs reside in a container.   To create a container:

Sign in to the Management Portal.

Click Storage from the list of available options and select the Storage Account created in the previous steps.

Click CONTAINERS from the list of available options.

image

On the CONTAINERS dialog click + Add and specify the name for the new container.

image 

NOTE

Keep the default access level ‘Private’.

By default, the container is private and can be accessed only by the account owner. To allow public read access to the blobs in the container, but not the container properties and metadata, use the "Public Blob" option. To allow full public read access for the container and blobs, use the "Public Container" option.

The following steps assume that a Windows Azure Storage container has been created, and a policy has been created with read, write, list, rights. Creating a policy on a container generates a SAS key which is safe to keep unencrypted in memory and needed by SQL Server to access the blob files in the container.

Create a Credential

Creating a credential creates a record that contains the authentication information that is required to connect to a resource outside SQL Server. (such as Azure Blob Store).  To create a credential for Azure Blob Store requires a Windows Azure Store Container and a policy to allow read, write, and list rights.  Creating a policy generates a SAS key which SQL Server uses to access the blobs in the container.

Syntax

CREATE CRENDENTIAL [Container Url] — Specifies the name of the credential being created, I.e. the Windows Azure Storage Container

WITH IDENTITY = ‘SHARED ACCESS SIGNATURE’ — Specifies the name of the account to be used when connecting outside the server, I.e. when used with a Windows Azure Storage Container this value is always ‘SHARED ACCESS SIGNATURE’.  A Shared Access Signature is a URI that grants restricted access rights to containers, blobs, queues, and tables for a specific time interval (see example below).

For information on creating and using Shared Access Signatures see http://msdn.microsoft.com/en-us/library/azure/jj721951.aspx.

SECRET = ‘Secret’ — Specifies the secret required for outgoing authentication.   In this scenario the SECRET represents the Shared Access Signature associated with the policy created on the container (see example below).

Example

USE master
CREATE CREDENTIAL [https://sqlcloud.blob.core.windows.net/data%5D
WITH IDENTITY = 'SHARED ACCESS SIGNATURE',
SECRET = 'sr=c&se=2014-08-25T18%3B34%3B29Z&sp=rwl&sig=wJripFB9nq%2FrwlARE11TYS1OccKpFrpn6y3QuRS%2Fv4o%3D'

To view the credential created in the steps above use:

SELECT * FROM sys.credentials

The sys.credentials Security Catalog View returns one row for each stored credential which includes:

name = Name of the credential. Is unique in the server.

credential_identity = Name of the identity to use.

create_date = Time at which the credential was created.

modify_date = Time at which the credential was last modified.

target_type = Type of credential. Returns NULL for traditional credentials such as SHARED ACCESS SIGNATURE.

target_id = ID of the object that the credential is mapped to. Returns 0 for traditional credentials.

image

Create a Database

Creating a database does not differ significantly from creating a database in a traditional on-premises SQL Server storage scenario using the CREATE DATABASE statement.

Syntax

CREATE DATABASE [Name] — Is the name of the new database.

ON ( NAME = [Database Name], FILENAME = [Data File Path and File Name] ) — Specifies that the disk files used to store the data sections of the database, data files, are explicitly defined.

LOG ON ( Name = [Log Name], FILENAME = [Log File Path and File Name] ) Specifies that the disk files used to store the database log, log files, are explicitly defined.

Example

CREATE DATABASE WSS_Content
ON ( NAME = WSS_Content, FILENAME = 'https://sqlcloud.blob.core.windows.net/data/WSS_Content.mdf' )
LOG ON ( NAME = WSS_Content_Log, FILENAME = 'https://sqlcloud.blob.core.windows.net/data/WSS_Content.ldf' )

Validate Database Creation

To validate the database and related files were created successfully in the container select Connect in SQL Server Management Studio and choose Windows Azure from the list of available options.  Specify the name of the storage account associated with the container and provide the related access key to access the container.

image

Add Database(s) to SharePoint

To add the database use the Mount-SPContentDatabase cmdlet which attaches an existing content database to the farm.

Syntax

Mount-SPContentDatabase

-Name Specifies the existing content database to attach to the farm.

-DatabaseServer Specifies the name of the host server for the content database specified in the Name parameter.

-WebApplication Attaches the content database to the specified SharePoint web application.

Example

Mount-SPContentDatabase “WSS_Content” –DatabaseServer CP-SQ-01 –WebApplication http://sharepoint.wbaer.com.co

Summary

SQL Server Data Files in Windows Azure simplifies migration processes by moving one database at a time between machines on-premises as well as between on-premises and cloud environments without any application changes and provides near limitless storage without the overhead of managing storage.

ULS Viewing Like a Boss (ULS Viewer is now available)

I’m excited to announce we’ve published a new and improved version of the ULS Viewer.

About the Unified Logging Service

The Unified Logging Service (ULS) is the primary logging mechanism in SharePoint to make it easier to develop applications, expose in-depth information for debugging, and vehicle to isolate problems or threshold issues when they are encountered.  ULS writes events to the Trace Log and stores them in the file system.

For Developers ULS logs act as an extension of existing development tools as another debugging facility, in some scenarios, mitigating the need to attach a debugger to isolate an event.

For IT Professionals and support personnel ULS logs provide enough information and metadata to help determine the course of action necessary in resolution of an event and expedite support escalations where required.

The ULS Viewer provides a solution the enables presentation of ULS Log entries in a human readable format to aid in troubleshooting.

New ULS Viewer Features

Monitor multiple servers simultaneously, because we know you need to troubleshoot more than just a standalone server…

ULS1

Personalize the output with the option to edit formatting.

ULS2

Support for locating a specific log line within one or more ULS Logs based on a command line argument which enables other tools and solutions can leverage ULS Viewer as an external log viewer.

Example:

ulsviewer.exe –fileat:<logpath>@<time>

Time format is yyyy/MM/ddTHH:mm:ss.FF

Support for opening multiple ULS Log files in a single tab based on a command line argument which enables other tools and solutions can leverage ULS Viewer as an external log viewer.

Example:

ulsviewer <file1> <file2> … -combine

Optionally you can combine with "-fileat":

Example:

ulsviewer -fileat:<file1>@<time> <file2> … -combine

Fixed in ULS Viewer

Resolved updating defined filters while in paused state which provides IT Professionals and Developers an additional tool to isolate issues in high trace flow environments.

Fixed Find Again command missing matching entries.

Fixed issues with multi-line messages.

Applies more strict filter with RegEx when finding the uls log files in the log folder so that non-uls log files are not picked.

Download

To download the ULS Viewer visit http://www.microsoft.com/en-us/download/details.aspx?id=44020.

Managing Sites Pages in SharePoint Server 2013 w/ OneDrive for Business Redirection in Service Pack 1

Overview

Service Pack 1 introduced new functionality that allows IT administrators to selectively redirect their users OneDrive for Business libraries to Office 365.  In addition to OneDrive for Business redirection, Service Pack 1 also allows for the redirection of users Sites pages to SharePoint Online.  When redirecting the Sites pages, when a user selects Sites on the navigation bar in SharePoint Server 2013 they are redirected to SharePoint Online.  Since there is no affinity between content followed across SharePoint Server 2013 and SharePoint Online, users are presented only with local (SharePoint Online) content followed.  In order to resolve the disconnected experience, IT can selectively deactivate following content in SharePoint Server 2013.

About OneDrive for Business

OneDrive for Business in SharePoint Server 2013 is personal online storage for users in an organization replacing SkyDrive Pro.

About Sites Page

The Sites page introduced in SharePoint Server 2013 is designed to provide users a unified location to create new sites and view sites they are following.

Discover Sites where Following Content is Activated

Following Content Feature when enabled allows user to follow content on sites where the Feature is activated.  IT Professionals and Developers can identify sites where Following Content is activated through a variety of methods to include C# and Windows PowerShell.  Examples below.

C# Example

namespace FindFollow
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.Administration;
    using Microsoft.Office.Server;
 
    class Program
    {
        static void Main(string[] args)
        {
            System.Globalization.CultureInfo culture = new System.Globalization.CultureInfo(1033);
            SPFeatureDefinitionCollection featureCollection = SPFarm.Local.FeatureDefinitions;
 
            foreach (SPFeatureDefinition feature in featureCollection)
            {
                if (feature.GetTitle(culture) == "Feature_Title")
                {
                    Guid id = feature.Id;
                    SPWebCollection webCollection = SPContext.Current.Site.AllWebs["Site"].Webs;
 
                    foreach (SPWeb web in webCollection)
                    {
                        if (feature.Scope == SPFeatureScope.Web)
                        {
                            SPFeatureCollection collFeatureCollection = web.Features;
  if (feature.DisplayName == "Following Content")
                            {
                                Console.WriteLine((feature.GetTitle(culture)) + " Activated on: " + web.Title + web.Url.ToString());
                            }
                        }
                        web.Dispose();
                    }
                }
            }
        }
    }
}

Windows PowerShell Example

$id = 043C4BDD-9745-441a-A9A7-0BCD9B910319

$web = Get-SPWeb http://wbaer.com.co

$feature = $web.Features[$id]

if ($feature –eq $null)
{

    “Not Activated”
}

else

{
    “Activated”
}

Deactivating Following Content

To disable users ability to follow content

C# Example

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.Office.Server;
 
namespace DisableFollow
{
    class Program
    {
        static void Main(string[] args)
        {
            SPWebApplication webApp = SPWebApplication.Lookup(new Uri("http://wbaer.com.co"));
 
            foreach (SPSite site in webApp.Sites)
            {
                foreach (SPWeb web in site.AllWebs)
                {
                    web.Features.Remove(new Guid("{043C4BDD-9745-441a-A9A7-0BCD9B910319}"));
                }
            }
        }
    }
}