mike-obrien.net Resume Blog Labs
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]  | 
Monday, January 29, 2007

There is a new version of the Hid Library in the labs. It has been converted to .NET 2.0 and includes a bug fix. This bug fix involved how the vendor and product id were cast in the structure consumed by the Hid API. So some devices like Logitec's gamepads would not be recognized by their product and vendor id's. Now that issue is resolved. N-joy!

USB Hid Device Library

.NET | C# | USB HID | VB.NET
Monday, January 29, 2007 10:36:12 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [27]  |