Ivan Krivyakov's Blog

Premature optimization is the root of all evil

December 14, 2009

Scripting .NET Apps

What are the options? This is what I found so far:
* Dynamically compile C# or VB.NET code into an assembly and execute it – I used this route before
* Implement Windows Scripting Host interfaces. Found a couple of links (see below), but no full implementation
* Use DLR
* Use a number of “Script.NET” like projects

Scripting using WSH:
CodeProject: C# interface defintions
DDJ article series on building Active Scripting Host in C#
In particular, part four seems to be of interest.

Unfortunately, there is no ready-to-use download, and it seems like a lot of work. Yes, I am a lazy guy and I have a tight deadline :)

UPD: found 8 year old VB.NET scripting sample ScriptPad from MSDN

December 13, 2009

Poltergeist? No, Vista Data Redirection

As I was working with a Vista machine, I started noticing that occasionally when I make a changes to some files, only certain programs can see them, but others can’t. Most often this happened with files in the “Program Files” directory. It was so weird, that initially I did not believe my eyes. You open a file in console-based FAR manager, and you see one thing. You open it in notepad – completely different thing.

It went on for a while, until the mystery affected an important config file. I spent several hours trying to understand what’s going on, and now it was personal.

It turns out that Vista Vista “virtualizes” write access to otherwise unwritable files in system directories, but it does it in a very peculiar way.

Apparently, Microsoft developers thought along these lines: OK, we must lock down the Program Files and other system directories, but many legacy applications do write their logs to Program Files. We don’t want them to break, do we? So, let’s quietly redirect their failed writes to a safe user-specific location. But of course, we can’t do that for all applications, only for the old ones.

This works, but it creates quite astonishing results. E.g., you legacy claims it created a log file in c:\program files\myapp\important.log. You can smell it, you can feel it, you can even open it inside the application if it has such a capability. But if you go to Windows Explorer or Notepad, the file is simply not there! Poltergeist? No, data redirection. The file is actually in AppData\Local\VirtualStore in your user profile. Windows Explorer and Notepad are obviously designed for Vista, so they see the real, unmodified version of the data.

As far as I understand, all programs are divided into “designed for Vista” and “legacy”. Programs designed for Vista do not require data redirection and thus see the real picture. When legacy programs try to write into an area such as “Program Files” that would fail, this write is redirected to the VirtualStore folder inside user profile. If the write would not fail, it is allowed to go through to “Program Files”. Only locally running programs are redirected.

Thus, it creates a number of astonishing inconsistencies.

  1. The changes made by your application are not visible to system programs, as described above.
  2. The same application sees different data when it runs in elevated “administrator” mode.
  3. If a legacy application accesses modified files via network, it will not see the unmodified data, since no redirection is performed for remote reads.
  4. Only unwritable files are redirected, files writable by non-administrators will be modified in place. If another user looks at the files, he will see some files modified, but not the others.

Furthermore, the config file that started this investigation was in ProgramData directory. This is a new directory in Vista, and no legacy program would write to it. Why data redirection is applied to this directory is yet another mystery.

December 12, 2009

Reading Larman: Iterative Process and “True Path”

Larman says (p. 22) that as the system goes through more iterations it converges “towards final requirements and design” and draws a wavy graph with the size of the waves diminishing with time. My experience seems to disagree with that. As long as the system is “alive” there is no such thing as ‘final requirements’: new features and requests are invented all the time. Occasionally they are just incremental, but frequently they change significant portions of existing functionality.

Reading Larman: to UP or not to UP

I bought Larman’s “Applying UML and Patterns” about a month ago, but had hard time getting to actually read it. This is my first note for a long time – I hope there will be more to follow.

He is promoting the [Rational] Unified Process (UP), but he is quite good in avoiding holy wars. He says (p. 18-19) that the UP is only an example, and you need to use some process to illustrate the techniques. Also, he says that the UP “combines commonly accepted best practices” and that the author “encourages clients to understand and adopt a blend of useful techniques from several methods, rather than a dogmatic ‘my method is better than your method’ mentality”.

This may be just a way to sweet talk opponents and play down the disagreements, but I do like it.

Minimizing Your Virtual PC Hard Drive

Just installed Microsoft Visual Studio 2010 Beta 2 in a virtual PC (Microsoft Virtual PC 2007). It is kinda slow, but it works.

In the process I created two “baseline” images – a “pure” Windows XP install, and the original VS 2010 just after the installation. What I found that the virtual hard drive size may increase considerably as you start using the system. Here’s the algorithm I used to minimize the size of the “baseline” file:

  1. Shut down the virtual PC
  2. Copy virtual hard drive to another file
  3. Edit your virtual PC settings to mount the copy as a second hard drive
  4. Run the virtual PC.
  5. Remove pagefile.sys from the copy. Make sure it does not end up in the recycle bin!
  6. Defragment the copy using Dave Whitney’s defragger (google it if the link is broken).
  7. Using CD menu of the Virtual PC mount “Virtual Disk Precompactor.iso” from “C:\Program Files\Microsoft Virtual PC\Virtual Machine Additions\” on your host system.
  8. The precompactor application by default zeroes out free space on all mounted hard disks. Stop it and use command line options to precompact only the second virtual hard disk.
  9. Shut down your virtual PC.
  10. From Virtual PC Console choose VHD wizard and compact the baseline disk.

These operations may take a while, but it is well worth it – I went from 4+GB image to 1.8GB.

Notwithstanding The Above…

I was downloading C# 4.0 feature list, and Microsoft presented me with a several page license document. Somehow, when I see words “nonwithstanding the above” in a text, I don’t expect anything good to come from it.

December 11, 2009

Public Classes, Protected Methods and Limitations of C# Visibility Control

I had an interesting problem today. I had a public class in my assembly called Session. It was a public class, but it used a lot of internal stuff in the implementation. It went something like this:

public class Session
{
    (public methods and properties here)

    private void HandleResponse(Response response) // Response class is internal
    {
        …
    }
}

Later I needed to split it into two classes: MarketDataSession and TradeSession. They have a lot in common, but they need to handle responses slightly differently. I decided to keep shared functionality in Session making it a base class. So, I modified Session like this:

public class Session
{
    (public methods and properties here)

    protected virtual void HandleResponse(Response response) // Response class is internal
    {
        …
    }
}

public class TradeSession : Session …
public class MarketDataSession : Session …

I immediately ran into trouble: inconsistent accessibility, Response class is less accessible then method HandleResponse. Indeed, HandleResponse is now a protected method of a public class, so theoretically it can be overriden outside of the assembly.

I could make Session an internal class, but public classes TradeSession and MarketDataSession are not allowed to derive from an internal class.

The only solution that allows me to keep Response class internal is to mark HandleResponse method as internal. This makes it invisible from outside of the assembly, but now it is wide open inside the assembly, which is also not so stellar.

There is another, rarely used access control option, protected internal, but it actually means protected OR internal, i.e. the method is accessible to anyone inside the assembly and to derived classes outside of the assembly.

What I need here is protected AND internal: accessible only to derived classes within the same assembly. AFAIK, this option exists in IL and in C++/CLI as private protected . Here’s a real example where it would be useful in C#.

Parsing .NET Enums: some unit tests

Of course, I had to verify that enum parsing really works as they say it does (see previous post). So I wrote a little unit test. All tests in this class pass:

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace UnitTests
{
    [TestClass]
    public class EnumParsingTest
    {
        enum Test
        {
            Foo = 10,
            Bar = 20
        }

        [TestMethod]
        public void ParseStringValue()
        {
            Assert.AreEqual(Test.Foo, Enum.Parse(typeof(Test), "Foo"));
        }

        [TestMethod]
        public void ParseIntValue()
        {
            Assert.AreEqual(Test.Foo, Enum.Parse(typeof(Test), "10"));
        }

        [TestMethod]
        public void ParseUnrelatedIntValue()
        {
            Assert.AreEqual((Test)40, Enum.Parse(typeof(Test), "40"));
        }

    }
}

Parsing .NET Enums

I needed the following functionality:
- class MarketSession has property MarketType (options, futures, …)
- this property is an enum, but in the underlying protocol it is actually a number
- in my Spring.NET configuration I wanted to specify a string which would be either a symbolic name or a number; one would use symbolic names for defined market types and numbers for the market types that did not make it yet into the enum

I was pleasantly surprised to find out, that the built-in Enum.Parse() provides exactly what I need. You can give it either a symbolic name, or a numeric value, and it will work fine, even if the value is out of range.

enum MarketType
{
    Futures = 10,
    Options = 20
}

public class MyClass
{
    MarketType _marketType;

    public string MarketType
    {
        get { return _marketType.ToString(); }
        set { _marketType = Parse<MarketType>(value); }
    }

    private static T Parse<T>(string s)
    {
        return (T)Enum.Parse(typeof(T), s);
    }
}

December 2, 2009

Where to put log files in Windows?

Following up on the previous post. Linux (and UNIX in general) has a centralized location for logs: that’s /var/log. Windows does not. The original idea was that you are supposed to use Event Log, which is uniform, centralized and well understood. The problem is, however, that it is a proprietary format, it requires a special viewer to see, non-trivial configuration steps to start writing, its API is cumbersome, slow, and buggy, et cetera, et cetera.

Writing log to plain text files is a deeply respected tradition that is not so easy to uproot. So, where does one put text log files on Windows? Many programs put it in “Program Files” alongside the code. The trouble is, this is now a protected area, and writing to the “Program Files” folder is generally considered a bad idea. Microsoft teams themselves seem to have a disagreement on the log location. System Restore, for example, writes to c:\windows\logs, while WMI goes to c:\windows\system32\logfiles.

The newest trend is to put the logs in c:\programdata\programname, but this makes logs hard to find, since Windows versions prior to Vista did not have the “c:\ProgramData” directory.

The bottom line is, there is no simple answer and every man is for himself.