2011-02-20 30 views
1

私は現在、OutputDebugStringメッセージ(Windows Sysinternals DbgViewまたはDBMon.NETに似ています)をキャプチャするための簡単なアプリケーションを開発中です。ローカルセッション(Local \ DBWIN_BUFFER_READY、ローカル\ DBWIN_DATA_READY、ローカル\ DBWIN_BUFFER)からOutputDebugStringメッセージにアクセスするときは、すべてが期待通りに機能しています。問題Win32 API経由でグローバル(セッション0)OutputDebugStringメッセージをキャプチャしますか?

しかし、セッション0(つまり、グローバル\ DBWIN_BUFFER_READYなど)からの出力にアクセスしようとすると、出力は受信されません。 DbgViewの動作に基づいて、私はあるレベルの管理者権限でアプリケーションを実行する必要があるという前提で動作しています。私はSecurityDescriptorを正しく設定していないと思っています。あるいは、Global OutputDebugStringメッセージにアクセスするために何かが完全に欠けています。

私は以下のコードのスニペットを強調しているが、完全なソースはCodePlex

でいただければ幸い問題上の任意のヘルプや洞察力を見つけることができます。前もって感謝します!

セキュリティ記述子の構成

私はいくつかの異なる構成を試してみましたが、次のようにコミットされたコードは、現在見えます。

[DllImport("advapi32.dll", SetLastError = true)] 
private static extern Boolean InitializeSecurityDescriptor(ref SecurityDescriptor sd, UInt32 dwRevision); 

[DllImport("advapi32.dll", SetLastError = true)] 
private static extern Boolean SetSecurityDescriptorDacl(ref SecurityDescriptor sd, Boolean daclPresent, IntPtr dacl, Boolean daclDefaulted); 

public SecurityDescriptor InitializeSecurityDescriptor() 
{ 
    const Int32 securityDescriptorRevision = 1; 
    var securityDescriptor = new SecurityDescriptor(); 

    // Initialize the security descriptor. 
    if (!InitializeSecurityDescriptor(ref securityDescriptor, securityDescriptorRevision)) 
    throw new Win32Exception(Marshal.GetLastWin32Error()); 

    // Set information in a discretionary access control list 
    if (!SetSecurityDescriptorDacl(ref securityDescriptor, true, IntPtr.Zero, false)) 
    throw new Win32Exception(Marshal.GetLastWin32Error()); 

    return securityDescriptor; 
} 

このコードは、最終的にあなたが期待するように私DbWinMessageSourceクラスの設定で呼び出される...

_windowsApi.Advanced.InitializeSecurityDescriptor(); 

SecurityAttributesとイベント現在のCodePlexにコミットしたコードを使用している

Local \ **という接頭辞ですが、唯一の違いはLocal \ **がGlobal \ **に置き換えられていることです。しかし、これは期待どおりに出力をキャプチャしていないようです。ここでも、関連するコードスニペット...

public const Int32 ErrorAlreadyExists = 183; 

    [DllImport("kernel32.dll", SetLastError = true)] 
    private static extern IntPtr CreateEvent(ref SecurityAttributes sa, Boolean bManualReset, Boolean bInitialState, String lpName); 

    public Handle CreateLocalEvent(ref SecurityAttributes securityAttributes, String objectName) 
    { 
     Verify.NotWhitespace(objectName); 
     return CreateEvent(ref securityAttributes, "Local", objectName); 
    } 

    public Handle CreateGlobalEvent(ref SecurityAttributes securityAttributes, String objectName) 
    { 
     Verify.NotWhitespace(objectName); 
     return CreateEvent(ref securityAttributes, "Global", objectName); 
    } 

    private static Handle CreateEvent(ref SecurityAttributes securityAttributes, String objectNamePrefix, String objectName) 
    { 
     IntPtr handle = CreateEvent(ref securityAttributes, false, false, String.Format(@"{0}\{1}", objectNamePrefix, objectName)); 

     if(Marshal.GetLastWin32Error() == ErrorAlreadyExists) 
     throw new Win32Exception(ErrorAlreadyExists); 

     if (handle == IntPtr.Zero) 
     throw new Win32Exception(Marshal.GetLastWin32Error()); 

     return new Handle(handle, CloseHandle); 
    } 

ここでも、最終的にDbWinMessageSourceのセットアップに呼び出され、次のように:

_dbwinBufferReadyEvent = _windowsApi.Basic.CreateGlobalEvent(ref securityAttributes, "DBWIN_BUFFER_READY"); 
    _dbwinDataReadyEvent = _windowsApi.Basic.CreateGlobalEvent(ref securityAttributes, "DBWIN_DATA_READY"); 
    _dbwinBufferFile = _windowsApi.Basic.CreateGlobalFileMapping(ref securityAttributes, "DBWIN_BUFFER"); 

私はのOutputDebugStringアペンダでlog4netのを使用して簡単なWebアプリケーションをテストしてい設定されます。 Visual Studioでアプリケーションを実行しているときに、すべてのローカル出力を期待どおりにキャプチャします。アプリケーションをIISに移動して、グローバルセッションで何かを取得するようにコードを構成すると、私は何も得られない。 DbgViewがIISからの出力をキャプチャしていることを確認しました(間違いなく間違いありません)。

うまくいけば十分な文脈ですが、より多くの情報や詳細が必要な場合は、お知らせ下さい。

注:Windows 7 Professionalで開発することで違いがあります。

EDIT Tyranid(ルーク)で指摘したように

は、必要とされなければならないことすべては、管理者priviledges、およびSE_CREATE_GLOBAL_NAMEです。私はいくつかのテストを実行し、上のコード設定は実際にはをキャプチャしています。グローバルメッセージ(たとえば、IISRESET中)。上記のコードは、アプリケーションがIISの内部(VSセッション中にLocal \ **を経由してルーティングされる)で実行されているとき、Log4Net OutputDebugStringアペンダからのデータをキャプチャしていません。すべてのWin32 API呼び出しが正常に返されているか、Marshal.GetLastWin32Error().呼び出し時にエラーが返されていません。現在のWindowsトークンにSE_CREATE_GLOBAL_NAMEがあることを確認するコードを追加しました。コードの荒さは次のようになります。

using (var identity = WindowsIdentity.GetCurrent()) 
    { 
    if (identity == null) 
     return; 

    TokenPrivilege tp; 

    tp.Count = 1; 
    tp.Luid = 0; 
    tp.Attr = SE_PRIVILEGE_ENABLED; 
    if (!LookupPrivilegeValue(null, SE_CREATE_GLOBAL_NAME, ref tp.Luid)) 
     throw new Win32Exception(Marshal.GetLastWin32Error()); 

    if (!AdjustTokenPrivileges(identity.Token, false, ref tp, Marshal.SizeOf(tp), IntPtr.Zero, IntPtr.Zero)) 
     throw new Win32Exception(Marshal.GetLastWin32Error()); 
    } 

これ以上の洞察があれば幸いです。

+0

正確には動作しません。オブジェクトは正常に作成されていますか?いくつかの特定の機能は失敗しますか? – Luke

+0

これはネイティブコードを使ってテストされており、うまく動作します。唯一の注意点は、1)管理者として実行する必要があり、2)SeCreateGlobalPrivilegeを有効にする必要があることです。 – Luke

+0

@ルーク、タイニッド氏は以下のように指摘しました。欠けている部分はSeCreateGlobalPrivilegeです。私は正しい方向に私を指し示すが、それをテストするチャンスを持っていないと思う次のリンクを発見した:http://msdn.microsoft.com/en-us/library/aa446619(v=VS.85) ).aspx –

答えて

2

セクション/ファイルマッピングオブジェクトの作成を管理していますか?はい、グローバル名前空間にファイルマッピングを作成するには、トークンにSeCreateGlobalPrivilegeが必要なので、管理者にする必要があります。これで、CreateFileMappingを呼び出す前に有効にする必要があるかもしれませんが、私はそれを演奏してから、私のコードを手にすることはしばらくありました。

あなたは本当にNULLのDACLを指定するべきではありません、それは多くのレベルで間違っている、私はdbgviewは知っているが、それだけで怠け者であり、

+0

興味深い...私はSeCreateGlobalPrivilegeを設定し、それが私がなりたい場所になるかどうかを調べます。また、NULL DACLを再訪する予定です。私は基本的な機能を適所に持っていきたいと思っています。 –

+0

+1私は正しい方向に向いていますが、それでもまだありません...私は(DbgViewはすべてを見ている)期待どおりにIISで実行時にOutputDebugStringアペンダー情報をキャプチャしていません。上記のコードをスニペットで更新して、SE_CREATE_GLOBAL_NAMEが確実に設定されていることを確認しましたが、それでも必要なものがあります。エラーはスローされず、すべてのWin32 API呼び出しが行われる限り、エラーは発生しません。すべてが成功したことを証明します。 –

+0

これは私の元来のグローバルなセッションキャプチャの問題の一部を捕捉するので、答えとして受け入れます。未解決の問題はカーネルフック(http://www.codeproject.com/KB/system/hooksys.aspx)を必要とし、技術的には私が以前に投稿したものとは別の問題です。最終的に私は別の道を下って行きました。 –

関連する問題