// I decided that I shall put an end to that.
// Yet, I am no factory of coolness, but I figured my favorite buddy,
// "fortune" will help me out a little.
// By the way, this tool can definitely be done much better with regard
// to the way it updates the MSN, but hey, I just wanted to play with
// C#. My first time :P
// BTW, the MSN thing works only if you have your MSN not minimized PLUS
// the toolbar showing. (LAME! I know.)
// If you really want to do it right, use http://www.xihsolutions.net/dotmsn/
// and send me the code ;) bhtek@yahoo.com
using Microsoft.Win32; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Automation; using System.Runtime.InteropServices; namespace ZenStatusUpdater { class Program { [DllImport("USER32.DLL", EntryPoint = "FindWindowA", CallingConvention = CallingConvention.StdCall)] private static extern IntPtr FindWindow(string sClassName, string sWindowName); [DllImport("USER32.DLL", EntryPoint = "PostMessageA", CallingConvention = CallingConvention.StdCall)] private static extern bool PostMessage(IntPtr hWnd, uint iMsg, long wParam, long lParam); static void exploreElement(AutomationElement sub) { foreach (AutomationProperty prop in sub.GetSupportedProperties()) { Console.WriteLine("\tProp[" + prop.ProgrammaticName + "]: " + sub.GetCurrentPropertyValue(prop)); } foreach (AutomationPattern pat in sub.GetSupportedPatterns()) { Console.WriteLine("\tPat[" + pat.ProgrammaticName + "]"); } } static void explore(AutomationElement el) { Console.WriteLine("Self..."); exploreElement(el); foreach (AutomationElement sub in el.FindAll(TreeScope.Descendants, Condition.TrueCondition)) { Console.WriteLine("Sub..."); exploreElement(sub); } } static void Main(string[] args) { String fortune = null; int tries = 0; do { fortune = GetFortune(); tries++; } while (fortune.Length > 130); Console.WriteLine("Try #" + tries + ": " + fortune); updateMsnStatus(fortune); updateYahooStatus(fortune); System.Threading.Thread.Sleep(5000); } protected static void updateYahooStatus(String fortune) { // Get the current signed in user // string sUserName = "bhtek"; Console.WriteLine("The currently logged in user is " + sUserName); // Now open the current user's profile and set the current status message, pass true to // OpenSubKey to request write access RegistryKey keyYahooCustomMessages = Registry.CurrentUser.OpenSubKey("Software\\Yahoo\\Pager\\profiles\\" + sUserName + "\\Custom Msgs", true); // Set the 5th message, seems like yahoo messenger has the functionality to move the newly set // message up as the first one. String status = fortune; keyYahooCustomMessages.SetValue("5", status); byte[] statusBin = (new ASCIIEncoding()).GetBytes(status); keyYahooCustomMessages.SetValue("5_bin", (byte[])statusBin); keyYahooCustomMessages.Close(); // We are done setting the value in the registry. We now need to notify y! of this change // // Find the yahoo messenger window and sent it the notification // 0x111: WM_COMMAND // 0x188: Code 392 IntPtr hWndY = FindWindow("YahooBuddyMain", null); System.Diagnostics.Debug.WriteLine("Find window got: " + hWndY.ToString()); PostMessage(hWndY, 0x111, 0x188, 0); } protected static void updateMsnStatus(String fortune) { AutomationElementCollection msnWindows = AutomationElement.RootElement.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "MSBLWindowClass")); if (msnWindows.Count > 1) { foreach (AutomationElement potentialMsn in msnWindows) { exploreElement(potentialMsn); } return; } AutomationElement msn = msnWindows[0]; msn.SetFocus(); AutomationElement tools = msn.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.AccessKeyProperty, "Alt+T")); ExpandCollapsePattern toolsPat = (ExpandCollapsePattern)tools.GetCurrentPattern(ExpandCollapsePattern.Pattern); toolsPat.Expand(); AutomationElement options = tools.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "Options...")); InvokePattern optionsPat = (InvokePattern)options.GetCurrentPattern(InvokePattern.Pattern); optionsPat.Invoke(); AutomationElement optionsWindow = AutomationElement.RootElement.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "Options")); AutomationElement personalMessage = optionsWindow.FindFirst(TreeScope.Descendants, new AndCondition( new PropertyCondition(AutomationElement.ClassNameProperty, "RichEdit20W"), new PropertyCondition(AutomationElement.NameProperty, "Type a personal message for your contacts to see:") ) ); ValuePattern personalMessagePat = (ValuePattern)personalMessage.GetCurrentPattern(ValuePattern.Pattern); personalMessagePat.SetValue(fortune); AutomationElement ok = optionsWindow.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "OK")); InvokePattern okPat = (InvokePattern)ok.GetCurrentPattern(InvokePattern.Pattern); okPat.Invoke(); } private static String GetFortune() { System.Diagnostics.Process process = new System.Diagnostics.Process(); process.StartInfo.FileName = "c:\\cygwin\\bin\\fortune.exe"; process.StartInfo.RedirectStandardOutput = true; process.StartInfo.UseShellExecute = false; process.Start(); String fortune = process.StandardOutput.ReadToEnd(); fortune = System.Text.RegularExpressions.Regex.Replace(fortune, "\\s+", " "); return fortune; } } }