InfoPath 2003 で Visual C# を使用して、ファイル添付ファイルをプログラムでエンコードしてデコードする方法
概要
Microsoft Office InfoPath 2007 または Microsoft Office InfoPath 2003 Service Pack 1 (SP1) では、 添付ファイル コントロールを使用して、ファイルを InfoPath フォーム テンプレートに添付できます。 特定の状況では、 添付 ファイル コントロールに添付されているファイルをエンコードしてデコードすることができます。 この場合、Microsoft Visual C# を使用して Encoder クラスとデコーダー クラスを作成できます。 その後、Encoder クラスとデコーダー クラスを使用して、添付ファイルをエンコードおよびデコードできます。
はじめに
この記事では、InfoPath 2003 で Microsoft Visual C# を使用して、ファイル添付ファイルをプログラムでエンコードおよびデコードする方法について説明します。 InfoPath 2010 または InfoPath 2007 でこれを行う方法については、次の Web ページを参照してください。 InfoPath 2010 または InfoPath 2007 で Visual C# を使用して、添付ファイルをエンコードしてデコードする方法をプログラムで 参照してください。
詳細情報
Microsoft は、例示のみを目的としてプログラミング例を提供しており、明示または黙示にかかわらず、いかなる責任も負わないものとします。 これには、市販性または特定の目的との適合性についての黙示の保証も含まれますが、これに限定はされません。 この記事は、説明されているプログラミング言語、手順を作成およびデバッグするために使用されているツールに読者が精通していることを前提にしています。 マイクロソフト サポート窓口では、特定のプロシージャの機能説明に関するご質問に対して支援いたしますが、本例を特定の目的を満たすために機能を追加したり、プロシージャを構築することは行いません。
Visual C# InfoPath 2003 プロジェクトを作成する
Microsoft Visual Studio .NET 2003 を起動します。
[ファイル] メニューの [新規作成] をクリックし、[プロジェクト] をクリックします。
[ 新しいプロジェクト ] ダイアログ ボックスで、Microsoft Office InfoPath プロジェクト フォルダーの [ Visual C# プロジェクト] をクリックします。
[名前] ボックスに「AttachmentEncoding」と入力し、[OK] をクリックします。
Microsoft Office プロジェクト ウィザードで、[ 新しいフォーム テンプレートの作成] をクリックし、[ 完了] をクリックします。
Microsoft Office プロジェクト ウィザードでは、AttachmentEncoding という名前の新しい Visual Studio .NET 2003 プロジェクトが作成されます。 InfoPath フォーム テンプレートも作成されます。 InfoPath フォーム テンプレートの名前は AttachmentEncoding です。
Visual Studio .NET 2003 で Encoder クラスを作成する
- ソリューション エクスプローラーで、AttachmentEncoding を右クリックし、[追加] をポイントして、[新しいアイテムの追加] をクリックします。
- [新しい項目の追加] ダイアログ ボックスで、[テンプレート] ウィンドウで [クラス] をクリックし、[名前] ボックスに「InfoPathAttachmentEncoder.cs」と入力し、[開く] をクリックします。
- InfoPathAttachmentEncoder.cs ファイル内のすべてのコードを次のコードに置き換えます。
using System; using System.IO; using System.Text; using System.Security.Cryptography; 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(); // Get 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()); } } }
Visual Studio .NET 2003 でデコーダー クラスを作成する
- ソリューション エクスプローラーで、AttachmentEncoding を右クリックし、[追加] をポイントして、[新しいアイテムの追加] をクリックします。
- [新しい項目の追加] ダイアログ ボックスで、[テンプレート] ウィンドウで [クラス] をクリックし、[名前] ボックスに「InfoPathAttachmentDecoder.cs」と入力して、[開く] をクリックします。
- InfoPathAttachmentDecoder.cs ファイル内のすべてのコードを次のコードに置き換えます。
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 get 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)) { 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; } } } }
ファイル添付コントロールとテキスト ボックス コントロールを InfoPath フォームに追加する
- AttachmentEncoding InfoPath フォーム テンプレートで、[デザイン タスク] 作業ウィンドウで [コントロール] をクリックします。
- [コントロール] 作業ウィンドウで、[コントロールの挿入] で [添付ファイル] をクリックします。
- [添付ファイル] コントロールを右クリックし、[添付ファイルのプロパティ] をクリックします。
- [ 添付ファイルのプロパティ ] ダイアログ ボックスで、[ フィールド名 ] ボックスにAttachmentField を入力し、[ OK] をクリックします。
- [コントロール] 作業ウィンドウで、[コントロールの挿入] で [テキスト ボックス] をクリックします。
- テキスト ボックス コントロールを右クリックし、[テキスト ボックスのプロパティ] をクリックします。
- [ テキスト ボックスのプロパティ] ダイアログ ボックスで、[ フィールド名 ] ボックスにAttachmentName を入力し、[ OK] をクリックします。
InfoPath フォームに [アタッチ] ボタンを追加する
- [コントロール] 作業ウィンドウで、[コントロールの挿入] の下にある [ボタン] をクリックします。
- 新しい Button コントロールを右クリックし、[ボタンの プロパティ] をクリックします。
- [ボタンのプロパティ] ダイアログ ボックスで、[ラベル] ボックスに「アタッチ」と入力し、ID ボックスに「btnAttach」と入力して、[フォーム コードの編集] をクリックします。
- btnAttach_OnClick メソッドに次のコードを追加します。
//Get a reference to the attachment node. IXMLDOMNode theAttachmentNode = thisXDocument.DOM.selectSingleNode("my:myFields/my:theAttachmentField"); //Get a reference to the filename node. IXMLDOMNode fileNameNode = thisXDocument.DOM.selectSingleNode("my:myFields/my:theAttachmentName"); //Get the text of the node. String fileName = fileNameNode.text; if(fileName.Length > 0) { //Encode the file and assign it to the attachment node. InfoPathAttachmentEncoding.Encoder myEncoder = new InfoPathAttachmentEncoding.Encoder(fileName); if(theAttachmentNode.attributes.getNamedItem("xsi:nil") != null) theAttachmentNode.attributes.removeNamedItem("xsi:nil"); theAttachmentNode.text = myEncoder.ToBase64String(); }
InfoPath フォームに [保存] ボタンを追加する
- AttachmentEncoding InfoPath フォーム テンプレートに切り替えます。
- [コントロール] 作業ウィンドウで、[コントロールの挿入] の下にある [ボタン] をクリックします。
- 新しい Button コントロールを右クリックし、[ボタンの プロパティ] をクリックします。
- [ボタンのプロパティ] ダイアログ ボックスで、「ラベル」ボックスに「保存」と入力し、ID ボックスに「btnSave」と入力して、[フォーム コードの編集] をクリックします。
- btnSave _OnClick メソッドに次のコードを追加します。
//Get a reference to the attachment node. IXMLDOMNode n = thisXDocument.DOM.selectSingleNode("my:myFields/my:theAttachmentField"); //Get the text of the node. String theAttachment = n.text; if(theAttachment.Length > 0) { InfoPathAttachmentEncoding.Decoder myDecoder = new InfoPathAttachmentEncoding.Decoder(theAttachment); myDecoder.SaveAttachment(@"<Path to save the file>"); }
注:
このコードでは、ファイルを保存する場所に置き換えます 。
InfoPath フォーム テンプレートが完全に信頼されていることを確認する
このフォームをテストする前に、InfoPath フォーム テンプレートが完全に信頼されている必要があります。 次のいずれかの方法を使用して、InfoPath フォーム テンプレートが完全に信頼されていることを確認できます。
Microsoft .NET Framework 1.1 構成ユーティリティを使用して、Visual C# コードのみに完全信頼アクセス許可を付与します。
InfoPath ソフトウェア開発キット (SDK) の RegForm ユーティリティを使用して、フォームを完全に信頼できるフォームにします。 これにより、Visual C# コードに対する完全信頼アクセス許可が付与されます。
コード署名証明書を使用して、フォーム テンプレート ファイル (.xsn) にデジタル署名します。 コード署名証明書を使用してフォーム テンプレート ファイルにデジタル署名すると、ユーザーはフォームを開くときにフォームを信頼するように求められます。 これにより、フォームは完全に信頼されます。 そのため、完全信頼アクセス許可は Visual C# コードに付与されます。
InfoPath SDK の IPFullTrust マクロを使用して、フォームを完全に信頼されたフォームにします。 IPFullTrust マクロは、完全信頼のために InfoPath プロジェクトのマニフェスト ファイル (.xsf) とフォーム テンプレート ファイルの設定を自動化し、IPFullTrust マクロによってフォーム テンプレートが自動的に登録されます。
マクロをインストールして使用する方法の詳細については、次の Microsoft Developer Network (MSDN) Web サイトを参照してください。
https://msdn.microsoft.com/en-us/library/aa202736(office.11).aspx
InfoPath で外部 Automation を使用して RegisterSolution メソッドを呼び出します。 通常、このメソッドはフォーム開発にのみ使用されます。登録されたフォームは個々のコンピューターにのみ登録されるためです。 その他のフォームについては、他のユーザーが自分のコンピューターに追加のフォームを登録する必要があります。 このメソッドは、追加のフォームにはお勧めしません。 フォームを発行するときは、前のいずれかの方法をお勧めします。
このフォームはフォーム開発中であるため、最後のメソッドを使用できます。 これを行うには、AttachmentEncoding InfoPath フォーム テンプレートを見つけて、次の手順に従います。
[ツール] メニューの [フォームのオプション] をクリックします。
[セキュリティ] タブをクリックします。
フォームの 設計に基づいてセキュリティ レベルを自動的に決定する (推奨) チェック ボックスをオフにします。
メモ InfoPath では、完全信頼アクセス許可を必要とするビジネス ロジックを自動的に検出できません。 そのため、完全信頼のアクセス許可を明示的に付与する必要があります。
[ 完全信頼] をクリックし、[OK] をクリック します。
AttachmentEncoding InfoPath フォーム テンプレートを閉じます。 変更を保存するように求められた場合は、[ はい] をクリックします。
メモ Visual Studio .NET 2003 プロジェクトを閉じないでください。
Visual Studio .NET 2003 で、ソリューション エクスプローラーで Manifest.xsf ファイルをダブルクリックします。 Manifest.xsf ファイルが開きます。
ルート ノードで publishUrl 属性を見つけます。 publishUrl 属性と publishUrl 属性の値を削除します。
変更を保存し、Manifest.xsf ファイルを閉じます。
[ スタート] ボタンをクリックし、[ 実行] をクリックし、「メモ帳」と入力して、[OK] をクリック します。
空のテキスト ファイルに次のコードを追加します。
oApp = WScript.CreateObject("InfoPath.ExternalApplication"); strAbsolutePath = "<project_folder_url>\\Manifest.xsf"; oApp.RegisterSolution(strAbsolutePath,"overwrite");
メモ このコードでは、 project_folder_url をプロジェクト フォルダー内の Manifest.xsf ファイルのパスに置き換えます。 Manifest.xsf ファイルのパスは必ずエスケープしてください。 パス内のすべての単一円記号 (\) は、2 つの円記号 (\\) に置き換える必要があります。
Manifest.xsf ファイルをRegister.js ファイルとしてコンピューターに保存します。
RegisterSolution メソッドを呼び出すには、作成した Register.js ファイルをダブルクリックします。
フォームをテストする
AttachmentEncoding Visual Studio .NET 2003 プロジェクトで、[デバッグ] メニューの [開始] をクリックします。 これにより、プレビュー モードで InfoPath フォームが開始されます。
InfoPath フォームで、テキスト ボックスに添付するファイルのパスを入力し、[ 添付] をクリックします。
メモ[添付ファイル] コントロールをダブルクリックして、ファイルが正しくエンコードされていることを確認します。
[保存] をクリックします。 [InfoPath フォームに保存ボタンを追加 する ] セクションで指定したパスを探します。
テストを終了するには、[ プレビューを閉じる] をクリックします。
関連情報
添付ファイルのヘッダー形式の詳細については、次の MSDN Web サイトを参照してください。
InfoPath 2003 でのファイルの添付 https://msdn.microsoft.com/en-us/library/aa168351(office.11).aspx