DOBON.NET DOBON.NETプログラミング掲示板過去ログ

名前付きパイプ通信について

分類:[.NET]


どなたか教えてください。

.NETで名前付きパイプ通信(クライアント側)をしたいのですが、
CreateFile、PeekNamedPipe、ClosePipeの
APIを使用したいのですが、サーバー側を起動させていても、
CreateFileで戻り値:-1しか返ってこなくて、
いろいろ調べてみましたが、うまく動きません。
宣言がまちがっていると思うのですが。。。
(サーバー側は、VBで作成していて、
 同じVBで作成したクライアント側とは、パイプ通信できています。)
また、もしかして、これらのAPIにかわるクラスがあるのでしょうか?
宜しくお願い致します。

--CreateFileの宣言
<StructLayout(LayoutKind.Sequential)> _
Public Structure SECURITY_ATTRIBUTES
Public nLength As Integer
Public lpSecurityDescriptor As Integer
Public bInheritHandle As Boolean
End Structure

Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" _
(ByVal lpFileName As String, _
ByVal dwDesiredAccess As Integer, _
ByVal dwShareMode As Integer, _
ByRef lpSecurityAttributes As Integer, _
ByVal dwCreationDisposition As Integer, _
ByVal dwFlagsAndAttributes As Integer, _
ByVal hTemplateFile As Integer) As Integer

Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" _
(ByVal lpFileName As String, _
ByVal dwDesiredAccess As Integer, _
ByVal dwShareMode As Integer, _
ByRef lpSecurityAttributes As SECURITY_ATTRIBUTES, _
ByVal dwCreationDisposition As Integer, _
ByVal dwFlagsAndAttributes As Integer, _
ByVal hTemplateFile As Integer) As Integer
> 宣言がまちがっていると思うのですが。。。

宣言で明らかにおかしいところは無いと思いますが、
CreateNamedPipe側(VB6?)の宣言はどうなっているの
でしょうか?
サーバー側(VB6)の宣言と、サーバー側のソースです。

Declare Function CreateNamedPipe Lib "kernel32.dll" Alias "CreateNamedPipeA" _
(ByVal lpName As String, _
ByVal dwOpenMode As Long, _
ByVal dwPipeMode As Long, _
ByVal nMaxInstances As Long, _
ByVal nOutBufferSize As Long, _
ByVal nInBufferSize As Long, _
ByVal nDefaultTimeOut As Long, _
lpSecurityAttributes As Any) As Long

Declare Function ConnectNamedPipe Lib "kernel32.dll" _
(ByVal hNamedPipe As Long, ByRef lpOverlapped As Any) As Long


With udtSecurityAttributes
.nLength = Len(udtSecurityAttributes)
.lpSecurityDescriptor = 0
.bInheritHandle = True
End With

hPipe = CreateNamedPipe(strPath, _
PIPE_ACCESS_DUPLEX, _
PIPE_WAIT Or _
PIPE_READMODE_MESSAGE Or _
PIPE_TYPE_MESSAGE, _
PIPE_UNLIMITED_INSTANCES, _
RECV_MAXLENGTH, _
RECV_MAXLENGTH, _
1000, _
udtSecurityAttributes)

If hPipe = INVALID_HANDLE_VALUE Then
MsgBox ("接続失敗")
Exit Sub
End If

  If ConnectNamedPipe(hPipe, udtOverlapped) = 0 Then
MsgBox "待機失敗。"
Call CloseHandle(hPipe) '接続切断
Exit Sub
End If

同じ、VB6で作成したクライアント側とは、
ちゃんと動いているのですが、、、、
・・・宜しくお願い致します。
私のほうで、このVB6パイプと、.netクライアントのCreateFile, PeekNamedPipe
でちゃんと通信できました。
ただし、\\.\pipe\pipename のw2k単独での確認です。

試しに、.net再領布版のみ入れたWinMe越しに繋がせたら、
-1で見事失敗しました。私もこの先はよく分かりません。(^^;;;

そのvb6パイプサーバ端末にクライアントも同居させて
CreateFileしたら成功するか(おそらく成功すると思う)、
を試してみて問題の切り分けをしていくしかないでしょう。

通信できたのですか!?
実行環境はWin2000で、同じ端末内でサーバーとクライアントを実行しています。
(サーバー側は別の端末でする予定ですが・・・)

甘えた事を申しますが・・・もし良ければクライアント側のソースをいただけないでしょうか?
私のクライアント側でのCreateFileする仕方が間違っているかもしれないです。。。

lGetPipe = CreateFile(sSetPipeName, _
GENERIC_WRITE Or GENERIC_READ, _
FILE_SHARE_READ Or FILE_SHARE_WRITE, _
0, _
OPEN_EXISTING, _
  FILE_ATTRIBUTE_NORMAL, _
0)

で実行したのですが、「-1」で返ってきてしまいます。

 申し訳ございませんが、宜しくお願い致します。
ココへUPされたsourceが元だからコーディングの問題ではなく、
多分環境的な違いだと思われます。
(ドメインに参加しないスタンドアロンな端末のローカルadministratorアカウントで
Server・Client同居で試されたら絶対動くと思う。
OS,.net,VS6をクリーンインストしたらさらに完璧。)

'************************************************************ .net Client

  Private Const GENERIC_WRITE = &H40000000
  Private Const GENERIC_READ = &H80000000
  Private Const FILE_SHARE_WRITE = &H2
  Private Const FILE_SHARE_READ = &H1
  Private Const OPEN_EXISTING = 3
  Private Const FILE_ATTRIBUTE_NORMAL = &H80
  Private Const INVALID_HANDLE_VALUE = -1

  <StructLayout(LayoutKind.Sequential)> _
  Public Structure SECURITY_ATTRIBUTES
    Public nLength As Integer
    Public lpSecurityDescriptor As Integer
    Public bInheritHandle As Boolean
  End Structure

  Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" ( _
          ByVal lpFileName As String, _
          ByVal dwDesiredAccess As Integer, _
          ByVal dwShareMode As Integer, _
          ByRef lpSecurityAttributes As Integer, _
          ByVal dwCreationDisposition As Integer, _
          ByVal dwFlagsAndAttributes As Integer, _
          ByVal hTemplateFile As Integer) As Integer

  Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" ( _
          ByVal lpFileName As String, _
          ByVal dwDesiredAccess As Integer, _
          ByVal dwShareMode As Integer, _
          ByRef lpSecurityAttributes As SECURITY_ATTRIBUTES, _
          ByVal dwCreationDisposition As Integer, _
          ByVal dwFlagsAndAttributes As Integer, _
          ByVal hTemplateFile As Integer) As Integer

  Private Declare Auto Function PeekNamedPipe Lib "kernel32" ( _
          ByVal hNamedPipe As Int32, _
          ByVal lpBuffer As Byte(), _
          ByVal nBufferSize As Int32, _
          ByRef lpBytesRead As Int32, _
          ByRef lpTotalBytesAvail As Int32, _
          ByRef lpBytesLeftThisMessage As Int32) As Int32

  Private Declare Auto Function ReadFile Lib "kernel32" Alias "ReadFile" ( _
          ByVal hFile As Int32, _
          ByVal lpBuffer As Byte(), _
          ByVal nNumberOfBytesToRead As Int32, _
          ByRef lpNumberOfBytesRead As Int32, _
          ByVal lpOverlapped_NULL As Int32) As Int32

  Private Declare Auto Function CloseHandle Lib "kernel32" ( _
          ByVal hObject As Int32) As Int32

  Private m_hFile As Integer

  Private Sub Button1_Click(ByVal sender As System.Object, _
                            ByVal e As System.EventArgs) Handles Button1.Click
    Dim sa As SECURITY_ATTRIBUTES

    sa.nLength = Len(sa)

    m_hFile = CreateFile(TextBoxPipeName.Text, _
                         GENERIC_WRITE Or GENERIC_READ, _
                         FILE_SHARE_WRITE Or FILE_SHARE_READ, _
                         sa, _
                         OPEN_EXISTING, _
                         FILE_ATTRIBUTE_NORMAL, 0)

    Label1.Text = m_hFile & " (" & INVALID_HANDLE_VALUE & "=失敗)"
    Label2.Text = ""
    Label3.Text = ""
    Label4.Text = ""
  End Sub

  Private Sub Button2_Click(ByVal sender As System.Object, _
                            ByVal e As System.EventArgs) Handles Button2.Click
    Dim ret As Integer
    Dim buf(1023) As Byte
    Dim intBytesRead As Integer
    Dim intTotalBytesAvail As Integer
    Dim intBytesLeftThisMessage As Integer

    ret = PeekNamedPipe(m_hFile, buf, buf.Length, _
                        intBytesRead, intTotalBytesAvail, _
                        intBytesLeftThisMessage)

    Label2.Text = String.Format( _
      "戻り(0=失敗)={0} : 読バイト={1} : 総バイト={2} : 残バイト{3}", _
      New Object() {ret, intBytesRead, intTotalBytesAvail, _
                    intBytesLeftThisMessage})
    TextBoxReadData.Text = Encoding.Default.GetString(buf)
  End Sub

  Private Sub Button3_Click_1(ByVal sender As System.Object, _
                              ByVal e As System.EventArgs) Handles Button3.Click
    Dim ret As Integer
    Dim buf(1023) As Byte
    Dim intNumberOfBytesRead As Integer

    ret = ReadFile(m_hFile, buf, buf.Length, intNumberOfBytesRead, 0)

    Label3.Text = String.Format("戻り(0=失敗)={0} : 読バイト={1}", _
                                New Object() {ret, intNumberOfBytesRead})
    TextBoxReadData.Text = Encoding.Default.GetString(buf)
  End Sub

  Private Sub Button4_Click(ByVal sender As System.Object, _
                            ByVal e As System.EventArgs) Handles Button4.Click
    Label4.Text = CloseHandle(m_hFile) & " (0=失敗)"
  End Sub


'************************************************************ VB6 Server
Option Explicit

Private Const PIPE_ACCESS_DUPLEX = &H3
Private Const PIPE_TYPE_MESSAGE = &H4
Private Const PIPE_UNLIMITED_INSTANCES = 255
Private Const PIPE_READMODE_MESSAGE = &H2
Private Const PIPE_WAIT = &H0
Private Const INVALID_HANDLE_VALUE = -1

Private Type SECURITY_ATTRIBUTES
  nLength As Long
  lpSecurityDescriptor As Long
  bInheritHandle As Long
End Type

Private Declare Function CreateNamedPipe _
        Lib "kernel32" Alias "CreateNamedPipeA" ( _
        ByVal lpName As String, _
        ByVal dwOpenMode As Long, _
        ByVal dwPipeMode As Long, _
        ByVal nMaxInstances As Long, _
        ByVal nOutBufferSize As Long, _
        ByVal nInBufferSize As Long, _
        ByVal nDefaultTimeOut As Long, _
        lpSecurityAttributes As SECURITY_ATTRIBUTES) As Long

Private Declare Function WriteFile Lib "kernel32" ( _
        ByVal hFile As Long, lpBuffer As Any, _
        ByVal nNumberOfBytesToWrite As Long, _
        ByRef lpNumberOfBytesWritten As Long, _
        ByVal lpOverlapped As Long) As Long

Private Declare Function CloseHandle Lib "kernel32" ( _
        ByVal hObject As Long) As Long

Private m_hPipe As Long

Private Sub Command1_Click()
  Const RECV_MAXLENGTH = 1024
  Dim udtSecurityAttributes As SECURITY_ATTRIBUTES
  
  With udtSecurityAttributes
    .nLength = Len(udtSecurityAttributes)
    .lpSecurityDescriptor = 0
    .bInheritHandle = True
  End With
    
  m_hPipe = CreateNamedPipe(txtPipeName.Text, _
            PIPE_ACCESS_DUPLEX, _
            PIPE_WAIT Or _
            PIPE_READMODE_MESSAGE Or _
            PIPE_TYPE_MESSAGE, _
            PIPE_UNLIMITED_INSTANCES, _
            RECV_MAXLENGTH, _
            RECV_MAXLENGTH, _
            1000, _
            udtSecurityAttributes)
            
  Label1 = m_hPipe & " (" & INVALID_HANDLE_VALUE & "=失敗)"
  Label2 = ""
  Label3 = ""
End Sub

Private Sub Command2_Click()
   Dim lngNumberOfBytesWritten As Long
   Dim strData As String
   Dim ret As Long
   
   strData = txtWriteString.Text
   ret = WriteFile(m_hPipe, ByVal strData, LenB(strData), _
                   lngNumberOfBytesWritten, 0)
   
   Label2 = ret & " (0=失敗) : 書込byte数=" & lngNumberOfBytesWritten
End Sub

Private Sub Command3_Click()
   Label3 = CloseHandle(m_hPipe) & " (0=失敗) "
End Sub
(この記事にはファイル"window.gif"が添付されていましたが、削除されました。)

ご回答有難う御座います。

教えていただいた通り、ソースでの違いではなかったみたいです。
環境的な問題での事・・・で、わからない事があるのですが(すみません)
@サーバー(VB6.0)とクライアント(VB6.0)で実行している環境と、
Aサーバー(VB6.0)とクライアント(.net)で実行している環境とは
全く一緒の環境なのですが、@は実行できるのです。
環境的には、administratorアカウントではなく、
Server・Client同居でしています。
@で動くのに、Aでは動かない、
ご回答いただいた事を考えると、
IISの設定等になってくるという事なのでしょうか?(セキュリティとか?)
・・・的外れな事を言ってたらすみません。
まだ同居でも動いていないんですか。。。

そもそも CreateFile で -1 が返ってきた直後の GetLastError()
は、何番でしたか?

IISは関係ないでしょう。

ご回答有難う御座います。

GetLastErrorは「284146223030468613」で返ってきています。
それと、使用しているアカウントには、
デバッグユーザーとアドミニ権限を付与しています。
(↑関係ないですか???)

宜しくお願い致します。
> GetLastErrorは「284146223030468613」で返ってきています。

で、でかい!
これは Long のままで取りましたね。
16進で 3F17D7C00000005 だから、後ろの 5 がerrorかな。
5 なら ERROR_ACCESS_DENIED 「アクセスは拒否されました」
です。

パイプの存在は認識できたけど、つなぐ権限がないという状態。
さて、なぜでしょうね。(私もよく分からない)

まず、端末におけるアセンブリの権限はフルトラストでしょうか。
コントロールパネル→管理ツール→Microsoft .NET Framework Configuration
で、ランタイムセキュリティ項目などを確認してみてください。

ご回答有難う御座います。

> で、でかい!
> これは Long のままで取りましたね。
> 16進で 3F17D7C00000005 だから、後ろの 5 がerrorかな。
> 5 なら ERROR_ACCESS_DENIED 「アクセスは拒否されました」
> です。

・・・すみません。
エラーコードの調べ方もわからないままだったので・・・
勉強になります。
Microsoft .NET Framework Configurationの
ランタイムセキュリティ項目を確認してみたのですが、
まだまだ勉強不足で、何が何の項目で設定しているのかが
わかってないです。

ランタイムセキュリティ項目についてもう少し勉強してみます。

DOBON.NET | プログラミング道 | プログラミング掲示板