- PR -

Windowsサービスでの共有メモリ使用

1
投稿者投稿内容
未記入
会議室デビュー日: 2005/09/29
投稿数: 3
投稿日時: 2005-09-29 10:43
【開発環境】
 VisualStudio.NET⇒VisualBasic⇒Windowsサービス

上記の環境で、アプリケーション開発を行っています。

以前、VB.NETのWindowsアプリケーションで
共有メモリを扱うアプリケーションを作成しており、
それをWindowsサービスでも実現したいと思っています。

MSDNのサンプル等を見て、サービスの開始・終了時にログを残す、
というPGは作成できたのですが、OnStopイベント・OnStartイベント等に
以前作成したコードを書き込んで実行しようとしても、
そのコードを通る時に落ちてしまいます。(デバックして確認。)

OnStopイベント・OnStartイベント等にWindowsアプリケーション感覚で
コードを記述する事自体に問題があるということでしょうか?

何とかWindowsアプリケーションで作成したコードを反映できれば
共有メモリの扱いはどうにかなるのですが…。

ご意見・ご指摘をお願いします。
甕星
ぬし
会議室デビュー日: 2003/03/07
投稿数: 1185
お住まい・勤務地: 湖の見える丘の上
投稿日時: 2005-09-29 14:32
引用:

未記入さんの書き込み (2005-09-29 10:43) より:
【開発環境】
 VisualStudio.NET⇒VisualBasic⇒Windowsサービス


上のような記述ではシステムの構成が全く見えません。VB.NETとVB6.0とWindowsサービスはそれぞれどのように関連しているのですか?

引用:

MSDNのサンプル等を見て、サービスの開始・終了時にログを残す、
というPGは作成できたのですが、OnStopイベント・OnStartイベント等に
以前作成したコードを書き込んで実行しようとしても、
そのコードを通る時に落ちてしまいます。(デバックして確認。)


落ちるとは?何か例外が発生するのですか?それなら例外の内容を確認してください。それともメモリアクセス例がですか?それがどのようなAPIで発生するのですか?それ以前の段階でAPIがエラー値を返している可能性は無いのですか?
未記入
会議室デビュー日: 2005/09/29
投稿数: 3
投稿日時: 2005-09-29 16:18
引用:

上のような記述ではシステムの構成が全く見えません。VB.NETとVB6.0とWindowsサービスはそれぞれどのように関連しているのですか?



VisualBasic.NETでWindowsサービスを作成した、という意味です。
分かり辛い書き方ですみません…。

引用:

落ちるとは?何か例外が発生するのですか?それなら例外の内容を確認してください。それともメモリアクセス例がですか?それがどのようなAPIで発生するのですか?それ以前の段階でAPIがエラー値を返している可能性は無いのですか?



あれからコードを見直し、APIの使い方が微妙に間違っており、
それを直すことで一応APIの所を通る時に落ちる事はなくなりました。

因みに、コードはOnStopイベント内に記述しています。

ですが、API関数がエラーを返してくるので、調査中です。
何かお気づきの事があれば、ご指摘下さい。

(以下、コード)
'【OnStopイベント】
Protected Overrides Sub OnStop()

Filename = "C:\\\\Test.txt"

'@ファイルハンドルを取得
hFile = CreateFile(Filename, GENERIC_READ Or GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0)
'↑エラー値-1が返ってくる。

'Aマッピングオブジェクトを作成
hFileMap = CreateFileMappingLong(hFile, 0, PAGE_READWRITE, 0, FileLength, "test")
If hFileMap = 0 Then GoTo LabelLast
'↑hFileが不正なので、エラーが返る。

'Bメモリマップトファイルを作成
nAddress = MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, 0)
If nAddress = 0 Then GoTo LabelLast

LabelLast:
End Sub


'【モジュール】
Option Strict Off
Option Explicit On
Module Module1

Public hOpened, hFileMap, hFile, nAddress As Long
Public FileLength As Integer
Public Filename As String

Public dByte() As Byte
Public dByte2() As Byte

Public stFrpDatTo_Bfr As stFrpDatTo
Public iCnt, iPos As Integer

'*****************
'* API関数引数用 *
'*****************
Public Const CREATE_NEW As Short = 1
Public Const CREATE_ALWAYS As Short = 2

Public Const FILE_ATTRIBUTE_ARCHIVE As Short = &H20S
Public Const FILE_ATTRIBUTE_COMPRESSED As Short = &H800S
Public Const FILE_ATTRIBUTE_DIRECTORY As Short = &H10S
Public Const FILE_ATTRIBUTE_HIDDEN As Short = &H2S
Public Const FILE_ATTRIBUTE_NORMAL As Short = &H80S
Public Const FILE_ATTRIBUTE_READONLY As Short = &H1S
Public Const FILE_ATTRIBUTE_SYSTEM As Short = &H4S
Public Const FILE_ATTRIBUTE_TEMPORARY As Short = &H100S

Public Const FILE_FLAG_WRITE_THROUGH As Integer = &H80000000
Public Const FILE_FLAG_OVERLAPPED As Integer = &H40000000
Public Const FILE_FLAG_NO_BUFFERING As Integer = &H20000000
Public Const FILE_FLAG_RANDOM_ACCESS As Integer = &H10000000
Public Const FILE_FLAG_SEQUENTIAL_SCAN As Integer = &H8000000
Public Const FILE_FLAG_DELETE_ON_CLOSE As Integer = &H4000000
Public Const FILE_FLAG_POSIX_SEMANTICS As Integer = &H1000000

'(MapViewOfFile)
Public Const FILE_MAP_COPY As Short = &H1S
Public Const FILE_MAP_WRITE As Short = &H2S
Public Const FILE_MAP_READ As Short = &H4S
Public Const FILE_MAP_ALL_ACCESS As Integer = &HF001F

'(CreateFile)
Public Const GENERIC_READ As Integer = &H80000000
Public Const GENERIC_WRITE As Integer = &H40000000

'(CreateFile)
Public Const INVALID_HANDLE_VALUE As Integer = &HFFFFFFFF

'(CreateFile)
Public Const OPEN_EXISTING As Short = 3
Public Const OPEN_ALWAYS As Short = 4

Public Const PAGE_READONLY As Short = &H2S
Public Const PAGE_READWRITE As Short = &H4S
Public Const PAGE_WRITECOPY As Short = &H8S

Public Const SEC_COMMIT As Integer = &H8000000
Public Const SEC_IMAGE As Integer = &H1000000
Public Const SEC_NOCACHE As Integer = &H10000000
Public Const SEC_RESERVE As Integer = &H4000000

Public Const TRUNCATE_EXISTING As Short = 5

'***************
'* API関数宣言 *
'***************
Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" _
(ByVal lpFileName As String, _
ByVal dwDesiredAccess As Integer, _
ByVal dwShareMode As Integer, _
ByVal lpSecurityAttributes As Integer, _
ByVal dwCreationDisposition As Integer, _
ByVal dwFlagsAndAttributes As Integer, _
ByVal hTemplateFile As Integer) As Integer


Declare Function CreateFileMappingLong Lib "kernel32" Alias "CreateFileMappingA" _
(ByVal hFile As Integer, _
ByVal lpFileMappigAttributes As Integer, _
ByVal flProtect As Integer, _
ByVal dwMaximumSizeHigh As Integer, _
ByVal dwMaximumSizeLow As Integer, _
ByVal lpName As String) As Integer


Declare Function MapViewOfFile Lib "kernel32" _
(ByVal hFileMappingObject As Integer, _
ByVal dwDesiredAccess As Integer, _
ByVal dwFileOffsetHigh As Integer, _
ByVal dwFileOffsetLow As Integer, _
ByVal dwNumberOfBytesToMap As Integer) As Integer

End Module
Hongliang
ぬし
会議室デビュー日: 2004/12/25
投稿数: 576
投稿日時: 2005-09-29 18:31
気になったところだけ。

引用:

ですが、API関数がエラーを返してくるので、調査中です。


で、GetLastErrorは何を返すのでしょうか?

引用:

Filename = "C:\\Test.txt"


VB.NETでは\にエスケープは不要ですから一つだけで良いのですが。

引用:

hFile = CreateFile(Filename, GENERIC_READ Or GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0)


dwShareModeを0に指定していますね。これでは他のプロセスからの読み出しや書き込みができなくなりますが良いのでしょうか?
ちなみに、System.IO.FileStreamクラスのインスタンスをファイル名などを指定して作成すれば、HandleプロパティでWin32APIで使用できるファイルハンドルを取得できたりします。

引用:

Public hOpened, hFileMap, hFile, nAddress As Long


ハンドルやポインタはWin32では32bitですが、Longでは64bitになってしまいます。
ハンドルやポインタを.NETで扱う際はSystem.IntPtrで宣言・定義・利用してください。

引用:

Public Const CREATE_NEW As Short = 1
Public Const CREATE_ALWAYS As Short = 2
以下略


この辺、As ShortよりもAs Integerの方が良いと思います。関数が要求しているのはIntegerですからね。
よりよいのは列挙体にすることですが。

引用:

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


Declareステートメントでは、NT系でW系の関数を使用できるように、Declare Autoを使ってAliasを指定しない方が良いと思います。
//まあDeclare Autoの場合、Stringが含まれてる構造体を使用する際に、その構造体にStructLayout属性でCharSetフィールドにCharSet.Autoを指定しなきゃいけないんですが。
それから、前述したとおりハンドル/ポインタにはSystem.IntPtr型を対応させるようにしましょう。
FileStreamを使えばこの関数の定義自体不要になりますけど。


ところで、VB.NETではポインタを使用したメモリのリード・ライトは苦手とするところですが、なぜ敢えて実ファイルをメモリマッピングするんでしょうか? hFileにINVALID_HANDLE_VALUEを指定して実ファイルではなくページングファイルを使用するというのなら分かるのですが。
FileStreamはバッファリングを行うので、パフォーマンスにもそう差はないはずですし。
未記入
会議室デビュー日: 2005/09/29
投稿数: 3
投稿日時: 2005-09-30 09:03
引用:

Filename = "C:\\Test.txt"
VB.NETではエスケープは不要ですから一つだけで良いのですが。



↑すみません。
掲示板上で文字化け(¥⇒スラッシュ2個)しているようです。

細かい点をご指摘頂き、ありがとうございます。
FileStreamを使う事を検討し、PGを一から見直したいと思います。

パフォーマンスに差がないのなら、
そちらを使う方が.NETでは一般的でしょうし。

System.IntPtrで宣言・定義・利用は、今まで気付かなかった(勉強不足です…。)
事なので、それにかんしても勉強し、使っていきます。
1

スキルアップ/キャリアアップ(JOB@IT)