<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>danielcolomb.com &#187; programming</title>
	<atom:link href="http://www.danielcolomb.com/category/programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.danielcolomb.com</link>
	<description>rantings of a technophile</description>
	<lastBuildDate>Tue, 13 Dec 2011 14:26:27 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Deploying Windows Services from TFS</title>
		<link>http://www.danielcolomb.com/2011/06/27/deploying-windows-services-from-tfs/</link>
		<comments>http://www.danielcolomb.com/2011/06/27/deploying-windows-services-from-tfs/#comments</comments>
		<pubDate>Mon, 27 Jun 2011 18:26:11 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[Source Control]]></category>
		<category><![CDATA[TFS]]></category>
		<category><![CDATA[deploy]]></category>
		<category><![CDATA[PsExec]]></category>
		<category><![CDATA[Service]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://www.danielcolomb.com/?p=577</guid>
		<description><![CDATA[<p>As part of our initiative to automate code deployments, we needed to move windows services from TFS to our test servers. The way we did this before was to have a build stage all the files and then either stop the services on the destination machine manually, copy files, and restart the services, or [...]]]></description>
			<content:encoded><![CDATA[<p>As part of our initiative to automate code deployments, we needed to move windows services from TFS to our test servers. The way we did this before was to have a build stage all the files and then either stop the services on the destination machine manually, copy files, and restart the services, or use a homebrewed application to deploy the service; which is fine and dandy, except that the original developer isn&#8217;t with the company anymore and the application is limited in certain ways.</p>
<p>So to solve this, I went ahead and created a new build template that would deploy our windows services from a TFS build.</p>
<p><strong>Some prerequisites:<br />
</strong></p>
<ul>
<li><span style="font-weight: normal;">PsExec must be on the build machine </span></li>
<li>Your build service must be an admin on the machine you&#8217;re deploying to (to be able to stop and start services)</li>
</ul>
<p>First, we&#8217;ll set up a new Code Activity, it&#8217;s very similar to the <a title="Deploying to Multiple Locations in TFS 2010" href="http://www.danielcolomb.com/2011/02/23/deploying-to-multiple-locations-in-tfs-2010/">DeployFiles</a> class i wrote about before</p>
<pre class="brush: csharp; title: Code block; notranslate">
using System;
using System.Activities;
using System.IO;
using System.Text.RegularExpressions;
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.Build.Workflow.Activities;
using Microsoft.TeamFoundation.Build.Workflow.Tracking;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;
namespace BuildProcess.Activities
{
    [BuildActivity(HostEnvironmentOption.Agent)]
    public sealed class DeployWindowsService : CodeActivity
    {
        //Source dir being deployed from
        [RequiredArgument]
        public InArgument&lt;string&gt; SourceDir { get; set; }
        //Destination dir being copied from
        [RequiredArgument]
        public InArgument&lt;string[]&gt; DestinationDir { get; set; }
        //Files to include
        [RequiredArgument]
        public InArgument&lt;string&gt; FileInclusions { get; set; }
        //Folders to include
        [RequiredArgument]
        public InArgument&lt;string&gt; FolderInclusions { get; set; }
        [RequiredArgument]
        public InArgument&lt;string&gt; CollectionName { get; set; }
        public InArgument&lt;string&gt; ConfigLocations { get; set; }
        //globals
        public string fileInclusionPattern = &quot;&quot;;
        public string folderInclusionPattern = &quot;&quot;;
        protected override void Execute(CodeActivityContext context)
        {
            // Obtain the runtime value of the Text input argument
            string fileInclusions = context.GetValue(this.FileInclusions);
            string folderInclusions = context.GetValue(this.FolderInclusions);
            string configLocations = context.GetValue(this.ConfigLocations);
            string[] destinations = context.GetValue(this.DestinationDir);
            string collectionName = context.GetValue(this.CollectionName);
            DirectoryInfo sourceDir = new DirectoryInfo(context.GetValue(this.SourceDir));
            //parse exclusions, add them to regex patterns
            if (!String.IsNullOrWhiteSpace(fileInclusions))
            {
                string[] fileinarr = fileInclusions.Split(',');
                fileInclusionPattern = &quot;(&quot;;
                foreach (string s in fileinarr)
                {
                    fileInclusionPattern += s.ToUpper().Trim().Replace(&quot;.&quot;, @&quot;\.&quot;).Replace(&quot;*&quot;, @&quot;[a-zA-Z0-9]*&quot;) + &quot;$|&quot;;
                }
                if (fileInclusionPattern.EndsWith(&quot;|&quot;))
                    fileInclusionPattern = fileInclusionPattern.Substring(0, fileInclusionPattern.Length - 1);
                fileInclusionPattern += &quot;)&quot;;
            }
            if (!String.IsNullOrWhiteSpace(folderInclusions))
            {
                string[] folderinarr = folderInclusions.Split(',');
                folderInclusionPattern = &quot;(&quot;;
                foreach (string s in folderinarr)
                {
                    folderInclusionPattern += s.ToUpper().Trim().Replace(&quot;.&quot;, @&quot;\.&quot;).Replace(&quot;*&quot;, @&quot;[a-zA-Z0-9]*&quot;) + &quot;$|&quot;;
                }
                if (folderInclusionPattern.EndsWith(&quot;|&quot;))
                    folderInclusionPattern = folderInclusionPattern.Substring(0, folderInclusionPattern.Length - 1);
                folderInclusionPattern += &quot;)&quot;;
            }
            foreach (string dir in destinations)
            {
                DirectoryInfo destDir = new DirectoryInfo(dir);
                //Used for debugging, you don't need this, unless you want to display something custom here.
                context.Track(new BuildInformationRecord&lt;BuildMessage&gt;()
                {
                    Value = new BuildMessage()
                    {
                        Importance = BuildMessageImportance.High,
                        Message = &quot;Source: &quot; + sourceDir.FullName +
                            &quot;\r\nDestination: &quot; + destDir.FullName +
                            &quot;\r\nFolder Inclusion Pattern: &quot; + folderInclusionPattern +
                            &quot;\r\nFile Inclusion Pattern: &quot; + fileInclusionPattern +
                            &quot;\r\nFolder Inclusions String: &quot; + folderInclusions +
                            &quot;\r\nFile Inclusions String: &quot; + fileInclusions,
                    },
                });
                CopyDir(sourceDir, destDir);
            }
            //copy config files
            if (!String.IsNullOrWhiteSpace(configLocations))
            {
                string strTFSName = collectionName;
                //set up TFS connectivity
                Uri tfsName = new Uri(strTFSName);
                TfsTeamProjectCollection tfs = new TfsTeamProjectCollection(tfsName);
                VersionControlServer vcs = (VersionControlServer)tfs.GetService(typeof(VersionControlServer));
                //copy config files to proper location
                string timestamp = DateTime.Now.Ticks.ToString();
                string workspacePath = @&quot;C:\temp\TFSConfigDeployment_&quot; + timestamp;
                Workspace ws = vcs.CreateWorkspace(&quot;TFSConfigDeployment_&quot; + timestamp, vcs.AuthorizedUser);
                //get the workspace locally
                ws.Map(configLocations, workspacePath);
                ws.Get();
                foreach (string configDir in destinations)
                {
                    CopyDir(new DirectoryInfo(workspacePath), new DirectoryInfo(configDir));
                }
                RemoveWorkSpaceDirectory(workspacePath);
            }
        }
        private void RemoveWorkSpaceDirectory(string workspacePath)
        {
            DirectoryInfo dir = new DirectoryInfo(workspacePath);
            var files = dir.EnumerateFiles();
            foreach (FileSystemInfo info in files)
            {
                string filePath = info.FullName;
                if ((File.GetAttributes(filePath) &amp; FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
                {
                    File.SetAttributes(filePath, FileAttributes.Normal);
                }
            }
            var subDirs = dir.EnumerateDirectories();
            foreach (DirectoryInfo subDir in subDirs)
            {
                RemoveWorkSpaceDirectory(subDir.FullName);
            }
            dir.Delete(true);
        }
        private void CopyDir(DirectoryInfo sourceDir, DirectoryInfo destDir)
        {
            //create destination dir if it doesn't exist
            if (!destDir.Exists)
            {
                destDir.Create();
            }
            // get all files from current dir
            FileInfo[] files = sourceDir.GetFiles();
            //copy ze files!!
            foreach (FileInfo file in files)
            {
                string destFilePath = Path.Combine(destDir.FullName, file.Name);
                if (!String.IsNullOrWhiteSpace(fileInclusionPattern))
                {
                    if (Regex.IsMatch(file.Name.ToUpper(), fileInclusionPattern))
                    {
                        if (File.Exists(destFilePath))
                        {
                            if ((File.GetAttributes(destFilePath) &amp; FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
                            {
                                File.SetAttributes(destFilePath, FileAttributes.Normal);
                            }
                            File.Delete(destFilePath);
                        }
                        file.CopyTo(destFilePath);
                        if ((File.GetAttributes(destFilePath) &amp; FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
                        {
                            File.SetAttributes(destFilePath, FileAttributes.Normal);
                        }
                    }
                }
            }
            // get subdirectories.
            DirectoryInfo[] dirs = sourceDir.GetDirectories();
            foreach (DirectoryInfo dir in dirs)
            {
                // Get destination directory.
                string destinationDir = Path.Combine(destDir.FullName, dir.Name);
                if (!String.IsNullOrWhiteSpace(folderInclusionPattern))
                {
                    if (Regex.IsMatch(dir.Name.ToUpper(), folderInclusionPattern))
                    {
                        // Call CopyDirectory() recursively.
                        CopyDir(dir, new DirectoryInfo(destinationDir));
                    }
                }
            }
        }
    }
}
</pre>
<p>For the next step, you&#8217;ll also want to look at the previous post about <a title="Deploying to Multiple Locations in TFS 2010" href="http://www.danielcolomb.com/2011/02/23/deploying-to-multiple-locations-in-tfs-2010/">deploying files from TFS</a>. After you&#8217;ve opened up your ProcessTemplate, you&#8217;ll want to have the following arguements:</p>
<ul>
<li>DeploymentDir &#8211; In &#8211; String[]</li>
<li>SourceRootDir &#8211; In &#8211; String</li>
<li>CollectionName &#8211; In &#8211; String</li>
<li>PsExecPath &#8211; In &#8211; String</li>
<li>ServiceName &#8211; In &#8211; String</li>
<li>ServerName &#8211; In &#8211; String</li>
<li>FileInclusions &#8211; In &#8211; String</li>
<li>FolderInclustions &#8211; In &#8211; String</li>
<li>RestartService &#8211; In &#8211; Boolean &#8211; True</li>
</ul>
<p>Each of these you&#8217;ll probably want to add to the Metadata Argument so you can keep your build definitions organized.</p>
<p><a href="http://www.danielcolomb.com/wp-content/uploads/2011/06/buildDef.png"><img class="alignnone size-full wp-image-584" title="buildDef" src="http://www.danielcolomb.com/wp-content/uploads/2011/06/buildDef.png" alt="" width="745" height="197" /></a></p>
<p>And you&#8217;ll want to add the following Variable:</p>
<ul>
<li>PsExecResult &#8211; Int32 &#8211; Revert Workspace and Copy Files&#8230;</li>
</ul>
<p>Under Process &gt; Sequence &gt; Run On Agent &gt; Try Compile, Test, and Associate Changesets and Work Items &gt; Revert Workspace and Copy Files to Drop Location &gt; If Deployment Location is Set you&#8217;ll want to place a new Sequence and call it Stop Service, Copy Files, Start Service.</p>
<p><a href="http://www.danielcolomb.com/wp-content/uploads/2011/06/StopCopyStartServices.png"><img class="alignnone size-full wp-image-578" title="StopCopyStartServices" src="http://www.danielcolomb.com/wp-content/uploads/2011/06/StopCopyStartServices.png" alt="" width="508" height="673" /></a></p>
<p>Inside that Sequence you&#8217;ll want to place an Invoke Process activity, the new DeployWindowsServices code activity, and an If statement with another Invoke Process activity in the Then clause.</p>
<p>For the first Process Invocation:</p>
<p><a href="http://www.danielcolomb.com/wp-content/uploads/2011/06/InvokePsExecStopService.png"><img class="alignnone size-full wp-image-581" title="InvokePsExecStopService" src="http://www.danielcolomb.com/wp-content/uploads/2011/06/InvokePsExecStopService.png" alt="" width="351" height="176" /></a></p>
<p>Arguements:  ServerName + &#8221; -s -d net stop &#8221; + ServiceName<br />
DisplayName: Stop Service<br />
FileName: PsExecPath<br />
Result: PsExecResult</p>
<p>For the Deployment Activity:</p>
<p><a href="http://www.danielcolomb.com/wp-content/uploads/2011/06/DeployService.png"><img class="alignnone size-full wp-image-579" title="DeployService" src="http://www.danielcolomb.com/wp-content/uploads/2011/06/DeployService.png" alt="" width="354" height="173" /></a></p>
<p>CollectionName: CollectionName<br />
DestinationDir: DeploymentDir<br />
DisplayName: Deploy Windows Service<br />
FileInclustions: FileInclusions<br />
FolderInclustions: FolderInclusions<br />
SourceDir:  BinariesDirectory + &#8220;\&#8221; + SourceRootDir</p>
<p>For the If statement, just check to see if RestartService is set to True, and then enter the values for the second Process Invocation:</p>
<p><a href="http://www.danielcolomb.com/wp-content/uploads/2011/06/InvokePsExecStartService.png"><img class="alignnone size-full wp-image-580" title="InvokePsExecStartService" src="http://www.danielcolomb.com/wp-content/uploads/2011/06/InvokePsExecStartService.png" alt="" width="353" height="179" /></a></p>
<p>Arguements:  ServerName + &#8221; -s -d net start &#8221; + ServiceName<br />
DisplayName: Start Service<br />
FileName: PsExecPath</p>
<p><strong>*NOTE, THE FOLLOWING SECTION DOES NOT WORK PROPERLY YET*</strong></p>
<p>After the If statement, you&#8217;ll want to add in another If, this will check to see if PsExec has failed or not.<a href="http://www.danielcolomb.com/wp-content/uploads/2011/06/PsExecFail.png"><img class="alignnone size-full wp-image-582" title="PsExecFail" src="http://www.danielcolomb.com/wp-content/uploads/2011/06/PsExecFail.png" alt="" width="482" height="223" /></a></p>
<p>Since this isn&#8217;t working properly yet, i just check to see if PsExecResult is &#8217;1&#8242;, which it hasn&#8217;t been as of this writing. In the Then block, add a Throw activity and have it throw an exception of:</p>
<pre class="brush: csharp; title: Code block; notranslate">
New Exception(&quot;PsExecResult: &quot; + PsExecResult.ToString())
</pre>
<p>Optionally, you can also add WriteBuildMessage and WriteBuildWarning activities to your Invoke Process Activities, these are nice because you can see what the process you are invoking outputs.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.danielcolomb.com/2011/06/27/deploying-windows-services-from-tfs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Deploying to Multiple Locations in TFS 2010</title>
		<link>http://www.danielcolomb.com/2011/02/23/deploying-to-multiple-locations-in-tfs-2010/</link>
		<comments>http://www.danielcolomb.com/2011/02/23/deploying-to-multiple-locations-in-tfs-2010/#comments</comments>
		<pubDate>Wed, 23 Feb 2011 16:32:55 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[TFS]]></category>
		<category><![CDATA[deploy]]></category>
		<category><![CDATA[multiple locations]]></category>
		<category><![CDATA[TFS 2010]]></category>

		<guid isPermaLink="false">http://www.danielcolomb.com/?p=517</guid>
		<description><![CDATA[<p>This is just a forewarning, I am not an expert in the ways of TFS. I&#8217;ve only been working with TFS in general for about a year, and TFS 2010 for about 2 months or so. That being said, if anyone has recommendations on a better way to do this, please point me in [...]]]></description>
			<content:encoded><![CDATA[<p>This is just a forewarning, I am not an expert in the ways of TFS. I&#8217;ve only been working with TFS in general for about a year, and TFS 2010 for about 2 months or so. That being said, if anyone has recommendations on a better way to do this, please point me in the right direction <img src='http://www.danielcolomb.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h4>Scenario:</h4>
<p>We want to deploy our built code to different environments, but, we don&#8217;t want everything that&#8217;s dumped into the Release folder.</p>
<h4>The Plan:</h4>
<p>The plan is to create a custom build activity to copy files from one place to another checking each file against an exclusion list.</p>
<h4>The Guts:</h4>
<p>Referencing my previous post, <a title="Dependency Replication in TFS 2010" href="http://www.danielcolomb.com/2011/01/20/dependency-replication-in-tfs-2010/">Dependency Replication in TFS 2010</a>, I will build upon the write-ups by <a title="Customizing Team Build 2010" href="http://www.ewaldhofman.nl/post/2010/04/20/Customize-Team-Build-2010-e28093-Part-1-Introduction.aspx">Ewald Hofman</a>.</p>
<p>You can grab the file here: <a title="C# source" href="http://www.danielcolomb.com/files/DeployFiles.cs">DeployFiles.cs</a></p>
<p>Here&#8217;s the whole activity:</p>
<pre class="brush: csharp; title: Code block; notranslate">
using System;
using System.Activities;
using System.IO;
using System.Text.RegularExpressions;
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.Build.Workflow.Activities;
using Microsoft.TeamFoundation.Build.Workflow.Tracking;

namespace BuildProcess.Activities
{
    [BuildActivity(HostEnvironmentOption.Agent)]
    public sealed class DeployFiles : CodeActivity
    {
        //Source dir being deployed from
        [RequiredArgument]
        public InArgument&lt;string&gt; SourceDir { get; set; }
        //Destination dir being copied from
        [RequiredArgument]
        public InArgument&lt;string[]&gt; DestinationDir { get; set; }
        //Files to exclude
        [RequiredArgument]
        public InArgument&lt;string&gt; FileExclusions { get; set; }
        //Folders to exclude
        [RequiredArgument]
        public InArgument&lt;string&gt; FolderExclusions { get; set; }

        //globals
        public string fileExclusionPattern = &quot;&quot;;
        public string folderExclusionPattern = &quot;&quot;;

        protected override void Execute(CodeActivityContext context)
        {
            // Obtain the runtime value of the Text input argument
            string fileExclusions = context.GetValue(this.FileExclusions);
            string folderExclusions = context.GetValue(this.FolderExclusions);
            string[] destinations = context.GetValue(this.DestinationDir);
            DirectoryInfo sourceDir = new DirectoryInfo(context.GetValue(this.SourceDir));

            //parse exclusions, add them to regex patterns
            if (!String.IsNullOrWhiteSpace(fileExclusions))
            {
                string[] fileexarr = fileExclusions.Split(',');
                fileExclusionPattern = &quot;(&quot;;
                foreach (string s in fileexarr)
                {
                    fileExclusionPattern += s.ToUpper().Trim().Replace(&quot;.&quot;, @&quot;\.&quot;).Replace(&quot;*&quot;, @&quot;[a-zA-Z0-9]*&quot;) + &quot;|&quot;;
                }

                if(fileExclusionPattern.EndsWith(&quot;|&quot;))
                    fileExclusionPattern = fileExclusionPattern.Substring(0, fileExclusionPattern.Length - 1);

                fileExclusionPattern += &quot;)&quot;;
            }

            if (!String.IsNullOrWhiteSpace(folderExclusions))
            {
                string[] folderexarr = folderExclusions.Split(',');
                folderExclusionPattern = &quot;(&quot;;

                foreach (string s in folderexarr)
                {
                    folderExclusionPattern += s.ToUpper().Trim().Replace(&quot;.&quot;, @&quot;\.&quot;).Replace(&quot;*&quot;, @&quot;[a-zA-Z0-9]*&quot;) + &quot;|&quot;;
                }

                if(folderExclusionPattern.EndsWith(&quot;|&quot;))
                    folderExclusionPattern = folderExclusionPattern.Substring(0, folderExclusionPattern.Length - 1);

                folderExclusionPattern += &quot;)&quot;;
            }

            foreach (string dir in destinations)
            {
                DirectoryInfo destDir = new DirectoryInfo(dir);

                context.Track(new BuildInformationRecord&lt;BuildMessage&gt;()
                {
                    Value = new BuildMessage()
                    {
                        Importance = BuildMessageImportance.High,
                        Message = &quot;Source: &quot; + sourceDir.FullName + &quot;\nDestination: &quot; + destDir.FullName +
                            &quot;\nFolder Exclusion Pattern: &quot; + folderExclusionPattern +
                            &quot;\nFile Exclusion Pattern: &quot; + fileExclusionPattern,
                    },
                });

                CopyDir(sourceDir, destDir);
            }
        }

        private void CopyDir(DirectoryInfo sourceDir, DirectoryInfo destDir)
        {
            //create destination dir if it doesn't exist
            if (!destDir.Exists)
            {
                destDir.Create();
            }

            // get all files from current dir
            FileInfo[] files = sourceDir.GetFiles();

            //copy ze files!!
            foreach (FileInfo file in files)
            {
                if (!String.IsNullOrWhiteSpace(fileExclusionPattern))
                {
                    if (!Regex.IsMatch(file.Name.ToUpper(), fileExclusionPattern))
                    {
                        if (File.Exists(Path.Combine(destDir.FullName, file.Name)))
                        {
                            File.Delete(Path.Combine(destDir.FullName, file.Name));
                        }
                        file.CopyTo(Path.Combine(destDir.FullName, file.Name));
                    }
                }
                else
                {
                    if (File.Exists(Path.Combine(destDir.FullName, file.Name)))
                    {
                        File.Delete(Path.Combine(destDir.FullName, file.Name));
                    }
                    file.CopyTo(Path.Combine(destDir.FullName, file.Name),true);
                }
            }

            // get subdirectories.
            DirectoryInfo[] dirs = sourceDir.GetDirectories();

            foreach (DirectoryInfo dir in dirs)
            {
                // Get destination directory.
                string destinationDir = Path.Combine(destDir.FullName, dir.Name);

                if (!String.IsNullOrWhiteSpace(folderExclusionPattern))
                {
                    if (!Regex.IsMatch(dir.Name.ToUpper(), folderExclusionPattern))
                    {
                        // Call CopyDirectory() recursively.
                        CopyDir(dir, new DirectoryInfo(destinationDir));
                    }
                }
                else
                {
                    // Call CopyDirectory() recursively.
                    CopyDir(dir, new DirectoryInfo(destinationDir));
                }
            }
        }
    }
}
</pre>
<h4>Explanation:</h4>
<p>Now i&#8217;ll go section by section explaining exactly what&#8217;s going on. First up are the input requirements:</p>
<pre class="brush: csharp; light: true; title: Code block; notranslate">
         //Source dir being deployed from
        [RequiredArgument]
        public InArgument&lt;string&gt; SourceDir { get; set; }
</pre>
<p>The SourceDir is where the deployment starts from. This means what subdirectory from the BinariesDirectory gets deployed. This is important for Websites, since they get dropped in a _PublishedWebsites folder inside the BinariesDirectory.</p>
<pre class="brush: csharp; light: true; title: Code block; notranslate">
        //Destination dir being copied from
        [RequiredArgument]
        public InArgument&lt;string[]&gt; DestinationDir { get; set; }
</pre>
<p>The DestinationDir argument is a string array of paths being passed in (we use UNC network paths, ie: \\deploymentbox\websites\sitename)</p>
<pre class="brush: csharp; light: true; title: Code block; notranslate">
        //Files to exclude
        [RequiredArgument]
        public InArgument&lt;string&gt; FileExclusions { get; set; }
</pre>
<p>The FileExclusions argument is meant to be a comma delimited string of filenames and patterns you want to exclude. (ie: &#8220;web.config, *.pdb&#8221;)</p>
<pre class="brush: csharp; light: true; title: Code block; notranslate">
        //Folders to exclude
        [RequiredArgument]
        public InArgument&lt;string&gt; FolderExclusions { get; set; }
</pre>
<p>The FolderExclusions argument is similar to the FileExclusions, except that if there are certain folders you don&#8217;t want deployed, you can specify them here</p>
<pre class="brush: csharp; light: true; title: Code block; notranslate">
        //globals
        public string fileExclusionPattern = &quot;&quot;;
        public string folderExclusionPattern = &quot;&quot;;
</pre>
<p>These two variables will be used to build the Regex pattern which we will check files and folders against.</p>
<p>Now we&#8217;ll go into</p>
<pre class="brush: csharp; light: true; title: Code block; notranslate">protected override void Execute(CodeActivityContext context)</pre>
<p>explaining each part in more detail.</p>
<pre class="brush: csharp; light: true; title: Code block; notranslate">
            // Obtain the runtime value of the Text input argument
            string fileExclusions = context.GetValue(this.FileExclusions);
            string folderExclusions = context.GetValue(this.FolderExclusions);
            string[] destinations = context.GetValue(this.DestinationDir);
            DirectoryInfo sourceDir = new DirectoryInfo(context.GetValue(this.SourceDir));
</pre>
<p>Here we get the values being passed in at execution time</p>
<pre class="brush: csharp; light: true; title: Code block; notranslate">
            //parse exclusions, add them to regex patterns
            if (!String.IsNullOrWhiteSpace(fileExclusions))
            {
                string[] fileexarr = fileExclusions.Split(',');
                fileExclusionPattern = &quot;(&quot;;
                foreach (string s in fileexarr)
                {
                    fileExclusionPattern += s.ToUpper().Trim().Replace(&quot;.&quot;, @&quot;\.&quot;).Replace(&quot;*&quot;, @&quot;[a-zA-Z0-9]*&quot;) + &quot;|&quot;;
                }

                if(fileExclusionPattern.EndsWith(&quot;|&quot;))
                    fileExclusionPattern = fileExclusionPattern.Substring(0, fileExclusionPattern.Length - 1);

                fileExclusionPattern += &quot;)&quot;;
            }

            if (!String.IsNullOrWhiteSpace(folderExclusions))
            {
                string[] folderexarr = folderExclusions.Split(',');
                folderExclusionPattern = &quot;(&quot;;

                foreach (string s in folderexarr)
                {
                    folderExclusionPattern += s.ToUpper().Trim().Replace(&quot;.&quot;, @&quot;\.&quot;).Replace(&quot;*&quot;, @&quot;[a-zA-Z0-9]*&quot;) + &quot;|&quot;;
                }

                if(folderExclusionPattern.EndsWith(&quot;|&quot;))
                    folderExclusionPattern = folderExclusionPattern.Substring(0, folderExclusionPattern.Length - 1);

                folderExclusionPattern += &quot;)&quot;;
            }
</pre>
<p>Here we check to see if anything was passed into the file or folder exclusion parameters. If something was passed in, we split the comma delimited string into an array and then iterate through it adding the exclusions to their appropriate Regex pattern.</p>
<pre class="brush: csharp; light: true; title: Code block; notranslate">
            foreach (string dir in destinations)
            {
                DirectoryInfo destDir = new DirectoryInfo(dir);

                context.Track(new BuildInformationRecord&lt;BuildMessage&gt;()
                {
                    Value = new BuildMessage()
                    {
                        Importance = BuildMessageImportance.High,
                        Message = &quot;Source: &quot; + sourceDir.FullName + &quot;\nDestination: &quot; + destDir.FullName +
                            &quot;\nFolder Exclusion Pattern: &quot; + folderExclusionPattern +
                            &quot;\nFile Exclusion Pattern: &quot; + fileExclusionPattern,
                    },
                });

                CopyDir(sourceDir, destDir);
            }
</pre>
<p>Now we loop through all the destinations we need to deploy to, copying the files and folders.</p>
<p>Now lets take a look at</p>
<pre class="brush: csharp; light: true; title: Code block; notranslate">private void CopyDir(DirectoryInfo sourceDir, DirectoryInfo destDir)</pre>
<pre class="brush: csharp; light: true; title: Code block; notranslate">
            //create destination dir if it doesn't exist
            if (!destDir.Exists)
            {
                destDir.Create();
            }
</pre>
<p>Let&#8217;s make sure the destination directory exists, creating it if it doesn&#8217;t exist already.</p>
<pre class="brush: csharp; light: true; title: Code block; notranslate">
            // get all files from current dir
            FileInfo[] files = sourceDir.GetFiles();
</pre>
<p>Here we get the all the files from the source directory</p>
<pre class="brush: csharp; light: true; title: Code block; notranslate">
            //copy ze files!!
            foreach (FileInfo file in files)
            {
                if (!String.IsNullOrWhiteSpace(fileExclusionPattern))
                {
                    if (!Regex.IsMatch(file.Name.ToUpper(), fileExclusionPattern))
                    {
                        if (File.Exists(Path.Combine(destDir.FullName, file.Name)))
                        {
                            File.Delete(Path.Combine(destDir.FullName, file.Name));
                        }
                        file.CopyTo(Path.Combine(destDir.FullName, file.Name));
                    }
                }
                else
                {
                    if (File.Exists(Path.Combine(destDir.FullName, file.Name)))
                    {
                        File.Delete(Path.Combine(destDir.FullName, file.Name));
                    }
                    file.CopyTo(Path.Combine(destDir.FullName, file.Name),true);
                }
            }
</pre>
<p>Let&#8217;s copy some files! Check each file against the exclusion pattern, if one is set, and copy it if needed. If the file needs to be copied and it exists in the destination already, we&#8217;ll delete it and copy the file over.</p>
<pre class="brush: csharp; light: true; title: Code block; notranslate">
            // get subdirectories.
            DirectoryInfo[] dirs = sourceDir.GetDirectories();

            foreach (DirectoryInfo dir in dirs)
            {
                // Get destination directory.
                string destinationDir = Path.Combine(destDir.FullName, dir.Name);

                if (!String.IsNullOrWhiteSpace(folderExclusionPattern))
                {
                    if (!Regex.IsMatch(dir.Name.ToUpper(), folderExclusionPattern))
                    {
                        // Call CopyDirectory() recursively.
                        CopyDir(dir, new DirectoryInfo(destinationDir));
                    }
                }
                else
                {
                    // Call CopyDirectory() recursively.
                    CopyDir(dir, new DirectoryInfo(destinationDir));
                }
            }
</pre>
<p>Last we check to see if the directory has any sub-directories and we call CopyDir() recursively to copy all sub directories and files inside them, only of course if they aren&#8217;t on the folder exclusion list.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.danielcolomb.com/2011/02/23/deploying-to-multiple-locations-in-tfs-2010/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dependency Replication in TFS 2010</title>
		<link>http://www.danielcolomb.com/2011/01/20/dependency-replication-in-tfs-2010/</link>
		<comments>http://www.danielcolomb.com/2011/01/20/dependency-replication-in-tfs-2010/#comments</comments>
		<pubDate>Thu, 20 Jan 2011 17:47:04 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
				<category><![CDATA[Computers]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[Source Control]]></category>
		<category><![CDATA[TFS]]></category>
		<category><![CDATA[dependency]]></category>
		<category><![CDATA[replication]]></category>
		<category><![CDATA[TFS 2010]]></category>

		<guid isPermaLink="false">http://www.danielcolomb.com/?p=494</guid>
		<description><![CDATA[<p>I&#8217;m not sure exactly how many people do this, but it seems like there isn&#8217;t much documentation out there on how to do this exactly. So after lots of trial and error I&#8217;ve finally gotten dll replication to work for our TFS environment.</p> <p>So, first i&#8217;ll go over the general overview of what needs [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m not sure exactly how many people do this, but it seems like there isn&#8217;t much documentation out there on how to do this exactly. So after lots of trial and error I&#8217;ve finally gotten dll replication to work for our TFS environment.</p>
<p>So, first i&#8217;ll go over the general overview of what needs to be done to enable TFS to replicate files during a build. Just a reminder, this is for TFS 2010, not any previous version of TFS.</p>
<p>1) You&#8217;ll need a custom build template<br />
2) You&#8217;ll need a custom TFS Activity</p>
<p>Second, I&#8217;ll let you know i basically followed the <a href="http://www.ewaldhofman.nl/post/2010/04/20/Customize-Team-Build-2010-e28093-Part-1-Introduction.aspx">tutorials</a> by Ewald Hofman and then modified things to work the way I needed them to.</p>
<p>So our scenario is that we have multiple products that use dll&#8217;s from a core product. When that core product gets changed, we don&#8217;t want to have to copy the dll&#8217;s manually from the build location to the locations needed by the other products. Each one of our products have a folder called SharedBinaries, this is where those dll&#8217;s live.</p>
<p>Now the question is, how do we do this? If you&#8217;re using TFS 2008 or 2005, you can easily just acquire <a href="http://tfsdepreplicator.codeplex.com/">TFS Dependency Replicator</a>, it will handle all that for you. For TFS 2010 however, this doesn&#8217;t work anymore. Or more precisely, I was unable to get it to work. So, time to learn how to use Windows Workflow. At first this seems very daunting, but after you take it a bit at a time, things start to make sense.</p>
<p>I would highly recommend you take a look at the tutorials i mentioned earlier, they will give you a good base to work from. And if i were to go through and document the whole process here, i would feel like i&#8217;m plagiarizing someone else&#8217;s work. Go at least as far as <a title="Creating your own custom activity" href="http://www.ewaldhofman.nl/post/2010/04/29/Customize-Team-Build-2010-e28093-Part-4-Create-your-own-activity.aspx">Part 4 &#8211; Creating your own activity</a>, this is where i&#8217;ll start my documentation.</p>
<p>I created a new Code Activity and called it &#8216;ReplicateFiles.cs&#8217;.  You can download it <a title="Source File" href="http://www.danielcolomb.com/files/ReplicateFiles.cs" target="_blank">here</a>.</p>
<p>You&#8217;ll want to add three Arguments to your custom template.</p>
<p><a href="http://www.danielcolomb.com/wp-content/uploads/2011/01/TemplateArguments.png"><img class="alignnone size-full wp-image-506" title="TemplateArguments" src="http://www.danielcolomb.com/wp-content/uploads/2011/01/TemplateArguments.png" alt="" width="898" height="78" /></a><a href="http://www.danielcolomb.com/wp-content/uploads/2011/01/TemplateArguments.png"><br />
</a></p>
<p>In the Metadata Argument, you&#8217;ll want to add those three Arguments as required fields.</p>
<p><a href="http://www.danielcolomb.com/wp-content/uploads/2011/01/TemplateArgumentsMetadata.png"><img class="alignnone size-full wp-image-504" title="TemplateArgumentsMetadata" src="http://www.danielcolomb.com/wp-content/uploads/2011/01/TemplateArgumentsMetadata.png" alt="" width="920" height="630" /></a></p>
<p>In the custom template, I added the custom activity just before the gated check-in process.</p>
<p><a href="http://www.danielcolomb.com/wp-content/uploads/2011/01/TemplateCustomActivity.png"><img title="TemplateCustomActivity" src="http://www.danielcolomb.com/wp-content/uploads/2011/01/TemplateCustomActivity.png" alt="" width="533" height="776" /></a></p>
<p>Lastly, you&#8217;ll want to add the three Arguments into the appropriate fields on the custom activity properties, as well as specifying the BinariesDirectory as the SourceLocation to copy the files from.</p>
<p><a href="http://www.danielcolomb.com/wp-content/uploads/2011/01/TemplateCustomActivityProperties.png"><img class="alignnone size-full wp-image-503" title="TemplateCustomActivityProperties" src="http://www.danielcolomb.com/wp-content/uploads/2011/01/TemplateCustomActivityProperties.png" alt="" width="312" height="215" /></a></p>
<p>While setting up your build, you&#8217;ll want to make sure you fill out those newly required fields in Build Editor Process Section.</p>
<p><a href="http://www.danielcolomb.com/wp-content/uploads/2011/01/BuildDefinitionProcessDetails1.png"><img class="alignnone size-full wp-image-512" title="BuildDefinitionProcessDetails" src="http://www.danielcolomb.com/wp-content/uploads/2011/01/BuildDefinitionProcessDetails1.png" alt="" width="795" height="321" /></a></p>
<p>Before you go wild and start running builds, go through this checklist.</p>
<ul>
<li>Does your build controller know the path to the custom binaries you&#8217;ve made (for the custom build activity).  (<a title="How is custom assembly found" href="http://www.ewaldhofman.nl/post/2010/05/27/Customize-Team-Build-2010-e28093-Part-7-How-is-the-custom-assembly-found.aspx" target="_blank">reference</a>)</li>
<li>Have you checked in the latest version of your custom template, as well as the custom activity dll</li>
</ul>
<ul>
<li>The required arguments in the ReplicateFiles.cs are what you pass into the class from the custom template you&#8217;ve created, make sure those are filled out in the build template.</li>
<li>Make sure you have the correct path to your TFS server for tfsName in ReplicateFiles.cs.</li>
<li>Make sure that the user you run your build service under has file system permissions for the location where you want to create your temporary workspaces.</li>
<li>I had this issue, and it almost drove me nuts! I kept getting access denied errors when trying to overwrite the files in the target branches. Make sure that the files being replicated ARE NOT checked out and locked!</li>
</ul>
<p>If you have any corrections, feedback, or ideas! Please comment and let me know!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.danielcolomb.com/2011/01/20/dependency-replication-in-tfs-2010/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Some things new, some things old</title>
		<link>http://www.danielcolomb.com/2010/03/04/some-things-new-some-things-old/</link>
		<comments>http://www.danielcolomb.com/2010/03/04/some-things-new-some-things-old/#comments</comments>
		<pubDate>Thu, 04 Mar 2010 18:25:19 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
				<category><![CDATA[Computers]]></category>
		<category><![CDATA[Eve Online]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[video games]]></category>
		<category><![CDATA[web programming]]></category>
		<category><![CDATA[Acer]]></category>
		<category><![CDATA[Character]]></category>
		<category><![CDATA[Checker]]></category>
		<category><![CDATA[Eve]]></category>
		<category><![CDATA[iPay]]></category>
		<category><![CDATA[Online]]></category>
		<category><![CDATA[X223W]]></category>

		<guid isPermaLink="false">http://www.danielcolomb.com/?p=426</guid>
		<description><![CDATA[<p>So, yeah, i know.. it&#8217;s been a while. It&#8217;s been a combination of things that have kept me from posting anything; mainly laziness i think. But i have my laptop at work today, and it&#8217;s lunch time, so i figured.. why the hell not? It&#8217;s about f-ing time.</p> <p>//Work</p> <p>First up is work. Things [...]]]></description>
			<content:encoded><![CDATA[<p>So, yeah, i know.. it&#8217;s been a while. It&#8217;s been a combination of things that have kept me from posting anything; mainly laziness i think. But i have my laptop at work today, and it&#8217;s lunch time, so i figured.. why the hell not? It&#8217;s about f-ing time.</p>
<p><strong>//Work</strong></p>
<p>First up is work. Things have been going great! I&#8217;m still learning more than my brain can handle every day and I&#8217;ve been put on a multitude of projects. Well, one project but a bunch of tasks. The issues i thought i was going to have for a while, like understanding how everything is layered and how they like to structure things have come and gone. I&#8217;m really starting to understand the bigger picture of how everything works together.  Things are picking up now though, there are release dates that have to be hit, and code that needs to be pushed. And there&#8217;s a new guy. He seems pretty cool, and seems to know his stuff. And most of all, has replaced both Zach and I as the new guy. Though we&#8217;re still noobs.</p>
<p><strong>//Eve</strong></p>
<p>I&#8217;ve become re-addicted to Eve. I know, i seem to say that a lot. But this time does seem a little different. ONYX Heavy Industries has a good bunch of people in it, and I enjoy hanging out with them while online. Heck, there have been a few time when i wouldn&#8217;t even be in game, and i&#8217;d just be doing my thing (programming or whatever) and chat on teamspeak.</p>
<p><strong>//Development</strong></p>
<p>Speaking of development, that bug has bitten again too. I&#8217;ve been working on this <a title="eveCharCheck (title pending)" href="http://www.blackmesacorp.com/eveCharCheck" target="_blank">http://www.blackmesacorp.com/eveCharCheck</a>. It&#8217;s going to become a site that allows directors in corporations to check character&#8217;s Limited API keys and see if they can really do all the things they claim (based on the skills and certificates they have). There is currently only very limited functionality, but i hope to expand on it soon once i figure out some major bugs. Something between the ale Eve API libraries and my database libraries is colliding.. and i&#8217;m not sure why it&#8217;s doing that.</p>
<p><strong>//Social gatherings</strong></p>
<p>I&#8217;ve been hanging out too. Not as much as i used to, but i think that&#8217;s good too. Sometimes i just want to be alone at my house.  I went and saw The Crazies the other weekend. It wasn&#8217;t a bad flick for a horror/thriller/action-ish movie.</p>
<p><strong>//New computer parts</strong></p>
<p>I bought a new monitor the other day, it&#8217;s wicked. I am now rocking two 22&#8243; LCD monitors! So much desktop space! They&#8217;re Acer <a title="ACER X223W" href="http://www.unistarcomputer.com/attachedimages/d_2008-10-16-15-58-35f_9.jpg" target="_blank">x223w</a>&#8216;s and they&#8217;re fabulous!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.danielcolomb.com/2010/03/04/some-things-new-some-things-old/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Week One Complete!</title>
		<link>http://www.danielcolomb.com/2010/01/10/week-one-complete/</link>
		<comments>http://www.danielcolomb.com/2010/01/10/week-one-complete/#comments</comments>
		<pubDate>Sun, 10 Jan 2010 15:28:12 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[life]]></category>
		<category><![CDATA[web programming]]></category>
		<category><![CDATA[body clock]]></category>
		<category><![CDATA[Daybreakers]]></category>
		<category><![CDATA[first week]]></category>
		<category><![CDATA[Infiniti G35]]></category>
		<category><![CDATA[Za's]]></category>

		<guid isPermaLink="false">http://www.danielcolomb.com/?p=424</guid>
		<description><![CDATA[<p>I&#8217;ve finished my first week at my new job. It&#8217;s a weird sensation. I feel like I&#8217;ve been there for quite a while already, but that time has gone by really fast. Maybe it has to do with the fact that i was totally sick for about half the week? The first three days [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve finished my first week at my new job. It&#8217;s a weird sensation. I feel like I&#8217;ve been there for quite a while already, but that time has gone by really fast. Maybe it has to do with the fact that i was totally sick for about half the week? The first three days were pretty much getting to know what the company does and how they do things on a very high level. Thursday and Friday were pretty much dedicated to scouring over thousands of lines of C#, ASP.Net, and Javascript to learn how their Consumer site works. Not the most exciting stuff in the world. Everyone is very nice and patient with our questions.</p>
<p>Boy, was i ready for saturday though! I guess my body was still used to sleeping for 10 hours every night. Instead i&#8217;ve been up by 7am everyday and out the door by 7:30. Yesterday i finally got to sleep in a bit, lounge around in my PJ&#8217;s, and then finally in the afternoon leave the house. Josh and I went up to Louisville so Josh could test drive a Infiniti G35. A very nice car! After that we went and ate pizza and drank beer at Za&#8217;s where we met up with some friends, one of whom neither of us had seen in years! After pizza and beer we went and saw Daybreakers, which was ok. It&#8217;s nothing to rave about, and I feel the previews mislead the audience to thinking the movie was something else. But exploding vampires are always nice.</p>
<p>Tomorrow starts week two! Hopefully nothing will go wrong, and the roads will stay clear!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.danielcolomb.com/2010/01/10/week-one-complete/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Arduino Tutorial on LJ</title>
		<link>http://www.danielcolomb.com/2009/09/05/arduino-tutorial-on-lj/</link>
		<comments>http://www.danielcolomb.com/2009/09/05/arduino-tutorial-on-lj/#comments</comments>
		<pubDate>Sat, 05 Sep 2009 16:49:24 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[Arduino]]></category>
		<category><![CDATA[Motion Sensor Alarm]]></category>
		<category><![CDATA[Passive Infrared]]></category>
		<category><![CDATA[Piezo Siren]]></category>
		<category><![CDATA[PIR]]></category>

		<guid isPermaLink="false">http://www.danielcolomb.com/2009/09/05/arduino-tutorial-on-lj/</guid>
		<description><![CDATA[<p>I made a tutorial over on an Livejournal Arduino Community page, go and check it out!</p> <p>http://community.livejournal.com/arduino_related/1219.html</p> ]]></description>
			<content:encoded><![CDATA[<p>I made a tutorial over on an Livejournal Arduino Community page, go and check it out!</p>
<p><a href="http://community.livejournal.com/arduino_related/1219.html">http://community.livejournal.com/arduino_related/1219.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.danielcolomb.com/2009/09/05/arduino-tutorial-on-lj/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>This is AWESOME~!</title>
		<link>http://www.danielcolomb.com/2009/02/10/this-is-awesome/</link>
		<comments>http://www.danielcolomb.com/2009/02/10/this-is-awesome/#comments</comments>
		<pubDate>Tue, 10 Feb 2009 22:15:37 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[typical jibberish]]></category>
		<category><![CDATA[hacked]]></category>
		<category><![CDATA[nazi zombies]]></category>
		<category><![CDATA[roadsigns]]></category>

		<guid isPermaLink="false">http://www.danielcolomb.com/?p=322</guid>
		<description><![CDATA[<p>http://i.gizmodo.com/5136970/hacking-road-signs-is-frightningly-easy-and-funny-and-illegal</p> <p>So Zach asked me if I&#8217;d heard about the hacked road signs, and since i&#8217;ve been out of the loop in things for a while I of course hadn&#8217;t. This is amazingly awesome! I wants to do it </p> ]]></description>
			<content:encoded><![CDATA[<p><a href="http://i.gizmodo.com/5136970/hacking-road-signs-is-frightningly-easy-and-funny-and-illegal" target="_blank">http://i.gizmodo.com/5136970/hacking-road-signs-is-frightningly-easy-and-funny-and-illegal</a></p>
<p>So Zach asked me if I&#8217;d heard about the hacked road signs, and since i&#8217;ve been out of the loop in things for a while I of course hadn&#8217;t. This is amazingly awesome! I wants to do it <img src='http://www.danielcolomb.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.danielcolomb.com/2009/02/10/this-is-awesome/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Uncertain Tempuratures</title>
		<link>http://www.danielcolomb.com/2009/01/26/uncertain-tempuratures/</link>
		<comments>http://www.danielcolomb.com/2009/01/26/uncertain-tempuratures/#comments</comments>
		<pubDate>Mon, 26 Jan 2009 21:56:03 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
				<category><![CDATA[books]]></category>
		<category><![CDATA[family]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[Buca Di Beppo]]></category>
		<category><![CDATA[Granola Bars]]></category>
		<category><![CDATA[Nick's Birthday]]></category>
		<category><![CDATA[Regex]]></category>
		<category><![CDATA[Regular Expressions]]></category>

		<guid isPermaLink="false">http://www.danielcolomb.com/?p=315</guid>
		<description><![CDATA[<p> I&#8217;m sitting at my desk, everything is fine. I&#8217;m wearing my hoodie because it&#8217;s cold in the office. I start feeling this warm breeze come across my desk. Things are warming up, and it feels good. I take my hoodie off and keep working. Then the warm breeze gets cold and i start [...]]]></description>
			<content:encoded><![CDATA[<p> <img src='http://www.danielcolomb.com/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' />  I&#8217;m sitting at my desk, everything is fine. I&#8217;m wearing my hoodie because it&#8217;s cold in the office. I start feeling this warm breeze come across my desk. Things are warming up, and it feels good. I take my hoodie off and keep working. Then the warm breeze gets cold and i start to shiver. I put my hoodie back on. Ah, nice and toasty. 10 minutes later i&#8217;m back to sweating and prepare to take my hoodie off when the cold air starts again.</p>
<p>This is starting to get really annoying.  I&#8217;m surprised i haven&#8217;t gotten sick from the massive tempurature changes.</p>
<p>In other news the weekend is over and i&#8217;m back at work. Nothing much happened over the last three days. I spent time relaxing, playing Eve, and going out to celebrate my brothers&#8217; birthday.</p>
<p>Friday was grocery shopping. The fridge was filled and now there&#8217;s plenty to munch on in the house. I also made some pretty good granola bars. They&#8217;re awesome with a glass of milk, heh. It&#8217;s kind of like eating cereal in a bar <img src='http://www.danielcolomb.com/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' />  We also went to Barnes &amp; Noble, and i got a book on <a href="http://oreilly.com/catalog/9780596528126/" target="_blank">RegEx</a> (Regular Expressions). So far it&#8217;s been very helpful in my quest to learn the way of the code ninja.</p>
<p>Saturday evening we went to <a href="http://www.bucadibeppo.com/" target="_blank">Buca Di Beppo&#8217;s</a> for Nick&#8217;s birthday and man it was delicious! It&#8217;s an Italian family-style restaurant, where a small portion is enough to feed two people. There were about 10 of us and we all ordered something different. After all the food was out, we were barely able to try a little of everything! So much food!! All i have to say is that i didn&#8217;t have to make anything the next day for lunch. Plenty of leftovers <img src='http://www.danielcolomb.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<p>Sunday was hanging out at the house and then going to my parents&#8217; place to do some laundry and eat dinner. I picked up some mail that was still going there and played with the dogs. Man, it&#8217;s like i&#8217;ve been off on an expedition to the far side of the world when i come over. One more sign that dogs are loyal. Such excitement can rarely be encountered elsewhere.</p>
<p>Well, one more hour to kill at work. Time for more Professional Development <img src='http://www.danielcolomb.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.danielcolomb.com/2009/01/26/uncertain-tempuratures/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Oracle and PHP</title>
		<link>http://www.danielcolomb.com/2008/12/29/oracle-and-php/</link>
		<comments>http://www.danielcolomb.com/2008/12/29/oracle-and-php/#comments</comments>
		<pubDate>Mon, 29 Dec 2008 18:17:28 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[set up]]></category>

		<guid isPermaLink="false">http://www.danielcolomb.com/?p=282</guid>
		<description><![CDATA[<p>So a few weeks ago i talked about how confusing Oracle and its&#8217; clients can be. While i still think the lack of simple documentation, and confusing download layout are very annoying, I&#8217;ve begun to understand how things work. Well.. kind of. And by &#8220;kind of&#8221;, I totally mean, i&#8217;m still pretty lost. At [...]]]></description>
			<content:encoded><![CDATA[<p>So a few weeks ago i talked about how <a href="http://www.danielcolomb.com/2008/11/25/oracle-why-just-why/" target="_blank">confusing Oracle</a> and its&#8217; clients can be. While i still think the lack of simple documentation, and confusing download layout are very annoying, I&#8217;ve begun to understand how things work. Well.. kind of. And by &#8220;kind of&#8221;, I totally mean, i&#8217;m still pretty lost. At least now i have a dim candle lighting the dark cavern I&#8217;m in.</p>
<p>I&#8217;m going to go step by step on how I got my WAMP (Windows, Apache, MySQL, PHP) Stack to also incorporate Oracle support. I&#8217;m assuming you already have a properly working Apache Webserver running with PHP enabled.</p>
<p><span style="text-decoration: underline;"><strong>PHP and the Oracle: A layman&#8217;s story</strong></span></p>
<p><strong>1)</strong> Uninstall any existing copy of the Oracle Client, unless it&#8217;s needed for other functionality. (We had an Oracle 9i Client at work, which was installed on many of the machines, but wasn&#8217;t needed in this case, and i couldn&#8217;t find any documentation online to get it to work with PHP&#8230;)</p>
<p><strong>2)</strong> Install the <a href="http://www.oracle.com/technology/software/tech/oci/instantclient/index.html" target="_blank">Instant Client</a> provided at the Oracle site. Make sure to choose the proper options, like your architecture, and whatever client you wish; i used &#8216;Instant Client Package &#8211; Basic&#8217; &#8212; because it stated it had all the required files for OCI connections, which is what i was using for my Oracle&lt;-&gt;Webserver calls.</p>
<p><strong>3)</strong> Edit your PATH Environment Variable. Add the directory to where you installed your instant client to the end. For Example, I installed to C:\oracle\instant_client, so i added &#8216;;C:\oracle\instant_client&#8217; &#8212; note the preceding &#8216;;&#8217;, this is needed if the end of your PATH already doesn&#8217;t have it. It&#8217;s the delimiter for the different directories added to your path.</p>
<p>You only need to add the main directory to which you installed, the php_oci extension will look for the dll&#8217;s in that main directory. Also make sure you don&#8217;t have the trailing &#8216;\&#8217; at the end. Depending on your windows installation it might not like that&#8230; &#8212; Windows can be so picky when it want.. <img src='http://www.danielcolomb.com/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </p>
<p><strong>4)</strong> Open your php.ini file and uncomment the line &#8216;;extension=php_oci8.dll&#8217; &#8212; uncomment means take off the &#8216;;&#8217; before the &#8216;extension=&#8217;.</p>
<p><strong>5)</strong> Create a phpinfo file. Something simple like this will work.</p>
<p><code>&lt;?php<br />
phpinfo();<br />
?&gt;<br />
</code></p>
<p>Once you&#8217;ve created the file and placed it on your webserver, browse to it. Scroll through, if it&#8217;s properly set up, you should see a category called &#8220;oci8&#8243;.  If not, make sure that anywhere where PATH is referenced, it shows your updated PATH &#8212; with your Instant Client Directory added. If it&#8217;s not there you may need to restart your Windows server. I was having issues with my PATH properly updating and was forced to do this.</p>
<p>Setup should be complete now.  Next is testing.</p>
<p><strong>6)</strong> Try to connect to your Oracle server. I personally use the OCI. Something like this should work:</p>
<p><code>&lt;?php<br />
$user = "username";<br />
$pw = "password";<br />
$db = "(DESCRIPTION=(ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = your.host.domain)(PORT = 1521)))(CONNECT_DATA=(SID=yourSID)))";<br />
$conn = ocilogon($user,$pw,$db);<br />
?&gt;</code></p>
<p>You don&#8217;t need a TNSNAMES.ORA, but can use one (as far as i know). To use one just create the file in the root of the instant client installation.<br />
If you don&#8217;t get a fatal error you should be good to go now. You now have the functionality to connect to Oracle databases.  I&#8217;d love to hear how others have done this. Maybe there&#8217;s a better way to do it than what i did.</p>
<p>Some good resources for PHP and Oracle:<br />
<a href="http://www.oracle.com/technology/pub/articles/oracle_php_cookbook/index.html" target="_blank">http://www.oracle.com/technology/pub/articles/oracle_php_cookbook/index.html</a><br />
<a href="http://www.orafaq.com/wiki/PHP_FAQ" target="_blank">http://www.orafaq.com/wiki/PHP_FAQ</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.danielcolomb.com/2008/12/29/oracle-and-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AJAX, you&#8217;re so confusing!!</title>
		<link>http://www.danielcolomb.com/2008/12/20/ajax-youre-so-confusing/</link>
		<comments>http://www.danielcolomb.com/2008/12/20/ajax-youre-so-confusing/#comments</comments>
		<pubDate>Sat, 20 Dec 2008 21:33:07 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
				<category><![CDATA[ajax]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[so!soft]]></category>
		<category><![CDATA[typical jibberish]]></category>
		<category><![CDATA[Gatekeepers PaintBall]]></category>

		<guid isPermaLink="false">http://www.danielcolomb.com/?p=278</guid>
		<description><![CDATA[<p>So, i&#8217;ve been building a website for this Paintball team. They seem to do pretty well in tournaments and from what I&#8217;ve been told they already have possible sponsors lining up. They want their site ready as soon as possible, but at the same time I don&#8217;t want to give them garbage. I want [...]]]></description>
			<content:encoded><![CDATA[<p>So, i&#8217;ve been building a website for this Paintball team. They seem to do pretty well in tournaments and from what I&#8217;ve been told they already have possible sponsors lining up. They want their site ready as soon as possible, but at the same time I don&#8217;t want to give them garbage. I want to be able to give them quality software. It&#8217;s hard to do sometimes when I&#8217;m not even getting paid for it. The deal is we make them a website, and we get free advertising through them, kind of like a sponsorship. But AJAX is being a pain, so it&#8217;s easier to just go play eve instead of working..</p>
<p>Maybe i&#8217;ll go do that now..</p>
<p>I got the log in system working, so i might as well take a break.. my brain hurts</p>
]]></content:encoded>
			<wfw:commentRss>http://www.danielcolomb.com/2008/12/20/ajax-youre-so-confusing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

