Friday, July 16, 2010

PRE Tag Internet Explorer Scrollbar Solution

<pre> tag is very useful for writing code. I use it all the time actually for posting C# code.
There is however a problem with Internet Explorer:
If the text is too long, and a horizontal scroll bar appears, it overlaps the bottom line.
You can find many solutions to this problem in this link, including scanning the document with JavaScript fixing all the pre tags.
My solution is a lot simpler.

Solution:
If you know that the text is too long and a horizontal scroll bar will appear, then add the following code at the bottom, just before the </pre> ending tag:

<!--[if IE]>

<![endif]-->

Explanation:
If the user is using Internet Explorer, then there will be an extra (empty) line inside the pre tag, and the horizontal scroll bar will overlap the empty line and not the original content.

Thursday, July 15, 2010

איך יוצרים קישור למקום מסוים במפה של גוגל, ynet ווואלה

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


הכי נוח. מחפשים את המקום ואז יש כפתור "קישור" בצד שמאל.


שיטה 1 קלה:
הכניסו נתונים ולחצו על "צור קישור":
עיר: רחוב: מספר:

שיטה 2: נכנסים לאתר המפות של ynet, מחפשים את המקום שרוצים, ואז לוחצים על "הדפס" (למטה), בדף החדש מבטלים את ההדפסה, ומסתכלים על הכתובת:
http://ymap.winwin.co.il/...&Mode=1&forprint=y&displayMode=SMALLMAP
מורידים את החלק שסימנתי באדום, ומה שנשאר זה הלינק שלכם.

מפות
הכניסו נתונים ולחצו על "צור קישור":
עיר: רחוב: מספר:

Sunday, July 11, 2010

איך לעקוף את ההודעה: "בחירת כסאות לא מאושרת, אין להשאיר כסא בודד" בסינמה סיטי

This post is intended for people from Israel.

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

בעיה: אתם רוצים להזמין 4 מקומות לסרט בסינמה סיטי ויש 5 פנויים. אתם בוחרים ב-4 שקרובים לאמצע ואז מקבלים את ההודעה:
פתרון 1: נכנסים במחשב אחר, בוחרים את הכיסא שלא רוצים, לוחצים על "הבא", והמערכת שומרת לכם אותו למשך 6 דקות. ואז במחשב שלכם אתם יכולים להזמין את ה-4 שאתם כן רוצים.

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

אבל מה קורה אם הזמנתם את הכרטיסים שלכם בלי בעיה (למשל 4 מתוך 6), אבל אתם מפוזרים כמוני ושכחתם מישהו בטעות, ועכשיו אתם צריכים להזמין מקום 1 מתוך 2? מהירי המחשבה ישימו לב שלא ניתן להשתמש בשיטה הקודמת.
פתרון 2: נכנסים במחשב שלכם בוחרים את 2 הכיסאות ולוחצים על "הבא"; המערכת שומרת אותם ל-6 דקות. נכנסים במחשב אחר לאותו סרט באותו יום באותה שעה איפה שרואים ש-2 הכיסאות תפוסים, ולא עושים כלום. חוזרים למחשב שלכם, לוחצים על "הקודם", בוחרים את הכיסא שאתם רוצים ומזמינים אותו.
כמובן שזה עובד על כל מספר של כיסאות ולכן יותר חזק מפתרון 1.
אז מה קרה פה?
ההשערה שלי: כנראה שהמערכת של סינמה סיטי שומרת סוג של מטמון ברגע שנכנסים מהמחשב השני, וכאשר חוזרים למחשב שלכם ומזמינים כיסא אחד במקום 2 המערכת משתמשת באותו מטמון שבו עדיין שמורים 2 הכיסאות, ולכן אין כיסא בודד.

הערות:
במקום להשתמש בשני מחשבים, ניתן להשתמש בשני דפדפנים, או בכל דרך שבה מפרידים את הסשן.
שני הפתרונות עובדים נכון ל-12 ביולי 2010.

Tuesday, July 6, 2010

C# Sort Text and Numbers (like Explorer does)

For example:
myvideo.part2.rar
Should come before:
myvideo.part10.rar


// Usage:

list.Sort(new StringLogicalComparer());


// Comparer:

public class StringLogicalComparer : IComparer, IComparer<string>
{
    [DllImport("shlwapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
    public static extern int StrCmpLogicalW(string x, string y);

    public int Compare(object x, object y)
    {
        return StrCmpLogicalW(x.ToString(), y.ToString());
    }

    public int Compare(string x, string y)
    {
        return StrCmpLogicalW(x, y);
    }
}

Thursday, July 1, 2010

WebBrowser and HttpWebRequest Cookies Problem and Solution

If you are working with WebBrowser control and you want to make some WebRequest you need to synchronize the cookies.
And that would be the naive way to do it:
httpWebRequest.CookieContainer.SetCookies(
    webBrowser.Document.Url, 
    webBrowser.Document.Cookie.Replace(';', ',')
    ); // THIS CODE IS WRONG!!

The problem is the HttpOnly cookies that are missing from Document.Cookie for security reasons.
The HttpOnly cookies are probably the most important ones that you need.
This article explains how to get them:
http://www.codeproject.com/KB/shell/RetrieveHttponlyCookies.aspx

Here is a more compact version of the function for C#:
[DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool InternetGetCookieEx(string pchURL, string pchCookieName, StringBuilder pchCookieData, ref uint pcchCookieData, int dwFlags, IntPtr lpReserved);
const int INTERNET_COOKIE_HTTPONLY = 0x00002000;

public static string GetGlobalCookies(string uri)
{
    uint datasize = 1024;
    StringBuilder cookieData = new StringBuilder((int)datasize);
    if (InternetGetCookieEx(uri, null, cookieData, ref datasize, INTERNET_COOKIE_HTTPONLY, IntPtr.Zero)
        && cookieData.Length > 0)
    {
        return cookieData.ToString().Replace(';', ',');
    }
    else
    {
        return null;
    }
}
And the usage would be:
httpWebRequest.CookieContainer.SetCookies(
    webBrowser.Document.Url, 
    GetGlobalCookies(webBrowser.Document.Url.AbsoluteUri)
    );

Monday, June 28, 2010

Blogger C# API

Source: http://google-gdata.googlecode.com/svn/trunk/clients/cs/samples/blogger/ConsoleSample.cs

using System;
using System.Text;
using Google.GData.Client;
using System.Net;
using System.Xml;
using System.Text.RegularExpressions;

namespace BloggerDevSample
{
    class ConsoleSample
    {
        /** Lists the user's blogs. */
        static void ListUserBlogs(Service service)
        {
            Console.WriteLine("\nRetrieving a list of blogs");
            FeedQuery query = new FeedQuery();
            // Retrieving a list of blogs
            query.Uri = new Uri("http://www.blogger.com/feeds/default/blogs");
            AtomFeed feed = null;
            feed = service.Query(query);
            foreach (AtomEntry entry in feed.Entries)
            {
                Console.WriteLine("  Blog title: " + entry.Title.Text);
            }
        }

        /** Lists the user's blogs and returns the URI for posting new entries
         * to the blog which the user selected.
         */
        static Uri SelectUserBlog(Service service)
        {
            Console.WriteLine("\nPlease select a blog on which to post.");
            FeedQuery query = new FeedQuery();
            // Retrieving a list of blogs
            query.Uri = new Uri("http://www.blogger.com/feeds/default/blogs");
            AtomFeed feed = service.Query(query);

            // Publishing a blog post
            Uri blogPostUri = null;
            if (feed != null)
            {
                foreach (AtomEntry entry in feed.Entries)
                {
                    // Print out the title of the Blog
                    Console.WriteLine("  Blog name: " + entry.Title.Text);
                    Console.Write("  Post to this blog? (y/n): ");
                    if (Console.ReadLine().Equals("y"))
                    {
                        // find the href in the link with a rel pointing to the blog's feed
                        for (int i = 0; i < entry.Links.Count; i++)
                        {
                            if (entry.Links[i].Rel.Equals("http://schemas.google.com/g/2005#post"))
                            {
                                blogPostUri = new Uri(entry.Links[i].HRef.ToString());
                                Console.WriteLine("  Your new posts will be sent to " + blogPostUri.AbsoluteUri.ToString());
                            }
                        }
                        return blogPostUri;
                    }
                }
            }
            return blogPostUri;
        }

        /** Creates a new blog entry and sends it to the specified Uri */
        static AtomEntry PostNewEntry(Service service, Uri blogPostUri)
        {
            Console.WriteLine("\nPublishing a blog post");
            AtomEntry createdEntry = null;
            if (blogPostUri != null)
            {
                // construct the new entry
                AtomEntry newPost = new AtomEntry();
                newPost.Title.Text = "Marriage!";
                newPost.Content = new AtomContent();
                newPost.Content.Content = "
" + "

Mr. Darcy has proposed marriage to me!

" + "

He is the last man on earth I would ever desire to marry.

" + "

Whatever shall I do?

" + "
"; newPost.Content.Type = "xhtml"; newPost.Authors.Add(new AtomPerson()); newPost.Authors[0].Name = "Elizabeth Bennet"; newPost.Authors[0].Email = "liz@gmail.com"; createdEntry = service.Insert(blogPostUri, newPost); if (createdEntry != null) { Console.WriteLine(" New blog post created with title: " + createdEntry.Title.Text); } } return createdEntry; } /** Creates a new blog entry and sends it to the specified Uri */ static void PostAndDeleteNewDraftEntry(Service service, Uri blogPostUri) { Console.WriteLine("\nCreating a draft blog post"); AtomEntry draftEntry = null; if (blogPostUri != null) { // construct the new entry AtomEntry newPost = new AtomEntry(); newPost.Title.Text = "Marriage! (Draft)"; newPost.Content = new AtomContent(); newPost.Content.Content = "
" + "

Mr. Darcy has proposed marriage to me!

" + "

He is the last man on earth I would ever desire to marry.

" + "

Whatever shall I do?

" + "
"; newPost.Content.Type = "xhtml"; newPost.Authors.Add(new AtomPerson()); newPost.Authors[0].Name = "Elizabeth Bennet"; newPost.Authors[0].Email = "liz@gmail.com"; newPost.IsDraft = true; draftEntry = service.Insert(blogPostUri, newPost); if (draftEntry != null) { Console.WriteLine(" New draft post created with title: " + draftEntry.Title.Text); // Delete the newly created draft entry Console.WriteLine(" Press enter to delete the draft blog post"); Console.ReadLine(); draftEntry.Delete(); } } } /** Display the titles for all entries in the previously selected blog. */ static void ListBlogEntries(Service service, Uri blogUri) { if (blogUri != null) { Console.WriteLine("\nRetrieving all blog posts"); // Retrieve all posts in a blog FeedQuery query = new FeedQuery(); Console.WriteLine(" Query URI: " + blogUri.ToString()); query.Uri = blogUri; AtomFeed feed = service.Query(query); foreach (AtomEntry entry in feed.Entries) { Console.WriteLine(" Entry Title: " + entry.Title.Text); } } } /** Display title for entries in the blog in the hard coded date range. */ static void ListBlogEntriesInDateRange(Service service, Uri blogUri) { Console.WriteLine("\nRetrieving posts using query parameters"); // Retrieve all posts in a blog between Jan 1, 2006 and Apr 12, 2007 FeedQuery query = new FeedQuery(); query.Uri = blogUri; query.MinPublication = new DateTime(2006, 1, 1); query.MaxPublication = new DateTime(2007, 4, 12); AtomFeed feed = service.Query(query); foreach (AtomEntry entry in feed.Entries) { Console.WriteLine(" Entry Title: " + entry.Title.Text); } } /** Change the contents of the newly created blog entry. */ static AtomEntry EditEntry(AtomEntry toEdit) { Console.WriteLine("\nUpdating post"); // Edit the new entry if (toEdit != null) { toEdit.Title.Text = "Marriage Woes!"; Console.WriteLine(" Press enter to update"); Console.ReadLine(); toEdit = toEdit.Update(); } return toEdit; } /** Delete the specified blog entry. */ static void DeleteEntry(AtomEntry toDelete) { Console.WriteLine("\nDeleting post"); // Delete the edited entry if (toDelete != null) { Console.WriteLine(" Press enter to delete the new blog post"); Console.ReadLine(); toDelete.Delete(); } } /** Get the comments feed URI for the desired blog entry. */ static Uri SelectBlogEntry(Service service, Uri blogPostUri) { Console.WriteLine("\nPlease select a blog entry on which to comment."); FeedQuery query = new FeedQuery(); query.Uri = blogPostUri; AtomFeed feed = service.Query(query); Uri commentPostUri = null; if (feed != null) { foreach (AtomEntry entry in feed.Entries) { // Print out the title of the Blog Console.WriteLine(" Blog entry title: " + entry.Title.Text); Console.Write(" Post a comment on this entry? (y/n): "); if (Console.ReadLine().Equals("y")) { // Create the Post URL for adding a comment by finding this entry's id number. // Find the href in the link with a rel pointing to the blog's feed. for (int i = 0; i < entry.Links.Count; i++) { if (entry.Links[i].Rel == "edit") { string commentUriStart = Regex.Replace(blogPostUri.ToString(), "/posts/default", ""); string selfLink = entry.Links[i].HRef.ToString(); string entryId = Regex.Replace(selfLink, blogPostUri.ToString() + "/", ""); // Build the comment URI from the blog id in and the entry id. commentPostUri = new Uri(commentUriStart + "/" + entryId + "/comments/default"); Console.WriteLine(" Your new comments will be sent to " + commentPostUri.ToString()); return commentPostUri; } } } } } return commentPostUri; } static AtomEntry PostNewComment(Service service, Uri commentPostUri) { Console.WriteLine("\nCommenting on a blog post"); AtomEntry postedComment = null; if (commentPostUri != null) { // Add a comment. AtomEntry comment; comment = new AtomEntry(); comment.Title.Text = "This is my first comment"; comment.Content.Content = "This is my first comment"; comment.Authors.Add(new AtomPerson()); comment.Authors[0].Name = "Blog Author Name"; postedComment = service.Insert(commentPostUri, comment); Console.WriteLine(" Result's title: " + postedComment.Title.Text); } return postedComment; } static void ListEntryComments(Service service, Uri commentUri) { if (commentUri != null) { Console.WriteLine("\nRetrieving all blog post comments"); // Retrieve all comments on a blog entry FeedQuery query = new FeedQuery(); Console.WriteLine(" Query URI: " + commentUri.ToString()); query.Uri = commentUri; AtomFeed feed = service.Query(query); foreach (AtomEntry entry in feed.Entries) { Console.WriteLine(" Comment Title: " + entry.Title.Text); } } } static void DeleteComment(AtomEntry commentEntry) { Console.WriteLine("\nDeleting the comment"); if (commentEntry != null) { // Delete the comment. Console.WriteLine(" Press enter to delete the new comment post"); Console.ReadLine(); commentEntry.Delete(); } } static void Main(string[] args) { Service service = new Service("blogger", "blogger-example"); // ClientLogin using username/password authentication string username; string password; if (args.Length != 2) { Console.WriteLine("Usage: BloggerDevSample.exe <username> <password>"); return; } else { username = args[0]; password = args[1]; } service.Credentials = new GDataCredentials(username, password); ListUserBlogs(service); Uri blogPostUri = SelectUserBlog(service); AtomEntry createdEntry = PostNewEntry(service, blogPostUri); PostAndDeleteNewDraftEntry(service, blogPostUri); ListBlogEntries(service, blogPostUri); ListBlogEntriesInDateRange(service, blogPostUri); AtomEntry editedEntry = EditEntry(createdEntry); DeleteEntry(editedEntry); Uri commentPostUri = SelectBlogEntry(service, blogPostUri); AtomEntry commentEntry = PostNewComment(service, commentPostUri); ListEntryComments(service, commentPostUri); DeleteComment(commentEntry); Console.WriteLine("Press enter to quit"); Console.ReadLine(); } } }

Saturday, June 26, 2010

Remoting Exception "[...] is not registered for activation"

RemotingException "[...] is not registered for activation"

I had to write something about it, because I was stuck for a whole hour and couldn't google anything useful.

It happens when the Client is trying to create a new remoting class "X".
The Server, by mistake, registered a remoting class "Y".

The classes must have the same name. Fix the class name.
That's it.