質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.39%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

1回答

2080閲覧

V4ドライバー PrinterExtention での PrintTicketの編集時の例外について

hex

総合スコア7

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2018/02/12 08:41

編集2018/02/12 08:44

前提・実現したいこと

V4プリンタドライバのPrinterExtentionでの PrintTicketの編集時に例外が発生するのですが、原因について教えていただけませんでしょうか。下記URLからMicrosoftが提供しているサンプルを落とし、参考にして、動作確認を行っております。
[PrinterExtentionSample]
https://github.com/Microsoft/Windows-driver-samples/tree/master/print/v4PrintDriverSamples/PrinterExtensionSample

サンプルに従って、ビルドを行い、プリンタに関連付けて実行すると、PrintTicketの読み込み【ticketRootXElement.Load()】 は正常に行え、PrintTcketの内容が取得できます。
なお、PrintTicketの書き込み【ticketRootXElement.Save()】 を行うと例外(0x80004005)が発生してしまいます。中を見ると、System.Runtime.InteropServices.ComTypes.IStream の Write()で発生しました。
原因を2日ほど探しておりましたが、頭足らずで全く分かりませんでした。以下、上記URLの関連する場所を抜粋してソースコードを記載しております。お手数ですが、例外が発生する原因についてご回答いただけませんでしょうか。

発生している問題・エラーメッセージ

0x80004005

試したこと

【ticketRootXElement.SetLength()】を行ってもコードは異なりますが、例外(0x80004001)が発生しました。
実際には、System.Runtime.InteropServices.ComTypes.IStream の SetSize()で発生しました。

補足情報(FW/ツールのバージョンなど)

Visual Studio 2015

該当のソースコード

C#

1エラー発生箇所 PrintPreferenceWindow.xaml.cs - ModifyPrintTicketXml 2 3private void ModifyPrintTicketXml() 4{ 5 // 6 // Load the ticket XML (as a Stream) into an XElement object. 7 // 8 9 XElement ticketRootXElement = null; 10 using (Stream ticketReadStream = displayedPrintTicket.GetReadStream()) 11 { 12 ticketRootXElement = XElement.Load(ticketReadStream); 13 } 14 15 // 16 // Perform any modifications on the XElement object. 17 // 18 19 20 // 21 // Write the changes back to the print ticket. 22 // 23 using (Stream ticketWriteStream = displayedPrintTicket.GetWriteStream()) 24 { 25 ticketRootXElement.Save(ticketWriteStream); // ここで例外が発生します。 26 } 27}

C#

1PrinterExtensionAdapters.cs - PrintSchemaTicket 2internal class PrintSchemaTicket : IPrintSchemaTicket 3{ 4 ~~~~~~~~ 5 private System.Runtime.InteropServices.ComTypes.IStream XmlStream 6 { 7 get 8 { 9 System.Runtime.InteropServices.ComTypes.IStream istream = _printTicket.XmlNode as System.Runtime.InteropServices.ComTypes.IStream; 10 return istream; 11 } 12 } 13 14 public Stream GetReadStream() 15 { 16 return new ComIStreamAdapter(XmlStream, 17 false, // canWrite 18 true, // canSeek 19 true // canRead 20 ); 21 } 22 23 public Stream GetWriteStream() 24 { 25 return new ComIStreamAdapter(XmlStream, 26 true, // canWrite 27 true, // canSeek 28 false // canRead 29 ); 30 } 31}

C#

1PrinterExtensionAdapters.cs - ComIStreamAdapter 2 3// 4// The following class provide an adapter that exposes a 'Stream' and wraps a 5// COM pointer to the standard COM 'IStream' interface 6// 7internal class ComIStreamAdapter : Stream, IDisposable 8{ 9 public ComIStreamAdapter(System.Runtime.InteropServices.ComTypes.IStream stream, bool canWrite = false, bool canSeek = false, bool canRead = true) 10 { 11 if (stream != null) 12 { 13 _comIstream = stream; 14 } 15 else 16 { 17 throw new ArgumentNullException("stream"); 18 } 19 _streamValidation = new StreamValidation(canWrite, canSeek, canRead); 20 } 21 22 ~ComIStreamAdapter() 23 { 24 Dispose(false); 25 } 26 27 #region Overridden Stream methods 28 29 public override int Read(byte[] buffer, int offset, int count) 30 { 31 _streamValidation.ValidateRead(buffer, offset, count); 32 33 uint bytesRead = 0; 34 35 // Pin the byte array so that it will not be moved by the garbage collector 36 byte[] tempBuffer = new byte[count]; 37 GCHandle gcHandle = GCHandle.Alloc(tempBuffer, GCHandleType.Pinned); 38 IntPtr bytesReadPtr = Marshal.AllocHGlobal(sizeof(int)); 39 try 40 { 41 _comIstream.Read(tempBuffer, count, bytesReadPtr); 42 bytesRead = (uint)Marshal.ReadInt32(bytesReadPtr); 43 44 Array.Copy(tempBuffer, 0, buffer, offset, (int)bytesRead); // Safe to cast. Cannot be bigger than 'int count' 45 } 46 finally 47 { 48 Marshal.FreeHGlobal(bytesReadPtr); 49 gcHandle.Free(); 50 } 51 52 return (int)bytesRead; // Safe to cast; bytesRead can never be larger than 'int count' 53 } 54 55 public override void Write(byte[] buffer, int offset, int count) 56 { 57 _streamValidation.ValidateWrite(buffer, offset, count); 58 59 uint written; 60 61 // Pin the byte array so that it will not be moved by the garbage collector 62 byte[] tempBuffer = new byte[count]; 63 GCHandle gcHandle = GCHandle.Alloc(tempBuffer, GCHandleType.Pinned); 64 IntPtr writeCountPointer = Marshal.AllocHGlobal(sizeof(int)); 65 try 66 { 67 Array.Copy(buffer, offset, tempBuffer, 0, count); 68 69 _comIstream.Write(tempBuffer, count, writeCountPointer); 70 written = (uint)Marshal.ReadInt32(writeCountPointer); // safe to cast. 'written' is always non-negative 71 } 72 finally 73 { 74 gcHandle.Free(); 75 Marshal.FreeHGlobal(writeCountPointer); 76 } 77 78 if ((int)written < count) 79 { 80 throw new IOException(); 81 } 82 } 83 84 public override long Seek(long offset, SeekOrigin origin) 85 { 86 _streamValidation.ValidateSeek(offset, origin); 87 88 uint istreamSeekOrigin = 0; 89 90 switch (origin) 91 { 92 case SeekOrigin.Begin: 93 istreamSeekOrigin = (uint)PrinterExtensionLib.tagSTREAM_SEEK.STREAM_SEEK_SET; 94 break; 95 96 case SeekOrigin.Current: 97 istreamSeekOrigin = (uint)PrinterExtensionLib.tagSTREAM_SEEK.STREAM_SEEK_CUR; 98 break; 99 100 case SeekOrigin.End: 101 istreamSeekOrigin = (uint)PrinterExtensionLib.tagSTREAM_SEEK.STREAM_SEEK_END; 102 break; 103 } 104 105 IntPtr seekPositionPointer = Marshal.AllocHGlobal(sizeof(long)); 106 long seekPosition = 0; 107 try 108 { 109 _comIstream.Seek(offset, (int)istreamSeekOrigin, seekPositionPointer); 110 seekPosition = Marshal.ReadInt64(seekPositionPointer); 111 } 112 finally 113 { 114 Marshal.FreeHGlobal(seekPositionPointer); 115 } 116 117 return seekPosition; 118 } 119 120 public override long Length 121 { 122 get 123 { 124 _streamValidation.ValidateSeek(); 125 126 System.Runtime.InteropServices.ComTypes.STATSTG statstg; 127 _comIstream.Stat(out statstg, 1 /* STATSFLAG_NONAME*/ ); 128 return statstg.cbSize; 129 } 130 } 131 public override long Position 132 { 133 get { return Seek(0, SeekOrigin.Current); } 134 set { Seek(value, SeekOrigin.Begin); } 135 } 136 137 public override void SetLength(long value) 138 { 139 _streamValidation.ValidateSeek(); 140 _comIstream.SetSize(value); 141 } 142 143 public override void Flush() 144 { 145 _comIstream.Commit(0); 146 } 147 148 ~~ 略 ~ 149 150 #region Implementation details 151 152 // Prevent default construction 153 private ComIStreamAdapter() { } 154 155 private bool _disposed = false; 156 private System.Runtime.InteropServices.ComTypes.IStream _comIstream = null; 157 private StreamValidation _streamValidation = null; 158 159 #endregion 160}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

考えていただいた方がいらっしゃったのであれば、大変申し訳ございません。
質問の意図も伝わりづらいし、質問に記載したコードにも不備がありました。

using内で取得したStreamを複数回触ると発生していたようです。提示したコードに、Streamをいじるコードを一つ足していました。大変申し訳ございません。
なぜ、複数回Streamをいじると例外が発生してしまうのか不明なままですが、一回の取り出しで、一回の編集をすればなんとかできますので、自己解決とさせていただきます。すいませんでした。

投稿2018/02/28 14:34

hex

総合スコア7

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.39%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問