JohnMarkHowell Twitter
Tweets by JohnMarkHowell-
Recent Posts
Archives
- August 2014
- July 2014
- January 2013
- December 2012
- November 2012
- August 2012
- July 2012
- June 2012
- May 2012
- March 2012
- February 2012
- January 2012
- December 2011
- August 2011
- June 2011
- February 2011
- January 2011
- December 2010
- October 2010
- September 2010
- July 2010
- May 2010
- December 2009
- September 2009
- August 2009
- July 2009
- March 2009
- January 2009
- November 2008
- October 2008
- September 2008
- August 2008
- July 2008
- June 2008
- May 2008
- March 2008
- January 2008
- December 2007
- November 2007
- September 2007
- August 2007
- July 2007
- June 2007
- May 2007
- April 2007
- October 2006
- September 2006
- August 2006
- July 2006
- June 2006
- May 2006
- April 2006
- March 2006
- February 2006
- January 2006
- December 2005
- November 2005
- May 2005
Categories
Windows Installer 4.5 is now available!!!!!!
Sorry for the belated notice, this was turned loose on 6/3/08. Great news!!!!
Windows Installer 4.5 is now available!!!!!!
New and improved features in Windows Installer 4.5:
The following new and improved features have been implemented in Windows Installer 4.5.
Multiple package transaction
In a multiple package transaction, you can create a single transaction from multiple packages. In a multiple package transaction, a chainer is used to dynamically include packages in the transaction. If one or more of the packages do not install as expected, you can roll back the installation.
Embedded UI handler
You can embed a custom user interface (UI) handler in the Windows Installer package. This makes a custom UI easier to integrate. You can also invoke an embedded UI handler from the Add or Remove Programs item in Control Panel. Or, you can invoke an embedded UI handler during a Windows Installer repair process.
Embedded chainer
You can use the embedded chainer to add packages to a multiple package transaction. You can use an embedded chainer to enable installation events across multiple packages. For example, you can enable install-on-demand events, repair events, and uninstall events across multiple packages.
Update supersedence resiliency
This feature lets you correct for changes in the FeatureComponent table during supersedence.
Shared component patching resiliency during uninstall
This feature makes sure that the most recent version of a component is available to all products.
Custom action execution on update uninstall
This feature lets an update add or change a custom action so that the custom action is called when an update is uninstalled.
For more information you can check the MSDN Documentation or the Windows 4.5 Installer Team Blog.
Posted in Development
Leave a comment
Windows 2008, the new Windows Mobile Center & Windows Mobile 6
On the 64-bit platform, these work great together. The new UI is great and (at least for me) the sync’ing was much better than under the old platform and software. However, there is a major gotcha that you should watch out for. If you install and sync under the old versions (ActiveSync & Mobile 5.x) then upgrade, be aware that if it asks you to add a new partnership for the device, “just say no”. Otherwise, WMC (Windows Mobile Center) will not recognize your device. Uninstalling everything and re-installing will not resolve the issue. If I find a workaround, I’ll share it with the group but so far all efforts have not had any effect.
Posted in Computers and Internet
Leave a comment
Windows 2008 continued
Oh and I forgot one more thing. On my new machine (Dell Precision T5400), when I installed 64-bit Windows 2008, I could no longer use the DVD-RW. It just wouldn’t recognize any disk I put in. But I found a great work-around until they get that worked out. You can use "CD-Burner-XP" to burn CDs, DVDs, *RWs, … It works quite well, no matter how many bits or which OS!
Happy Coding!!!
Posted in Development
Leave a comment
Windows 2008 & Hyper-V
OK, I was yet another one that ran straight into the Windows 2008 brick wall. Lots of stuff didn’t work right out of the gate, lots of things to adjust and the one thing that I had been drooling for (Hyper-V) was just plain bitting me in the arse!!!
That has changed. I’m absolutely very PRO Windows 2008 Server!!!! It took some time (like I should have expected) to get things back on track. There are still some things to fix but I’m getting there. Hyper-V can be pretty frustrating at first until you figure out some of the tricks.
One trick that I found was that no matter what I did, I couldn’t get the VMs to recognize the network card. It was Broadcom NetXtreme Gigabit Ethernet card. That’s a very well known brand with great drivers. But the dern VM just didn’t want to recognize it. Then I looked at the settings and found the "Legacy Network Adapter" option. Once I used that, BAMMO! I was off and running!
Windows 2008 is fast, stable and sweet! I highly recommend it for everything, including desktop OS. The reason I say that is that you can pretty much transform your Server OS desktop into a Vista Workstation desktop with the following tricks:
Now I have the best of both worlds on one desktop!!!!
Happy Coding!
Posted in Virtualization
Leave a comment
Cool SQL 2005 Tool!
This is soooooo cool!!!!
TableDiff.exe
| • |
Table Difference tool allows you to discover and reconcile differences between a source and destination table or a view. Tablediff Utility can report differences on schema and data. The most popular feature of tablediff is the fact that it can generate a script that you can run on the destination that will reconcile differences between the tables. TableDiff.exe takes 2 sets of input;
|
TableDiff was intended for replication but can easily apply to any scenario where you need to compare data and schema.
You can find more information about command line utilities and the Tablediff Utility in Books Online for SQL Server 2005.
How can you not get excited about this kinda stuff?!?!?!?!?!???
Posted in Development
Leave a comment
And over the XML we go…
Feeling like Homer Simpson…
Sorry for being out of touch for so long. We had to get ready for beta in a foreign country and we’re rocking and rolling toward full production. (I now have less hair!) It’s all fun, but I had an issue that came up and the MSDN forums indicated it could be a duplicate Project GUID. Since we create our own project files (we have special needs J), I thought that was very possible. So in 15 minutes, I threw together a utility that would walk every directory and read every project file and look for duplicates. Seemed simple enough, however, my
DocumentElement.SelectSingleNode("//Project/PropertyGroup/ProjectGuid")
was always returning null!
The project file was simple enough:
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="2.0">
<PropertyGroup>
<BinplaceToBinariesFolder>true</BinplaceToBinariesFolder>
<BinplaceToSymbolsFolder>true</BinplaceToSymbolsFolder>
</PropertyGroup>
<Import Project="$(NTMAKEENV)My.Build.settings" />
<PropertyGroup>
<ProjectGuid>{71440C14-ED89-4FF0-B1EF-3A217CC6887D}</ProjectGuid>
<OutputType>library</OutputType>
<RootNamespace>My.Namespace.MyAssembly</RootNamespace>
<AssemblyName>MyAssembly</AssemblyName>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>….My.snk</AssemblyOriginatorKeyFile>
<StyleCopEnabled>true</StyleCopEnabled>
<DocumentationFile>$(IntermediateOutputPath)$(AssemblyName).xml</DocumentationFile>
</PropertyGroup>
… rest goes here …
</Project>
And the code to retrieve the ProjectGuid was simple enough as well:
// Load the project file
XmlDocument doc = new XmlDocument();
doc.Load(fileName);
// retrieve the Project Guid
XmlNode node = doc.DocumentElement.SelectSingleNode("//Project/PropertyGroup/ProjectGuid");
// do something here . . .
OK, I thought, I’m a smart guy, I know it’s a namespace problem. I can see in the project that there is a default namespace and according to the MSDN documentation for XmlNamespaceManager, to make a default namespace you use:
|
String.Empty |
The empty namespace. This value can be assigned to a prefix. For example, xmlns="" defines the default namespace to be the empty namespace. |
So I updated the code as follows:
// Load the project file
XmlDocument doc = new XmlDocument();
doc.Load(fileName);
// create a default namespace
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("", "http://schemas.microsoft.com/developer/msbuild/2003");
// get the Project Guid
XmlNode node = doc.DocumentElement.SelectSingleNode("//Project/PropertyGroup/ProjectGuid", nsmgr);
// do something here . . .
But still nothing! Thanks to a co-worker who whacked me in the back of the head saying “We dealt with this before” (to be honest, he had forgotten at first too!). The docs are incorrect when using a default namespace. You do have to give it a prefix. So the correct code was:
// Load the project file
XmlDocument doc = new XmlDocument();
doc.Load(fileName);
// create a default namespace
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("a", "http://schemas.microsoft.com/developer/msbuild/2003");
// get the Project Guid
XmlNode node = doc.DocumentElement.SelectSingleNode("//a:Project/a:PropertyGroup/a:ProjectGuid", nsmgr);
Now this is all fine and dandy and I’m glad I had it re-implanted into my brain cells. However, it’s not all that performant. Now, for what I was doing (building a utility), it didn’t matter as much, but for production quality code, performance does matter. One of the reasons it’s not too speedy is that it loads the XML into the DOM. To use an XmlReader, we could use the code below:
// create a reader
XmlTextReader xmlReader = new XmlTextReader(fileName);
// read until…
while (xmlReader.Read())
{
switch (xmlReader.NodeType)
{
// use the NodeType to look for an element
case XmlNodeType.Element:
// we find an element named "ProjectGuid"
if (xmlReader.Name == "ProjectGuid")
{
// use xmlReader.ReadString() to get the value of the element
// do something here
}
break;
}
}
}
Pretty simple stuff, but yet can trip you up and make you waste time (which none of us have enough of!).
Hope that helps and happy coding!
Posted in Uncategorized
Leave a comment
RE: The shocking truth about the C# lock statement
OK, so my example was a bit contrived. In most cases what we do in our critical sections would be more than just adding to a List<>. And in those cases, if an exception is thrown, we would hold the lock. The next thought that came from that was that if you use an established pattern (lock), then why mix? I believe that you should use the right tool for the right job. I will have to chew on this more before I acquiesce on this point, however. I would like to hear other opinions.
Posted in Performance
Leave a comment
The shocking truth about the C# lock statement!
In delving deep into C#, the CLR, IL and what really happens under the hood, I’ve discovered a shocking truth about the commonly used lock statement. Everyone knows that when it’s compiled the lock statement actually uses a light weight Monitor object to handle the lock, but what you might not know (and I didn’t) was that it also throws in a try/finally in there for good measure.
Consider the following the following method that uses the lock statement:
public void UsingLock(List<string> mystuff, string value)
{
lock (mystuff)
{
mystuff.Add(value);
}
}
Nothing too terribly exciting, but it is common. This method gets compiled down to the following IL:
.method public hidebysig instance void UsingLock(class [mscorlib]System.Collections.Generic.List`1<string> mystuff,
string ‘value’) cil managed
{
// Code size 25 (0x19)
.maxstack 2
.locals init ([0] class [mscorlib]System.Collections.Generic.List`1<string> CS$2$0000)
IL_0000: ldarg.1
IL_0001: dup
IL_0002: stloc.0
IL_0003: call void [mscorlib]System.Threading.Monitor::Enter(object)
.try
{
IL_0008: ldarg.1
IL_0009: ldarg.2
IL_000a: callvirt instance void class [mscorlib]System.Collections.Generic.List`1<string>::Add(!0)
IL_000f: leave.s IL_0018
} // end .try
finally
{
IL_0011: ldloc.0
IL_0012: call void [mscorlib]System.Threading.Monitor::Exit(object)
IL_0017: endfinally
} // end handler
IL_0018: ret
} // end of method Program::UsingLock
You’ll notice the extra try/finally that you didn’t ask for! Now, since the lock statement uses a Monitor object internally, you would expect the following method to compile down to the same IL:
public void UsingMonitor(List<string> mystuff, string value)
{
Monitor.Enter(mystuff);
mystuff.Add(value);
Monitor.Exit(mystuff);
}
But as you’ll notice, it doesn’t!
.method public hidebysig instance void UsingMonitor(class [mscorlib]System.Collections.Generic.List`1<string> mystuff,
string ‘value’) cil managed
{
// Code size 20 (0x14)
.maxstack 8
IL_0000: ldarg.1
IL_0001: call void [mscorlib]System.Threading.Monitor::Enter(object)
IL_0006: ldarg.1
IL_0007: ldarg.2
IL_0008: callvirt instance void class [mscorlib]System.Collections.Generic.List`1<string>::Add(!0)
IL_000d: ldarg.1
IL_000e: call void [mscorlib]System.Threading.Monitor::Exit(object)
IL_0013: ret
} // end of method Program::UsingMonitor
It results in four less IL statements than in the previous method! Talk about a waste of cycles! Now, just think that if this is a method that gets called relatively frequently or possibly many times at one time. That’s a lot of waste.
Now, I know that some would argue that the lock statement may be more elegant than using the Monitor object, but when it comes to scalability, common sense rules. Use the Monitor rather than the lock whenever you can.
Happy Coding!
Posted in Performance
Leave a comment
Silverlight 2.0 Beta 1
As you know, Silverlight 2.0 Beta 1 was turned loose on the 5th, but one of the things I didn’t know was that it had Adaptive Streaming – The Silverlight client can adaptively determine the bandwidth between the client and the server and set the bit-rate appropriately. And can change on-the-fly, if necessary.
If that’s not exciting, I don’t know what is!!!!!!!!
Posted in Silverlight
Leave a comment
The ‘volitile’ myth
OK, I think I should clarify something about what I said in regards to all of the Microsoft JIT’ed assignments are volatile. Yes, that is a true statement, but you cannot simply take that out of context and say “Well, then that means that all of my assignments are safe”. Yes, they will be, but that doesn’t mean that it will operate the way you think it does. Take for instance the following code snippet:
Char[] cArr = new Char[20];
public void Func()
{
object secondRef = cArr;
if (secondRef == cArr)
{
if (secondRef == cArr)
return;
}
}
Upon first glance, you might think that, “Well, since my assignments are all volatile, there’s nothing wrong with this code. The surprise comes in when you look at the JIT’ed IL:
public void Func()
{
object secondRef = cArr;
00000000 mov edx,dword ptr [ecx+4]
00000003 mov eax,edx
if (secondRef == cArr)
00000005 cmp eax,edx
00000007 jne 00000009
00000009 ret
}
You’ll notice that the code is optimized and stores the first object reference inside a register with the intent of not having to check the memory location subsequent times (this is the optimization). So now, let’s decorate the array with the volatile keyword. You immediately notice that the JITer no longer stores any previous addresses of the array inside a register. Each comparison call will get the array address from memory:
public void Func()
{
object secondRef = cArr;
00000000 mov eax,dword ptr [ecx+4]
if (secondRef == cArr)
00000003 cmp eax,dword ptr [ecx+4]
00000006 jne 0000000B
{
if( secondRef == cArr )
00000008 cmp dword ptr [ecx+4],eax
0000000b ret
}
If you omit the volatile keyword, the second check is simply removed and a register compare is performed with the previously determined address of the array. When you add the volatile keyword the cmd eax,edx becomes cmp eaxdword ptr[ecx+4] which in works like a memory barrier. So even though Microsoft’s JITer makes every assignment volatile, you HAVE to keep in mind what type of optimizations occur.
Posted in Development
Leave a comment