Thursday, May 28, 2009 |
|
|
Think your web applications are safe from cross site scripting? Maybe, maybe not. Why take a chance? I recently put together some notes for a presentation on cross site scripting, or XSS for short. I have decided to share some of the information, because I believe keeping a few thoughts in mind as we develop and test will go a long way when it comes to preventing attacks. Cross Site Scripting – What is it? Cross site scripting occurs when a web application gathers malicious data entered from a user, with or without negative intent. XSS can be achieved by exploiting locations in source code where users are able to input data, and the proper preventative measures have not been implemented to format and validate the inputted data. In other situations, session cookies and other sensitive data can be accessed by injecting malicious data and ultimately hijacking or impersonating a user’s account. There are three main types of XSS according to Wikipedia, so I won’t bother rephrasing. Visit http://en.wikipedia.org/wiki/Cross-site_scripting for more information. The most common technologies and languages used for XSS are JavaScript, VBScript, ActiveX, HTML, or Flash’s ActionScript. Not only do we need to protect our server code, but we need to think about our client code as well. Prevention of Cross Site Scripting The vast of majority of XSS attacks can be prevented by identifying the user input locations within the web application and ensuring the source code handling these has proper measures in place. From a developer’s perspective, this means ensuring all data inputted from a user is properly encoded to remove HTML and script markup to be replaced with text that all browsers can process. A simple example in C# is to use the HttpServerUtility.HtmlEncode method to convert all HTML markup characters into their text equivalent. For example, if a user were to supply the input for a textbox with the following, “This is my <b>bolded text</b>.” The end result of the HtmlEncode method would result in the following, “This is my lt;bolded textgt;.” This is important because it removes HTML markup, which could be malicious. For example, “This is my text. <script>alert(‘This is an attack’);</script>.” This example is passing a JavaScript alert to open a modal popup on the screen to display to the user. In addition to HTML inputted data encoded on the server, encoding data on the client can be equally important. JavaScript HTML elements can have two attributes, InnerHTML and InnerText. InnerText will render text, not HTML, so it is the safe option. InnerHTML can be used to inject an XSS attack because it can render user inputted HTML, including script. Ensure InnerHTML has the necessary string formatting to protect against this vulnerability. Cookies are another vulnerability to XSS attacks. If any part of the website issues cookies and an XSS access point is discovered, it is now possible to steal cookies and private information from the application’s users. If the cookie can be accessed, so can the information with it. Users can be impersonated, and site credibility will be lost. Encrypted web sites (SSL, HTTPS) are at risk just like their public counterparts. SSL sites appear to be protected, but it is possible to execute the same XSS attacks, they just happen over an encrypted connection. To protect our web applications, we need to be aware of the XSS vulnerabilities common to attackers and place defensive measures to ensure user confidentiality and confidence. Without becoming an expert on XSS and security, it is possible to develop safe, reliable applications by understanding XSS and the vulnerabilities exposed by our applications. What to Look for in Source Code Execute a simple search in source code looking for certain keywords is a good starting point. Many of the XSS bugs I have seen reported could have been prevented with the simple measures. Ensure HTML input is properly encoded on the server using HtmlEncode. Ensure HTML input is properly formatted on the client using string.Format and InnerText. In source code and wherever, look for the following vulnerabilities. - InnerHTML
- InnerText is not supported by all browsers but the two can be found together. Look for where the strings are originating and if they are properly formatted/encoded.
- SetInnerText()
- JavaScript’s Eval()
- Assigning of strings to page titles, control titles, ect.
- Sometimes we take request object data and immediately process it and render it on the client.
- Check the URL parameters passed in.
- The Request object
- Request.Params
- Request.Forms
- Request.QueryString
- Using HtmlTextWriter or any variation
- RenderBeginTag()
- AddAttribute()
- RenderEndTag()
- HtmlWriter.Write()
- Cookies
- Where are we using them and how are we handling them
Searching for these keywords within source will be a decent starting point for discovering XSS vulnerabilities Microsoft Anti-Cross Site Scripting Library V3.0 Beta Feel free to use a Microsoft API designed for XSS prevention within your code. http://www.microsoft.com/downloads/details.aspx?FamilyId=051ee83c-5ccf-48ed-8463-02f56a6bfc09&displaylang=en Closing Notes – because this topic can go on forever There are tools to help assess if your site is vulnerable. Search for them online. Whether or not you think you need third party APIs to help you write defensive code is entirely up to you. You can always write the code yourself. Cross-site scripting (XSS) can be damaging to a company’s credibility and can cause myriad undesirable effects for individual users. XSS is preventable. Familiarizing oneself with the smells of XSS is a valuable tool to posses as a developer and a tester. At a minimum, educate your developers and testers on the target hot-spots mentioned within this post. References and Resources http://en.wikipedia.org/wiki/Cross-site_scripting http://www.cgisecurity.com/xss-faq.html http://ha.ckers.org/xss.html http://www.owasp.org/index.php/Cross_site_scripting |
|
|
|
|
Wednesday, March 25, 2009 |
|
|
I am always looking for tools to allow me to do more by doing less. Administering Hyper-V with PowerShell can be tedious. James O’Neill’s PowerShell Management Library for Hyper-V is a great tool to improve automation of Hyper-V management using PowerShell. As a tester, I am constantly creating new environments, installing our product, taking snapshots, ect. Doing this by hand is a waste of time in my opinion. Doing this with a script makes life easier and frees up my time. Typically, I prefer to create is to create one VM and to have other VMs inherit from that base image. My second VM (the first child to inherit from the base), I will install daily builds of our product. I will then create a third child, which I use a sandbox. I can easily delete it and recreate as needed without having to install our product over again. I have not consistently found success with using snapshots, so I prefer to use differencing disks. The examples below use differencing disks. This first code block shows how I am using the PowerShell management library to simply the creation of a base VM. There is nothing magic about it. It’s pretty strait-forward. I create a VM, give it a name, set the CPU count, memory size, network adapters, hard drive, and DVD drive. $server = "my-dev-server"
$vmName = "TestParentVM"
$vmVirtualSwitch = "My Virtual Network"
# create a new virtual machine
$vm = New-VM $vmName -server $server
# set cpu count
Set-VMCPUCount $vm 2 -server $server
# set memory size
Set-VMMemory $vm 2 -memory 4GB -server $server
# add a legacy network adapter
Add-VMNIC -vm $vm -VirtualSwitch $vmVirtualSwitch -legacy
# add a default VMBus (non-legacy) network adapter
Add-VMNIC -vm $vm -VirtualSwitch $vmVirtualSwitch
# add the hard drive to the VM
Add-VMNewHardDisk –vm $vm -controllerID 0 -lun 0 -vhdpath "$(get-VHDdefaultPath)\$vmName.vhd" -size 20GB
# add the DVD with bootup ISO
Add-VMDRIVE –vm $vm 1 1 -server $server -DVD
Write-Host "Operation complete."
The next code block will create a differencing disk pointing to the parent created in the previous example. I create the usual, VM, CPU count, ect. What makes this a differencing disk is how the VHD is created by specifying the parent. I do some cleanup in this routine by deleting any previously created VMs or VHDs, and I loop through the creation a failure preventative. $server = "my-dev-server"
$vmName = "TestChildVM"
$vmParent = "TestParentVM"
$vmVirtualSwitch = "My Virtual Network"
#region functions - feel free to move to a separate file
Function DeleteVhd
{
Param ($pathToVhd)
# delete the disk that was added if it exists
if (test-path -path $pathToVhd)
{
Remove-Item -Path $pathToVhd -Force
}
}
#endregion
# delete the VHD if it already exists
DeleteVhd "$(get-VHDdefaultPath)\$vmName.vhd"
# delete the VM if it already exists
Remove-VM -vm $vmName -server $server
# create a new virtual machine
$vm = New-VM $vmName -server $server
# get the vm
$vm = Get-VM $vmName
# set cpu count
Set-VMCPUCount $vm 2 -server $server
# set memory size
Set-VMMemory $vm 2 -memory 4GB -server $server
# get VM Nics available
$vmNics = Get-VMNic -server $server -vmbus -legacy
$vmNicSwitchList = New-Object System.Collections.ArrayList
# get VM Nic Switch available for each VM Nic and add it to our list
foreach ($vmNic in $vmNics)
{
$vmSwitchElementName = (Get-VMNicSwitch $vmNic).ElementName
if ($vmNicSwitchList.Contains($vmSwitchElementName) -ne $true)
{
$vmNicSwitchList.Add($vmSwitchElementName)
}
}
# Use the first available VM Nic Switch - this assumes
# I do not create more than on per each environment.
if ($vmNicSwitchList.Count -gt 0)
{
$vmVirtualSwitch = $vmNicSwitchList[0]
}
# add a legacy network adapter
Add-VMNIC -vm $vm -VirtualSwitch $vmVirtualSwitch -legacy
# add a default VMBus (non-legacy) network adapter
Add-VMNIC -vm $vm -VirtualSwitch $vmVirtualSwitch
# add the hard drive to the VM
$parent = "$(get-VHDdefaultPath)\$vmParent.vhd"
$vhdPath = "$(get-VHDdefaultPath)\$vmName.vhd"
Add-VMNewHardDisk –vm $vm -controllerID 0 -lun 0 -vhdpath $vhdPath -parent $parent
# get the VM to see if a disk is attached to it, if it is not, then it failed
$disks = Get-VMDisk -vm $vm
$count = 1
# if the disk was not successfully added, try and add it again
while ($disks -eq $null -and $count -le 5)
{
Write-Host "RETRY $count - The disk was not properly added. Attempting to retry."
# delete the disk that was added
DeleteVhd "$(get-VHDdefaultPath)\$vmName.vhd"
Add-VMNewHardDisk –vm $vm -controllerID 0 -lun 0 -vhdpath $vhdPath -parent $parent
$disks = Get-VMDisk -vm $vm
$count++
}
if ($disks -eq $null)
{
Write-Host "Operation failed to create this virtual machine. Contact an admin."
}
else
{
Write-Host "Operation completed successfully. Attempting to start the VM."
Start-VM -vm $vm -wait
}
I have found that the VM creation is not consistently successful on the first pass, so I have added the while loop. Since adding that, I have not had any issues.
I hope these help. They should be easy to change if you prefer snapshots versus differencing disks. Thanks to James O’Neill for creating this library. It makes administering Hyper-V much easier. It is available via CodePlex, where the latest release, updates, and forum support can be found. |
Wednesday, March 25, 2009 2:44:50 PM (Mountain Standard Time, UTC-07:00) | | PowerShell | Tools
|
|
|
|
Thursday, November 13, 2008 |
|
|
This is by no means a comprehensive review of SketchPath, but I just wanted to say thanks Phil Fearon, for developing this app. I use XML/XPath/XSL less frequently today than with previous positions, but every now and then, when chiseling away at a slab of XML, having an XPath tool can make my life much easier. I always relied on Interactive XPath Expression Builder 4.0, but larger XML files hindered performance. In an effort to find a good XPath editor, I have installed several I have found on the web, used them, and uninstalled all of them. Ideally, I am looking for a tool that is light and free. By light I mean, I am not looking to install a development studio, nor something that attempts to integrate with all of my existing applications, nor something that requires a reboot when installing or uninstalling, nor something that cannot fully uninstall itself. I plan on using this tool as often as I have to deal with XML/XPath/XSL these days, which is once every few months. Usually the time it takes me to find a tool, install it, author what I need, and uninstall it, I could have written the XPath by hand. As I searched online for tools this time, I stumbled across SketchPath. While hesitant to install another XML app to only end up in my graveyard of XML apps, I gave this one a try. It is free, so I figured, why not. "YES! F-bomb YEAH!" After installing, I loaded up my XML, clicked on an attribute within a node, and sure enough, the XPath needed to locate that element was displayed. It was that simple. After a few more node selections, I had the XPath I needed for my app. In and out like a robbery. "SketchPath is a free XPath Editor and XML analysis and testing tool supporting XPath 1.0 and XPath 2.0. It provides an integrated graphical environment for viewing XML files, developing and testing XPath expressions against them and managing the expressions in file libraries." Thanks Phil! This was exactly what I needed. I will not be uninstalling. |
Thursday, November 13, 2008 10:28:13 AM (Mountain Standard Time, UTC-07:00) | | Tools | Xml/Xsl
|
|
|
|
Tuesday, April 08, 2008 |
|
|
Duplicate code to me is wrong. Writing duplicate code to me is like using poor grammar. If I am unaware of it, I am none the wiser. However, if I knowingly use poor grammar or duplicate code, I feel bad.
After seeing too many duplications across methods in one or more classes, I decided to investigate a way to remove these. I am always looking to remove duplicate code, even code that shares similarities, I look to refator. Removing duplications is important to adapt more easily to change. When a code change is required, we should only have to make it in one place. The following article will show two relatively simple means to address this code smell, delegates and an Aspect-Oriented approach.
The example I am using in this article is seen below. It is a unit test class, StackFixture class, and it is extremely trivial. This is a typical unit test taken from Test-Driven Development in Microsoft .NET. I have added the logging functionality as an easy means to show how these types of DRY violations can occur. While the duplications in this example deal with logging, they could pertain to other, more complex, functionality as well. The approaches to removing duplications across methods in this article can work with these simple scenarios, as well as more complex ones.
Take for example this sample test case. Each test method logs a message before and after executing the test logic. This violates DRY. We want to keep our test logic in our method, but factor out the duplicate logging. Again, if we were not logging, but doing some repetitive logic, we could factor that out as well.
1: [TestFixture] 2: public class StackFixture : AbstractBaseFixture 3: { 4: private Stack stack; 5: 6: [SetUp] 7: public void SetUp() 8: { 9: stack = new Stack(); 10: } 11: 12: [Test] 13: public void Empty() 14: { 15: Log.Info("Starting Empty test"); 16: 17: Assert.IsTrue(stack.IsEmpty); 18: 19: Log.Info("Ending Empty test"); 20: } 21: 22: [Test] 23: public void PushOne() 24: { 25: Log.Info("Starting PushOne test"); 26: 27: stack.Push("first element"); 28: Assert.IsFalse(stack.IsEmpty, "After Push, IsEmpty should be false."); 29: 30: Log.Info("Ending PushOne test"); 31: } 32: 33: [Test] 34: public void Pop() 35: { 36: Log.Info("Starting Pop test"); 37: 38: stack.Push("first element"); 39: stack.Pop(); 40: Assert.IsTrue(stack.IsEmpty, "After Push - Pop, IsEmpty should be true."); 41: 42: Log.Info("Ending Pop test"); 43: } 44: 45: [Test] 46: [ExpectedException(typeof(InvalidOperationException))] 47: public void PopEmptyStack() 48: { 49: Log.Info("Starting PopEmptyStack test"); 50: 51: stack.Pop(); 52: 53: Log.Info("Ending PopEmptyStack test"); 54: } 55: }
Remove Duplications with Delegates
Quite simply, we can remove our method duplications using a delegate, in this case, the System.Action delegate. Thanks to Ayende for helping me understand this option. We create a method, TestMethod (as shown below), and add it to our StackFixture class. The method takes two strings (string beforeMessage and string afterMessage) and the Action delegate, representing the test method logic. We will call this method within our test cases.
1: public void TestMethod(string beforeMessage, string afterMessage, Action action) 2: { 3: // before 4: Log.Info(beforeMessage); 5: 6: // invoke our method 7: action(); 8: 9: // after 10: Log.Info(afterMessage); 11: }
Then, in our tests, we replace the following test method...
1: [Test] 2: public void Pop() 3: { 4: Log.Info("Starting Pop test"); 5: 6: stack.Push("first element"); 7: stack.Pop(); 8: Assert.IsTrue(stack.IsEmpty, "After Push - Pop, IsEmpty should be true."); 9: 10: Log.Info("Ending Pop test"); 11: }
With the same method using our delegate approach.
1: [Test] 2: public void Pop() 3: { 4: TestMethod("Starting Pop test", "Ending Pop test", 5: delegate 6: { 7: stack.Push("first element"); 8: stack.Pop(); 9: Assert.IsTrue(stack.IsEmpty, "After Push - Pop, IsEmpty should be true."); 10: }); 11: }
We can replace each of our test methods with the same TestMethod using the System.Action delegate. It will then easy to omit our before and after strings replacing them with "action.Method.Name," or some other intelligent logic to determine what to log.
This approach works well, but delegates are often difficult to understand. If this solution suits your needs, make sure the implementation is easily maintainable. What is nice about this approach is how simple it is. There is no need to reference any assemblies outside of the .Net framework, i.e. no third party dependencies.
The Aspect-Oriented Approach
Aspect-Oriented Programming (AOP) is an entirely different animal. It certainly deserves more than just a blog post. Please read more about it online. This article will not explain the details of AOP.
If you are reading this, welcome back. I will assume you are now familiar with AOP. There are several options for AOP frameworks. Some frameworks I have used are Spring.net, Castle Project, and PostSharp. The former two provide IoC capabilities as well. I suggest using a well-supported framework, one with community support and frequent updates. Investigate for yourself, there are several nice options available.
AOP with Castle DynamicProxy
Hamilton Verissimo put together a good sample using Castle's DynamicProxy. It is a nice, clean implementation.This worked fine for me and would work well in other situations. However, in my scenario, if I were to use this approach, I needed to have each of my test classes extend from MarshalByRef. In addition, I would need to modify the underlying NUnit framework to create my proxies in order to provide advice. Since I could not do the latter, or did not want to investigate, I searched for other AOP options.
The DynamicProxy aproach to solving your AOP needs is a great option. It just did not work in my situation, only because NUnit executes each of my methods. I would need to somehow intercept the creation of my test class, create a proxy of it, and execute the test methods on it.
AOP with PostSharp
Gael Fraiteur's PostSharp is a great option for AOP needs. It is extremely clean and easy to use. It is the simplest AOP framework I have used. I suggest watching Gael's video tutorial.
The first thing I needed to do, besides downloading and installing PostSharp, is to add two references to my project, PostSharp.Laos and PostSharp.Public. After that, I create a simple class extending OnMethodInvocationAspect, called LoggingMethodInvocationAspect.
1: [Serializable] 2: public sealed class LoggingMethodInvocationAspect : OnMethodInvocationAspect 3: { 4: private ILogger log; 5: 6: public LoggingMethodInvocationAspect(ILogger logger) 7: { 8: log = logger; 9: { 10: 11: public override void OnInvocation(MethodInvocationEventArgs eventArgs) 12: { 13: // before 14: log.Info("OnInvocation Before proceed"); 15: 16: // invoke 17: eventArgs.Proceed(); 18: 19: // after 20: log.Info("OnInvocation After proceed"); 21: } 22: }
At this point, all we need to do is apply our aspect on target methods. The "AttributeTargetMembers" attribute can use wildcards. This tells the AOP framework to only intercept those methods in the "MathService" class that start with "Test." Below is the sample where I specify the target assembly, target type (class or classes to intercept), and target methods to intercept. There are many features beyond what I am showing so do further investigation.
1: [assembly: ClassLibrary.SampleInterfaces.LoggingMethodInvocationAspect( 2: AttributeTargetAssemblies = "ClassLibrary.UnitTesting.Sandbox", 3: AttributeTargetTypes = "ClassLibrary.UnitTesting.Sandbox.MathService", 4: AttributeTargetMembers = "Test*")]
Finally, my StackFixture class now looks something like this. Notice that the duplicate logging logic is now removed and each test method is prefixed with "Test" in the method name. This is so that PostSharp can filter what methods to intercept.
1: [assembly: ClassLibrary.SampleInterfaces.LoggingMethodInvocationAspect( 2: AttributeTargetAssemblies = "ClassLibrary.UnitTesting.Sandbox", 3: AttributeTargetTypes = "ClassLibrary.UnitTesting.Sandbox.MathService", 4: AttributeTargetMembers = "Test*")] 5: 6: [TestFixture] 7: public class StackFixture 8: { 9: private Stack stack; 10: 11: [SetUp] 12: public void SetUp() 13: { 14: stack = new Stack(); 15: } 16: 17: [TearDown] 18: public void TearDown(){} 19: 20: [Test] 21: public void TestEmpty() 22: { 23: Assert.IsTrue(stack.IsEmpty); 24: } 25: 26: [Test] 27: public void TestPushOne() 28: { 29: stack.Push("first element"); 30: Assert.IsFalse(stack.IsEmpty, "After Push, IsEmpty should be false."); 31: } 32: 33: [Test] 34: public void TestPop() 35: { 36: stack.Push("first element"); 37: stack.Pop(); 38: Assert.IsTrue(stack.IsEmpty, "After Push - Pop, IsEmpty should be true."); 39: } 40: 41: [Test] 42: [ExpectedException(typeof(InvalidOperationException))] 43: public void TestPopEmptyStack() 44: { 45: stack.Pop(); 46: } 47: }
The end result, a StackFixture test class with duplicate logging logic removed. The PostSharp AOP framework post-processes the compiled assembly and inserts itself, easily providing points of interception.
The PostSharp approach does involve a third-party dependency, but I feel like it is cleaner than the delegate approach. Gael informed me future versions of PostSharp will provide a more configurable solution than adding the [assembly ...] reference for the aspects, perhaps an XML configuration option. This can be done today, but involves some work.
Whether you use delegates, AOP, or some other approach, remove duplicate code wherever possible. I am happy to use either approach in my projects. There are tradeoffs to either solution, so investigate for yourself. |
|
|
|
|
Friday, April 04, 2008 |
|
|
What happened to my ReSharper type completion functionality? "Alt+enter" recently stopped showing up for me. I checked around everywhere looking for a setting that enables type completion. The image below shows no ability to use a shortcut to provide type completion.
After looking around and finding nothing, finally a co-worker mentioned clicking "Apply" again. Sure enough that worked. If you come across this problem, access your ReSharper options, ReSharper -> Options -> Environment -> General. Then click "Apply" and see if that resolves it.
Finally, it is back, in all its glory.

|
Friday, April 04, 2008 1:37:02 PM (Mountain Standard Time, UTC-07:00) | | Tools
|
|
|
|
Tuesday, April 01, 2008 |
|
|
Craig Neuwirt recently started a blog focused on NHibernate, as mentioned by Ayende. NHibernate is an ORM tool I have used on current and past projects and it is something I feel I would like I want to study further. So far, Craig is walking us through NHibernate from the ground-up, with the latest and greatest. I anticipate this being an informative blog to follow.
The NHibernate FAQ Craig Neuwirt Hibernating Rhinos |
|
|
|
|
Thursday, March 27, 2008 |
|
|
I am currently working in a new development environment, unlike any that I have used in the past. It is different for two reasons, magnitude of dependencies and build process. The warning I have been given is, "this is a complex beast with lots of stuff in it, and much can go wrong." That statement pretty much covers the magnitude of dependencies stuff. As for the build process, my first question asked was, "you mean we don't use 'Ctrl+Shift+B' (in Visual Studio)?" No, we build using a command-line style approach, outside of the IDE. Due the dependencies and build process, I wanted to schedule nightly builds on my local machines. This was when I discovered Windows PowerShell. PowerShell uses the .NET CLR and the .NET framework to provide new tools and methods for administering Windows environments. While similar in some aspects as DOS, PowerShell is much more. It is a command-line shell and scripting language that allows administrators to use C#. Each night I want to backup certain files, sync files, clean and build my projects for 32 and 64 bit systems, update my environment with dependency changes, and email myself the log files generated during this process. I am not a DOS command nor scripting guru, but I could figure this out with some time. With PowerShell, I can leverage my C# knowledge to do all these tasks in a short amount of time. If you want more control over administering your environments and would like to use C#, check out PowerShell. There is a good amount of support and tutorials to help get started. Trivial Examples The following is a trivial example of how to connect to a SQL database, query the Employees table of the Northwind database, and write those results to the screen. The PowerShell scripting syntax can be seen below. 1: $conn = New-Object System.Data.SqlClient.SqlConnection 2: $conn.ConnectionString = "Data Source=.;Database=Northwind;" 3: $cmdText = "SELECT TOP 10 * FROM EMPLOYEES" 4: 5: $conn.Open() 6: $cmd = New-Object System.Data.SqlClient.SqlCommand($cmdText,$conn) 7: $rdr = $cmd.ExecuteReader() 8: 9: while($rdr.Read()) 10: { 11: $id = $rdr["EmployeeID"].ToString() 12: $fn = $rdr["FirstName"].ToString() 13: $ln = $rdr["LastName"].ToString() 14: Write-Host "$id $fn $ln" 15: } 16: 17: $conn.Close()
While that example is extremely trivial, it does show the power of using C# logic with the PowerShell language. It is easy to see how the code example above was translated from C# into PowerShell. The differences are syntactic.
For my nightly build scenario, I am able to create a scheduled task that calls a batch file, with similar contents as below.
1: REM Calling Nightly Build 2: 3: REM do the necessary to clean and build my environment 4: call MyBuildLogicFile.bat 5: 6: REM call powershell scripts 7: powershell -command "& C:\PowerShellScripts\MyBuildScript.ps1
The batch file does the building then calls a PowerShell script I created to do help me parse my log files and email the contents. It actually call two scripts, one for parsing the content of my resulting log file, and the other to email the contents of the log file. The contents of the two files can be seen below.
PowerShell provides a number of predefined methods that can be used out of the box. Since I am interested in reading a log file, parsing its contents, and emailing the results, there are some functions available for making this scenario easier. For example, I do not need to recreate the wheel to read in a file's contents. I can use Get-Content. Before getting carried away with writing too much C#, check the available cmdlets (commandlets) to see if your desired functionality exists.
My file content parser script, using Get-Content.
1: # Create a StringBuilder to retain our log file contents 2: $sb = new-object System.Text.StringBuilder 3: 4: # append a line break point, <br/> for the log file contents 5: foreach ($line in get-content "C:\Output.log") 6: { 7: $sb.Append($line).Append("<br/>") 8: } 9: 10: # Call our Emailer.ps1 to send this content to us 11: powershell -command "& C:\PowerShellScripts\Emailer.ps1 -param '$sb'"
My email script that is called from the above code.
1: param($param1) 2: 3: $message = new-object System.Net.Mail.MailMessage("me@mail.com", "me@mail.com") 4: $message.IsBodyHtml = $True 5: $message.Subject = "Automated Build Update" 6: $message.Body += $param1; 7: 8: $smtp = new-object Net.Mail.SmtpClient(”smtp.mail.com”, 587) 9: $smtp.EnableSsl = $True 10: $smtp.Credentials = new-object System.Net.NetworkCredential("username", "password") 11: $smtp.Send($message)
Pretty simple. Thanks to PowerShell, I have more control over administering my development and test environments using my preexisting knowledge of C#. One command that was always useful in Unix/Linux is grep. PowerShell uses Regex to simulate similar functionality, and you can find examples of those online. |
Thursday, March 27, 2008 9:41:57 PM (Mountain Standard Time, UTC-07:00) | | Technology | Tools
|
|
|
|
Monday, March 24, 2008 |
|
|
I am using Internet Explorer 8 Beta right now after learning about the new features it provides beyond its previous version, IE7. I hate to admit this, but some time ago I gave up on using FireFox when it starting consuming nearly 100% of my CPU. This was happening all too frequently and I tried to resolve the issue using several approaches I found posted on blogs. After not having any luck, I started thinking, "why do I prefer FireFox over IE?" What I liked about FireFox I could now install in IE7 with IE7Pro, an add-on for IE7 managed by a multi-national team, not a Microsoft affilate. FireFox does have a strong community creating and sharing browser niceties that make the web experience easier and more pleasant. Internet Explorer has this as well in the form of IE7 add-ons. At this point, I am happy with IE7 running IE7Pro. My browser experience is great, and when I absolutely need to use one of my FireFox extensions, I will start-up FireFox and run the extension, hopefully before it consumes my CPU. Since I installed the latest version of Internet Explorer, IE8 Beta, FireFox is that much further from my mind. IE8 provides a number of built-in tools that make the browsing experience that much sweeter. For a web developer, the integrated developer tools are a must have, and for someone new to web developing, these tools will certainly shorten the learning curve. The JavaScript debugging capabilities are great. I am no longer dependent upon my Visual Studio IDE since a built-in IDE-like tool is provided for accessing and manipulating HTML, CSS, and JavaScript. Another great feature is how Ajax navigation history is retained in IE8. This is perfect for mapping software where you constantly interact with the map by zooming in or out. The window.location.hash is set with a value to enable managing the page history. This is possible in previous versions of IE, but it requires some work, usually in the form of installing and configuring a framework to use with your site, something like the ReallySimpleHistory library. I will spare you more details on IE8. I do encourage you to try it out for yourself. There are a number of other nice features not mentioned. IE8 integrates nicely with Live Writer, which makes posting easier. |
Monday, March 24, 2008 8:54:09 PM (Mountain Standard Time, UTC-07:00) | | Technology | Tools
|
|
|
|
Friday, March 21, 2008 |
|
|
After three years, I decided to finally update my blog engine to the latest version of DasBlog. What I have discovered over three years is that finding time to blog can be difficult, and finding time to maintain the blog site takes a backseat to blogging. Now that I have updated to the latest DasBlog, I inherit a number of nice security features to battle spam, as well as some cool usability features. Thanks to the DasBlog team for their efforts in creating this project, one of the few blog engines that does not require a database. I have not spent much time skinning this site and I do not plan on it right now. I use the built in RSS capabilities of Microsoft Office Outlook for aggregating my feeds, so I rarely view the actual websites that I read. I am guessing that most readers use a similar approach, so with this in mind, my current site theme works for now. What RSS readers are you using? |
Friday, March 21, 2008 8:54:42 AM (Mountain Standard Time, UTC-07:00) | | Misc | Technology | Tools
|
|
|
|
Saturday, December 29, 2007 |
|
|
I am not a build engineer, but I do enjoy architecting systems to help make the software build process better. I work in a start up for various reasons, one of which is the opportunity to solve wide ranging business problems. Recently, I put on my build engineer's hat and dedicated some time to improving our software build process, stepping outside of my immediate comfort zone.
I rely on a number of tools for our continuous integration practices. One of which is CruiseControl.NET, the other is NAnt. Both of these tools use .NET technologies and are ports from their Java projects, CruiseControl and Ant. Besides Lucene.Net, what .NET projects are not better than their Java cousins? Just kidding, take it easy. In addition, CruiseControl.NET integrates with a number of technologies to improve the build process. NAnt, MSBuild, NUnit, FxCop, and FitNesse are just a few. With NAnt and MSBuild, we can call more applications as well, like TypeMock, BeyondCompare, and other necessary applications for our system.
As I mentioned, I am not a build engineer, but I get the opportunity to play the role. Our continuous integration process uses a number of free and open-source projects because they are widely supported and proven technologies, and the price is right. As our developers commit code into our SCM system (we use Subversion), the CruiseControl server checks for updates and begins the build and verification process. Helping with this process is NAnt, an extremely helpful .NET build tool.
What I like most about NAnt, and probably the primary reason for this post, is that I can leverage my knowledge of C# to write functions to aid in the process of building better products. CruiseControl uses XML config files, where projects are created, properties are configured, dependencies are defined, and much more. In my scenario, I have the CruiseControl config file calling my NAnt build scripts, which are also written in XML. Fortunately, I feel confident in my XML skills, so this is easy for building basic projects and adding to them.
The NAnt build scripts are used to define how the project is built. As NAnt is executed, it calls a build script. A typical scenario of actions defined in the script could be to check out the latest code, clean the build environment, build the project, test the project, and deploy the project with necessary configuration files (app.config, web.config, ect.). CruiseControl notifies the development team immediately on the build’s status - pass or fail.
What I set out to do, and where NAnt helped me the most, is with versioning my assemblies and deploying to a common location. Versioning of the assemblies requires more control over my build scripts. In this instance it requires incrementing the Major.Minor.Build.Revision version in my AssemblyInfo.cs files for all projects before the build, and rolling these changes back anywhere during the process if the build should fail.
Discovering how to call C# functions within NAnt increased my ability to do more and saved time. NAnt has a number of predefined functions that can be used to make life easier, and it also has the ability to create custom functions that can be written in any number of .NET languages. The ability to write custom functions made my life much easier and gave me the control I needed to do more for my automated build system.
Defining custom functions looks like the following.
1: <script language="C#" prefix="CSharp"> 1: 2: <code> 3: <![CDATA[ 4: 5: [Function("HelloWorld")] 6: public static string HelloWorld() 7: { 8: return "Hello World"; 9: } 10: 11: [Function("GetIncrementedBuildVersion")] 12: public static string GetIncrementedBuildVersion(string buildVersionFile, string svnRevision) 13: { 14: // Read in a file 15: System.IO.FileStream fs = new System.IO.FileStream(buildVersionFile, ... (more code here) 16: 17: // Increment file version number 18: version++; // you get the idea 19: 20: // Return incremented version 21: return version; 22: } 23: ]]> 24: </code> </script>
Calling the custom functions now looks like this in NAnt scripts. I am using an "echo" element simply to call my method, HelloWorld, and echo "Hello World" back to the screen. I use a "property" element to return the value of my GetIncrementedBuildVersion method and save this for latter use in my scripts.
1: <echo message="My Hello World Message is ${CSharp::HelloWorld()}"/> 2: <property name="incremented.build.version" value="${CSharp::GetIncrementedBuildVersion(master.build.version,svn.revision)}" />
Custom functions are pretty powerful and they certainly saved me a good deal of time, and in a start up, this is gold. Being a build engineer is a fulltime position and I quickly learned this over the past two weeks. These are a few of the tools I chose to use to help me improve our software build process.If you would like more detailed examples of CruiseControl configs or NAnt scripts, I would be happy to provide those, just email me. I did not want to become that detailed in this post. |
Saturday, December 29, 2007 1:22:08 PM (Mountain Standard Time, UTC-07:00) | | Design | Tools | Xml/Xsl
|
|
|
|
Monday, September 24, 2007 |
|
|
|
Monday, September 24, 2007 6:02:32 PM (Mountain Standard Time, UTC-07:00) | | Design | Tools
|
|
|
|
Tuesday, September 18, 2007 |
|
|
Configuring Log4Net to using with ASP.NET and NHibernate |
Tuesday, September 18, 2007 9:46:23 PM (Mountain Standard Time, UTC-07:00) | | Tools
|
|
|
|
Wednesday, May 23, 2007 |
|
|
SQL Server 2005 Connection Issues |
Wednesday, May 23, 2007 9:17:59 PM (Mountain Standard Time, UTC-07:00) | | Technology | Tools
|
|
|
|
Tuesday, August 22, 2006 |
|
|
Using the Really Simple History framework for solving AJAX URL history woes |
Tuesday, August 22, 2006 8:34:02 PM (Mountain Standard Time, UTC-07:00) | | Tools
|
|
|
|
Tuesday, July 11, 2006 |
|
|
Some thoughts on my use with VMWare so far |
Tuesday, July 11, 2006 12:03:37 PM (Mountain Standard Time, UTC-07:00) | | Tools
|
|
|
|
Monday, January 16, 2006 |
|
|
Tracking Usability with StatCounter, a free, web-tracking service. |
Monday, January 16, 2006 2:55:39 PM (Mountain Standard Time, UTC-07:00) | | Tools
|
|
|
|
|
|
|
| Archive |
| June, 2009 (1) |
| May, 2009 (1) |
| April, 2009 (1) |
| March, 2009 (1) |
| February, 2009 (2) |
| January, 2009 (1) |
| December, 2008 (2) |
| November, 2008 (1) |
| October, 2008 (1) |
| September, 2008 (1) |
| August, 2008 (1) |
| July, 2008 (2) |
| June, 2008 (1) |
| May, 2008 (1) |
| April, 2008 (8) |
| March, 2008 (8) |
| February, 2008 (2) |
| January, 2008 (1) |
| December, 2007 (2) |
| November, 2007 (2) |
| October, 2007 (4) |
| September, 2007 (3) |
| August, 2007 (1) |
| July, 2007 (2) |
| June, 2007 (1) |
| May, 2007 (2) |
| April, 2007 (2) |
| March, 2007 (1) |
| February, 2007 (1) |
| January, 2007 (3) |
| December, 2006 (1) |
| November, 2006 (1) |
| October, 2006 (2) |
| September, 2006 (1) |
| August, 2006 (1) |
| July, 2006 (2) |
| June, 2006 (3) |
| May, 2006 (9) |
| April, 2006 (1) |
| March, 2006 (4) |
| February, 2006 (2) |
| January, 2006 (3) |
| December, 2005 (4) |
| November, 2005 (4) |
| October, 2005 (3) |
| September, 2005 (5) |
| August, 2005 (7) |
| July, 2005 (5) |
| June, 2005 (5) |
| May, 2005 (7) |
| April, 2005 (3) |
| March, 2005 (6) |
| February, 2005 (7) |
| January, 2005 (9) |
| December, 2004 (4) |
|
|
|
|
| About |
Powered by:
Disclaimer
The opinions expressed herein are my own personal opinions and do not represent
my employer's view in any way.
© Copyright 2010 MuellerDesigns.net
Sign In
|
|
|
|