- 題名: API DeletePrinterの使用について
- 日時: 2010/06/30 21:10:29
- ID: 26997
- この記事の返信元:
- (なし)
- この記事への返信:
- [26998] Re[1]: API DeletePrinterの使用について2010/07/01 8:08:40
- [27001] Re[1]: API DeletePrinterの使用について2010/07/01 21:59:54
- ツリーを表示
■No26997に返信(ぷりんさんの記事) > 実際のコードを下記に載せますので、いけない点をご指摘頂けないでしょうか? 検証できる環境が手元に無いので、机上デバッグのみで指摘していきます。 > アクセス拒否(GetLastError()エラー番号:5)が発生してしまい、 提示されたコードでは、Err.LastDllError を利用されているようですので、 既に御存知なのかとは思いますが、VB からは GetLastError API ではなく、 Err.LastDllError もしくは Marshal.GetLastWin32Error() を利用すべきです。 > Private Declare Function OpenPrinter Lib "winspool.drv" Alias "OpenPrinterA" _ > (ByVal PrinterName As String, ByRef hPrinter As IntPtr, ByVal pDefault As PRINTER_DEFAULTS) As Boolean VB6 当時ならいざ知らず、Win9x 系 OS がほぼ使われなくなった現在では 「Alias "〜A"」の ANSI 系 API を利用する意味は無いはずです。 通常は、Unicode バージョンを利用するようにしましょう。 > Private Declare Function ClosePrinter Lib "winspool.drv" _ > (ByVal hPrinter As IntPtr) As Int32 OpenPrinter の戻り値を Boolean として、ClosePrinter/DeletePrinter の戻り値を Int32 にしているのは何故でしょうか? これらの戻り値は、いずれも "BOOL" として定義されています。 .NET でマーシャリングする場合には、 As <MarshalAs(UnmanagedType.Bool)> Boolean とした方が良いでしょう。 > Structure PRINTER_DEFAULTS この型は文字列の受け渡しを伴うため、 <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> の属性を付与しておいた方が良いと思います。 それと、この型は Class で宣言してください。Structure でも間違いではありませんが、 その場合には OpenPrinter の第3引数を ByRef に変更する必要があります。 ちなみに、OpenPrinter に PRINTER_DEFAULTS を渡さない(NULL 指定)としたい場合には、 pDefault 引数を「ByVal + クラス」で宣言しておいて Nothing を渡すようにするか、 あるいは ByVal IntPtr のオーバーロードを用意しておき、IntPtr.Zero を渡すようにします。 > Structure PRINTER_DEFAULTS > Dim pDatatype As Integer > Dim pDevMode As Integer > Dim DesiredAccess As Integer > End Structure すべて Integer 型で宣言されていますね。 本来は、それぞれ "LPTSTR"、"LPDEVMODE"、"ACCESS_MASK" 型です。 最初のメンバーは As String または As IntPtr、 次のメンバーは As DEVMODE または As IntPtr です。 (ただし、DEVMODE の宣言は面倒なので、IntPtr で済ませてしまうのも手かも) 最後のメンバーは、As Integer で良さそうです(あるいは ACCESS_MASK 列挙体)。 > MsgBox("[" & Err.LastDllError & "] " & Err.Description, MsgBoxStyle.Critical + MsgBoxStyle.OKOnly, "エラー") 本題とは無関係ですが、MsgBox の第2引数は「+ 演算子」ではなく「Or 演算子」で繋ぐべきです。 > Dim x As Int32 = DeletePrinter(hPrinter) > ClosePrinter(hPrinter) これだと、OpenPrinter が失敗したときにも hPrinter が処理されてしまう気がします。
分類:[.NET]
初めて投稿させて頂きます。よろしくお願いします。
プリンタドライバのインストール、アンインストールを行うプログラムを作成しています。プリンタキューを削除するのに、APIのDeletePrinter関数を使っていますが、アクセス拒否(GetLastError()エラー番号:5)が発生してしまい、削除ができません。丸一日悩みましたが、どこがいけないのかわかりません。実際のコードを下記に載せますので、いけない点をご指摘頂けないでしょうか?
よろしくお願いいたします。
*************************************************************
Private Declare Function OpenPrinter Lib "winspool.drv" Alias "OpenPrinterA" _
(ByVal PrinterName As String, ByRef hPrinter As IntPtr, ByVal pDefault As PRINTER_DEFAULTS) As Boolean
Private Declare Function ClosePrinter Lib "winspool.drv" _
(ByVal hPrinter As IntPtr) As Int32
Public Declare Function DeletePrinter Lib "winspool.drv" _
(ByVal hPrinter As IntPtr) As Int32
Structure PRINTER_DEFAULTS
Dim pDatatype As Integer
Dim pDevMode As Integer
Dim DesiredAccess As Integer
End Structure
Public Const STANDARD_RIGHTS_REQUIRED As Integer = &HF0000
Public Const PRINTER_ACCESS_ADMINISTER As Integer = &H4
Public Const PRINTER_ACCESS_USE As Integer = &H8
Public Const PRINTER_ALL_ACCESS As Boolean = (STANDARD_RIGHTS_REQUIRED Or PRINTER_ACCESS_ADMINISTER Or PRINTER_ACCESS_USE)
Public sub Main()
Dim hPrinter As IntPtr
Dim udtPrinterDefaults As PRINTER_DEFAULTS
'プリンタアクセス権を指定
With udtPrinterDefaults
.DesiredAccess = PRINTER_ALL_ACCESS
End With
'プリンタのハンドルを取得する
If Not OpenPrinter("HITACHI SP-Component", hPrinter, udtPrinterDefaults) Then
MsgBox("[" & Err.LastDllError & "] " & Err.Description, MsgBoxStyle.Critical + MsgBoxStyle.OKOnly, "エラー")
End If
'プリンタキューの削除
Dim x As Int32 = DeletePrinter(hPrinter)
If x = 0 Then
MsgBox("[" & Err.LastDllError & "] " & Err.Description, MsgBoxStyle.Critical + MsgBoxStyle.OKOnly, "エラー")
End If
'プリンタのハンドルを閉じる
ClosePrinter(hPrinter)
End Sub
*************************************************************