2015-10-16 36 views
16

I特定の文字列でグローバルアドレス帳を検索するために、次のコードがあります。グローバルアドレス一覧を検索する場合、部分的な検索を行う方法があるだけでなく、「のstartsWith」

「CONF」

「CONF-123」は、それが表示されますが、私は名前を持っている場合は、「JOE-CONF:それはやっているように見えること

var esb = new ExchangeServiceBinding(); 
esb.Url = @"https://myurl.com/EWS/Exchange.asmx"; 

esb.Credentials = new NetworkCredential(_user,_pwd, _domain); 

var rnType = new ResolveNamesType {ReturnFullContactData = true, UnresolvedEntry = "CONF"}; 

ResolveNamesResponseType response = esb.ResolveNames(rnType); 
ArrayOfResponseMessagesType responses = resolveNamesResponse.ResponseMessages; 
var responseMessage = responses.Items[0] as ResolveNamesResponseMessageType; 

ResolutionType[] resolutions = responseMessage.ResolutionSet.Resolution; 

問題がある、私が呼ばれる名前を持っているので、検索「から始まります」 "それはしません。以下のようなものだった

がどのように私は私が望んでいたこのライン

var rnType = new ResolveNamesType {ReturnFullContactData = true, UnresolvedEntry = "CONF-"}; 

上の部分文字列検索を行うことができます。

var rnType = new ResolveNamesType {ReturnFullContactData = true, UnresolvedEntry = "%CONF-%"}; 

はそれが動作するようには思えません。

+4

にアクセスしています。私は、 ' - 'が 'CONF'の後ろにあるとは思っていません。もし ' - 'なしで 'CONF'を使うとどうなりますか? – Ilnetd

+0

はタイプミスでした。 。私は質問を更新しました – leora

+0

あなたはまだ解決策をお探しですか? – rsteward

答えて

0

インデックス付きテキストフィールドのあいまい検索は、接頭辞(または接尾辞...)でのみ行うことができます。そのため、ExchangeはおそらくクエリをLIKE 'CONF%'として実装しているのです。

私はドキュメントを見てきましたが、それを回避する方法はありません - 完全なテーブルスキャン(%CONF%の場合)は意味をなさないと思われます。

5

EDIT: 1月4,2016 - ADを検索するためのサンプルコードが追加されました。 ResolveNames経由GALを検索

を動作しません何

は常にあいまいな名前解決(ARN)のプレフィックス文字列の一致を使用しています。 EWSのマニュアルではこれを明示的には示していませんが、Exchange ActiveSyncのマニュアルでは説明しています。 EWSとExchange ActiveSyncは単なるプロトコルです。どちらもARNに依存しているため、ActiveSyncプロトコルを使用しているかEWSを使用しているかに関わらず、プレフィックスの一致に悩まされています。

はここでプレフィックス文字列一致

で を使用されているExchange ActiveSyncのドキュメント(https://msdn.microsoft.com/en-us/library/ee159743%28v=exchg.80%29.aspx

検索コマンドに提供されたテキストクエリ文字列から関連の引用です。

行うための最善のことは、あなたのユースケースに依存して動作しますが、ここではいくつかのアイデアですう何

検索のActive Directoryクライアントプログラムで(あなたが示したコードを含むプログラムは、あなたの質問で)

GALを検索するためのサービスを設定します。クライアントプログラムはExchangeとサービスの両方に接続します。または、サービスがEWSをプロキシできるため、クライアントプログラムはサービスにのみ接続する必要があります。

どのようにGALデータを取得しますか?1つの方法は、EALS ResolveNamesを繰り返し使用して、一度に100エントリずつGALデータを取得し、このデータをサービスにキャッシュすることです。最初に、すべての "a"とすべての "b"などを取得します。もちろん、100以上の "a"がGALに存在する可能性があるので、すべての "a" - 各検索から返された最後のエントリに基づいて、次の検索文字列を作成します。これは遅く、痛いことがあります。このデータをデータベースにキャッシュし、定期的に更新することをお勧めします。

また、MAPI経由でGALにアクセスすることもできます。 MAPIを直接使用することができます(https://msdn.microsoft.com/en-us/library/cc765775%28v=office.12%29.aspx)か、償還(http://www.dimastr.com/redemption/home.htm)のようなヘルパーライブラリを使用します。 MAPIを直接使用するかRedemptionを使用するかにかかわらず、コードが実行されているコンピュータにOutlook(またはExchange)をインストールする必要があります。この制限があるため、クライアントプログラムでMAPIを使用せず、一部のサーバーで実行されているサービスにMAPIを適用し、クライアントプログラムをそのサービスに接続させるのが最善の方法です。

ADコードサンプル

のActive Directoryを検索するサンプルコードを提供するもう一つの答え。私は検索を通してこの質問を見つけるかもしれない人々が一般的な使用に適しているかもしれないコードサンプルを追加しています。構築されたフィルタ文字列が有効であるように、

  • 検索文字列は、(括弧のような)特殊文字が含まれている場合は、それらがエスケープされています。他のサンプルと比較して、以下のコードは、次のような改善があります。

  • samaccountnameだけでは十分ではありません。 "David Smith"にアカウント名 "dsmith"がある場合、samaccountnameで "David"を検索しても彼は見つかりません。私のサンプルは、より多くのフィールドで検索する方法を示し、検索したいフィールドのいくつかを示しています。

  • "GC:"のようなルートで開始すると、Domain.GetComputerDomain()からLDAPエントリを作成しようとするよりも堅牢です。

  • すべてIDisposable sが(通常using構築物にそれらを使用することにより)廃棄されなければなりません。

    // Search Active Directory users. 
    public static IEnumerable<DirectoryEntry> SearchADUsers(string search) { 
        // Escape special characters in the search string. 
        string escapedSearch = search.Replace("*", "\\2a").Replace("(", "\\28") 
         .Replace(")", "\\29").Replace("/", "\\2f").Replace("\\", "\\5c"); 
    
        // Find entries where search string appears in ANY of the following fields 
        // (you can add or remove fields to suit your needs). 
        // The '|' characters near the start of the expression means "any". 
        string searchPropertiesExpression = string.Format(
         "(|(sn=*{0}*)(givenName=*{0}*)(cn=*{0}*)(dn=*{0}*)(samaccountname=*{0}*))", 
         escapedSearch); 
    
        // Only want users 
        string filter = "(&(objectCategory=Person)(" + searchPropertiesExpression + "))"; 
    
        using (DirectoryEntry gc = new DirectoryEntry("GC:")) { 
         foreach (DirectoryEntry root in gc.Children) { 
          try { 
           using (DirectorySearcher s = new DirectorySearcher(root, filter)) { 
            s.ReferralChasing = ReferralChasingOption.All; 
            SearchResultCollection results = s.FindAll(); 
            foreach (SearchResult result in results) { 
             using (DirectoryEntry de = result.GetDirectoryEntry()) { 
              yield return de; 
             } 
            } 
           } 
          } finally { 
           root.Dispose(); 
          } 
         } 
        } 
    } 
    
+0

AD Searchのより良い実装を共有していただき、ありがとうございます。しかし、良い/礼儀正しく&その代わりに "上記の答えを向上させる"、 "それに追加する"のような言葉を使用してください。私はあなたの言葉を使用しないように/音 "上の答えは多くの欠点を持って"より良い "。誰もが助け、お互いから学ぶことです。どのコードにも改善の余地があることは間違いありません。問題の要点は、leoraが直面しているのは一致するものを含む検索である。私はそれに答えることを試みました。最も効率的なコードを書くことに焦点を当てるのではなく、私はleoraが何の問題も書かないと信じています。 –

+0

あなたは正しいです、Abhijit。私に適切なマナーを教えてくれてありがとう。私は言葉を編集した。 – George

4

ワイルドカード検索は、EWSでは不可能ですが、それはADの検索で可能です。 ADクエリはワイルドカードをサポートします。つまり、* CONF *はADで検索できます。これは "CONF"を含むすべての結果を返します。結果に基づいて、対応するExchangeオブジェクトのEWSを照会します。対応するEWSエントリを見つけるためのパラメータを見つける必要があります。私は電子メールアドレス(ユーザー名)が対応する交換オブジェクトを見つけるのに十分であるはずだと思います。

AD検索コードスニペット...

private SearchResultCollection SearchByName(string username, string password, string searchKeyword) 
{ 
    DirectorySearcher ds = new DirectorySearcher(new DirectoryEntry("LDAP://" + Domain.GetComputerDomain().ToString().ToLower(), username, password)); 
    ds.Filter = "(&((&(objectCategory=Person)(objectClass=User)))(samaccountname=*" + searchKeyword + "*))"; 
    ds.SearchScope = SearchScope.Subtree; 
    ds.ServerTimeLimit = TimeSpan.FromSeconds(90); 
    return ds.FindAll(); 
} 

ADクエリ例here

0

私はまた、php-ewsを使用してPHPからGALを検索しようとしています。 Webページでは、ユーザーが検索する名前を入力し始めます.2文字が入力されると、入力された2文字を渡すread_contacts.phpの呼び出しが行われます。 read_contacts.phpは、EWS ResolveNamesリクエストを使用して、限定された連絡先リストを取得します。コードはいくつかの条件をフィルタリングし、displayNameが入力された文字で始まるかどうかをチェックします。すなわち、これは動作しているようですほとんどの時間

<?php 
$staffName = $_GET['q'];  
require_once './php-ews/EWSType.php'; 
require_once './php-ews/ExchangeWebServices.php'; 
require_once 'php-ews/EWSType/RestrictionType.php'; 
require_once 'php-ews/EWSType/ContainsExpressionType.php'; 
require_once 'php-ews/EWSType/PathToUnindexedFieldType.php'; 
require_once 'php-ews/EWSType/ConstantValueType.php'; 
require_once 'php-ews/EWSType/ContainmentModeType.php'; 
require_once 'php-ews/EWSType/ResolveNamesType.php'; 
require_once 'php-ews/EWSType/ResolveNamesSearchScopeType.php'; 
require_once 'php-ews/NTLMSoapClient.php'; 
require_once 'php-ews/NTLMSoapClient/Exchange.php'; 

$host = '[exchange server]'; 
$user = '[exchange user]'; 
$password = '[exchange password]'; 

$ews = new ExchangeWebServices($host, $user, $password); 

$request = new EWSType_ResolveNamesType(); 

$request->ReturnFullContactData = true; 
$request->UnresolvedEntry = $staffName; 


$displayName = ''; 
$i = 0; 
$staff_members = false; 
$response = $ews->ResolveNames($request); 
if ($response->ResponseMessages->ResolveNamesResponseMessage->ResponseClass == 'Error' && $response->ResponseMessages->ResolveNamesResponseMessage->MessageText == 'No results were found.') { 
} 
else { 
    $numNamesFound = $response->ResponseMessages->ResolveNamesResponseMessage->ResolutionSet->TotalItemsInView; 
    $i2=0; 
    for ($i=0;$i<$numNamesFound;$i++) { 
     if ($numNamesFound == 1) { 
      $displayName = $response->ResponseMessages->ResolveNamesResponseMessage->ResolutionSet->Resolution->Contact->DisplayName; 
     } 
     else { 
      $displayName = $response->ResponseMessages->ResolveNamesResponseMessage->ResolutionSet->Resolution[$i]->Contact->DisplayName; 
     } 
     echo "DisplayName: " . $displayName . "\n";  
     if (stripos($displayName, 'External') == true) { 
     } 
     else { 
      $searchLen = strlen($staffName); 
      if (strcasecmp(substr($displayName, 0, $searchLen), $staffName) == 0) { 
       if ($numNamesFound == 1) { 
        $emailAddress = $response->ResponseMessages->ResolveNamesResponseMessage->ResolutionSet->Resolution->Mailbox->EmailAddress; 
       } 
       else { 
        $emailAddress = $response->ResponseMessages->ResolveNamesResponseMessage->ResolutionSet->Resolution[$i]->Mailbox->EmailAddress; 
       } 
       $staff_members[$i2] = array('name' => $displayName,'email' => $emailAddress); 
       $i2++; 
      } 
     } 
    } 
    $staffJson = json_encode($staff_members); 
echo $staffJson; 
} 

::これはその後、フィルタリングされたリストを返す「MI」、「ジョーは、」私は「シリコン」または送信する場合を除き、マイク、マイケル、またはジョー、ジョンを返します。 'si'、Simonの場合、ResolveNames呼び出しはGALから最初の100エントリを返します。

当分の間、私は3に入力される文字の最小数を増やしました。つまり、 'sim'とこれが動作します。問題は、2文字のファーストネームしか持たないスタッフがいるときです。

私はちょうど助けがあるかどうかを知るためにコードを共有し、誰かが私の「si」が正しく動作しない理由を知っているかどうかを知りたいと思った。

私は、あなたが「CONF-」を探していますが、「JOE-CONFが」復帰に表示されないことを示すExchange 2010の

関連する問題