Back in the mid 90's, I hypothesised that everybody had a distinctive pattern to the way that they typed specific words. The pattern that I typed my password was predictable and consistant. Meaning that if my password was "toyota", the time it took me to type the letters "t" and "o" was relatively static, but would be completely different from someone else typing the same word. So my idea was to build a product that added keyboard recoginition as another layer of authentication. With this technique, I could tell you my password and unless you were a proficient percussionist, you wouldn't be able to autheniticate with my credentials. I did some prototypes, writing a Gina dll and tested with a few people, but before I took the time to refine it, this company published their implementation.
Today I read of a new technique (link) that uses a microphone to listen to someone typing. Apparently, by recording the sound of someone typing, they are able to reconstruct the keys that were pressed. A new reason to be paranoid...
I've given a introductory talk on Code Access Security a few times now. As I'm showing all the pieces from an administrative point of view (Code Groups, PermissionSets), and I go to create a code group, there is an option in the wizard that allows you to import the settings from an XML file. People listening to my talk always, without fail, ask, "How can I generate that XML file". It's fustrating, because there is no clear way to do. No menu option, no command line utility. I alway mean to research how to do it, but never seem to find the time. A couple of nights ago, I looked into it. It turns out on each PermissionSet, or CodeGroup, there is a ToXml method. Since it appears the only way to get the XML is using that method, I wrote a utility that will export the XML to a file. You can download it here.

Arg!! Serves me right for not reading the documentation and assuming the way a component works. I have a test framework that I use to generate random data when running unit tests on the data layer. I don't care what the data looks like as long as data is in fact saved. I use Random.Next to get a value that I use for a variety of purposes: Getting a letter, a number, or a boolean value. To get a random boolean value, I was using this code:System.Random r = new Random();
bool tstResult = r.Next(0,1) ==0 ? true : false; The problem is that Random.Next will return a value >= the first parameter and < the second parameter. So you can see that my routine always returns true. I had assumed that the arguments were the range of numbers you were interested in.
There are a lot of areas in the .NET framework that I haven't paid attention to because I don't have come across a need for a particular area (the WMI stuff) and/or the area looked somewhat complicated. In the XML Serialization engine, there is support for "Overrides". The serialization that I had done to date had worked fine, so I glossed over these objects when I was doing research.
I've written a data layer for my current project. It's a pretty robust data layer if I do say so myself. It has support for parent/child relationships, data transactions, delay loading, cascading deletes, exports to datasets and it's fully generated using a code generator (MyGeneration).... It's really the Cadillac of data layers.
When an object is serialized, I prevent the serialization of child objects by adding the [XMLIgnore] attribute to the child collection properties. I do this for performance and size reasons. Because the data layer is delay loaded, the collection might not be populated yet, causing tremendous database activity when a developer decides to serialize the object. Also, if you serialize an object high in the hierarchy, you would end up getting a hugely sized piece of XML. The children of the children of the children would be included in the document. After patting myself on the back for writing a fully featured, lightweight, fast and consistent data layer quickly with relatively few defects, the need came down for the objects to include all of their children in special circumstances... But only select child objects, not all.
I gave this some thought over the weekend and resigned myself to the fact that I was going to have to write some specialized method that serialized each object individually and then molded all the results into one big XML document. After doing some more reading, I came across the XmlAttributeOverrides object. This object allows you to selectively override XML serialization attributes that you set for specific properties. Using this object, I created a serializer, told it which additional properties I wanted serialized, and BAM!.. Done. //Set up overrides
XmlAttributeOverrides overrides = new XmlAttributeOverrides();
//ChildItems
XmlAttributes dontIgnore = new XmlAttributes();
dontIgnore.XmlIgnore=false;
overrides.Add(typeof(ParentObject),"ChildItems",dontIgnore);
XmlSerializer xs = new XmlSerializer(typeof(ParentObject),overrides);
I was troubleshooting some versioning problems we were having with a built; checking versions, strong name, modified dates... One of the assemblies I came across had an assemblyversion of 0.0.0.0 . I thought that was kind of funny, normally you see files with 1.0.0.0 or 0.9.0.0 or 1.0.12424.53264 . After researching it, the reason this assembly had zeros for the version is because the developer removed AssemblyInfo.cs from the project. This caused the assembly to be built without the AssemblyVersion attribute, leaving it with the default 0.0.0.0 version.
Just an interesting observation that I found when looking at some code using reflector. If you have a switch statement on a string, and there is a small set of cases, (<~10), the switch is changed to a series of if/else statements. If your list is more than 10, it creates a hashtable, and inserts all the strings. Then using the expression value it find the index of the value in the hashtable and uses that as its key. I'm sure this is done for a performance reason, but I couldn't speculate as to what it was. By looking at this, it would seem to be that it is best to use enumerations, rather than hardcoded strings wherever possible.Decompiled Switch statement with 5 cases public string SelectILTest5(string input)
{
string text2;
if ((text2 = input) != null)
{
text2 = string.IsInterned(text2);
if (text2 != "a1")
{
if (text2 == "a2")
{
return "a2";
}
if (text2 == "a3")
{
return "a3";
}
if (text2 == "a4")
{
return "a4";
}
if (text2 == "a5")
{
return "a5";
}
}
else
{
return "a1";
}
}
return "";
}Decompiled Switch statement with 15 cases(C#)
public string SelectILTest15(string input)
{
switch (input)
{
case "a1":
{
return "a1";
}
case "a2":
{
return "a2";
}
case "a3":
{
return "a3";
}
case "a4":
{
return "a4";
}
case "a5":
{
return "a5";
}
case "a6":
{
return "a6";
}
case "a7":
{
return "a7";
}
case "a8":
{
return "a8";
}
case "a9":
{
return "a9";
}
case "a10":
{
return "a10";
}
case "a11":
{
return "a11";
}
case "a12":
{
return "a12";
}
case "a13":
{
return "a13";
}
case "a14":
{
return "a14";
}
case "a15":
{
return "a15";
}
}
return "";
}Decompiled Switch statement with 15 cases (IL)
.method public hidebysig instance string SelectILTest15(string input) cil managed
{
// Code Size: 524 byte(s)
.maxstack 4
.locals init (
string text1,
object obj1)
L_0000: volatile
L_0002: ldsfld [mscorlib]System.Collections.Hashtable <PrivateImplementationDetails>::$$method0x6000015-1
L_0007: brtrue L_0124
L_000c: ldc.i4.s 30
L_000e: ldc.r4 0.5
L_0013: newobj instance void [mscorlib]System.Collections.Hashtable::.ctor(int32, float32)
L_0018: dup
L_0019: ldstr "a1"
L_001e: ldc.i4.0
L_001f: box int32
L_0024: call instance void [mscorlib]System.Collections.Hashtable::Add(object, object)
L_0029: dup
L_002a: ldstr "a2"
L_002f: ldc.i4.1
L_0030: box int32
L_0035: call instance void [mscorlib]System.Collections.Hashtable::Add(object, object)
L_003a: dup
L_003b: ldstr "a3"
L_0040: ldc.i4.2
L_0041: box int32
L_0046: call instance void [mscorlib]System.Collections.Hashtable::Add(object, object)
L_004b: dup
L_004c: ldstr "a4"
L_0051: ldc.i4.3
L_0052: box int32
L_0057: call instance void [mscorlib]System.Collections.Hashtable::Add(object, object)
L_005c: dup
L_005d: ldstr "a5"
L_0062: ldc.i4.4
L_0063: box int32
L_0068: call instance void [mscorlib]System.Collections.Hashtable::Add(object, object)
L_006d: dup
L_006e: ldstr "a6"
L_0073: ldc.i4.5
L_0074: box int32
L_0079: call instance void [mscorlib]System.Collections.Hashtable::Add(object, object)
L_007e: dup
L_007f: ldstr "a7"
L_0084: ldc.i4.6
L_0085: box int32
L_008a: call instance void [mscorlib]System.Collections.Hashtable::Add(object, object)
L_008f: dup
L_0090: ldstr "a8"
L_0095: ldc.i4.7
L_0096: box int32
L_009b: call instance void [mscorlib]System.Collections.Hashtable::Add(object, object)
L_00a0: dup
L_00a1: ldstr "a9"
L_00a6: ldc.i4.8
L_00a7: box int32
L_00ac: call instance void [mscorlib]System.Collections.Hashtable::Add(object, object)
L_00b1: dup
L_00b2: ldstr "a10"
L_00b7: ldc.i4.s 9
L_00b9: box int32
L_00be: call instance void [mscorlib]System.Collections.Hashtable::Add(object, object)
L_00c3: dup
L_00c4: ldstr "a11"
L_00c9: ldc.i4.s 10
L_00cb: box int32
L_00d0: call instance void [mscorlib]System.Collections.Hashtable::Add(object, object)
L_00d5: dup
L_00d6: ldstr "a12"
L_00db: ldc.i4.s 11
L_00dd: box int32
L_00e2: call instance void [mscorlib]System.Collections.Hashtable::Add(object, object)
L_00e7: dup
L_00e8: ldstr "a13"
L_00ed: ldc.i4.s 12
L_00ef: box int32
L_00f4: call instance void [mscorlib]System.Collections.Hashtable::Add(object, object)
L_00f9: dup
L_00fa: ldstr "a14"
L_00ff: ldc.i4.s 13
L_0101: box int32
L_0106: call instance void [mscorlib]System.Collections.Hashtable::Add(object, object)
L_010b: dup
L_010c: ldstr "a15"
L_0111: ldc.i4.s 14
L_0113: box int32
L_0118: call instance void [mscorlib]System.Collections.Hashtable::Add(object, object)
L_011d: volatile
L_011f: stsfld [mscorlib]System.Collections.Hashtable <PrivateImplementationDetails>::$$method0x6000015-1
L_0124: ldarg.1
L_0125: dup
L_0126: stloc.1
L_0127: brfalse L_0202
L_012c: volatile
L_012e: ldsfld [mscorlib]System.Collections.Hashtable <PrivateImplementationDetails>::$$method0x6000015-1
L_0133: ldloc.1
L_0134: call instance object [mscorlib]System.Collections.Hashtable::get_Item(object)
L_0139: dup
L_013a: stloc.1
L_013b: brfalse L_0202
L_0140: ldloc.1
L_0141: unbox int32
L_0146: ldind.i4
L_0147: switch (L_018a, L_0192, L_019a, L_01a2, L_01aa, L_01b2, L_01ba, L_01c2, L_01ca, L_01d2, L_01da, L_01e2, L_01ea, L_01f2, L_01fa)
L_0188: br.s L_0202
L_018a: ldstr "a1"
L_018f: stloc.0
L_0190: br.s L_020a
L_0192: ldstr "a2"
L_0197: stloc.0
L_0198: br.s L_020a
L_019a: ldstr "a3"
L_019f: stloc.0
L_01a0: br.s L_020a
L_01a2: ldstr "a4"
L_01a7: stloc.0
L_01a8: br.s L_020a
L_01aa: ldstr "a5"
L_01af: stloc.0
L_01b0: br.s L_020a
L_01b2: ldstr "a6"
L_01b7: stloc.0
L_01b8: br.s L_020a
L_01ba: ldstr "a7"
L_01bf: stloc.0
L_01c0: br.s L_020a
L_01c2: ldstr "a8"
L_01c7: stloc.0
L_01c8: br.s L_020a
L_01ca: ldstr "a9"
L_01cf: stloc.0
L_01d0: br.s L_020a
L_01d2: ldstr "a10"
L_01d7: stloc.0
L_01d8: br.s L_020a
L_01da: ldstr "a11"
L_01df: stloc.0
L_01e0: br.s L_020a
L_01e2: ldstr "a12"
L_01e7: stloc.0
L_01e8: br.s L_020a
L_01ea: ldstr "a13"
L_01ef: stloc.0
L_01f0: br.s L_020a
L_01f2: ldstr "a14"
L_01f7: stloc.0
L_01f8: br.s L_020a
L_01fa: ldstr "a15"
L_01ff: stloc.0
L_0200: br.s L_020a
L_0202: ldstr ""
L_0207: stloc.0
L_0208: br.s L_020a
L_020a: ldloc.0
L_020b: ret
}
We're in the early stages of a project I'm currently working on and we're starting to see some performance concerns. Since the piece that I wrote (The data access layer) is used pretty heavily, I decided to profile the application to see if there were any glaring bottlenecks.
I downloaded nprof from SourceForge and used that as the profiler. Overall, it was pretty easy to setup and use. My perception is that profiling with nprof didn’t add a lot of overhead to the profiled process.
When you’re done running a profile, you’re left with some pretty good statistics: # times a method was called, total percentage of total time spent in that method, total percentage time spent in the child method. These are all broken out by thread. You can view who called a particular method and what methods it calls. It would be nice if there was more information about the thread, such as the life of the thread and so forth.
Turns out there is a measurable amount of time in my data layer creating temporary serialization assemblies, so I’m going to rework it to use this method by Daniel Cazzulino
On the whole, it is a great tool. It’s unfortunate that there hasn’t been any refinement to it lately.
Code Camp IV, held this past weekend was pretty cool. It was amazing to see the incredible turnout. The support the Boston community has for these types of events... All the attendees I talked with loved the sessions. One of the main themes I kept hearing was, "I know something about topic XYZ. But you never know what you don't know. The session gave me a lot more depth."
I delivered three talks that went over reasonably well. It was cool to meet some of my fellow user group leaders like Julia Lerman and Jason Haley.
Can't wait for Code Camp V!
|
Copyright © 2008 Phil Denoncourt III. All rights reserved.
DasBlog 'Portal' theme by Johnny Hughes.
Pick a theme:
|
|
|