mike-obrien.net Resume Blog Labs
Thursday, May 31, 2007

A while ago I posted a link to MIT's Open Courseware (OCW) site. Recently I have begun to make use of it and wanted to share some of what I have found. First of all, it rocks! It really is a great resource, especially for those who want to learn about a subject and would like to do self study. I didn’t realize this earlier but a number of the courses also publish videos of the lectures. For example 3.091, "Introduction to Solid State Chemistry" has all 35 lectures posted, thats almost 30 hours of lecture time! These videos (If available) can be found possibly in 3 locations, so keep that in mind. The first is on the OCW site. Browse to the course you are interested in, for example Introduction to Solid State Chemistry. Under the "Lecture Notes" (This label may be a little different between courses) section you will find the video streams and the lecture notes. The second location is on the regular class page. 3.091 has a tab called "Videos" and another called "Archives", both have links to lecture videos and notes. Now the third place you can check, if you want to easily download the videos, is Google Video. Searching for "3.091" brings up all but 2 of the course videos which can be downloaded in in a format that can be played by your video IPod. Actually Google Video has over 450 MIT Lectures available for download! There are also nearly 300 UC Berkeley lectures as well. If you want to download any of the lecture videos (to your hard disk) that are offered as a stream on the MIT website you can use a program like FlashGet to save the stream as a file and then convert the file to what you want. The MIT site publishes RealVideo streams (That use the RTSP protocol).

Other courses that offer video lectures are (To name a few):

Physics - Electricity and Magnetism
Physics - Vibrations and Waves
Physics - Classical Mechanics
Physics - General Relativity
Mathematics - Differential Equations
Mathematics - Linear Algebra
Chemistry - Principles of Chemical Science
Chemistry - Solid Sate Chemistry
Biology - Introductory Biology
Computer System Engineering
Circuits and Electronics
Atomistic Computer Modeling of Materials
Media, Education, and the Marketplace
Electromagnetics and Applications

You may want to look on the course listing to see if there is a newer version of the course as newer ones are periodically added.

The OCW site also offers the course syllabus, study materials, readings, exams and a number of other resources. They offer the option to download the entire course as a zip file so that you don’t have to download the resources individually.

Now a few words about the "Introduction to Solid State Chemistry" (3.091) course... If you are interested in learning about chemistry I would highly recommend the 3.091 course. Donald Sadoway is the lecturer for this course and he does an amazing job! You can tell he loves the subject and he knows it very well. He has a great sense of humor and he really makes the material come alive (At least for me anyways). This course lays an excellent foundation for other areas of study.

Thursday, May 31, 2007 3:48:07 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [2]  | 
Thursday, April 12, 2007

So I am trying to write log information to an XML document using the XmlTextWriter.  When it reaches a certian size I want it closed out and archived. What I mean by "closed out" is that while the log file is "open" the root element is not closed so that I can keep adding entries over a period of time. In other words:

<?xml version="1.0"?>
<log>
    <entry date="1/1/2007">Yada yada yada</entry>
    <entry date="1/1/2007">Yada yada yada</entry>
    ...


Then once its full I will write the closing root element and rename it:

<?xml version="1.0"?>
<log>
    <entry date="1/1/2007">Yada yada yada</entry>
    <entry date="1/1/2007">Yada yada yada</entry>
    ...
    <entry date="1/1/2007">Yada yada yada</entry>
</log>

Well the XmlTextWriter automatically closes out all open elements when you close it. Looking in Reflector reveals what is happening behind the scenes:

public override void Close()
{
   try
   {
      this.AutoCompleteAll();
   }
   catch {}
   finally
   {
      this.currentState = State.Closed;
      this.textWriter.Close();
   }
}

First the AutoCompleteAll() method is called, then the underlying stream is closed. The AutoCompleteAll() method is as follows:

private void AutoCompleteAll()
{
   if (this.flush)
   {
      this.FlushEncoders();
   }
   while (this.top > 0)
   {
      this.WriteEndElement();
   }
}

Doesent look like there is any official way to explicitly close only the elements you want to close, its just automatically done for you when you close the writer. The only work around I could figure out is to explicitly close the elements I want closed, then close the base stream (Not the XmlTextReader). This works but IMO its a little hackey since the code in the Close() method could potentially change in the future and you could end up circumventing some code that you might want executed when your done with the reader.

.NET | C# | VB.NET | XML/XSL
Thursday, April 12, 2007 7:01:42 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  | 
Monday, March 26, 2007

I recently reconnected with my yearbook teacher from high school, Jonathon Siminoe, and learned that he is now teaching in Thailand. I highly recommend checking out his blog and short stories. He is an excellent writer and I find myself checking his blog every morning, coffee cup in hand, to read about his adventures in this Southeast Asian country. To whet your appetite, may I suggest Coffee House Run and Damn Shiny Car Wash? Great stuff!

Monday, March 26, 2007 2:12:49 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  | 
Friday, March 23, 2007

I have been working with the new custom configuration classes in .NET 2.0 and they really make creating custom xml configuration a snap. They are a little quirky to use at first but once you get past the initial learning curve they really make the job a lot easier.

One thing I really wanted to figure out is how to use these new classes to read files other than the default app/web.config. For example if you have one config file that might be shared between exes or if a config file is pulled from a URL. Its actually pretty easy to do.

First create your custom configuration file. It will look exactly the same as a web/app.config file except it will only contain your custom section(s). Create a section handler element identifying the custom section handler and the name of the section. Again, nothing different from doing this in the app/web.config.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
 <configSections>
  <section name="mySettings" type="CustomConfigHandler.MySettingSection, CustomConfigHandler"/>
 </configSections>
 <mySettings>
  <someSetting someAttribute="This is an attribute value from Settings1.config"/>
 </mySettings>
</configuration>

Next create a Configuration object that points to your file by passing in an ExeConfigurationFileMap with the ExeConfigFilename set.

// Create an exe file map containing the path to your config file
ExeConfigurationFileMap FileMap = new ExeConfigurationFileMap();
FileMap.ExeConfigFilename = "MySystem.config";

// Create a configuration object that is tied to your custom config file.
Configuration Config = ConfigurationManager.OpenMappedExeConfiguration(FileMap, ConfigurationUserLevel.None);

// Create the custom config section handler
MySettingSection MySettings = (MySettingSection)Config.GetSection("mySettings");

Console.WriteLine(MySettings.SomeSetting.SomeAttribute);


The entire source can be downloaded here:

ExternalConfigFile.zip (40.24 KB)
.NET | C# | Configuration | VB.NET
Friday, March 23, 2007 8:30:17 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  | 
Friday, March 16, 2007

This is a very moving photo essay on the after effects of Chernobyl. Very sad to see how children were affected.

http://inmotion.magnumphotos.com/essays/chernobyl.aspx

Friday, March 16, 2007 7:23:32 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [2]  | 
Tuesday, February 27, 2007

Nice little util to extract the boot sector from an ISO or disk. The home page is located here or you can download from the link below:

bbie.zip (18.83 KB)

Here are boot sectors for a couple of OS's:

WIN_ME.zip (717.94 KB)
WIN_XP_PRO.zip (1.09 KB)
WIN_SVR_2003.zip (1.1 KB)

OS
Tuesday, February 27, 2007 6:24:15 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  | 
Wednesday, February 14, 2007

I had a baffling problem arise today. Here is the scenario; I have a .NET WinForms app with a WebBrowser control. The WebBrowser control loads a web page that contains an embedded Flash movie. I need to send keystrokes to the Flash movie from the WinForms app. Now MS provides the SendKeys class under the Windows.Forms namespace for this very purpose, but in this instance it doesent pass them on to the Flash movie (Although it does pass them to HTML elements in the page). Hmmmmmm... A little digging in Reflector uncovers the reason. The SendKeys class internally calls the SetKeyboardState() native method to send the keyboard input. Here is what MSDN says about that call:

The SetKeyboardState function copies a 256-byte array of keyboard key states into the calling thread's keyboard input-state table. This is the same table accessed by the GetKeyboardState and GetKeyState functions. Changes made to this table do not affect keyboard input to any other thread.

I'm no expert on how embedded ActiveX controls work within a web page in IE but I bet the Flash control is not running in the same thread as the browser UI. And in the case of using the WebBrowser control, not in the UI thread of the WinForms app. So SendKeys will not be able to send keystrokes to embedded Flash in a WebBrowser control. Just a guess, but it seems that is what is happening here. Well, scratch that, I just checked Spy++ and everything is running under the WinForm UI thread including the Flash ActiveX control. So at this point I have no idea why SendInput() works but SetKeyboardState() doesent (And thus the SendKeys class), very strange indeed! If anyone knows for sure, please leave a comment! :)

So the other option is calling the SendInput method. FYI, this method supersedes the keybd_event method. Here is a sample of the code required to send keystrokes to the foreground window. Remember, you must make sure that the WebBrowser control has focus for it to receive the keystrokes (As does the Flash control in the web page, see further down for more info).

private void Main_Load(object sender, EventArgs e)
{
    WebBrowserControl.Navigate(@"file://C:\Temp\Flash.html");
    Timer.Enabled = true;
}

private int Index = 0;

private void Timer_Tick(object sender, EventArgs e)
{
    Index++;

    NativeMethods.INPUT[] structInput = new NativeMethods.INPUT[1];

    structInput[0] = new NativeMethods.INPUT();
    structInput[0].type = NativeMethods.INPUT_KEYBOARD;
    structInput[0].ki.wScan = 0;
    structInput[0].ki.time = 0;
    structInput[0].ki.dwFlags = 0;
    structInput[0].ki.dwExtraInfo = NativeMethods.GetMessageExtraInfo();
    structInput[0].ki.wVk = NativeMethods.VK_RIGHT;

    // Key up every other pass
    if (Index % 2 == 0)
    {
        structInput[0].ki.dwFlags = NativeMethods.KEYUP;
    }

    NativeMethods.SendInput(1, structInput, Marshal.SizeOf(structInput[0]));
}

The basic native method & struct declarations are as follows. PInvoke.NET has a nice definition of all of these.

public const int INPUT_KEYBOARD = 1;
public const int KEYUP = 2;

public const int VK_LEFT = 0x25;
public const int VK_UP = 0x26;
public const int VK_RIGHT = 0x27;
public const int VK_DOWN = 0x28;


[StructLayout(LayoutKind.Sequential)]
public struct MOUSEINPUT
{
    int dx;
    int dy;
    int mouseData;
    int dwFlags;
    int time;
    IntPtr dwExtraInfo;
}

[StructLayout(LayoutKind.Sequential)]
public struct KEYBDINPUT
{
    public short wVk;
    public short wScan;
    public int dwFlags;
    public int time;
    public IntPtr dwExtraInfo;
}

[StructLayout(LayoutKind.Sequential)]
public struct HARDWAREINPUT
{
    int uMsg;
    short wParamL;
    short wParamH;
}

[StructLayout(LayoutKind.Explicit)]
public struct INPUT
{
    [FieldOffset(0)]
    public int type;
    [FieldOffset(4)]
    public MOUSEINPUT mi;
    [FieldOffset(4)]
    public KEYBDINPUT ki;
    [FieldOffset(4)]
    public HARDWAREINPUT hi;
}

[DllImport("user32.dll", SetLastError = true)]
public static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);

[DllImport("user32.dll", SetLastError = false)]
public static extern IntPtr GetMessageExtraInfo();

The only other thing you need to do to make this completely automated is to set focus on the Flash movie in the web page using JavaScript. Simply call the focus method of the Flash control as follows:

window.document.MyFlash.focus();

The entire project can be downloaded here.

.NET | C# | Flash | Win32 API
Wednesday, February 14, 2007 10:31:15 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [4]  | 
Tuesday, February 06, 2007

Zipped source files are getting really lame! I found a hosted Subversion solution (wush.net) for about 7 bucks a month and am hosting all the source code for the Labs there. The setup was very simple and I was up and running in about 15 minutes. The starter package gives you 1 repository and 100mb of space, plenty for personal use. You can browse the repository here with a web browser, but the best way to access it is using a Subversion client such as TortoiseSVN.

Tuesday, February 06, 2007 5:58:42 AM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  | 

For those of you who still use SMS Installer the following script enables you to detect if a certian version of the .NET Framework is installed on the machine. Just switch over to the "Script Editor", copy the text from the following file and paste it where you want it. Basically it only extracts and runs the redist if the desired version is not installed. This makes the setup run a lot faster for users who will already have a particular version of the framework installed.

DOTNETSMS.txt (6.23 KB)
Tuesday, February 06, 2007 5:49:33 AM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  |