4

サービスとコンソール アプリケーションを含む Vista でアプリケーションを作成しています。どちらも同じユーザー アカウントで実行されています。

サービスでは、イベントを作成し、そのイベントを待ちます。コンソール アプリケーションでは、同じイベントを開き (問題はここから始まります)、SetEvent関数を呼び出します。コンソール アプリケーションでイベントを開くことができません (エラー 5 の取得、アクセスが拒否されました)。ネットで検索したところ、整合性レベルに関する情報が表示されました (問題が整合性レベルに関連しているかどうかはわかりません)。アプリケーションはさまざまな整合性レベルを取得しました。

ここにIPCが発生するコードの一部があります

サービス

DWORD
WINAPI IpcThread(LPVOID lpParam)
{
HANDLE ghRequestEvent = NULL ;

ghRequestEvent = CreateEvent(NULL, FALSE,
FALSE, "Global\\Event1") ; //creating the event

if(NULL == ghRequestEvent)
{
//error
}
while(1)
{
WaitForSingleObject(ghRequestEvent, INFINITE) //waiting for the event
//here some action related to event
}
}

コンソール アプリケーション

ここでは、アプリケーションで、イベントを開いてイベントを設定します

unsigned int
event_notification()
{
HANDLE ghRequestEvent = NULL ;



 ghRequestEvent = OpenEvent(SYNCHRONIZE|EVENT_MODIFY_STATE, FALSE, "Global\\Event1") ;

if(NULL == ghRequestEvent)
{
//error
}
SetEvent(ghRequestEvent) ;
} 

管理者権限で両方のアプリケーション (サービスとコンソール アプリケーション) を実行しています (管理者としてログインし、右クリックして [管理者として実行] オプションを使用してコンソール アプリケーションを実行しています)。

コンソール アプリケーション (イベントを開いている場所) で発生するエラーは、エラー番号 5(アクセスが拒否されました。) です。

Vistaでサービスとアプリケーション間のIPCを行う方法を教えていただけると大変助かります。

前もって感謝します

ナバニース

4

5 に答える 5

3

サービスとアプリケーションは、整合性レベルが異なる同じユーザーとして実行されていますか、それとも異なるユーザーとして実行されていますか?

前者の場合は、整合性レベルについて説明している MSDN の記事が役立つ可能性があります。ファイルの整合性レベルを下げるためのサンプル コードがいくつかあります。ただし、これがイベントに関連するかどうかはわかりません。

#include <sddl.h>
#include <AccCtrl.h>
#include <Aclapi.h>

void SetLowLabelToFile()
{
  // The LABEL_SECURITY_INFORMATION SDDL SACL to be set for low integrity 
  #define LOW_INTEGRITY_SDDL_SACL_W L"S:(ML;;NW;;;LW)"
  DWORD dwErr = ERROR_SUCCESS;
  PSECURITY_DESCRIPTOR pSD = NULL;    

  PACL pSacl = NULL; // not allocated
  BOOL fSaclPresent = FALSE;
  BOOL fSaclDefaulted = FALSE;
  LPCWSTR pwszFileName = L"Sample.txt";

  if (ConvertStringSecurityDescriptorToSecurityDescriptorW(
         LOW_INTEGRITY_SDDL_SACL_W, SDDL_REVISION_1, &pSD;, NULL)) 
  {
    if (GetSecurityDescriptorSacl(pSD, &fSaclPresent;, &pSacl;, 
         &fSaclDefaulted;))
    {
      // Note that psidOwner, psidGroup, and pDacl are 
      // all NULL and set the new LABEL_SECURITY_INFORMATION
      dwErr = SetNamedSecurityInfoW((LPWSTR) pwszFileName, 
                 SE_FILE_OBJECT, LABEL_SECURITY_INFORMATION, 
                 NULL, NULL, NULL, pSacl);
    }
    LocalFree(pSD);
  }
}

後者の場合は、NULL ACLを作成し、それをオブジェクトに関連付けることを提案するこのリンクを見ることができます (この例では、名前付きパイプですが、イベントのアプローチは似ていると確信しています:

BYTE sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
SECURITY_ATTRIBUTES sa;

sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = &sd;

InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, TRUE, (PACL) 0, FALSE);

CreateNamedPipe(..., &sa);
于 2008-09-22T09:41:47.037 に答える
1

「グローバル」名前空間でオブジェクトを作成しているが、ローカル名前空間でオブジェクトを開こうとしていることに気付きました。公募の名前に「グローバル」を追加すると効果がありますか?

また、//エラー領域に、作成されていないことを通知するものはありますか?

于 2008-09-22T10:16:02.647 に答える
0

まず、何が必要かを概念的に理解することが重要です。それが理解できたら、そこからそれを取ることができます。

サーバーでは、次のようになります。

{
   HANDLE hEvent;
   hEvent = CreateEvent(null, true, false, TEXT("MyEvent"));
   while (1)
   {
       WaitForSingleObject (hEvent);
       ResetEvent (hEvent);
       /* Do something -- start */
       /* Processing 1 */
       /* Processing 2 */
       /* Do something -- end */
   }
}

クライアントで:

{
   HANDLE hEvent;
   hEvent = OpenEvent(0, false, TEXT("MyEvent"));
   SetEvent (hEvent);
}

注意すべきいくつかの点:

  • ResetEvent は、WaitForSingleObject または WaitForMultipleObjects の直後に、できるだけ早く実行する必要があります。複数のクライアントがサーバーを使用していて、最初のクライアントの処理に時間がかかる場合、2 番目のクライアントがイベントを設定し、サーバーが最初の要求を処理している間はイベントがキャッチされない可能性があります。
  • サーバーが処理を終了したことをクライアントに通知するメカニズムを実装する必要があります。
  • win32サービスのマンボジャンボを実行する前に、サーバーを単純なアプリケーションとして実行してください。これにより、セキュリティ関連の問題が解消されます。
于 2008-09-22T10:05:25.357 に答える
0

「1800 情報」は正しい - これは UIPI の問題です。とにかく、新しいコードでイベントを使用しないでください。イベントでブロックされているターゲットが、発生時にユーザーモードの APC コードにある場合、イベント信号が失われる可能性があります。Win32 でサービス/アプリケーションを記述する標準的な方法は、RPC 呼び出しを使用して UIPI 境界を越えることです。

于 2008-09-24T05:08:47.910 に答える
0

@ナバニース:

優れたフィードバック。あなたのエラーは Access Denied であるため、目的のアクセスを EVENT_ALL_ACCESS から変更しますが、これは実際には必要ありません。

(SYNCHRONIZE | EVENT_MODIFY_STATE)

SYNCHRONIZE を使用すると、イベントを待機でき、EVENT_MODIFY_STATE を使用すると、SetEvent、ResetEvent、および PulseEvent を呼び出すことができます。

より多くのアクセスが必要になる可能性がありますが、それは非常にまれです。

于 2008-09-23T14:33:17.140 に答える