Tags: , | Categories: Xml Posted by talgiladi on 6/3/2008 9:02 PM | Comments (6)

ראינו לא מזמן כיצד ליצור RSS Feed לאתר (הסימן הכתום הזה שהדפדפן מראה כשאפשר להירשם לחדשות ועידכונים מהאתר...)
שם בעצם יצרנו קובץ xml פשוט והדפדפן הציג לנו אותו בצורה יפה ומסודרת. רציתי להראות משהו נחמד שנקרא xslt שזהו בעצם קובץ, שאומר לתוכנה שקוראת xml, איך להציג את הקובץ
שימו לב, את הקובץ xml עם התוכן אני יוצר כרגיל איך שיצרתי עד היום בלי שינוי, הקובץ הזה רק נותן הוראה איך להציג את התוכן, וכך הדפדפן, או כל קורא xml יודע להציג אותו בצורה יפה ולא בתור טקסט פשוט
נראה דוגמה ואז נבין איזה פשוט זה.
נניח שיש לי קובץ xml כזה:

<?xml version="1.0" encoding="utf-8" ?>
    <channel>
        <title>coding games</title>
        <link>http://www.talgiladi.net</link>
        <description>code samples </description>
        <ttl>180</ttl>
        <item>
            <title><![CDATA[Creating xml documents with xml text writer]]></title>
            <link>http://www.talgiladi.net/XmlTextWriter.aspx</link>
            <guid isPermaLink="true">http://www.talgiladi.net/XmlTextWriter.aspx</guid>
            <description><![CDATA[xml text writer for fast and easy creation of xml documents]]></description>
            <pubDate>2/5/2008 9:24:18 PM</pubDate>
        </item>
</channel>

זה בעצם אותו קובץ שהשתמשתי בו בשביל ה RSS רק הורדתי 2 שורות כדי שהדפדפן לא יזהה אותו בתור RSS ויציג אותו בצורה שונה.
כעת נלך ליצירת קובץ חדש ונבחר xslt

createXslt

קיבלנו קובץ xml חדש. 3 שורות הראשונות אנחנו לא נוגעים, כעת נתחיל לתת הוראות. זיכרו שהקובץ הזה אמור להורות לקורא xml כיצד להציג כל חלק בקובץ
נתחיל להסביר לו איך לקרוא:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes msxsl" >
<xsl:output method="xml" indent="yes"/>

עד כאן השורות המקוריות שאומרות שהקובץ הוא xslt, שהוא בעצם גיליון עיצוב ל xml, ושהתוצאה שלו תהיה xml

<xsl:template match="/">

פה אנו אומרים לו שיתחיל להתאים את העיצוב מתחילת קובץ ה xml שלי, ולא לחפש איזה אלמנט מסוים, ומתחילים להקליד לו את התבנית שאותה הוא כבר ידפיס למסך

<html><head><title>

מכיוון שאני רוצה שהתוצאה תהיה html חוקי אני אומר לו להדפיס את תגי ה html
כעת אני רוצה לתת לדף שלי כותרת לפי ערך שאני בוחר מקובץ ה xml ולכן נכתוב את ההוראה:

<xsl:value-of select="/channel/title" />

ההוראה הזאת אומרת להציג ערך שהוא התוצאה של האלמנט בשם "channel/title", כך שכל ערך שאשים במסמך ה xml שלי בתוך האלמנט הזה הוא יהיה הכותרת של הדף.
כעת נמשיך ב html פשוט

</title></head><body>

וכאן מתחיל גוף הדף, כך שכל אחד יכול לשים את העיצובים היפים שלו כאן... אני אשים div קטן כדי לישר את הכל לימין...

<div style="direction:rtl" />

ועכשיו אני לתת הוראה לרוץ בלולאה, עבור כל אלמנט item שיש לי ב xml

<xsl:for-each select="/rss/channel/item">

ועבור כל אלמנט נכתוב את התבנית הבאה:

 

<ddiv style="direction:rtl">/span>
<a href="{link}">/span>
<xsl:value-of select="title" />
</a>

בתוך הלינק שמתי {link} כך שהערך שנמצא באלמנט link בקובץ xml שלי יוכנס כאן.
ואז שוב השתמשתי במה שראינו מקודם- להציג את הערך שנמצא בתוך אלמנט title בתוך כל item. ונוסיף גם לדף שלנו את התיאור של כל item:

&<span>
</span>xsl:value-of select="description" disable-output-escaping="yes" />
&</span>

שוב אותה שיטה, רק הוספתי גם הוראה לא לפרמט את התוצאה - הכוונה היא שאם הקורא יראה את הסימן span class="code_keywords"><

אז לא לפרמט אותו ל &lt; וזאת מכיוון שיתכן שהתיאור שלי במאמר יכיל בעצמו Html כמו טקסט בולט, קו תחתון וכו' ואני רוצה שזה אכן יראה כמו Html ולא כמו אוסף של דברים מוזרים...
זהו... כעת במסמך ה xml שלי שעבורו בניתי את ה xslt יש להוסיף שורה למעלה שאומרת לקורא ה xml שיש קובץ מיוחד שמסביר איך להציג את התוכן , ולתת קישור לקובץ הזה:

 

<?xml-stylesheet type="text/xsl" href="MyXSLT.xslt" version="1.0"?>

ישנה מחלקה מיוחדת בדוט נט בשם XPath שעוזרת לנו להשתמש ב xslt בצורה תכנותית להמרה של קבצי xml, שזה בעצם מה שהדפדפן עושה או כל קורא xml אחר, בעזרת השם נדבר על המחלקה הזאת בקרוב

להורדת דוגמה

למידע נוסף

Technorati Tags: ,

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags: , | Categories: C# Posted by talgiladi on 6/3/2008 7:56 PM | Comments (6)

, לשם כך יש צורך ביצירת אתר חדש או ספריה וירטואלית חדשה (אלא אם כן השתמשתם בקאסיני...)
יוצא לפעמים שאנחנו צריכים להכין תוכנת התקנה של אתר ללקוחות הקוד לא ארוך ומסובך אבל מעצבן קצת.
קודם נוסיף הפניה לשם המתחם using System.DirectoryServices; שמשמש בעצם גם לגישה ל active directory. שימו לב שההפניה צריכה להיות דרך Add Reference :

addreferenceactivedirectory

כעת נפנה ל IIS:

 DirectoryEntry iisRoot = new DirectoryEntry("IIS://" +

                    serverUrl + "/W3SVC/1/Root");

כש serverUrl זו הכתובת של המחשב שעליו מתקינים, במקרה של התקנה אצל הלקוח זה בדרך localhost
כעת, מכיוון שאנחנו רוצים ליצור ספריה וירטואלית ולא ליצור אתר חדש, אנחנו צריכים הפניה לאיזה אתר קיים כבר, אני אפנה לאתר הדיפולטי ושם אצור את הספריה:

 DirectoryEntries defaultSite = iisRoot.Children; ;//default site

כעת ניצור את הספריה החדשה:

 DirectoryEntry newVirtualDirectory =  defaultSite.Add(virtualDirectoryName,iisRoot.SchemaClassName.ToString());//add new site

newVirtualDirectory.CommitChanges();

ו virtualDirectoryName הוא כמובן שם הספריה החדשה

כעת נגיד לו איפה נמצאים הקבצים שהספריה הזאת צריכה להציג

newVirtualDirectory.Properties["Path"].Value = physicalPath;//the path to the files

ו physicalPath זה כמובן הנתיב המלא לתיקיה עם הדפים של האתר החדש שלנו...

כעת קצת מאפיינים לאתר החדש שלנו:

newVirtualDirectory.Properties["AccessRead"][0] = false;

            newVirtualDirectory.Properties["AccessWrite"][0] = true;

            newVirtualDirectory.Invoke("AppCreate", true);

            newVirtualDirectory.Properties["AppFriendlyName"][0] = virtualDirectoryName;

ובסוף לשמור

newVirtualDirectory.CommitChanges();//save the changes

זהו... קליל ביותר, רק קצת קשה לזכירה, אבל גם ככה בקושי משתמשים בקוד הזה אז זה בסדר... פעם אחרת בעזרת השם ניצור אתר חדש ולא ספריה וירטואלית...

עוד משהו קטן, אם אנחנו רוצים לבדוק אם כבר קיימת כזאת ספריה וירטואלית לפני שמנסים ליצור אותה, אז ניתן להשתמש בקוד:

newVirtualDirectory = defaultSite.Find(virtualDirectoryName, oDE.SchemaClassName.ToString());

רק שימו לב שהפונקציה הזאת לא כל כך נחמדה, היא לא מחזירה null אלא זורקת exception אם לא נמצאה הספרייה, אז להקיף ב try catch בבקשה... תיהנו!

להורדת פרוייקט דוגמה

 

Technorati Tags: ,

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags: , | Categories: C# Posted by talgiladi on 6/2/2008 9:50 PM | Comments (3)

לעיתים אנו רוצים לשלוט ב WinService על המחשב דרך הקוד. בתוכנה שלנו למשל, מופעלים מספר שירותים על המחשב, ועוד אחד שמפקח עליהם, ועוד יש התקנה של המוצר שצריכה גם להתקין את הסרביסים האלה, ולכן שליטה מוחלטת דרך הקוד הכרחית עבורנו. לשם כך ניעזר במחלקה ServiceController.
קודם כל צריכים להוסיף הפניה לאסמבלי System.ServiceProcess שכן הפניה לשם לא קיימת בברירת המחדל
כעת אפשר להתחיל להשתמש בו

System.ServiceProcess.ServiceController myController = new System.ServiceProcess.ServiceController(svcName);

כפי שניתן לראות הבנאי שלו מקבל את שם הסרביס שאיתו אני רוצה לעבוד - השם הוא כמו שמופיע כשלוחצים alt+ctrl+del ובוחרים את טאב הסרביסים
בינתיים גם אם הסרביס לא קיים הכל עובד כרגיל. ישנה בעיה קטנה - אם פונקציה שעונה לי פשוט האם סרביס קיים או לא, ולכן נתחכם קצת :

if (myController != null)
{
try
{
string s=myController.DisplayName;
myController.Dispose();
return true;
}
catch { return false; }
}
return false;

ניסינו בעצם למשוך מידע ממנו - ואם הסרביס לא קיים אז נקבל טעות ונדע שהוא לא קיים
טוב אז יש לנו סרביס שקיים, כעת אנו רוצים לדעת מה המצב שלו - הוא מותקן בוודאות, אבל אולי הוא התרסק ועצר?

ServiceControllerStatus scs= myController.Status;

אם נרצה לעצור אותו, נשתמש בפונקציה מובנית

switch (myController.Status)
{
case ServiceControllerStatus.Stopped:
//already stopped...nothing to do
break;
case ServiceControllerStatus.StopPending:
myController.WaitForStatus(ServiceControllerStatus.Stopped);
break;
default:
myController.Stop();
myController.WaitForStatus(ServiceControllerStatus.Stopped);
break;
}
myController.Close();

רק נוודא שאנו ממתינים שהוא אכן יעצור...
ולהריץ אותו נשתמש בשיטה זהה:

switch (myController.Status)
{
case ServiceControllerStatus.Stopped:
myController.Start();
myController.WaitForStatus(ServiceControllerStatus.Running);
break;
case ServiceControllerStatus.StopPending:
//wait for it to stop
myController.WaitForStatus(ServiceControllerStatus.Stopped);
//... and then start
myController.Start();
myController.WaitForStatus(ServiceControllerStatus.Running);
break;
case ServiceControllerStatus.StartPending:
//nothing to do...just wait
myController.WaitForStatus(ServiceControllerStatus.Running);
break;
case ServiceControllerStatus.Running:
//nothing to do.already running...
break;
default:
myController.Start();
myController.WaitForStatus(ServiceControllerStatus.Running);
break;
}

כפי שניתן לראות השימוש די אינטואיטיבי, אנו בודקים את מצבו כרגע, לפי זה מחליטים מה לעשות, ובסוף ממתינים שאכן השינוי יתבצע

עכשיו, כדי להתקין ולהסיר סרביסים דרך הקוד, כבר נצטרך שימוש בקוד c++, אבל לא הרבה... להתקנת שירות נגדיר קצת קבועים:

int SC_MANAGER_CREATE_SERVICE = 0x0002;
int SERVICE_WIN32_OWN_PROCESS = 0x00000010;
//int SERVICE_DEMAND_START = 0x00000003;
int SERVICE_ERROR_NORMAL = 0x00000001;
int STANDARD_RIGHTS_REQUIRED = 0xF0000;
int SERVICE_QUERY_CONFIG = 0x0001;
int SERVICE_CHANGE_CONFIG = 0x0002;
int SERVICE_QUERY_STATUS = 0x0004;
int SERVICE_ENUMERATE_DEPENDENTS = 0x0008;
int SERVICE_START = 0x0010;
int SERVICE_STOP = 0x0020;
int SERVICE_PAUSE_CONTINUE = 0x0040;
int SERVICE_INTERROGATE = 0x0080;
int SERVICE_USER_DEFINED_CONTROL = 0x0100;
int SERVICE_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED |
SERVICE_QUERY_CONFIG |
SERVICE_CHANGE_CONFIG |
SERVICE_QUERY_STATUS |
SERVICE_ENUMERATE_DEPENDENTS |
SERVICE_START |
SERVICE_STOP |
SERVICE_PAUSE_CONTINUE |
SERVICE_INTERROGATE |
SERVICE_USER_DEFINED_CONTROL);
int SERVICE_AUTO_START = 0x00000002;

הפונקציה שלנו תקבל 3 משתנים

string svcPath, string svcName, string svcDispName

את הנתיב הפיסי לסרביס שאנו רוצים להתקין, את שם הסרביס ואת השם שבו הוא יוצג
וכעת להתקנה עצמה:

IntPtr sc_handle =NativeMethods.OpenSCManager(null,
null, SC_MANAGER_CREATE_SERVICE);
if (sc_handle.ToInt32() != 0)
{
IntPtr sv_handle = CreateService(sc_handle,-->c++ native method svcName, svcDispName, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, svcPath, null, 0,
null, null, null);
if (sv_handle.ToInt32() == 0)
{
CloseServiceHandle(sc_handle);-->c++ native method
throw new
ExternalException("Could not create service");
}
}
else
{
throw new
ExternalException("Could not open handle to service manager");
}

כשאנו משתמשים בעצם ב 2 פונקציות מספריית windows
כמובן שצריך להגדיר פונקציות חיצוניות לפני השימוש...:

[DllImport(
"advapi32.dll")]
public static
extern IntPtr OpenSCManager(string lpMachineName,
string lpSCDB, int scParameter);
[DllImport("Advapi32.dll")]
public static
extern IntPtr CreateService(IntPtr SC_HANDLE,
string lpSvcName, string lpDisplayName,
int dwDesiredAccess, int
dwServiceType, int dwStartType, int
dwErrorControl, string lpPathName,
string lpLoadOrderGroup, int
lpdwTagId, string lpDependencies, string lpServiceStartName, string
lpPassword);

ההגדרה DllImport היא ממש לפי המשמעות - אנו מגדירים הפניה ל DLL מקומי, מגדירים איך נראית הפונקציה ואז ניתן לפנות אליה
זה אמור להספיק כדי להתקין את הסרביס...
אם נרצה להסיר אותו השיטה דומה- קודם נעצור אותו בעזרת השיטה שראינו לעיל, אחר כך נקרא לפונקציות חיצוניות כדי להסיר ולמחוק אותו

StopService(svcName);-->out function
int GENERIC_WRITE = 0x40000000;
IntPtr sc_hndl = OpenSCManager(
null, pan class="code_keywords">nunull, GENERIC_WRITE);
-->c++ method
if (sc_hndl.ToInt32() != 0)
{
int DELETE = 0x10000;
IntPtr svc_hndl = OpenService(sc_hndl, svcName,
DELETE);-->c++ method
if (svc_hndl.ToInt32() != 0)
style="color: #a31515" {
int i = DeleteService(svc_hndl);
-->c++ method
if (i != 0)
{
CloseServiceHandle(sc_hndl);-->c++ method
}
else
{
CloseServiceHandle(sc_hndl);-->c++ method
throw new ExternalException("Could not delete service");
}
}
else
throw new
ExternalException("Could not open service");
}
else throw new ExternalException("Could not open handle to service manager");

לא מסובך כל כך... אומנם משעמם להשתמש בפונקציות והגדרות מובנות במערכת ההפעלה, אבל סביר...

להורדת הפרוייקט

חלק מהקוד נלקח מ http://www.thescripts.com/forum/post932461-9.html

Technorati Tags: ,

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5