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….

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

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.

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.

the language of this installation package is not supported by your system

When trying to install SharePoint Designer 2010 on my PC, I ran into an error saying Designer 2007 was installed on the box.

The problem was, I had SharePoint Designer 2007 installed, and it’s a 32-bit install. When I tried to uninstalled Designer 2007 I was getting this error:

The language of this installation package is not supported by your system

No matter what google-related-fix I tried, I couldn’t uninstall it.

What I did to fix things:
Installed Office 2007
Installed Designer 2007

Uninstalled Desinger 2007
Uninstalled Office 2007

Then I was able to install SharePoint Designer 2010.