MonthSeptember 2005

Apu hod med be

Rendszeresen hallani olyan esetekről, amikor nem figyelt oda az Exchange adminisztrátor és az adatbázis mérete átlépte a bűvös 16 GB értéket. (Pedig a problémát meg lehet előzni: írni kell egy wmi szkriptet, beidőzíteni napi egyszeri futásra. Ez azt csinálja, hogy ha az adatbázis mérete nagyobb, mint 15 GB, akkor mondjuk pirosra váltja a háttérképet. Ha nagyobb lesz, mint 16 GB, akkor meg postázza az admin munkakönyvét.)(1)

No mindegy, megtörtént a baj, mit lehet ilyenkor csinálni? Nyilván offline tömörítés, törlés, offline tömörítés gyógyítja a túlsúlyt… de nem biztos, hogy erre pont az az időpont a megfelelő, amikor az adatbázis elment kávézni. Mit nem adnánk ilyenkor egy kis haladékért?

A jó hír az, hogy létezik ilyen haladék. Természetesen registry turkálással aktivizálható. (A magam részéről utálom ezt a technikát. Ebből származnak azok a mítoszok, hogy registry buherával mindent meg lehet csinálni. Hogyan lesz a Windows szerveremből kenyérpirító? Írd be ezt meg ezt a registrybe…)

A matatás előfeltétele, hogy vagy Exchange 2003 legyen a szoftver vagy 2000 alatt legyen felugratva a post service pack 3 rollup. A beállítás után újra kell indítani a gépet és máris kaptunk plusz egy gigát. Ja, és mit kell beírni? Itt van a KB cikk.

Oké. Most nézzük, mi van akkor, ha standard Exchange szerverünk van, nem akarunk enterspájzot, de az adatbázisunk mérete rakétaként szárnyal? Probléma szál se, tiszta szerencse, hogy műveltek vagyunk. Például tudjuk, hogy az Exchange 2003 SP2-ben a méretkorlát felugrik 75GB-re. Ez a csomag ugyan még nincs kint, de a béta verzió már igen és a korlátfeloldást ez is tudja. Azaz ha nagyon szorongat az ügyvezető és átvállalja a béta kockázatát (MS természetesen nem ajánlja), akkor meg lehet próbálni ezt az utat.

Csakhogy. Feltettük, az adatbázis átvágtatott a 16 GB célvonalon és eldőlt. Ilyenkor mi van?
Szokásos trükk. A méretkorlát feloldása nem automatikus. Vajon hol lehet bekapcsolni? Úgy van. Registry. I like this company.
Kellemes mellékhatás, hogy az SP2 után létezik egy másik paraméter is a registryben – ezzel figyelmeztető értéket lehet beállítani az adatbátisméretére.
Mindez szépen le van írva az Exchange csapat blogjában.

[Update]
(1) Gömöri Zoli szólt, hogy ő már írt egy ilyen szkriptet. Íme.
Én a magam részéről egyszerűbbre gondoltam – szvsz. elég lehet fájlszinten lekérdezni az .edb/.stm méreteket – bár így sem rossz.

Keresés az AD-ben e-mail címre

Egy régi problémám volt az, hogy hogyan találjunk meg egy felhsználót az Active Directoryban az e-mail címe alapján. Volt erről egy hosszú thread a technetklub levlistán (http://listmanager.technetklub.hu/read/messages?id=122959 [2008-05-30: Ez a link már nem él. A technetklub levlista kimúlt, béke poraira. Még nem adtam fel, hogy az archívumot egyszer kirakom az internetre publikusan, de sajna nincs időm befejezni a kódot.]) amiből az derült ki, hogy valamelyik proxyAddress alapján nehéz megtalálni a felhasználót, ráadásul lassú is. A probléma alapja, hogy azt gondoltom (gondoltuk többen), hogy a proxyAddresses propertyben nem lehet keresni mert az egy multivalue property. Már tervezgettem, hogy írok valami szolgáltatást a dologra. Egy progi megadott időközönként végigtúrja az AD-t épít belőle egy adatbázist amiben utána én tudok gyorsan keresni.
Ma megint kellet volna ez a dolog így tüzetesebben utánnanéztem a Windows 2000 Scripting Guide-ban (http://www.microsoft.com/technet/scriptcenter/guide/default.mspx). Olvasva az ADSI keresésre vonatkozó részt egy mondatra figyeltem fel (itt: http://www.microsoft.com/technet/scriptcenter/guide/sas_ads_jgtf.mspx):
…use objectCategory rather than objectClass because objectCategory is single-valued and ideal for servicing search requests…
 
Várjunk csak, ezek szerint lehet multivalue propertyben keresni. Kipróbáltam. Íme az eredmény:
var SearchMail = "test@domain.hu"; 
var ADConnect = new ActiveXObject("ADODB.Connection"); 
var ADCommand = new ActiveXObject("ADODB.Command"); 
var rootDSE, ForestRoot, ADRS; 
rootDSE = GetObject("LDAP://rootDSE"); 
ForestRoot = rootDSE.Get("rootDomainNamingContext"); 
ADConnect.Open("Provider=ADsDSOObject;"); 
ADCommand.ActiveConnection = ADConnect; 
ADCommand.CommandText = "<GC://" + ForestRoot + 
    ">;(&(objectCategory=user)(proxyAddresses=smtp:" + 
    SearchMail + "));name;subtree"; 
ADRS = ADCommand.Execute(); 
for(; !ADRS.EOF; ADRS.MoveNext()) 
    WScript.Echo(ADRS.Fields("name").Value); 
ADConnect.Close();

Mail fájlok és a CDO 2.

Pár napja írtam már a fenti címről. Akkor úgy gondoltam, hogy egy JScript példa elég lesz. Közben rájöttem, hogy .Net környezetben ez kevés (a típusosság miatt jóval több dolgot meg kell adni). Ezért most itt egy C# metódusként megírt példa (a referenciák közé fel kell venni az ADO és a CDO COM Objektumokat):
public static CDO.Message LoadMsgFile(string FileName)
{
    CDO.Message Msg = new CDO.MessageClass();
    ADODB.Stream MsgStream = new ADODB.Stream();
    MsgStream.Type = ADODB.StreamTypeEnum.adTypeBinary;
    MsgStream.Open((object)System.Type.Missing,
        ADODB.ConnectModeEnum.adModeUnknown,
        ADODB.StreamOpenOptionsEnum.adOpenStreamUnspecified,
        "","");
    MsgStream.LoadFromFile(FileName);
    Msg.DataSource.OpenObject(MsgStream,"_Stream");
    return Msg;
}

Mail fájlok és a CDO 1.

Abba a problémába futottam a levlista program fejlesztgetése során, hogy hogyan dolgozzuk fel azokat a leveleket amik az SMTP szerver drop könyvtárába érkeznek, vagy bármilyen más MIME formátumú levelet. Ha ez a levél eml kiterjesztéssel rendelkezik és egyszerűen rákattintunk akkor jön az Outlook Express és megmutatja a levelet. Természetesen ha programból kell csinálnunk valamit vele, akkor ez nem lesz ilyen egyszerű.  Például mi van akkor, ha szükségünk van egy From egy To vagy egy Subject mezőre? Esetleg a levél törzsét (HTML Body) szeretnénk letárolni egy adatbázisba?
Megtehetjük azt, hogy reguláris kifejezésekkel kiszedjük a fájlból amire szükségünk van. Megtehetjük, hogy írunk egy feldolgozó programot ami megfelelően szétszedi a levelet az igényeinknek megfelelően. Egyik megoldás sem egyszerű, ráadásul szükségtelen. A Microsoftnak van egy megfelelő objektum könyvtára erre. Ez a CDO (vagy CDOEX).
A feladatunk annyi, hogy a levelet betültsük egy CDO.Message objektumba. Ezzel csak egy probléma van. Ez az objektum nem kínál közvetlenül olyan lehetőséget, hogy fájlból betöltsük a tartalmát. Ezért azt tehetjük meg, hogy a fájlt megnyitjuk egy ADODB.Stream-ként és ezt adjuk meg adatforrásként a CDO.Message objektumnak. Ez JScriptben így fog kinézni:
function LoadMsgFile(FileName) 
{ 
    var adTypeBinary = 1; 
    var Msg; 
    var MsgStream; 
    Msg = new ActiveXObject("CDO.Message"); 
    MsgStream = new ActiveXObject("ADODB.Stream"); 
    MsgStream.Type = adTypeBinary; 
    MsgStream.Open(); 
    MsgStream.LoadFromFile(FileName); 
    Msg.DataSource.OpenObject(MsgStream,"_Stream"); 
    return Msg; 
}