VirtualBox Config Workaround

I have been having some trouble with VirtualBox since I upgraded some time ago. Every time I close a VM VirtualBox places an invalid character (for an XML-parser anyway) in the config file, rendering the file unreadable for VirtualBox the next time I want to start it.
So I did this naïve Python script to fix it.

filename = "/home/user/VirtualBox VMs/MyMachine/MyMachine.vbox" 
istr = '"/VirtualBox/GuestAdd/VersionEx"'
jstr = 'value="'
kstr = '"'

fi = open(filename)
s = fi.read()
fi.close()

i = s.index(istr) + len(istr)
j = s.index(jstr, i) + len(jstr)
k = s.index(kstr, j)
t = s[:j] + s[k:]

fi = open(filename, "w+")
fi.write(t)
fi.close()

Read from WebClient with the right encoding

I’ve had some encoding trouble with the DownloadString(Async) method on the WebClient class, so I wrote my own encoding detection to get a string with the correct encoding.

readonly static Regex m_enc = new Regex(
    @"charset=(?'encoding'[^\s]+)",
    RegexOptions.Compiled | RegexOptions.CultureInvariant
        | RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase);

static string GetString(WebHeaderCollection responseHeaders, byte[] data)
{
    string html;
    Encoding encoding = null;
    try
    {
        string contentEncoding = responseHeaders[HttpResponseHeader.ContentEncoding];
        if (string.IsNullOrEmpty(contentEncoding))
            contentEncoding 
                = m_enc.Match(responseHeaders[HttpResponseHeader.ContentType])
                        .Groups["encoding"]
                        .Value;
        encoding = Encoding.GetEncoding(contentEncoding);
    }
    catch (Exception)
    {
        try
        {
            using (var ms = new MemoryStream(data))
            {
                using (var xmlreader = new XmlTextReader(ms))
                {
                    xmlreader.MoveToContent();
                    encoding = xmlreader.Encoding;
                }
            }
        }
        catch (Exception)
        {
        }
    }
    using (var ms = new MemoryStream(data))
    using (var sr = encoding != null 
        ? new StreamReader(ms, encoding) 
        : new StreamReader(ms, true))
        html = sr.ReadToEnd();
    return html;
}

Iterate folders non-recursively

Here are a few methods to help iterate complete directory trees and the files in them without using recursive method calls. The directories are read one at a time to keep memory usage at a minimum. These restrictions enables iterating trees in very large file shares.

static IEnumerable<string> GetDirectories(string startDirectory)
{
    var dirsToVisit = new Stack<string>();
    dirsToVisit.Push(startDirectory);
    while (dirsToVisit.Count > 0)
    {
        string dir = dirsToVisit.Pop();
        yield return dir;
        string[] subDirs;
        try
        {
            subDirs = Directory.GetDirectories(dir);
        }
        catch (UnauthorizedAccessException)
        {
            subDirs = new string[0];
        }
        foreach (var subDir in subDirs)
            dirsToVisit.Push(subDir);
    }
}

static IEnumerable<string> GetFiles(string startDirectory)
{
    foreach (var dir in GetDirectories(startDirectory))
    {
        string[] files;
        try
        {
            files = Directory.GetFiles(dir);
        }
        catch (UnauthorizedAccessException)
        {
            files = new string[0];
        }
        foreach (var file in files)
            yield return file;
    }
}

NLog configuration file

I often use NLog for diagnostic tracing in e.g. services. NLog is very much like log4net (log4j for .net) except that it is still being maintained, was written for .NET and features a very flexible end extensible logging framework.
See also the post about interceptors.
This is an example of a nlog.config I recently used for a service to get asynchronous logging and detailed exception information in a concise and structured format.

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <targets>
    <target name="asyncFile" xsi:type="AsyncWrapper">
      <target name="logfile" xsi:type="File" fileName="${environment:variable=ALLUSERSPROFILE}\MYSERVICE\Logs\${shortdate}.txt">
        <layout xsi:type="CSVLayout" delimiter="Tab">
          <column name="time" layout="${date:format=HH\:mm\:ss.ff}" />
          <column name="thread" layout="${threadid}" />
          <column name="level" layout="${level}" />
          <column name="idenity" layout="${windows-identity}" />
          <column name="message" layout="${message}" />
          <column name="exception" layout="${exception:format=type,message,method:maxInnerExceptionLevel=5;
innerFormat=shortType,message,method }" />
        </layout>
      </target>
    </target>
  </targets>
  <rules>
    <logger name="*" minLevel="Debug" writeTo="logfile" />
  </rules>  
</nlog>
Follow

Get every new post delivered to your Inbox.