hayse ian
Category Archives: SharePoint
How to encode and to decode a file attachment Visual Basic
Microsoft was nice enough to post a code example in C#, but I’m lazy and haven’t moved away from Visual Basic.
How to encode and to decode a file attachment programmatically by using Visual C# Visual Basic in InfoPath 2010 or in InfoPath 2007
C# example:
http://support.microsoft.com/kb/2517906
VB examples:
decode.vb
Imports System
Imports System.IO
Imports System.Text
Namespace InfoPathAttachmentEncoding
'''
<summary> ''' Decodes a file attachment and saves it to a specified path.
''' </summary>
Public Class InfoPathAttachmentDecoder
Private Const SP1Header_Size As Integer = 20
Private Const FIXED_HEADER As Integer = 16
Private fileSize As Integer
Private attachmentNameLength As Integer
Private attachmentName As String
Private m_decodedAttachment As Byte()
'''
<summary> ''' Accepts the Base64 encoded string
''' that is the attachment.
''' </summary>
Public Sub New(ByVal theBase64EncodedString As String)
Dim theData As Byte() = Convert.FromBase64String(theBase64EncodedString)
Using ms As New MemoryStream(theData)
Dim theReader As New BinaryReader(ms)
DecodeAttachment(theReader)
End Using
End Sub
Private Sub DecodeAttachment(ByVal theReader As BinaryReader)
'Position the reader to obtain the file size.
Dim headerData As Byte() = New Byte(FIXED_HEADER - 1) {}
headerData = theReader.ReadBytes(headerData.Length)
fileSize = CInt(theReader.ReadUInt32())
attachmentNameLength = CInt(theReader.ReadUInt32()) * 2
Dim fileNameBytes As Byte() = theReader.ReadBytes(attachmentNameLength)
'InfoPath uses UTF8 encoding.
Dim enc As Encoding = Encoding.Unicode
attachmentName = enc.GetString(fileNameBytes, 0, attachmentNameLength - 2)
m_decodedAttachment = theReader.ReadBytes(fileSize)
End Sub
Public Sub SaveAttachment(ByVal saveLocation As String)
Dim fullFileName As String = saveLocation
If Not fullFileName.EndsWith(Path.DirectorySeparatorChar.ToString()) Then
fullFileName += Path.DirectorySeparatorChar
End If
fullFileName += attachmentName
If File.Exists(fullFileName) Then
File.Delete(fullFileName)
End If
Dim fs As New FileStream(fullFileName, FileMode.CreateNew)
Dim bw As New BinaryWriter(fs)
bw.Write(m_decodedAttachment)
bw.Close()
fs.Close()
End Sub
Public ReadOnly Property Filename() As String
Get
Return attachmentName
End Get
End Property
Public ReadOnly Property DecodedAttachment() As Byte()
Get
Return m_decodedAttachment
End Get
End Property
End Class
End Namespace
encode.vb
Imports System
Imports System.IO
Imports System.Text
Imports System.Security.Cryptography
Imports InfoPathAttachmentEncoding
Namespace InfoPathAttachmentEncoding
'''
<summary> ''' InfoPathAttachment encodes file data into the format expected by InfoPath for use in file attachment nodes.
''' </summary>
Public Class InfoPathAttachmentEncoder
Private base64EncodedFile As String = String.Empty
Private fullyQualifiedFileName As String
'''
<summary> ''' Creates an encoder to create an InfoPath attachment string.
''' </summary>
'''
Public Sub New(ByVal fullyQualifiedFileName As String)
If fullyQualifiedFileName = String.Empty Then
Throw New ArgumentException("Must specify file name", "fullyQualifiedFileName")
End If
If Not File.Exists(fullyQualifiedFileName) Then
Throw New FileNotFoundException("File does not exist: " + fullyQualifiedFileName, fullyQualifiedFileName)
End If
Me.fullyQualifiedFileName = fullyQualifiedFileName
End Sub
'''
<summary> ''' Returns a Base64 encoded string.
''' </summary>
''' String
Public Function ToBase64String() As String
If base64EncodedFile <> String.Empty Then
Return base64EncodedFile
End If
' This memory stream will hold the InfoPath file attachment buffer before Base64 encoding.
Dim ms As New MemoryStream()
' Obtain the file information.
Using br As New BinaryReader(File.Open(fullyQualifiedFileName, FileMode.Open, FileAccess.Read, FileShare.Read))
Dim fileName As String = Path.GetFileName(fullyQualifiedFileName)
Dim fileNameLength As UInteger = CUInt(fileName.Length) + 1
Dim fileNameBytes As Byte() = Encoding.Unicode.GetBytes(fileName)
Using bw As New BinaryWriter(ms)
' Write the InfoPath attachment signature.
bw.Write(New Byte() {&HC7, &H49, &H46, &H41})
' Write the default header information.
bw.Write(CUInt(&H14))
' size
bw.Write(CUInt(&H1))
' version
bw.Write(CUInt(&H0))
' reserved
' Write the file size.
bw.Write(CUInt(br.BaseStream.Length))
' Write the size of the file name.
bw.Write(CUInt(fileNameLength))
' Write the file name (Unicode encoded).
bw.Write(fileNameBytes)
' Write the file name terminator. This is two nulls in Unicode.
bw.Write(New Byte() {0, 0})
' Iterate through the file reading data and writing it to the outbuffer.
Dim data As Byte() = New Byte(64 * 1024 - 1) {}
Dim bytesRead As Integer = 1
While bytesRead > 0
bytesRead = br.Read(data, 0, data.Length)
bw.Write(data, 0, bytesRead)
End While
End Using
End Using
' This memorystream will hold the Base64 encoded InfoPath attachment.
Dim msOut As New MemoryStream()
Using br As New BinaryReader(New MemoryStream(ms.ToArray()))
' Create a Base64 transform to do the encoding.
Dim tf As New ToBase64Transform()
Dim data As Byte() = New Byte(tf.InputBlockSize - 1) {}
Dim outData As Byte() = New Byte(tf.OutputBlockSize - 1) {}
Dim bytesRead As Integer = 1
While bytesRead > 0
bytesRead = br.Read(data, 0, data.Length)
If bytesRead = data.Length Then
tf.TransformBlock(data, 0, bytesRead, outData, 0)
Else
outData = tf.TransformFinalBlock(data, 0, bytesRead)
End If
msOut.Write(outData, 0, outData.Length)
End While
End Using
msOut.Close()
Return InlineAssignHelper(base64EncodedFile, Encoding.ASCII.GetString(msOut.ToArray()))
End Function
Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, ByVal value As T) As T
target = value
Return value
End Function
End Class
End Namespace
Imports
Imports InfoPathAttachmentEncoding
btnAttach_Clicked
Public Sub btnAttach_Clicked(ByVal sender As Object, ByVal e As ClickedEventArgs)
Dim ns As XmlNamespaceManager = Me.NamespaceManager
Dim xnMain As XPathNavigator = Me.MainDataSource.CreateNavigator()
Dim xnAttNode As XPathNavigator = xnMain.SelectSingleNode("/my:myFields/my:theAttachmentField", ns)
Dim xnFileName As XPathNavigator = xnMain.SelectSingleNode("/my:myFields/my:theAttachmentName", ns)
'Obtain the text of the filename node.
Dim fileName As String = xnFileName.Value
If fileName.Length > 0 Then
'Encode the file and assign it to the attachment node.
Dim myEncoder As New InfoPathAttachmentEncoder(fileName)
'Check for the "xsi:nil" attribute on the file attachment node and remove it
'before setting the value to attach the filerRemove the "nil" attribute
If xnAttNode.MoveToAttribute("nil", "http://www.w3.org/2001/XMLSchema-instance") Then
xnAttNode.DeleteSelf()
End If
'Attach the file
xnAttNode.SetValue(myEncoder.ToBase64String())
End If
End Sub
btnSave_Clicked
Public Sub btnSave_Clicked(ByVal sender As Object, ByVal e As ClickedEventArgs)
'Create an XmlNamespaceManager
Dim ns As XmlNamespaceManager = Me.NamespaceManager
'Create an XPathNavigator object for the Main data source
Dim xnMain As XPathNavigator = Me.MainDataSource.CreateNavigator()
'Create an XPathNavigator object for the attachment node
Dim xnAttNode As XPathNavigator = xnMain.SelectSingleNode("/my:myFields/my:theAttachmentField", ns)
'Obtain the text of the node.
Dim theAttachment As String = xnAttNode.Value
If theAttachment.Length > 0 Then
Dim myDecoder As New InfoPathAttachmentDecoder(theAttachment)
myDecoder.SaveAttachment("----------ENTER THE PATH HERE-----------")
End If
End Sub
Calculating Age or Anniversary Years
Ever wanted to calculate someones age or how long they have been with a company?
1. Create a new List.
2. Create a new column, set the type to Date and Time, with the Date and Time Format set to Date Only.
3. Create a column and name it Today, data type of Single line of text.
4. Create another column and name it Anniversary, type is Calculated (calculation based on other columns), set the data type to Number, and set the decimal place to 0.
The formula is:
=YEAR(Today)-YEAR(HireDate)-IF(OR(MONTH(Today)<MONTH(HireDate),AND(MONTH(Today)=MONTH(HireDate),DAY(Today)<DAY(HireDate))),1,0)
5. Now you want to delete your Today column that you just created (trust me, just try it).
6. Navigate back to your list and try entering a few values. In my example, Today is equal to 8/18/2011.
Unable to load workflow actions from the server
Roll into work and a coworker alerts me to the fact that our SharePoint 2010 workflows are not flowing. When I tried to open any workflow, I was receiving this error:
Unable to load workflow actions from the server….
I cracked open Fiddler, opened SharePoint Designer, then tried to open a workflow.
On the left side of Fiddler, you will see a bunch of actions, look for one line that turns red and click on it. In the right window, you should see the error.
example:
soap:ServerException of type ‘Microsoft.SharePoint.SoapServer.SoapServerException’ was thrown.Failed to find the XML file at location ‘14\Template\Features\MissingFeature\feature.xml‘0x80131600……..
So I opened one of my WFE servers and navigated to the folder:
C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\FEATURES\MissingFeature
Sure enough, the feature folder in question was missing. To get the missing feature folder, I opened my app server and copied over the missing folder to my WFE servers. No iisreset needed.
Search Web Part Missing
After setting up a new Search Center, I tried to add the Refinement Panel web part, but was unable to locate it.
Navigate to your Site Collection and enable Search Server Web Parts.
From Microsoft:
To activate the Search Server Web Part feature
To open the Site Settings page for the top-level (root) site of the upgraded site collection, append /_layouts/settings.aspx to the root site’s URL, as follows:
http://RootSiteURL/_layouts/settings.aspx
In the Site Collection Administration section of the Site Settings page, click Site collection features.
For Search Server Web Parts, click Activate.
Link for more detail:
http://msdn.microsoft.com/en-us/library/ff512796.aspx
Not Crawling PDF
If your Farm is not crawling PDF files, make sure you have added the PDF extension to the File Types in the Search Application.
Central Administration Search Service Application: Manage Content Sources
Copy List from 2007 to 2010
I’m recreating a site in SharePoint 2010 and didn’t want to create each List and Library.
I tried exporting a List from SharePoint 2007, then import into SharePoint 2010. No go.
SharePoint 2010 doesn’t like .STP files.
I opened MS Access 2010, imported my SharePoint 2007 List, then created a new List in my SharePoint 2010 site using imported 2007 List.
Like this:
In Access 2010
External Data tab
In the Import and Link section, click on More, then click on SharePoint List.
Choose the Import the source data…. option.
With your new table open, look in the Export section of External Data tab.
Click on More, click on SharePoint List, when the Export – SharePoint Site box opens, enter your destination URL and List name.
Click OK.
You should now have your List duplicated to your SharePoint 2010 site.
camel query tool free
http://www.u2u.net/res/Tools/CamlQueryBuilder.aspx
Camel Query tool to build queries or check field names.
Copy files to another document library maintain metadata
(this applies to MOSS / WSS 2007) Scroll to the bottom for a script that will work with SharePoint 2010.
How do you move all the fires from library A to library B?
Easy answer is to open both libraries in Explorer View and copy them over.
Doing this is quick and easy, but your metadata will be lost (if you care).
In my case I had to maintain the metadata when moving a bunch of files to a library in another site.
[System.Reflection.Assembly]::LoadWithPartialName(”Microsoft.SharePoint”) $siteUrl = "http://sharepoint" $webName = "" $spSite = new-object Microsoft.SharePoint.SPSite($siteurl) $spWeb = $spSite.OpenWeb($webName) $spList = $spWeb.Lists["Documents"] $listItems = $spList.Items $listTotal = $listItems.Count for ($x=$listTotal-1;$x -ge 0; $x--) { try { $listItems[$x].CopyTo("http://sharepoint/Docs/Documents/"+ $listItems[$x].name) Write-Host("DELETED: " + $listItems[$x].name) $listItems[$x].Recycle() } Catch { Write-Host $_.Exception.ToString() } } $spSite.Dispose $spWeb.Dispose$listItems[$x].Recycle() can be replaced with $listItems[$x].Delete()
I wanted to move the items to the Recycle Bin for safe keeping.If the file already exists in the destination library, the file will not be moved or deleted.
*if you wanted to deal with this scenario, you could simply create a new file name in the Catch event, and copy the file over.*Foreach does not work if are wanting to loop through the library and delete items.
UPDATE
In this example, I’m using a CAML query to find all documents created before 01/01/2014. This example will also process the items in batches, cutting down on server load. When working with CAML queries, be mindful of the ‘ and ” characters.
$web = Get-SPWeb "http://sharepointed.com/" $list = $web.Lists["Shared Documents"] $spQuery = New-Object Microsoft.SharePoint.SPQuery $spQuery.ViewAttributes = "Scope='Recursive'"; $spQuery.RowLimit = 2000 $caml = '&lt;Where&gt;&lt;Lt&gt;&lt;FieldRef Name="Created" /&gt;&lt;Value IncludeTimeValue="TRUE" Type="DateTime"&gt;2014-01-01T04:06:45Z&lt;/Value&gt;&lt;/Lt&gt;&lt;/Where&gt; ' $spQuery.Query = $caml do { $listItems = $list.GetItems($spQuery) $spQuery.ListItemCollectionPosition = $listItems.ListItemCollectionPosition $listTotal = $listItems.Count for ($x=$listTotal-1;$x -ge 0; $x--) { try { $listItems[$x].CopyTo("http://sharepoint/Docs/Documents/"+ $listItems[$x].name) Write-Host("DELETED: " + $listItems[$x].name) $listItems[$x].Recycle() } catch { Write-Host $_.Exception.ToString() } } } while ($spQuery.ListItemCollectionPosition -ne $null)
My Site Emails Not Sending
In SharePoint 2010 I noticed I wasn’t receiving updates when people posted stuff on my MySite.
Turns out, my Active Directory Sync is not working, and my email account was not being populated in my User Profile.
Fix it!
Central Administration –> Manage User Profiles
Find the person having the issue.
Update the email address.
Cruise over to the mysite, post a note, look in your inbox for an email.





