text: Please join me in welcoming the rest of the MSCOM Operations Team to the world of blogging. Stop by, have some coffee and leave them a comment to let them know you care.
  -S
  Hi, Eric here again. A question came in to us, via email, to my post about "shelling" in .NET. I thought I would respond with a new blog entry to share with the community.
  The question was:
  From: AndreasSent: Friday, July 22, 2005 7:13 AMHi Eric I liked your piece of code that sends keystorkes too call wordpad.I am writing a mobile application and Iwas trying to output information from the application to a printer.I have written the information onto a text file in the windows CE mobile, sinceI could not find a way to output the textto the printer.I have seen your code I thought, if Icould get wordpad to read the textfile and output to the printer, by sendingkeystrokes.Please let me know if you have any ideas. Many ThanksAndreas
  1. opens wordpad2. opens a file3. prints it4. closes wordpad
  And you can give it a command line argument to specify the location of a file to print:
  shell.exe C:\WINDOWS\system32\clusoc.txt
  shell.exe C:\WINDOWS\system32\clusoc.txt
  If you don't give it this input argument, it has a hardcoded file path it tries to open.
  Good luck!
  - Eric
  _______
  {})");
  PrintThisFile = args[0];
  PrintThisFile = @"C:\WINDOWS\system32\perffilt.h";
  }
  A couple of months ago, after I had just installed the then-new Visual Studio 2005 Beta 2, I could not run any project in the IDE, as it would crash VS. Then I found a workaround using a Visual Studio community feature that I built for MSDN Forums:.
  This workaround came from:
  Which I found at:
  You too can help yourself like I did, while in the Visual Studio 2005 IDE! Use the main menu to select “Community”, and then “Ask a Question”. This feature searches the MSDN Forums to find postings with the keywords you enter. For this feature, I developed a full component stack: SQL stored procedures, a .NET Web Service on top of that, a .NET class library on top of that, and the “Ask a Question” ASP.NET UI on top of that. Another way to search MSDN Forums is use their search UI.
  Help me, help you. :)
  As anyone who reads our little corner of the world knows, it's been a while. Now I could make excuses that we have been busy or we lost the password or dingos ate our blog, but in truth, we simply haven't taken the time to do it. It's funny, we all have the best of intentions. I can't tell you how many times I've been talking with my team and someone says "I almost blogged today about....." or "I should blog about ....", but it never seems to actually happen. I mean, we are busy and I did have to go look up the password again and ok, well the dingos were an exaggeration, but we need to make a concerted effort to poke our heads out and tell you what we've been up to. So whether you want us to be or not, we're back. Good to see you all again.
  -Scott
  Some time ago I posted with respect to creating a facility for automating the MOM service account password change process. I did indeed complete the program, which can be summarized as follows:
  Along the way, however, I encountered a number of roadblocks that made this process impractical, the most significant of which was a COM+ behavior that results in the current credentials being cached beyond the application shut down. This results in having to reboot all of the management servers anyway, one of the key things I was trying to eliminate as part of this new process.
  In the end, the best workaround I came across is documented (though not with respect to this issue specifically) in the MOM 2005 Security Guide, the URL for which and the key section from which are appended at the end of this post. It is important to note that this workaround only works on Windows Server 2003, since only it to date supports the use of the Network Service account. Also of particular note related to the guide’s instructions are:
  By following the steps outlined in the appended section of the security guide with the above notes in mind, you can simply automate through batch file or script the stopping and restarting of the MOM service and the use of SetActionAccount to reset the MOM action account credentials on the management servers; no reboot required. You also no longer have to worry about the DAS application, since it is running within the Network Service context.
  At least one other large IT group here at Microsoft beside ours is operating MOM 2005 this way, so far without any known problems.
  Kent
  * The new version of of SetActionAccount I refer to herein is available currently as a hotfix, which you can obtain by contacting Microsoft Product Support Services, or as part of MOM 2005 Service Pack 1 due out later this year.
  Microsoft Operations Manager 2005 Security Guide (Partial)
  Link to the complete document:
  To use Network Service for DAS
  This process requires procedures to be done on both the MOM Database Server and then the MOM Management Server.
  ImportantYou can only do this if the Management Server is running on Windows Server 2003. Windows 2000 does not support the Network Service account.
  On the MOM Database Server:
  1. On the MOM Database Server, verify that the MSSQLSvc Service Principal Name is registered by using “setspn.exe -L <SQL Server FQDN>" at the command line, where <SQL Server FQDN> is the Fully-Qualified Domain Name of the MOM Database Server Instance.
  2. In SQL Server Enterprise Manager, expand the OnePoint folder.
  3. Add a new database user by right-clicking on the Users sub-node of the OnePoint database folder and selecting New Database User.
  4. In the Database Users - New User dialog, enter the computer name in the Login name text box. Computer names follow the format domain\computername$. Do not forget the trailing “$”.
  5. Grant this computer account user the db_owner database role membership and click OK.
  6. Navigate to the Security folder for the SQL Server instance.
  7. Add a new SQL Server Login by right-clicking on the Logins folder and selecting New Login.
  8. On the General tab of the SQL Server Properties - New Login dialog, enter the computer name in the Name textbox. Computer names follow the format domain\computername$. Do not forget the trailing “$”.
  9. On the Database Access tab, grant this computer account db_owner access to the OnePoint database by selecting the Permit checkbox next to the OnePoint database and then the db_owner checkbox below.
  10. Click OK.
  On the Management Server
  1. On the Management Server, stop the MOM Service.
  2. In the Component Services snap-in, expand Component Services / Computers / My Computer / COM+ Applications.
  3. Right-click the Microsoft Operations Manager Data Access Server node and click Shut down.
  4. After the application has stopped, open its properties.
  5. On the Identity tab, select the System Account and the Network Service options, and then click OK.
  6. Start the MOM Service.
  7. After the MOM Service has started, open the MOM Administrator console and confirm that you do not see any DAS errors.
  Sometimes
  Maybe many of you out there in Developer Land are already aware of this, but I need to point out that you can indeed shell, sleep, and SendKeys using the new fancy C# and .NET Framework. You see, a few months ago, I needed to come up with a quick and dirty demo of a Windows application. Then I came up with the brilliant notion of shelling to it, then sending keystrokes to it to demo the app. I wondered, can you still peform this most crude form of application interoperability with the most elegant C# and .NET?
  The answer is a big YES! Check this C# code out:"); } }}
  The above code is a console EXE program that brings up WordPad, then types a big "Hello World", with a 0.5 second sleep in between to give WordPad time to open. I love this code -- it is SO old school. It warms my heart that you can still stoop to this level. I hope you enjoy it as much as I.
  For a list of all of the SendKeys codes, see the following page in MSDN online:
  Happy coding!
  This code (actually, code very much like it) made it through development and test (in a different team; we never make mistakes,) and worked beautifully. In production, however, it was an utter failure. It isn't difficult to spot the problem; can you?
  ----------------------------------------------
  For many years I have been pretty heavily involved in the gaming industry. Through scores of beta tests, to assisting in the design of scalable systems for third generation MMORPGs to writing reviews and conducting interviews I’ve been in, out and around the industry since it became an industry.
  Of course game graphics and system hardware have come a long way in a ridiculously short amount of time. Who remembers when 3dfx graphics cards were all the rage?
  In recent years the showdown on the graphics front is between nVidia and ATI. Now nVidia has held the lead for quite some time and the weight of it has made them stagger at times. ATI, ever the stalwart competitor has put up a good fight and come up with some very good products over the years.
  Being a massive nerd, I love to build my own game systems. During my last build I decided to take a shot on the latest and greatest ATI card. I had previously only purchased nVidia products as I had felt they were marginally better in performance but mostly because I knew that game developers used them in their development machines. But the RADEON 9800 Pro 256 was my choice at the time.
  A choice I have regretted every single day.
  Since the day I booted my newly assembled behemoth containing all of the latest and greatest gaming hardware (for that millisecond) the 3D gaming quality on this Sapphire OEM has been deplorable. Some games, the games that are more 2D based than 3D based had almost no problems, but every game that renders 3D objects has quality issues. Every single game. Now, simple model and texture games such as Zoo Tycoon 2 have the minor irritation of the occasional flashing texture. Easy to overlook and ignore and in all likelihood ATI will release a driver update to relieve this issue even more.
  But games with heavy 3D, like EverQuest 2, World of Warcraft, Doom 3, and Half-Life 2 have significant problems with bad textures, broken models, running text, ad nauseam. And forget about Battlefield Vietnam, that’s just texture stew.
  Sapphire tells me to talk to ATI, of course. ATI has been stringing me along with “that should be fixed in driver update X” messages for months. The store I bought it from wouldn’t take it back after the first 30 days (and who can blame them? After 30 days a used graphics card is scrap silicon to a retailer).
  I had taken the last 6 weeks off of my harassment campaign for support and decided to try it once again. Just to see if I got any different kind of result. Um, yeah.
  In all the time I’ve been trying to resolve this problem with ATI, not one single time has anyone asked for a screenshot of the problem despite my offering to provide them every time. In all this time not once was there ever a mention of simply replacing my defective card with a new one. I paid almost $500 for it and you can now pick that same card up for about $250. And I know it is simply my card that is defective. I’ve borrowed the exact same card from a friend who bought his from the same place I did at the same time I did and his works just fine in my machine. I’ve also tried an nVidia based card. No problems. Clearly I have a defective unit and you would think ATI could afford to replace it.
  The last email I received from ATI suggested that I adjust my bios settings with things such as “Set your AGP support from 8X to 2X”, among others.
  I made sure to reply: “Thank you for supporting nVidia.”
  Will
  Ah,!
  While I waited for my order to arrive, I decided to write a utility program to better organize my 6000 photos. It was taking forever to open my big photo file folder! My new program copies all of the files found within one folder tree to a new folder tree, which has the files broken out by the date each picture was taken. A distinct folder is created for each day a picture was taken. Now it is easy to open the root folder, and find all the pictures from Christmas 2003, for example. With a little more polish, this utility could be ready for public consumption.
  Eric
  I was recently working on a thermometer control and decided to write a temperature class to go along with it. What I found interesting is that there are temperature systems that I had never even heard of let alone used (namely Reaumer and Rankine). I'm from Canada and I've heard of some pretty nasty temperatures, but these were still a suprise to me. :-) Anyway I wrote the class in C# and thought others might find some use in it. Here it is:
  using System;
  namespace ThermometerDemo{ /// <summary> /// Summary description for Temperature. /// </summary> public class Temperature { public enum SystemOfMeasure { Fahrenheit = 0, Celsius, Kelvin, RanKine, Reaumer };
  private SystemOfMeasure _systemOfMeasure; public SystemOfMeasure Scale { get { return _systemOfMeasure; } set { _systemOfMeasure = value; } }
  private double _temperatureKelvin; public double Value { get { return Temperature.Convert( _temperatureKelvin, SystemOfMeasure.Kelvin, _systemOfMeasure ); } set { this._temperatureKelvin = Temperature.Convert( value, _systemOfMeasure , SystemOfMeasure.Kelvin ); } }
  public double AbsoluteZero { get { return Temperature.Convert( 0F, SystemOfMeasure.Kelvin, _systemOfMeasure ); } }
  #region Construction
  public Temperature() : this( SystemOfMeasure.Kelvin, 298.15F ) { // SI temperature at standard state in Kelvin. }
  public Temperature( SystemOfMeasure systemOfMeasure ) : this( systemOfMeasure, 298.15F ) { // SI temperature at standard state. }
  public Temperature( double temperature ) : this( SystemOfMeasure.Kelvin, temperature ) { }
  public Temperature( SystemOfMeasure systemOfMeasure, double temperature ) { _systemOfMeasure = systemOfMeasure; Value = temperature; }
  #endregion Construction
  # region Public Methods
  public static double Convert( double temperature, SystemOfMeasure originSystem, SystemOfMeasure targetSystem ) { // Convert to Kelvin. double temperatureKelvin; switch( originSystem ) { case SystemOfMeasure.Fahrenheit: temperatureKelvin = ( 5F / 9F ) * ( temperature - 32 ) + 273.15F; break;
  case SystemOfMeasure.Celsius: temperatureKelvin = temperature + 273.15F; break;
  case SystemOfMeasure.Kelvin: temperatureKelvin = temperature; break;
  case SystemOfMeasure.Reaumer: temperatureKelvin = ( 5F / 9F ) * temperature + 273.15F; break;
  case SystemOfMeasure.RanKine: temperatureKelvin = temperature / 1.8F; break;
  default: throw new ArgumentOutOfRangeException( "originSystem", originSystem, "Unsupported origin system of measure"); }
  // Convert to the new system. double resultTemperature; switch( targetSystem ) { case SystemOfMeasure.Fahrenheit: resultTemperature = 32F + ( 1.8F ) * ( temperatureKelvin - 273.15F ); break;
  case SystemOfMeasure.Celsius: resultTemperature = temperatureKelvin - 273.15F; break;
  case SystemOfMeasure.Kelvin: resultTemperature = temperatureKelvin; break;
  case SystemOfMeasure.Reaumer: resultTemperature = ( 1.8F ) * ( temperatureKelvin - 273.15F ); break;
  case SystemOfMeasure.RanKine: resultTemperature = temperatureKelvin * 1.8F; break;
  default: throw new ArgumentOutOfRangeException( "originSystem", originSystem, "Unsupported target system of measure"); }
  return resultTemperature; }
  public static string GetUnitAbbreviation( SystemOfMeasure systemOfMeasure ) { switch( systemOfMeasure ) { case SystemOfMeasure.Fahrenheit: return "°F";
  case SystemOfMeasure.Celsius: return "°C";
  case SystemOfMeasure.Kelvin: return "K";
  case SystemOfMeasure.Reaumer: return "°Re";
  case SystemOfMeasure.RanKine: return "°Ra";
  default: throw new ArgumentOutOfRangeException( "systemOfMeasure", systemOfMeasure, "Unsupported system of measure"); } }
  #endregion Public Methods }}
  eHowitzer
  The entertainment industry is a funny business. It is completely dependant on the random whims of consumers. That is not to say that the success of a product is unpredictable, simply that there are a great many factors involved in design, development and distribution of an entertainment property that getting them all together is a fluid venture at best.
  As I’m sure we all know, Halo 2 dropped recently to great fanfare. This follow up to the perennial Xbox title was highly anticipated and accompanied with some killer trailers and excellent television commercials. The media was whipped into a savage frenzy that culminated in a $125 million dollar opening day bombshell.
  Numbers like that are simply unprecedented. Nothing has ever come close to matching a single day total like that of Halo 2. Even such powerhouse properties as the Spider-Man movie franchise pales in comparison. Spider-Man 2 bowed in with an opening weekend, a long 4th of July weekend I might add, with $115 million. But let’s compare something a little closer, digital animated feature films. Shrek 2 bowed in with an opening weekend of $108 million. Finding Nemo racked up $70 million in its debut weekend.
  By those comparisons, Halo 2 devastated the entertainment industry. However, if we take a step back and view the entire domain of digital entertainment, a different picture begins to take shape. Shrek 2 piled up $436 million in US domestic box office sales during its 14 week theatrical run and Finding Nemo scored $339 million for its 29 week run. Remember, that is the US box office sales.
  Some estimates suggest that approximately 15 million Xbox units have been sold worldwide. If one copy of Halo 2 were sold for every Xbox at $50 per sale, then Halo 2 would scratch up $750 million in worldwide sales. As much as I would love to see that come to fruition, I just can't see it. In fact, I can’t see sales of Halo 2 topping $400 million, but it is possible.
  Now look at this picture again, Shrek 2 scored $436 million in US box office sales. Halo 2 _could_ reach $750 million world wide.
  Take another step back and the fog begins to clear. Worldwide box office figures for Shrek 2 and Nemo top out at $849 and $865 million respectively. And we haven’t even begun to touch DVD and VHS sales or rentals yet.
  Sure the Halo 2 release was a massive success, but let’s not consider it an earth shattering event just yet.
  Which brings me to another issue. What the hell is wrong with Disney? Have they become so bloated that they have forgotten how to make a good animated movie?
  Look at the charts and it’s clear to see that the future of Disney animation is Pixar. At least, one would think so. Since 1989 Disney has released 9 traditional animation movies and 6 digital animation movies in conjunction with Pixar. The most lackluster of all the Pixar movies, A Bug’s Life (1998), currently sits at #84 in the all time box office charts with $357 million. At $357 million, A Bug’s Life roasts all of the traditional animation releases except for Tarzan (1999, #51 @ $435), Aladdin (1992, #35 @ $501) and The Lion King (1992, #15 @ $784).
  And, with the exception of A Bug’s Life, each successive Pixar movie has out grossed it’s predecessor. With an opening weekend take of $143 million, The Incredibles looks to continue this trend (remember, Finding Nemo took in $70 million in its opening bow in 2003).
  One would think that cultivating a relationship with Pixar would be a top priority at Disney, but instead they have done nothing but breed animosity and distrust. To the point where Pixar has decided to take their toys and play in someone else’s sandbox. Cars, the next feature from Pixar (slated for 2005) will be the final movie in the current contract between Disney and Pixar. Rather than try and smooth the ruffled feathers and extend that contract, Disney has apparently decided to spin up their own digital animation division (how long did it take to make this decision? 6 years? Right on time guys.) and crank out…Toy Story 3. Toy Story 2 is where the bad blood began between these companies to begin with.
  The question has been raised as to whether Pixar can survive without Disney. In my opinion this isn’t even a question. Even if Pixar did not want to handle their own financing, publicity and distribution business (which they certain could) there are many powerhouse studios who are just waiting to swoop in and steal this money maker. Fox Studios has struggled with their animation division for years and finally landed a winner with Ice Age. They’ve got the juice to take on Pixar. Dreamworks has their own very successful animation studio (coincidentally Disney is building their digital division in Glendale California, not far from the Dreamworks studio) however, Dreamworks has shown a penchant for being opportunistic and could certainly handle bringing Pixar into their stable. Sony, Paramount and perhaps half a dozen others could all be interested in handling the load.
  At this rate Disney animation will die a slow and agonizing Lilo & Stitch 6 death.
  I have recently encountered a situation where my code was receiving objects sent, via a scoping event, from code on another thread. These "scope" objects require my code to change state to reflect the object received. This resulted in my code receiving scoping events at inopportune times (such as in the middle of working on the previous scope change). I needed a way to "de-bounce" the scope changes in order to ignore them while I was updating, and also check when I was finished updating to see what scope changes had occurred while I was processing. Here is a simple solution that I put together to help solve the problem. The first code block shows my usage of the class, and the second is the class itself. I hope you find it interesting (and maybe useful).
  // Code Block #1: Usage private ScopeTracker _scopeTracker = new ScopeTracker( ScopeTracker.TrackingStyle.DiscardAllButLast );
  public override void OnScopeChanged(object scope) { _scopeTracker.TrackChange( scope ); If( !updatingState ) { if( _scopeTracker.IsNewScopeChange() ) { this.UpdateState( _scopeTracker.ConsumeNextScopeChange() ); } } }
  private void UpdateState ( object o ) { if( updatingState ) { return; }
  updatingState = true;
  // do work on another thread (possibly)…
  updatingState = false;
  if( _scopeTracker.IsNewScopeChange() ) { this.UpdateState( _scopeTracker.ConsumeNextScopeChange() ); } }
  // Code Block #2: Class definition. public class ScopeTracker { public enum TrackingStyle { QueueAll, DiscardAllButLast }; public object LastScopeChange { get { return _lastScopeChange; } }
  private TrackingStyle _trackingStyle; private Queue _trackedScopeChanges = new Queue(); private object _lastScopeChange = null;
  public ScopeTracker( TrackingStyle TrackingStyle ) { _trackingStyle = TrackingStyle; }
  /// <summary> /// Returns true if the change is tracked, else returns false. /// </summary> /// <param name="ScopeObject"></param> /// <returns></returns> public bool TrackChange( object ScopeObject ) { bool bTracked = false;
  // If we are only tracking the last scope change, then throw away any previous // scope changes we are tracking. if( _trackingStyle == TrackingStyle.DiscardAllButLast ) { _trackedScopeChanges.Clear(); }
  // Only track changes if they are changes. if( 1 > _trackedScopeChanges.Count ) { // Since we don't have any changes in the queue check to see if this new // one is different than our last one. if( _lastScopeChange != ScopeObject ) { _trackedScopeChanges.Enqueue( ScopeObject ); bTracked = true; } } else { // We have changes in the queue, so see if this new one is the same as the last // change we put in the queue. if( ScopeObject != _trackedScopeChanges.Peek() ) { _trackedScopeChanges.Enqueue( ScopeObject ); bTracked = true; } }
  return bTracked; }
  public object ConsumeNextScopeChange() { if( 1 > _trackedScopeChanges.Count ) { return null; }
  _lastScopeChange = _trackedScopeChanges.Dequeue(); return _lastScopeChange; }
  public bool IsNewScopeChange() { if( 1 > _trackedScopeChanges.Count ) { return false; } else { return true; } }
  public object SyncToValidScope() { if( this.IsNewScopeChange() ) { return this.ConsumeNextScopeChange(); } else { if( null != _lastScopeChange ) { return _lastScopeChange; } else { return null; } } } }