כידוע יש ב - Windows מה שנקרא "Run this program in compatibility mode" מה שמאפשר להריץ את האפליקציות ב"מוד" קודם של מערכת ההפעלה.
היום ניסתי להריץ msi כלשהו וקבלתי הודעת שגיאה שזה יכול לרוץ רק על xp או vista, חשבתי לעצמי שאוכל פשוט להריץ את ה - msi ב - Compatibility Mode, לדאבוני התברר לי שאין לקבצי msi אפשרות להרצה ב"מוד" קודם.
קצת שיטוט בגוגל והגעתי
לכאן, הוא מציע להשתמש ב -
Orca שזה הכלי של מייקרוסופט לשינוי קבצי msi אחרי שהם נסגרו (אפשר להוריד את זה
מכאן)
בתירגום פשוט אלו השלבים:
1. התקינו Orca
2. קליק ימין על ה - msi ובחירה ב - Edit in orca
3. תחפשו ברשימה בצד שמאל מה שנקרא "LaunchCondition"
4. תחפשו בצד ימין שורה שמדברת על הגרסאות
5. הסירו אותה (בעזרת קליק ימין על השורה ובחירה ב - Cut Row)
6. לחיצה על Tools בחירה ב - Options תחפשו את הטאב database ותוודאו ש - "Copy embedded streams during Save As" מסומן.
7. לחיצה על File ובחירה ב - Save As
8. תצאו מ - Orca לפני הפעלה של ה - msi
בהצלחה
נניח שיש לכם את המחלקה הבאה:
class Dolar
{
public double Value { get; set; }
public Dolar(double value)
{
Value = value;
}
}
וב - main
Dolar d1 = new Dolar(10);
Dolar d2 = new Dolar(20);
if (d1.Value > d2.Value)
{
}
לכאורה הקוד היה יותר קריא לו יכולנו לכתוב כך
כדי לעשות את זה צריך להוסיף למחלקה את הקוד הבא
public static bool operator >(Dolar d1, Dolar d2)
{
return d1.Value > d2.Value;
}
public static bool operator <(Dolar d1, Dolar d2)
{
return d1.Value < d2.Value;
}
למעשה נוכל לדרוס כמעט את כל האופרטרים שקיימים, אבל צריך לעשות את זה בזהירות כי אם נחליט שאנחנו מממשים את האופרטור < על PersonManager אף אחד לא יבין את הקוד שלנו, מה שצריך לזכור שהמטרה של OperatorOverload זה להקל על הקריאות של הקוד ולא להקשות עליו.
נקודה נוספת, שתמיד צריך לעשות את זה בצמדים כלומר אם אתם מממשים את האופרטור < אתם חייבים לממש את האופרטור > ואם תממשו את האופרטור == אתם חייבים לממש גם את != וכו'
כמובן שאפשר גם לכתוב כך
public static bool operator >(Dolar d1, double d2)
{
return d1.Value > d2;
}
public static bool operator <(Dolar d1, double d2)
{
return d1.Value < d2;
}
public static bool operator >(double d1, Dolar d2)
{
return d1 > d2.Value;
}
public static bool operator <(double d1, Dolar d2)
{
return d1 < d2.Value ;
}
ואז ב - main
if (d1 > 50)
{
}
if (50 > d1)
{
}
הקרדיט מגיע לאחי יוסי גולדברג
כתבתי פוסטים על שימוש ב -
Cookie. כעת נראה כיצד ניתן להסיר עוגיות בצד השרת.
נניח שיש לכם עוגייה שנקראת MyCookie ואתם רוצים להסיר אותה, למעשה בכל Request שיגיע מהלקוח ה - Cookie יצטרף לבקשה, מה שצריך לעשות זה לכתוב את הקוד הבא
Response.Cookies.Add(new HttpCookie("myCookie") { Expires = DateTime.Now.AddDays(-1) });
למעשה מצרפים ל - Response עוגייה עם אותו שם כשתאריך התפוגה נקבע לזמן ישן, כך כשהתשובה חוזרת ללקוח העוגייה נמחקת.
אם כבר מדברים על - Expires, אם נייצר עוגיות ולא ניתן שום ערך למאפיין הזה, הוא יחיה רק בזיכרון של הדפדפן וכשהדפדפן יסגר גם העוגייה תעלם, במידה וניתן ערך (עתידי) כלשהו לעוגייה העוגייה תשמר בזיכרון של המחשב עד לאותו תאריך.
ב - IIS ל - ApplicationPool יש מאפיין מאוד מעניין שהרבה לא מודעים אליו. Regular Time Interval תחת קטגוריית recycling.
כברירת מחדל הערך שלו זה 1740 (29 שעות) המשמעות של זה שכל 29 שעות ולא משנה מה קורה באותו רגע יש restart ל - application pool,
לפעמים יש לזה משמעות קריטית לזמן שבו יש restart (אם למשל אתם עושים streaming ופתאום האפליקצייה שלכם עושה restart זה לא נעים.
אני לא חושב שכדאי להגדיר אותו ל 0 (כלומר לא לעשות אף פעם restart) אבל חשוב להכיר את המאפיין הזה ולבטל אותו בשעת הצורך. אם זה אפשרי אפשר להשתמש במקומו במאפיין Specific Times שמקבל מערך של TimeSpan שמגדיר באיזה שעה לעשות recycling.
חפשתי איך אפשר לדעת בעוד כמה זמן ה - application pool יעשה recycling אבל לא הצלחתי למצוא פקודה כזאת - אשמח לשמוע על אחת כזאת אם זה קיים.
ב - WebService כדי לדעת מה ה - IP של ה - client שהפעיל את המתודה אנחנו כותבים:
HttpContext.Current.Request.UserHostAddress;
כדי לדעת את זה ב - WCF צריך לכתוב את הקוד הבא:
var context = OperationContext.Current;
var prop = (RemoteEndpointMessageProperty)
context.IncomingMessageProperties[RemoteEndpointMessageProperty.Name];
string ip = prop.Address;
כתבתי כמה
פוסטים על הפעלה של WebService מתוך JavScript ומקבלים תוצאות ב - JSON.
זה עובד מעולה בתוך אותו דומיין.
Microsoft JScript runtime error: Permission denied
חבר לעבודה
(ערן גרוס, CTO you-niversity ארה"ב) הציע רעיון נהדר כדי לעקוף את הבעייה.
במקום לפנות מהסקריפט ל - WebService כדי לקבל את ה - JSON, ניתן לכתוב Handler שיחזיר JSON ולייבא אותו כקובץ JavaScript.
לדוגמא נכתוב את ה - Handler הבא: (הדוגמא להפעלה עם WebService מוסברת בפוסט
הזה)
public class Student
{
public string Name { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
public int Age { get; set; }
}
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Data : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "application/x-javascript";
var students = new Student[]
{
new Student(){ Name = "Shlomo",
Age = 24,
Phone = "123456",
Address = "Elad"},
new Student(){ Name = "Yossi",
Age = 23,
Phone = "543256",
Address = "Beni brak"},
new Student(){ Name = "Tomer",
Age = 30,
Phone = "0000000",
Address = "Tel Aviv"}
};
DataContractJsonSerializer json = new DataContractJsonSerializer(typeof(Student[]));
MemoryStream stream = new MemoryStream();
json.WriteObject(stream, students);
stream.Seek(0, SeekOrigin.Begin);
StreamReader reader = new StreamReader(stream);
context.Response.Write(string.Format("var data = {0}", reader.ReadToEnd()));
}
public bool IsReusable
{
get
{
return false;
}
}
}
מוגדרת מחלקה בשם Student שאנחנו רוצים להחזיר מערך שלה.
המתודה ProcessRequest מגדירה שמה שחוזר ללקוח הוא מסוג application/x-javascript.
לאחר מכן היא מייצרת מערך של Student.
וכעת צריך לייצר אובייקט JSON מהמערך.
צריך להוסיף את ה - referencr הבאים:
System.Runtime.Serialization
System.ServiceModel.Web
הקוד שלאחר מכן כותב לתוך ה - stream את המידע ולאחר מכן מגדיר משתנה בשם data שמכיל את כל המידע.
כעת ב - html שלנו נכתוב כך:
<script type="text/javascript" src="Data.ashx"></script>
ובכל מקום בדף יהיה לנו משתנה גלובלי בשם data שמכיל את אותם Students.
כך נראה המשתנה data ב - watch (ב - Javascrip)
אלכס (ממשיך להפתיע מידי פעם) כתב מאקרו שימושי ל - Visual Studio.
(
וגיא דואג שיהיה לי על מה לכתוב)
------------
כשאנחנו סוגרים את Visual Studio נוכל להתחרט ולעצור את תהליך הסגירה רק במידה ויש לנו קובץ פתוח שלא נשמר - והסביבה תוודא האם אנחנו רוצים לשמור את הקובץ או לבטל את היציאה.
מאוד רצוי שהסביבה תוודא שאנחנו אכן רוצים לסגור את ה - Visual Studio גם אם אין קובץ שלא נשמר (פתיחה מחדש יכולה לקחת כמה דקות מעצבנות בפרוייקטים מספיק גדולים)
תחת Tools -> Macros -> Macros IDE או All + F11
נלחץ פעמיים על MyMacros (זה TreeView - רק שלא רואים את סימן הפלוס)
נכנס ל - EnvironmentEvents
ונוסיף את קטע הקוד הבא
Private Sub SolutionEvents_BeforeClosing() Handles SolutionEvents.BeforeClosing
Try
If MsgBox("Close Solution?", MsgBoxStyle.YesNo, "Close Solution") = MsgBoxResult.Yes Then
Return
End If
DTE.ItemOperations.NewFile("General\Text File", "Undo Close")
DTE.ActiveDocument.Selection.Text = "Press 'Cancel' to abort solution close."
Catch ex As Exception
MsgBox("Error in SolutionEvents_BeforeClosing macro: " + ex.Message)
End Try
End Sub
לא אכנס להסבר הקוד - אבל מה שזה יעשה - שבכל פעם שסוגרים את VS - נקבל שאלה האם אנחנו בטוחים שאנחנו רוצים לסגור את הסביבה.
ותודה לאלכס (על הפוסט) ולגיא (שאתה חושב עלי)
הפוסט הזה הוא באדיבות מיטל (חברה טובה ומתכנתת מאוד מוכשרת)
אם יש לכם Crystal Report שמכיל פרמטרים ו - SubReports ותכתבו קוד כמו זה
report.SetDataSource(RevenueReceipt());
report.SetParameterValue("barcode", "123456");
report.Subreports["Sub.rpt"].SetDataSource(SubDetails());
report.ExportToStream(ExportFormatType.PortableDocFormat);
תקבלו הודעת שגיאה כזאת:
CrystalDecisions.CrystalReports.Engine.ParameterFieldCurrentValueException was unhandled by user code
Message="Missing parameter values."
כדי לפתור את זה - צריך להפוך את הסדר, כלומר ההגדרה של ה - DataSource עבור ה - SubReport צריכה להיות לפני הגדרת הפרמטרים ל - Report
report.SetDataSource(RevenueReceipt());
report.Subreports["Sub.rpt"].SetDataSource(SubDetails());
report.SetParameterValue("barcode", "123456");
report.ExportToStream(ExportFormatType.PortableDocFormat);
מאחד הפיצ'רים שהודגמו שם ממש התלהבתי - מדובר על האפשרות לתת עיצוב ל - disabled controls בצורה די אוטומטית.
נניח שיש לנו את קוד ה - html הבא
<asp:TextBox ID="txt" runat="server"></asp:TextBox>
<asp:Button ID="btnEnable" Text="Enable" runat="server"
onclick="btnEnable_Click" />
<asp:Button ID="btnDisable" Text="Disable" runat="server"
onclick="btnDisable_Click" />
ובצד השרת
protected void btnEnable_Click(object sender, EventArgs e)
{
txt.Text = "Enable";
txt.Enabled = true;
}
protected void btnDisable_Click(object sender, EventArgs e)
{
txt.Text = "Disable";
txt.Enabled = false;
}
די ברור מה הקוד הזה יעשה - אבל עד היום עם היינו רוצים להגדיר עיצוב מיוחד לתיבת הטקסט שהיא disabled היינו צריכים לכתוב קוד כלשהו שיחליף את ה - CssClass.
כיום מה שאנחנו צריכים לעשות - זה להוסיף CssClass מיוחד שנקרא aspNetDisabled וההגדרות שבו יחולו על הפקדים שהם במצב disable
.aspNetDisabled
{
font-size:20pt;
}
נניח שרוצים לקשר בין TreeView לבין קובץ xml
ונרצה להציג אותו ב - Tree
כשנכתוב קוד כזה
<asp:TreeView ID="TreeView1" runat="server" DataSourceID="XmlDataSource1">
</asp:TreeView>
<asp:XmlDataSource ID="XmlDataSource1" runat="server"
DataFile="~/currency.xml"></asp:XmlDataSource>
נקבל תוצאה כזאת
כלומר נקבל את המבנה ולא את המידע בעצמו.
כדי לפתור את זה נצטרך להוסיף Binding ל - TreeView
הכי קל זה בעזרת ה - Designer
נוסיף את המאפיינים שאנחנו רוצים לראות ונבחר ב - TextField את הערך המתאים.
בסופו של דבר נקבל
<asp:TreeView ID="TreeView1" runat="server" DataSourceID="XmlDataSource1">
<DataBindings>
<asp:TreeNodeBinding DataMember="NAME" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="UNIT" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="CURRENCYCODE" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="COUNTRY" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="RATE" TextField="#InnerText" />
<asp:TreeNodeBinding DataMember="CHANGE" TextField="#InnerText" />
</DataBindings>
</asp:TreeView>
מה שיחזיר
לאחרונה בשיטוטים שלי מצאתי dll שיש לו יכולות מדהימות של השמעת טקסט (והקלטה)
צריך להוסיף reference ל - System.Speech
שימו לב לקוד הבא:
string textToSpeak = Console.ReadLine();
SpeechSynthesizer ss = new SpeechSynthesizer();
ss.Speak(textToSpeak);
ומהרמקולים של המחשב נשמע את הטקסט שהמשתמש הקליד.
למחלקה הזאת יש המון יכולות.
החל משליטה על העוצמה והמהירות, האפשרות להחליט להיכן ינותב הפלט (האם לרמקול או לקובץ wav)
אפשר לקבל events מה הסטטוס של השמעת הטקסט, בעזרת רישום לאירוע SpeakProgress (ויש עוד כמה אירועים מעניינים)
אפשר לבנות מחרוזת להשמעה עם סגנונות (כלומר חלק מהטקסט יותר גבוה חלק מהר יותר וכדו') בעזרת מחלקה שנקראת PromtBuilder
אפשר להפעיל את ההשמעה בצורה אסינכרונית בעזרת המתודה SpeakAsync (וכמובן שאפשר לבטל אותה באמצע)
בקיצור - dll עם יכולות מאוד מעניינות - ותשחקו איתו ותהנו.
כל Console Application שאנחנו כותבים נראה כך:
static void Main(string[] args)
{
}
הפוסט הזה ידבר על "מה זה ה - args שאנחנו רואים ואיך שולחים פרמטרים לשם ואיך ניתן לגשת לפרמטרים ממתודות אחרות (בלי לשלוח את ה - aegs כפרמטר)."
הרבה תוכניות מסוג Console כשהן עולות צריכות לקבל מהמשתמש ארגומנטים כדי לדעת מה לעשות (בדרך כלל שם הפקודה בתוספת ? / תציג את כל האפשרויות. לדוגמא - אני מניח שכולם מכירים את הפקודה dir שמציגה רשימת קבצים ותיקיות - אם נכתוב
dir /?
נקבל את כל האפשרויות להפעלה - לדוגמא
dir /a r
תציג רק את הקבצים שהם ReadOnly.
אז איך שולחים פרמטרים ?
בחיים האמיתיים (כלומר כהלקוח מריץ את התוכנית) לאחר השם של התוכנית - כל מה שנכתוב יכנס כפרמטר למערך לפי התו רווח, לדוגמא:
myApp.exe abc 123 "abc 123"
נקבל מערך בעל שלושה כניסות
abc
123
abc 123
בזמן פיתוח כדי לשלוח ערכים נוכל במאפיינים של הפרוייקט תחת הטאב של Debug להכניס בתיבת הטקסט Command Line Args את הערכים.
כדי להגיע בכל מקום לפרמטרים - נוכל בעזרת
שיחזיר מחרוזת שתראה כך
myApp.exe abc 123 "abc 123"
או בעזרת
string[] arr = Environment.GetCommandLineArgs()
שיחזיר מערך בעל 4 כניסות
MyApp.exe
abc
123
abc 123
דימה הראה לי טריק מגניב של Windows 7 שלא הכרתי.
לחיצה עם הלחצן האמצעי בעכבר על אחד מהחלונות ב - TaskBar ישכפל את החלון.
לדוגמא - אם אני רוצה לפתוח Internet Explorer חדש - הדרך הכי מהירה היא ללחוץ עם הלחצן האמצעי של העכבר על האיקון של IE.
תנסו ותהנו.
אני מניח שיצא לכם לכתבו קוד כזה
<asp:DropDownList ID="ddl" runat="server">
<asp:ListItem Text="Select Item"></asp:ListItem>
</asp:DropDownList>
ואם רציתם לקשר רשימה כלשהי בצד השרת
IEnumerable<int> list = Enumerable.Range(0, 10);
ddl.DataSource = list;
ddl.DataBind();
הבעייה בקוד הזה שזה מוחק את ה - Select Item והבעייה הגדולה בדרך כלל במקרה הזה שאם נרשמתם לאירוע של SelectIndexChanged כדי לבחור את הראשון תצטרכו קודם לבחור את השני ורק אחרי זה תוכלו לבחור את הראשון.
מה שגיליתי לא מזמן - זה את המאפיין AppendDataBoundItems וזה נראה כך
<asp:DropDownList ID="ddl" runat="server" AppendDataBoundItems="true">
<asp:ListItem Text="Select Item"></asp:ListItem>
</asp:DropDownList>
ועכשיו ה - Bind יוסיף את הערכים ולא ידרוס.
בתפוז עלתה שאלה, איך ניתן לקרוא מידע מקובץ קונפיג חיצוני (כלומר - לא הקונפיג של ה - exe שמריץ את התוכנית)
הנה דוגמא
string path = @"bin\Debug\ConsoleApplication1.exe";
Configuration config = ConfigurationManager.OpenExeConfiguration(path);
var a = config.AppSettings.Settings["MyKey"].Value;
ה - path הינו לקובץ ה - exe האחר שיש לו קונפיג.
כדי שזה יעבוד צריך להוסיף referenct ל - System.Configuration
More Posts
Next page »