I'm trying to insert a bunch of data into a SharePoint list. The List is a custom list based on the Item content type with a couple of custom columns, Contact and Code, where code is a custom field type based on SPFieldText.
I am exploring the list using PowerShell 2.0, and enumerating the fields of the list (or any given list item) causes an exception as follows:
PS C:\> $list.Fields
# output of a few fields
An error occurred while enumerating through a collection: Exception has been thrown by the target of an i
nvocation..
At line:1 char:7
+ $list. <<<< Fields
+ CategoryInfo : InvalidOperation: (Microsoft.Share...on+SPEnumerator:SPEnumerator) [], Run
timeException
+ FullyQualifiedErrorId : BadEnumeration
I don't really get why this is the case - nothing on the site seems to be broken, and SharePoint Manager is able to enumerate all the fields and list items without a problem. Further, when I try to grab a single list item and inspect its fields, I get null from my custom field:
PS C:\> $list.Items[0]["Contact"]
2;#Collins, Ben
_______________________________________________________________________________________
PS C:\> $list.Items[0]["Code"]
_______________________________________________________________________________________
PS C:\> $list.Items[0]["Code"] -eq $null
True
The "Code" field in the list doesn't actually have a null value, so I'm at a bit of a loss. Anyone know what might be going on?
Turns out the feature containing this field type wasn't activated (the list had already been created, and I've been making changes to the feature).
Doh.
Related
I'm trying to add a custom header for AIP's msip_labels to a Powershell script that I'm writing. I've figured out how to do this with .Net.SMTP using:
$message.Headers.Add("msip_labels","MSIP_Label_aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee_Enabled=True; MSIP_Label_aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee_SiteId=00000000-1111-2222-3333-444444444444; MSIP_Label_aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee_Owner=user2#domain.tld; MSIP_Label_aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee_SetDate=$((Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ")); MSIP_Label_aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee_Name=Internal; MSIP_Label_aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee_Application Microsoft Azure Information Protection; MSIP_Label_aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee_ActionId ffffffff-5555-6666-7777-888888888888; MSIP_Label_aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee_Extended_MSFT_Method Manual")
Based on research I've done this should work using Outlook 2016 in theory:
$Outlook = New-Object -ComObject Outlook.Application
$message = $Outlook.CreateItem(0)
$message.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/string/{00020386-0000-0000-C000-000000000046}/msip_labels", "MSIP_Label_aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee_Enabled=True; MSIP_Label_aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee_SiteId=00000000-1111-2222-3333-444444444444; MSIP_Label_aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee_Owner=user2#domain.tld; MSIP_Label_aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee_SetDate=$((Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ")); MSIP_Label_aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee_Name=Internal; MSIP_Label_aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee_Application=Microsoft Azure Information Protection; MSIP_Label_aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee_ActionId=ffffffff-5555-6666-7777-888888888888; MSIP_Label_aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee_Extended_MSFT_Method=Manual")
$message.To = "user1#domain.tld"
$message.Cc = "user3#domain.tld"
$message.Subject = "Report"
$message.HTMLBody = #"
<p><font face = "Calibri" size = "3">Hello World</p></font>
"#
$reportMessage.Send()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($Outlook) | Out-Null
I confirmed this using a MAPI viewer that this is what's used in Outlook itself with other emails I've sent using just Outlook. But, when I tried running this in my script I get this error:
Exception setting "SetProperty": Cannot convert the "MSIP_Label_aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee_Enabled=True; MSIP_Label_aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee_SiteId=00000000-1111-2222-3333-444444444444;
MSIP_Label_aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee_Owner=user2#domain.tld; MSIP_Label_aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee_SetDate=$((Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ")); MSIP_Label_aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee_Name=Internal;
MSIP_Label_aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee_Application=Microsoft Azure Information Protection; MSIP_Label_aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee_ActionId=ffffffff-5555-6666-7777-888888888888;
MSIP_Label_aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee_Extended_MSFT_Method=Manual" value of type "string" to type "Object".
At C:\emailtest.ps1:21 char:1
+ $message.PropertyAccessor.SetProperty("http://schemas.microsoft ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : RuntimeException
Which doesn't seem to make much sense it's suppose to be a string in the MAPI schema, so I'm not sure why it thinks it should be an object. I even tried converting those values to objects using ConvertFrom-String, but it didn't work. Any advice on this would be greatly appreciated.
Try to reduce the string length you pass as a value. Does it work correctly?
It seems you need to use a low-level API on which Outlook is based on - Extended MAPI. It doesn't have any restrictions on the string length unlike OOM if you use the OpenProperty method. Also, you may consider using any third-party wrapper around that API such as Redemption.
If you use PropertyAccessor, you must have good knowledge of exception handling logic. Below I list some roadblocks that you may run into:
The body and content of an attachment of an Outlook items are not accessible through PropertyAccessor.
The PropertyAccessor ignores any seconds of the date/time value
String properties are limited in size depending on the information store type.
Limitation: Personal Folders files (.pst) and Exchange offline folders files (.ost) cannot be more than 4,088 bytes.
Limitation: For direct online access to Exchange mailbox or Public Folders hierarchy, the limit is 16,372 bytes.
Binary properties only those whose values are under 4,088 byte can be retrieved or set. (If trying to use larger values, you get an out-of-memory error).
You may find the Don't stumble over a stone working with the PropertyAccessor and StorageItem classes in Outlook 2007 article helpful.
It worked for me by appending a null character at the end of the string ( "`0" ) This is required by type "PtypString", required by property.
https://learn.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-oxcdata/0c77892e-288e-435a-9c49-be1c20c7afdb
I am able to query active-directory/ldap to get the user information along with custom attributes. However I would to know the underlying DataType/attributeSyntax for each of those attribute returned.
Another the problem is that the query will not return the attribute itself if it does not contain any value.
So if can get fetch the attributes and their respective DataTypes then it provides me flexibility to set a default value basing on the DataType while preparing the final output object.
Eg:
1. I query AD to find foo user with attributes givenName, mail, myCustom1, myCustom2
{
givenName : "foo foo",
mail : "foo#boo.com",
myCustom1 : "TRUE"
}
but may not contain myCustom2 because it is not holding the value in AD.
get syntax for attributes givenName, mail, myCustom1, myCustom2
{
givenName : unistring,
mail : unistring,
myCustom1 : boolean,
myCustom2 : integer,
}
using above I can map the first result and prepare the final object as
{
givenName : "foo foo"
mail : "foo#boo.com"
myCustom1 : "TRUE"
myCustom2 : //usingHelperFunctionGetDefaultValueFor -> myCustom2
}
Active Director does not return attributes that do not have values, so that's not just the LDAPjs library, that's just how AD works.
Every object has an attribute called allowedAttributes that will show you every valid attribute that the object can potentially have.
If you need it, allowedAttributesEffective will list every attribute that the current user has permissions to modify.
These are both constructed attributes, meaning you have to ask for them specifically, or else you won't get them. For example, when searching, you have the option to specify the attributes you want to get back. If you specify nothing, you will get every non-constructed attribute that has a value. If you want any constructed attributes, you have to add it specifically to that list.
That's just a list of attributes. It won't tell you the type. You have to look to the schema for that, which is more difficult. You have to do a search using the base DN of CN=Schema,CN=Configuration,DC=domain,DC=com, where "domain.com" is the root domain of your forest, which may or may not be the same as the domain you're searching. You could look at the subSchemaSubEntry attribute of any object to find the location of the schema, although it will usually be CN=Aggregate,CN=Schema,CN=Configuration,DC=domain,DC=com (note the added CN=Aggregate).
But anyway, each object in there will have an attribute called ldapDisplayName, which is the name of the attribute as it appears on objects.
So if you want to find details on the givenName attribute, you would search the schema for (ldapDisplayName=givenName). Then the oMSyntax attribute is an enum that will tell you the type. The enum values are shown here. For givenName, that would be 64, which is a Unicode string.
The only benefit to looking up the types like this is if you are expecting your code to be run on any AD environment. If your code will only ever be run in one environment, then you can save coding time and run time by just hard-coding the attributes you are looking for and their types.
When i'm trying to add a new field, with type Taxonomy (Managed Metadata) via powershell with the method : AddFieldAsXml, It throw me an error :
Error while adding field : Exception calling "AddFieldAsXml" with "1" argument(s): "The object has been updated by another user since it was last fetched."
The weird thing is that I'm adding the field so it can't have been modified or updated by another user ! Can it ?
If you have ideas ?
Thanks
this is some code I wrote:
Add-PSSnapin Microsoft.SharePoint.PowerShell
$webURL = "http://nycs00058260/sites/usitp"
$lists = "OsEM1","OsEM2","OsEM3","OsEM4"
$web = Get-SPWeb -Identity "http://nycs00058260/sites/usitp"
foreach($list in $lists)
... ...
Write-Host $item["Title"]
#$item["Item"]=$item["Title"] +" ,"+$webURL+"\"+$filename
$item["Item"]="$tmpValue"+" ,$item[Title]"
$item.Update()
}
}
}
it said: Unable to index into an object of type MicroSoft.SharePoint.SPListItem.
something worong when I change the $item["Item"] value?
There are a few reasons that cause this behavior:
Your permissions don't match what you need to change an item. If you have PowerShell rights, this is often not the case.
Your list is somehow corrupted. This could have something to do with site columns, content types, the list itself, or views. If you created and did not update the list schema (definition), it wouldn't let you edit it.
You don't have AllowUnsafeUpdates set to on for the SPWeb (site) object.
All three of these issues generally have better (matching) error messages but sometimes SharePoint doesn't give you all the information that you need in the error messages.
If you need more details, please ask.
I accidentally created a field type called "Test" instead of Text using the following
Powershell command:
Get site and web object
$site = Get-SPSite -Identity "http://mysite/sites/.."
$web = $site.RootWeb
#Assign fieldXML variable with XML string for site column
$fieldXML = '<Field Type="Test"...etc.
Poweshell threw the following error:
Exception calling "AddFieldAsXml" with
"1" argument(s): "Field type Test is
not installed properly. Go to the
list settings page to delete this
field. " At
C:\Scripts\addsitecolumn.ps1:25
char:26
+ $web.Fields.AddFieldAsXml <<<< ($fieldXML)
+ CategoryInfo : NotSpecified: (:) [],
MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Is there a Powershell command to delete the Test Field or is there a way to get to this fields 'hidded' page?
I ran into a similar problem today. I ran Sharepoint Manager 2010 and got the SchemaXML off from the site collection and found out that there were 3 site columns with nothing defined in it. I tried to remove it by powershell above with display name (which is "") or index, but none of that work as the item object see it as null. Then I came across this post:
https://sharepoint.stackexchange.com/questions/11945/error-message-field-type-publishing-image-is-not-installed-properly-go-to-the
Which remove it from the content database and that worked for me. Right after that I check the SchemaXML and the 3 strange site columns were removed. It's interesting how the content type table ties directly into this problem.
Try this in PowerShell:
$web1 = Get-SPWeb "http://testWeb"
$field = $web1.Fields["Test 1"]
$field.Delete()
"Test 1" is the Display name of the field you tried to add earlier.