- PR -

WebサービスとWindowsアプリケーション間での共有メモリの使用について

1
投稿者投稿内容
yasuda
会議室デビュー日: 2002/02/18
投稿数: 7
投稿日時: 2004-11-08 18:18
C#から、別プロセス間で文字列のやり取りを行うために、共有メモリを利用したいと
考えているのですが、思うように動かないため、投稿します。
Windows環境で共有メモリを利用するにはCreateFileMappingAPIを利用することで実現できます。

2つのWindowsアプリケーションプロセスから、以下のコードを利用して共有メモリを読み書きすることはできたのですが、
1つのプロセスがWindowsアプリケーション、もうひとつのプロセスがWebサービスの場合、Windowsアプリケーションから共有メモリに書き込んだ内容がWebサービスから参照できないという現象が起きています。

Webサービスが実行されるユーザアカウントとWindowsアプリケーションが実行されるユーザアカウントが異なるため、アクセス権違反が起きているのではと推測していますが、ASP.NETを実行しているアカウントの権限にAdministratorsを追加しても現象は回避されませんでした。

WebサービスとWindowsアプリケーション間で共有メモリを実現する方法をご存知の方がいらっしゃれば教えていただければと思います。



-----------


using System;
using System.Runtime.InteropServices;

namespace SharedMemory
{
/// <summary>
/// SharedMemory の概要の説明です。
/// </summary>
public class SharedMemory
{
public static readonly IntPtr InvalidHandleValue = new IntPtr(-1);
public const UInt32 FILE_MAP_WRITE = 0x02;
public const UInt32 FILE_MAP_READ = 0x04;
public const UInt32 PAGE_READWRITE = 0x04;

//CREATE FILE MAPPING
[DllImport("Kernel32")]
public static extern IntPtr CreateFileMapping(IntPtr hFile,
IntPtr pAttributes, UInt32 flProtect,UInt32 dwMaximumSizeHigh,
UInt32 dwMaximumSizeLow, String pName);
//MAP VIEW FILE
[DllImport("Kernel32.dll",CharSet=CharSet.Auto)]
public static extern IntPtr
MapViewOfFile(IntPtr hFileMappingObject,
UInt32 dwDesiredAccess,UInt32 dwFileOffsetHigh,
UInt32 dwFileOffsetLow,UInt32 dwNumberOfBytesToMap);

//UNMAP VIEW FILE
[DllImport("Kernel32.dll",CharSet=CharSet.Auto)]
public static extern Boolean UnmapViewOfFile(IntPtr lpBaseAddress);

string sharedName;
public SharedMemory(string name)
{
this.sharedName = name;
}
public string ReadMessage()
{
IntPtr hMapping = CreateFileMapping(InvalidHandleValue,IntPtr.Zero, PAGE_READWRITE,0,1024,this.sharedName);
IntPtr sharedAddress = MapViewOfFile(hMapping, FILE_MAP_READ,0,0,0);

System.Text.Encoding ascii = System.Text.Encoding.ASCII;
byte[] messageBuffer = new byte[1024];

for(int i =0; i < messageBuffer.Length; i++)
{
messageBuffer[i] = Marshal.ReadByte(sharedAddress,i);
}
string message = ascii.GetString(messageBuffer);
return message;
}
public void WriteMessage(string message)
{
IntPtr hMapping = CreateFileMapping(InvalidHandleValue,IntPtr.Zero, PAGE_READWRITE,0,1024,this.sharedName);
IntPtr sharedAddress = MapViewOfFile(hMapping, FILE_MAP_WRITE,0,0,0);

System.Text.Encoding ascii = System.Text.Encoding.ASCII;
byte[] messageBuffer = ascii.GetBytes(message);

for(int i =0; i < messageBuffer.Length; i++)
{
Marshal.WriteByte(sharedAddress, i, messageBuffer[i]);
}
}
}
}
たつごろー
ぬし
会議室デビュー日: 2004/10/25
投稿数: 496
投稿日時: 2004-11-08 18:44
回答ではないです。
自分も興味あるもので。

Webメモリーマップトファイルでデータの共有ですかー。
できると楽しいです。いろいろできそう。

別のWebページ同士では通信できてますか?


_________________
たつごろー
MCSD.NET、MCDBA、MCSA、MCAD
Oracle Master Platinum 9i、Oracle Master Linux+

[ メッセージ編集済み 編集者: たつごろー 編集日時 2004-11-08 18:45 ]
nanbu
大ベテラン
会議室デビュー日: 2004/08/19
投稿数: 178
投稿日時: 2004-11-09 01:00
引用:

yasudaさんの書き込み (2004-11-08 18:18) より:

1つのプロセスがWindowsアプリケーション、もうひとつのプロセスがWebサービスの場合、Windowsアプリケーションから共有メモリに書き込んだ内容がWebサービスから参照できないという現象が起きています。


南部です。

「Webサービスから参照できない」という判断に至った現象を教えてください。
 名前付きオブジェクトが別のハンドルを返すとか。。(そんなわけないか)

引用:

Webサービスが実行されるユーザアカウントとWindowsアプリケーションが実行されるユーザアカウントが異なるため、アクセス権違反が起きているのではと推測していますが、ASP.NETを実行しているアカウントの権限にAdministratorsを追加しても現象は回避されませんでした。


Windowsの権限は詳しくありませんが、
共有メモリってアカウントの違いって関係あります?

ん? Webサービスって[WebMethod]?
\0って大丈夫なんだっけ?
甕星
ぬし
会議室デビュー日: 2003/03/07
投稿数: 1185
お住まい・勤務地: 湖の見える丘の上
投稿日時: 2004-11-09 07:28
プロセス間通信はセキュリティの関係で、ユーザー空間が異なるとLPSECURITY_ATTRIBUTESを指定しないと繋がりません。FileMappingだけでなく、MailSlotやPipeでも同様。
nanbu
大ベテラン
会議室デビュー日: 2004/08/19
投稿数: 178
投稿日時: 2004-11-09 11:36
引用:

甕星さんの書き込み (2004-11-09 07:28) より:
プロセス間通信はセキュリティの関係で、ユーザー空間が異なるとLPSECURITY_ATTRIBUTESを指定しないと繋がりません。FileMappingだけでなく、MailSlotやPipeでも同様。


南部です。

指定しないと既定のセキュリティ記述子になるってヘルプにあるけど、
これが、わかんないんですよね、、、
#「新規テキスト文書.txt」を作成したときのプロパティ→セキュリティで見えるもの?

「ユーザー空間」っていうのは、どういったものですか?
#グループ?

本題ですが、
こちらの環境では、うまくいきました。
アカウントは別ですが、グループはどちらもAdministratorsにいます。

ただ、やはり、\0つきの文字列はそのままリターンするとエラーになりました。
なので読み取り確認は、messageBufferを使用せずに、

string message = Marshal.PtrToStringAnsi(sharedAddress);

としました。


環境:
Windows Server 2003
.NET Framework 1.1 SP1

以上です。
nanbu
大ベテラン
会議室デビュー日: 2004/08/19
投稿数: 178
投稿日時: 2004-11-09 13:27
引用:

プロセス間通信はセキュリティの関係で、ユーザー空間が異なるとLPSECURITY_ATTRIBUTESを指定しないと繋がりません。



んーやっぱり、よくわかりません。
「取得したハンドルを子プロセスへ継承することを認める許可するかどうかを決定する」
ハンドルを子プロセスに引数とかで渡すときに、そっちでも有効にするかどうか、、、
くらいに認識していました。

なので、yasudaさんのコードだとハンドルをメソッド内で取得して使用しているので、
LPSECURITY_ATTRIBUTESの指定は必要ないと思いますが。
間違っていましたらご指摘下さい。
甕星
ぬし
会議室デビュー日: 2003/03/07
投稿数: 1185
お住まい・勤務地: 湖の見える丘の上
投稿日時: 2004-11-09 19:16
引用:

んーやっぱり、よくわかりません。
「取得したハンドルを子プロセスへ継承することを認める許可するかどうかを決定する」
ハンドルを子プロセスに引数とかで渡すときに、そっちでも有効にするかどうか、、、
くらいに認識していました。



私も理解しているわけじゃないんで・・・ACLって難解ですよね。
以前サービスとデスクトップアプリケーション間でオブジェクトの共有をかけたときに、SECURITY_DESCRIPTERを設定して旨く出来た事があるので、ASP.NETでも同様じゃないかと思い込んでいるだけです。とりあえず下のは、あらゆるアクセスを許可すると言う、セキュリティ的に不味いコードのサンプル。

SECURITY_DESCRIPTOR secDesc;
SECURITY_ATTRIBUTES sSa;
::InitializeSecurityDescriptor(&secDesc, SECURITY_DESCRIPTOR_REVISION);
::SetSecurityDescriptorDacl(&secDesc, TRUE, NULL, FALSE);
sSa.nLength = sizeof(SECURITY_ATTRIBUTES);
sSa.bInheritHandle = TRUE;
sSa.lpSecurityDescriptor = &secDesc;
CreateFileMapping(hFile, &sSa, ...);

後は、TerminalServiceを有効にしいるのに、\Globalを付け忘れているとか。
1

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