Showing posts with label tools. Show all posts
Showing posts with label tools. Show all posts

Monday, October 12, 2009

Monitoring log files in real time

Debugging Windows services, especially in a test or production environment, can be tricky. In many cases you won't have access to the box. You certainly won't have the ability to step through the code.

Thus, you are usually forced to monitor log files, looking for an indication of where the problem occurred. The typical method is to start by opening the file in Notepad. Then, when you want to see more recent log entries, you close and reopen the file. This is mildly annoying when dealing with a single service. If your business workflow is split among multiple services, this becomes incredibly inefficient.

An easier solution is to use a log monitor app such as BareTail. For this little demo I am using the free version of the tool.

I have three separate services logging to files named "process1.log", "process2.log" and "process3.log." To keep it simple I am only logging the RequestID for each received request. Here I have loaded all three logs into BareTail.


When I send a new request to the system it should update each log file. BareTail monitors the logs and displays any updates. In the screenshot below, note the new Request ID #2918891. Note also that the document tabs for each file show a green arrow - this indicates an update was made.


As you view each tab, the green arrow will be cleared to visually show which files you have already reviewed.


Say you were trying to debug a request that fails to make it through the system. A quick glance at the document tabs will show you how far a request made it through the system. After reviewing each log (to clear the green markers) we submit another request. In the following screenshot, note that we have a green arrow for process1.log and process2.log, but none for process3.log. So either the second process failed to send the message on, or the third process failed to receive it.

Thursday, May 8, 2008

DotNetMigrations

A friend of mine recently ported the Ruby on Rails "Migrations" tool to .Net. Assuming you can get all of the developers on a team to script out their database changes (and matching rollbacks) this tool will make it easier to build, update and deploy your database. It also becomes trivial to revert the changes when something breaks unexpectedly.

You can find details here.

Friday, March 14, 2008

Unlocking files when Visual Studio can't

There's an option in Visual Studio that, on compile, will pull all of your XML comments out into separate files. These can then be combined into a help file using a tool like Sandcastle. Most of the time this feature works correctly. If you cancel a build in process, or the compile fails, VS occasionally fails to release the file lock. From that point on, the compile fails with an error stating the file is in use by another process. I've not found a way within VS to force an unlock short of closing the app.

There is, however, a faster way using Process Explorer. Start Process Explorer and select Find > Find Handle or DLL... from the menu. Enter all or part of the filename currently locked, then click Search. You should see the guilty process - devenv.exe in this case.


Double-clicking on the entry will display a list of handles for that app, with the selected handle highlighted. Right-click on the selection and choose Close Handle. You'll see a dialog warning about potential crashes or system instability (meaning don't try this with a system file.) Tell it to continue and the handle will be closed. VS will again compile without issue.

Tuesday, February 12, 2008

Automate config changes for different environments

Most applications I've worked on contain one or more config files. These are generally used to track web service locations, database connection strings, and logging information. Keeping these settings outside the code makes it easy to modify them without a recompile. This is especially useful when moving a deployment from dev to test, or from test to production.

On most of these projects, the preferred method used by developers is to keep multiple config files in the source repository. These are distinguished by simple renaming of the files (such as app.config, app_qa.config, app_prod.config.) In theory this should work - once you have the config files set up for each environment, deployment requires replacing the file as appropriate. And if you use a .bat file or build script, the file rename will be automatic.

The scenario usually overlooked, however, is the case where something in the config changes. Maybe a new web service is being used by the application. Or perhaps a new assembly needs to be referenced. In my experience, the developer often makes the changes to the main file (app.config), but forgets to make the same changes to the others. During development the code appears to work fine. Unfortunately, the app fails to run in the QA environment. Usually, some amount of time is spent by the developer before realizing that the problem is with the config.

To reduce this sort of issue, I recommend only keeping one config in the source repository. This config will contain the values necessary to run in the development environment. During the build process, the config is updated for the target environment. The MSBuild Community Tasks contains a FileUpdate task that makes this easy.

Let's say you have a config file with the following:


<appSettings>
<add key="MyWebService" value="http://localhost/service/MyWebService.asmx" />
</appSettings>

The msbuild script to deploy to QA would contain:


<PropertyGroup>
<MyAppConfigFile>c:\source\MyApp\app.config</MyAppConfigFile>
<MyWebServiceRegex>http://.*/service/MyWebService.asmx</MyWebServiceRegex>
<QaWebServicePath>http://QaServer/service/MyWebService.asmx</QaWebServicePath>
</PropertyGroup>
<Target Name="ConfigureQA">
<FileUpdate
Files="$(MyAppConfigFile)"
Regex="$(MyWebServiceRegex)"
ReplacementText="$(QaWebServicePath)" />
</Target>

Tuesday, November 6, 2007

Quick and dirty debugging - DebugView and Trace.WriteLine

Here's another debug scenario for you. After taking great effort in testing your application you hand it off to QA. They throw it back with some interesting bug. Using the exact same steps, you're unable to reproduce on your machine. You have a general idea of where the app is failing, but can't be sure precisely what the issue is.

At this point one usually resorts to some sort of logging. These logging statements are placed in strategic locations through the suspect code (at every other line.) If the bug is in the UI, the common method is MessageBox.Show. If the problem is in an underlying assembly, you must resort to writing output to a text file. The downside is that lots of message boxes wear you out, and it's always a pain tracking down the necessary code to write files.

An easier option is to call Trace.WriteLine (located in System.Diagnostics.) In my sample application (MyApp) I have a single button. Inside the Click event, I add the following line

 Trace.WriteLine("Button1 was clicked");

The event then calls a method in a separate library. In this library method, I've added the following line ('x' was the parameter passed into the method)

 Trace.WriteLine("SomeMethod - Parameter x: " + x.ToString());

When I run the application from VisualStudio and click the button, the Output window contains the trace messages


That's fine if you're running VS, but what about on a QA box? For that I'm using DebugView. After starting up the utility, I fire up the sample application. Click the button (which again calls Trace.Writeline) and DebugView displays the messages previously seen in Visual Studio.

Monday, September 24, 2007

Hidden Desktops and NUnitForms

In my last post I noted a problem working with NUnitForms. I was unable to get the hidden desktop to work with a [SetUp] method. After digging through the source code, I have my solution.

The code that sets up the hidden desktop is in the method init(). This method is marked with the [SetUp] attribute. When I created my own method with this attribute, init() was no longer being called. Thus, no hidden desktop.

The solution is to override the Setup() method provided in NUnitFormsTest, but to not mark it with the [SetUp] attribute. The last thing init() does before exiting is make a call to Setup(). The TearDown attribute and method have a similar implementation.

When the documentation seems to be lacking, it's always nice to have the source code.

Tuesday, September 4, 2007

Upgrading from NUnit 2.2 to 2.4

Until recently, I was running NUnit 2.2.9 on both my work and home computers. This weekend I decided to upgrade my home computer to version 2.4.3. The quick and painless process went as follows:

1) Uninstall v2.2.9
2) Install v2.4.3
3) Open an existing project containing unit tests
4) Updating the references to point to the new assemblies
5) Compile and run...

Well, it all worked except for that last step. At one point, I seem to recall NUnit requiring you to reference nunit.core. Whatever that reason, it's no longer a requirement, and was the cause of the build failure. After removing the reference, everything ran as before.

Constraint-based assertions

One of the most noticeable changes in version 2.4 was the inclusion of constraint-based assertions, similar to some of the mock frameworks available. Previously, you might write assertions like:

Assert.IsTrue(age < 21);
Assert.AreEqual(9, age);

Using constraints, you can now write:

Assert.That(age, Is.LessThan(21));
Assert.That(age, Is.EqualTo(9));

Also, if your test fixture is derived from AssertionHelper, you can shorten the previous lines to:

Expect(age, LessThan(21));
Expect(age, EqualTo(9));

Note: you will need to add using statements for NUnit.Framework.Constraints and NUnit.Framework.SyntaxHelpers. For more examples, including comparisons to the older Assert methods, look for AssertSyntaxTests.cs under the NUnit install directory.

Thursday, June 21, 2007

Stopping a COM+ Application Via the Command Line

I'm currently working on a project requiring multiple steps to deploy correctly. Being the efficient (aka lazy) developer that I am, I decided to automate some of the process. One step calls for stopping a COM+ application. I'm assuming there's a command line utility to handle this, but I've not yet found it. I tried consulting a friendly guru, but that didn't help. So, I was forced to write the VBScript below.

To use, create a new file, StopComApp.vbs, and add the following:

 dim objCatalog
set objCatalog = CreateObject("COMAdmin.COMAdminCatalog")

set args = WScript.Arguments
serviceName = args.Item(0)

objCatalog.ShutDownApplication serviceName


To use, run the following from the command prompt (or batch file):

 wscript StopComApp.vbs <AppName>

Sunday, June 10, 2007

A Useful Way To Launch WinDiff

A co-worker recently expressed his annoyance that certain tools installed with Visual Studio didn't have Start menu shortcuts. One in particular was WinDiff. In my experience, however, starting WinDiff by itself was never very useful. Once it was running you still had to browse to the files (or folders) you wanted to compare. I prefer selecting two items, right-clicking, and choosing WinDiff from the menu.

To set this up, create a new file, windiff.bat, with the following:
 "C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\Bin\WinDiff.exe" %1 %2


Save the file to C:\Documents and Settings\<username>\SendTo

To use, select two files in the same folder. Right-click and choose Send To > windiff.bat. This can also be used to diff the contents of two folders.

Friday, May 18, 2007

Adding FxCop to the build

Most (though certainly not all) developers agree that code reviews are a useful step in the development process. I won't go into specific benefits, as there are numerous writings on the subject.

One of the downsides, however, is that code reviews take time. In fact, you could spend more time reviewing the code than you did writing it. This is where FxCop can help. Though it won't catch problems with things like business rules, it does flag various issues related to performance, security, and code consistency/maintainability. By adding it to the build, we get a decent code review with every checkin.

For this demo, I downloaded the source for the MSBuild Community Tasks. Dropping this into SourceSafe, I set up a new project in CruiseControl.Net.


<project name="MSBuild.Community.Tasks">
<sourcecontrol type="vss" autoGetSource="true">
<ssdir>c:\vss</ssdir>
<executable>C:\Program Files\Microsoft Visual SourceSafe\ss.exe</executable>
<project>$/MSBuild.Community.Tasks</project>
<workingDirectory>MSBuild.Community.Tasks</workingDirectory>
</sourcecontrol>
<tasks>
<msbuild>
<executable>c:\winnt\Microsoft.Net\Framework\v2.0.50727\msbuild.exe</executable>
<projectFile>MSBuild.Community.Tasks\Source\MSBuild.Community.Tasks.sln</projectFile>
<buildArgs>/noconsolelogger </buildArgs>
<logger>c:\ThoughtWorks.CruiseControl.MsBuild.dll</logger>
</msbuild>
</tasks>
<publishers>
<statistics/>
<xmllogger/>
</publishers>
</project>


To add FxCop, we first need to create a project file. Start FxCop. From the menu, choose File > Save Project. Out of laziness, I saved the file as c:\DefaultRules.FxCop. Now to update the build file. Below the <msbuild> section, add the following


<exec>
<executable>C:\Program Files\Microsoft FxCop 1.35\FxCopCmd.exe</executable>
<buildArgs>/project:"C:\DefaultRules.FxCop" /fo /q /searchgac /file:"%CCNetWorkingDirectory%\MSBuild.Community.Tasks\Source\MSBuild.Community.Tasks\bin\Debug\MSBuild.Community.Tasks.dll" /out:FxCopLog.xml</buildArgs>
</exec>

Within the <publishers> section, add


<merge>
<files>
<file>FxCopLog.xml</file>
</files>
</merge>

Save these changes and force a build - which fails. Looking at the project report, it looks like everything should have worked. We even have FxCop information on the page. The Build Log, however, notes the missing dependency Microsoft.VisualStuido.SourceSafe.Interop. The assembly isn't being copied to the build output folder.

To fix, open the .sln in VisualStudio. Under the project's References, select the missing interop and set the Copy Local property to True. Checkin the modified project and you should see a successful build.

Now we have FxCop info displaying on the Build Report. We also have a detailed FxCop Report we can access from the Dashboard's menu. Which is all well and good, but the reports aren't the most useful.





Fortunately, you can download alternative stylesheets from the Thoughtworks site. Unzip fxcop-summary.xsl and FxCopReport.xsl, and place in \webdashboard\xsl\ under the cc.net install directory. Open FxCopReport.xsl in your favorite xml editor. Replace all instances of

src="images/

with

src="/ccnet/images/

With the new reports in place, reload the dashboard. If all goes as planned, you should see slightly improved FxCop reports. Note these still aren't perfect, and there are likely others available on the web.