Programmgesteuertes Codieren und Decodieren einer Dateianlage mithilfe von Visual C# in InfoPath 2010 oder InfoPath 2007

Zusammenfassung

In Microsoft InfoPath 2010 oder in Microsoft Office InfoPath 2007 können Sie ein Dateianlage-Steuerelement verwenden, um eine Datei an die InfoPath-Formularvorlage anzufügen. Unter bestimmten Umständen möchten Sie möglicherweise die Datei, die an das Dateianlage-Steuerelement angefügt ist, codieren und dann decodieren. In diesem Fall können Sie Microsoft Visual C# verwenden, um eine Encoderklasse und eine Decoderklasse zu erstellen. Anschließend können Sie die Encoderclass und die Decoderclass verwenden, um die Dateianlage zu codieren und zu decodieren. In diesem Artikel wird beschrieben, wie Sie eine InfoPath-Formularvorlage entwerfen, die eine Datei für die Anlage an das Formular codiert und die Anlage zum Speichern im Dateisystem decodiert.  

Wenn Sie weitere Informationen dazu in InfoPath 2003 erhalten möchten, klicken Sie auf die folgende Artikelnummer, um den Artikel in der Microsoft Knowledge Base anzuzeigen:

892730 Programmgesteuertes Codieren und Decodieren einer Dateianlage mithilfe von Visual C# in InfoPath

Weitere Informationen

Microsoft stellt Programmierbeispiele nur zur Veranschaulichung zur Verfügung, ohne ausdrückliche oder stillschweigende Garantie, einschließlich, aber nicht beschränkt auf die stillschweigenden Garantien der Marktgängigkeit und/oder Eignung für einen bestimmten Zweck. Dieser Artikel setzt voraus, dass Sie mit der zu demonstrierenden Programmiersprache und den Tools zum Erstellen und Debuggen von Prozeduren vertraut sind. Die Microsoft Support-Spezialisten können bei der Erläuterung der Funktionalität bestimmter Prozeduren helfen, jedoch verändern sie diese Beispiele nicht in Bezug auf eine erweiterte Funktionalität, noch entwickeln sie Prozeduren, die auf Ihre besonderen Bedürfnisse zugeschnitten sind.

Im folgenden Beispiel führen Sie die folgenden Schritte aus:

  1. Erstellen Sie ein Formular, das ein Visual C#-Projekt enthält.
  2. Erstellen Sie eine Encoderklasse.
  3. Erstellen Sie eine Decoderklasse.
  4. Ändern Sie das Formular, um den Code aufzurufen.
  5. Testen Sie die Codevorgänge im Formular.

Erstellen eines Formulars, das ein Visual C#-Projekt enthält

Erstellen Sie eine Formularvorlage und ein Projekt mithilfe der Anweisungen für die version von InfoPath, die Sie verwenden.

InfoPath 2010

  1. Erstellen Sie in InfoPath Designer eine leere Formularvorlage, und klicken Sie dann auf das Symbol "Speichern".
  2. Wenn Sie dazu aufgefordert werden, geben Sie den Dateinamen ein, und klicken Sie dann auf "Speichern".
  3. Klicken Sie auf die Registerkarte **Entwicklertools **, und klicken Sie dann auf Sprache.
  4. Wählen Sie unter "Codesprache der Formularvorlage" die Option "C#" aus, und klicken Sie dann auf "OK".

InfoPath 2007

  1. Klicken Sie im Menü **Datei ** auf "Formularvorlage entwerfen".
  2. Klicken Sie im Aufgabenbereich **Formularvorlage entwerfen **auf "Leer " und dann auf "OK".
  3. Klicken Sie im Menü Datei auf Speichern .
  4. Wenn Sie dazu aufgefordert werden, geben Sie den Dateinamen "InfoPathAttachmentEncoding" ein, und klicken Sie dann auf "Speichern".
  5. Klicken Sie im Menü Extras auf Formularoptionen .
  6. Klicken Sie im Dialogfeld **Formularoptionen **unter "Kategorie " auf "Programmierung".
  7. Wählen Sie unter "Programmiersprache" in der Codesprachenliste der Formularvorlage"C#" aus, und klicken Sie dann auf "OK".

Erstellen einer Encoderklasse

Erstellen Sie eine Encoderklasse mithilfe der Anweisungen für die version von InfoPath, die Sie verwenden.

InfoPath 2010

  1. Klicken Sie auf der Registerkarte "Entwicklertools" auf **Code-Editor **, um den Visual Studio-Tools für Anwendungen (VSTA)-Editor zu starten.
  2. Klicken Sie im Menü "Projekt" auf "Neues Element hinzufügen".
  3. Klicken Sie, um " Klasse" auszuwählen.
  4. Ändern Sie im Feld "Name " den Namen in "InfoPathAttachmentEncoder.cs", und klicken Sie dann auf "Speichern".
  5. Ersetzen Sie im Codefenster den vorhandenen Code durch den Code aus dem folgenden Abschnitt "Encodercode".

InfoPath 2007

  1. Starten Sie den Visual Studio-Tools für Anwendungen(VSTA)-Editor. 
  2. Klicken Sie im Bereich **Projektexplorer ** mit der rechten Maustaste auf InfoPathAttachmentEncoding, klicken Sie auf "Hinzufügen", und klicken Sie dann auf "Neues Element".
  3. Wählen Sie im Abschnitt "Vorlagen " die Option "Klasse" aus, ändern Sie den Namen in "InfoPathAttachmentEncoder.cs", und klicken Sie dann auf "Hinzufügen".
  4. Fügen Sie im Codefenster den Code aus dem folgenden Abschnitt "Encodercode" ein.

Encodercode

Verwenden Sie den folgenden Code in InfoPath 2010 oder InfoPath 2007:

using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;
using 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 string base64EncodedFile = string.Empty;
private string fullyQualifiedFileName;

/// <summary>
/// Creates an encoder to create an InfoPath attachment string.
/// </summary>
/// <param name="fullyQualifiedFileName"></param>
public InfoPathAttachmentEncoder(string fullyQualifiedFileName)
{
if (fullyQualifiedFileName == string.Empty)
throw new ArgumentException("Must specify file name", "fullyQualifiedFileName");

if (!File.Exists(fullyQualifiedFileName))
throw new FileNotFoundException("File does not exist: " + fullyQualifiedFileName, fullyQualifiedFileName);

this.fullyQualifiedFileName = fullyQualifiedFileName;
}

/// <summary>
/// Returns a Base64 encoded string.
/// </summary>
/// <returns>String</returns>
public string ToBase64String()
{
if (base64EncodedFile != string.Empty)
return base64EncodedFile;

// This memory stream will hold the InfoPath file attachment buffer before Base64 encoding.
MemoryStream ms = new MemoryStream();

// Obtain the file information.
using (BinaryReader br = new BinaryReader(File.Open(fullyQualifiedFileName, FileMode.Open, FileAccess.Read, FileShare.Read)))
{
string fileName = Path.GetFileName(fullyQualifiedFileName);

uint fileNameLength = (uint)fileName.Length + 1;

byte[] fileNameBytes = Encoding.Unicode.GetBytes(fileName);

using (BinaryWriter bw = new BinaryWriter(ms))
{
// Write the InfoPath attachment signature. 
bw.Write(new byte[] { 0xC7, 0x49, 0x46, 0x41 });

// Write the default header information.
bw.Write((uint)0x14);// size
bw.Write((uint)0x01);// version
bw.Write((uint)0x00);// reserved

// Write the file size.
bw.Write((uint)br.BaseStream.Length);

// Write the size of the file name.
bw.Write((uint)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.
byte[] data = new byte[64*1024];
int bytesRead = 1;

while (bytesRead > 0)
{
bytesRead = br.Read(data, 0, data.Length);
bw.Write(data, 0, bytesRead);
}
}
}

// This memorystream will hold the Base64 encoded InfoPath attachment.
MemoryStream msOut = new MemoryStream();

using (BinaryReader br = new BinaryReader(new MemoryStream(ms.ToArray())))
{
// Create a Base64 transform to do the encoding.
ToBase64Transform tf = new ToBase64Transform();

byte[] data = new byte[tf.InputBlockSize];
byte[] outData = new byte[tf.OutputBlockSize];

int bytesRead = 1;

while (bytesRead > 0)
{
bytesRead = br.Read(data, 0, data.Length);

if (bytesRead == data.Length)
tf.TransformBlock(data, 0, bytesRead, outData, 0);
else
outData = tf.TransformFinalBlock(data, 0, bytesRead);

msOut.Write(outData, 0, outData.Length);
}
}

msOut.Close();

return base64EncodedFile = Encoding.ASCII.GetString(msOut.ToArray());
}
}
}

Erstellen einer Decoderklasse

Erstellen Sie eine Decoderklasse mithilfe der Anweisungen für die version von InfoPath, die Sie verwenden.

InfoPath 2010

  1. Klicken Sie im Code-Editor im Menü "Projekt" auf "Neues Element hinzufügen", und klicken Sie dann, um "Klasse" auszuwählen.
  2. Ändern Sie im Feld "Name " den Namen in "InfoPathAttachmentDecoder.cs", und klicken Sie dann auf "Speichern".
  3. Ersetzen Sie im Codefenster den vorhandenen Code durch den Code aus dem folgenden Abschnitt "Decodercode". 

InfoPath 2007

  1. Klicken Sie in VSTA im Bereich **Projektexplorer **mit der rechten Maustaste auf InfoPathAttachmentEncoding, klicken Sie auf "Hinzufügen", und klicken Sie dann auf "Neues Element".
  2. Wählen Sie im Abschnitt "Vorlagen " die Option "Klasse" aus, ändern Sie den Namen in "InfoPathAttachmentDecoder.cs", und klicken Sie dann auf "Hinzufügen".
  3. Fügen Sie im Codefenster den Code aus dem folgenden Abschnitt "Decodercode" ein.

Decodercode

Verwenden Sie den folgenden Code in InfoPath 2010 oder InfoPath 2007:

using System;
using System.IO;
using System.Text;

namespace InfoPathAttachmentEncoding
{
/// <summary>
/// Decodes a file attachment and saves it to a specified path.
/// </summary>
public class InfoPathAttachmentDecoder
{
private const int SP1Header_Size = 20;
private const int FIXED_HEADER = 16;

private int fileSize;
private int attachmentNameLength;
private string attachmentName;
private byte[] decodedAttachment;

/// <summary>
/// Accepts the Base64 encoded string
/// that is the attachment.
/// </summary>
public InfoPathAttachmentDecoder(string theBase64EncodedString)
{
byte [] theData = Convert.FromBase64String(theBase64EncodedString);
using(MemoryStream ms = new MemoryStream(theData))
{
BinaryReader theReader = new BinaryReader(ms);
DecodeAttachment(theReader);
}
}

private void DecodeAttachment(BinaryReader theReader)
{
//Position the reader to obtain the file size.
byte[] headerData = new byte[FIXED_HEADER];
headerData = theReader.ReadBytes(headerData.Length);

fileSize = (int)theReader.ReadUInt32();
attachmentNameLength = (int)theReader.ReadUInt32() * 2;

byte[] fileNameBytes = theReader.ReadBytes(attachmentNameLength);
//InfoPath uses UTF8 encoding.
Encoding enc = Encoding.Unicode;
attachmentName = enc.GetString(fileNameBytes, 0, attachmentNameLength - 2);
decodedAttachment = theReader.ReadBytes(fileSize);
}

public void SaveAttachment(string saveLocation)
{
string fullFileName = saveLocation;
if (!fullFileName.EndsWith(Path.DirectorySeparatorChar.ToString())){
fullFileName += Path.DirectorySeparatorChar;
}

fullFileName += attachmentName;

if(File.Exists(fullFileName))
File.Delete(fullFileName);

FileStream fs = new FileStream(fullFileName, FileMode.CreateNew);
BinaryWriter bw = new BinaryWriter(fs);
bw.Write(decodedAttachment);

bw.Close();
fs.Close();
}

public string Filename
{
get{ return attachmentName; }
}

public byte[] DecodedAttachment
{
get{ return decodedAttachment; }
}
}
}

Ändern des Formulars

Fügen Sie dem InfoPath-Formular ein Dateianlage-Steuerelement, ein Textfeld-Steuerelement und ein Schaltflächen-Steuerelement hinzu. Gehen Sie dazu wie folgt vor:

  1. Öffnen Sie den Aufgabenbereich "Steuerelemente ", indem Sie die Anweisungen für die von Ihnen verwendete Version von InfoPath verwenden. 

    • InfoPath 2010:Erweitern Sie in der InfoPathAttachmentEncoding InfoPath-Formularvorlage unter der Registerkarte **Start **den Katalog **Steuerelemente **.
    • InfoPath 2007:Klicken Sie in der InfoPathAttachmentEncoding InfoPath-Formularvorlage im Aufgabenbereich **Entwurfsaufgaben **auf Steuerelemente .
  2. Fügen Sie dem InfoPath-Formular ein Dateianlage-Steuerelement hinzu, indem Sie die Anweisungen für die von Ihnen verwendete Version von InfoPath verwenden:

    • InfoPath 2010:Klicken Sie im Aufgabenbereich "Steuerelemente " unter "Objekte" auf "Dateianlage".
    • InfoPath 2007:Klicken Sie im Aufgabenbereich "Steuerelemente " unter "Datei" und "Bild" auf "Dateianlage".
  3. Klicken Sie mit der rechten Maustaste auf das Steuerelement **Dateianlage **, und klicken Sie dann auf "Dateianlageeigenschaften".

  4. Geben Sie im Dialogfeld **Dateianlageneigenschaften **das Feld "AttachmentField" in das Feld "**Feldname **" ein, und klicken Sie dann auf "OK".

  5. Fügen Sie dem InfoPath-Formular ein Textfeld-Steuerelement hinzu, indem Sie die Anweisungen für die von Ihnen verwendete Version von InfoPath verwenden:

    • InfoPath 2010: Klicken Sie im Aufgabenbereich "Steuerelemente " unter "Eingabe" auf "Textfeld".
    • InfoPath 2007: Klicken Sie im Aufgabenbereich "Steuerelemente " unter "Standard" auf "Textfeld".
  6. Klicken Sie mit der rechten Maustaste auf das Textfeld-Steuerelement, und klicken Sie dann auf "Textfeldeigenschaften".

  7. Geben Sie im Dialogfeld **Textfeldeigenschaften **den Namen "AttachmentName" in das Feld "**Feldname **" ein, und klicken Sie dann auf "OK".

  8. Fügen Sie dem InfoPath-Formular eine Schaltfläche "Anfügen" hinzu, indem Sie die Anweisungen für die von Ihnen verwendete Version von InfoPath verwenden:

    • InfoPath 2010: Klicken Sie im Aufgabenbereich "Steuerelemente" unter "Objekte" auf "Schaltfläche".
    • InfoPath 2007: Klicken Sie im Aufgabenbereich "Steuerelemente" unter "Standard" auf "Schaltfläche".
  9. Klicken Sie mit der rechten Maustaste auf das neue Schaltflächensteuerelement, und klicken Sie dann auf "Schaltflächeneigenschaften".

  10. Geben Sie im Dialogfeld **Schaltflächeneigenschaften **im Feld **Beschriftung ** den Text "Anfügen" ein, geben Sie "btnAttach" in das ID-Feld ein, und klicken Sie dann auf "Formularcode bearbeiten".

  11. Wechseln Sie zum oberen Rand des Codefensters, und fügen Sie dann die folgende Codezeile hinzu:

    using InfoPathAttachmentEncoding;
    
  12. Kehren Sie zu "Schreiben Sie ihren Code hier" zurück, und fügen Sie dann den folgenden Code hinzu:

     //Create an XmlNamespaceManager
     XmlNamespaceManager ns = this.NamespaceManager;
    
    //Create an XPathNavigator object for the Main data source
     XPathNavigator xnMain = this.MainDataSource.CreateNavigator();
    
    //Create an XPathNavigator object for the attachment node
     XPathNavigator xnAttNode = xnMain.SelectSingleNode("/my:myFields/my:theAttachmentField", ns);
    
    //Create an XPathNavigator object for the filename node
     XPathNavigator xnFileName = xnMain.SelectSingleNode("/my:myFields/my:theAttachmentName", ns);
    
    //Obtain the text of the filename node.
     string fileName = xnFileName.Value;
     if (fileName.Length > 0)
     {
      //Encode the file and assign it to the attachment node.
      InfoPathAttachmentEncoder myEncoder = 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"))
       xnAttNode.DeleteSelf();
    
    //Attach the file
      xnAttNode.SetValue(myEncoder.ToBase64String());
     }              
    
    

Hinzufügen einer Schaltfläche "Speichern" zum InfoPath-Formular

  1. Kehren Sie zur InfoPathAttachmentEncoding-Formularvorlage zurück.

  2. Fügen Sie eine Schaltfläche "Speichern" mithilfe der Anweisungen für die von Ihnen verwendete Version von InfoPath hinzu:

    • InfoPath 2010: Klicken Sie im Aufgabenbereich "Steuerelemente" unter "Objekte" auf "Schaltfläche".
    • InfoPath 2007: Klicken Sie im Aufgabenbereich "Steuerelemente" unter "Standard" auf "Schaltfläche".
  3. Klicken Sie mit der rechten Maustaste auf das neue Schaltflächensteuerelement, und klicken Sie dann auf "Schaltflächeneigenschaften".

  4. Geben Sie im Dialogfeld **Schaltflächeneigenschaften **im Feld **Beschriftung **speichern ein, geben Sie "btnSave" in das Feld "**ID **" ein, und klicken Sie dann auf "Formularcode bearbeiten".

  5. Fügen Sie den folgenden Code ein:

     //Create an XmlNamespaceManager
     XmlNamespaceManager ns = this.NamespaceManager;
    
    //Create an XPathNavigator object for the Main data source
     XPathNavigator xnMain = this.MainDataSource.CreateNavigator();
    
    //Create an XPathNavigator object for the attachment node
     XPathNavigator xnAttNode = xnMain.SelectSingleNode("/my:myFields/my:theAttachmentField", ns);
    
    //Obtain the text of the node.
     string theAttachment = xnAttNode.Value;
     if(theAttachment.Length > 0)
     {
         InfoPathAttachmentDecoder myDecoder = new InfoPathAttachmentDecoder(theAttachment);
         myDecoder.SaveAttachment(@"Path to the folder to save the attachment");
     }                                              
    
    

Hinweis

In diesem Code stellt der Platzhalterpfad zum Ordner zum Speichern der Anlage den Speicherort dar, an dem Sie die Datei speichern möchten.

Klicken Sie auf das Symbol "Speichern", und schließen Sie dann VSTA.

Testen des Formulars

Bevor dieses Formular eine Datei anfügen kann, muss die InfoPath-Formularvorlage voll vertrauenswürdig sein. Um dies sicherzustellen, führen Sie eine der folgenden Aktionen aus:

  • Verwenden Sie ein Codesignaturzertifikat, um die Formularvorlagendatei (XSN) digital zu signieren. Wenn Sie dies tun, werden Benutzer aufgefordert, dem Formular zu vertrauen, wenn sie das Formular öffnen. Dadurch wird das Formular vollständig vertrauenswürdig. Daher werden Ihrem Visual C#-Code voll vertrauenswürdige Berechtigungen gewährt.
  • Erstellen Sie eine installierbare Vorlage.

Nachdem Sie sichergestellt haben, dass die Formularvorlage voll vertrauenswürdig ist, sollten Sie sie testen. Gehen Sie dazu wie folgt vor:

  1. Öffnen Sie das Formular im Vorschaumodus, indem Sie die Schritte für die von Ihnen verwendete Version von InfoPath ausführen:

    • InfoPath 2010 Klicken Sie auf der Registerkarte " Start " auf " Vorschau".
    • InfoPath 2007 Klicken Sie auf der Standardtoolleiste auf " Vorschau".
  2. Geben Sie im InfoPath-Formular den Pfad der Datei, die Sie anfügen möchten, in das Textfeld ein, und klicken Sie dann auf "Anfügen".

    Hinweis Doppelklicken Sie auf das Dateianlagen-Steuerelement, um zu überprüfen, ob die Datei ordnungsgemäß codiert ist. 

  3. Klicken Sie auf Speichern.

  4. Suchen Sie den Pfad, den Sie im Code für den Abschnitt "Schaltfläche 'Speichern' zum InfoPath-Formular hinzufügen'" angegeben haben, und stellen Sie dann sicher, dass die Datei in diesem Ordner gespeichert wurde. 

  5. Klicken Sie auf "Vorschau schließen". Damit wird der Test beendet.