Thursday, May 30, 2013

Add License Comment to every C# file during Visual Studio Build

I have been working on an open-source project and wanted to add a license comment (like the one below) to every class file.  Additionally, I wanted to do this as a Visual Studio Build Event so that any new class files would automatically get updated.



//-----------------------------------------------------------------------
// <copyright file="CloneIntentsAttribute.cs" company="Copacetic Software">
// Copyright (c) Copacetic Software. 
// <author>Philip Pittle</author>
// <date>Wednesday, May 29, 2013 6:45:52 PM</date>
// Licensed under the Apache License, Version 2.0,
// you may not use this file except in compliance with one of the Licenses.
// 
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an 'AS IS' BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------

I ended up using a power shell script by Kishor Aher with modifications by Leniel Macaferi and with a few modifications I added myself:




param($target = "C:\MyProject\trunk", $companyname = "Copacetic Software") 
 
#[System.Globalization.CultureInfo] 
$ci = [System.Globalization.CultureInfo]::GetCurrentCulture
 
# Full date pattern with a given CultureInfo 
# Look here for available String date patterns: http://www.csharp-examples.net/string-format-datetime/ 
 
$date = (Get-Date).ToString("F", $ci); 
 
# Header template 
$header = 
"//----------------------------------------------------------------------- 
// <copyright file=""{0}"" company=""{1}""> 
// Copyright (c) {1}.   
// <author>Philip Pittle</author>  
// <date>{2}</date>  
// Licensed under the Apache License, Version 2.0, 
// you may not use this file except in compliance with one of the Licenses. 
//   
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 
// 
// Unless required by applicable law or agreed to in writing, software 
// distributed under the License is distributed on an 'AS IS' BASIS, 
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
// See the License for the specific language governing permissions and 
// limitations under the License. 
// </copyright>  
//-----------------------------------------------------------------------`r`n"
 
  function Write-Header ($file) 
  { 
    # Get the file content as as Array object that contains the file lines     
    $content = Get-Content $file 
    
    # Getting the content as a String 
    $contentAsString = $content | Out-String 
    
    # If content starts with //-- the skip it 
    if(!$contentAsString.StartsWith("//--"))
    {     
        # Splitting the file path and getting the leaf/last part, that is, the file name 
        $filename = Split-Path -Leaf $file 
        
        # $fileheader is assigned the value of $header with dynamic values passed as parameters after -f     
        $fileheader = $header -f $filename, $companyname, $date 
        
        # Writing the header to the file 
        Set-Content $file $fileheader -encoding UTF8 
        
        # Append the content to the file
        Add-Content $file $content     
    }
} 
 
#Filter files getting only .cs ones and exclude specific file extensions 
Get-ChildItem $target -Filter *.cs -Exclude TemporaryGeneratedFile*.cs, *.Designer.cs,T4MVC.cs,*.generated.cs,*.ModelUnbinder.cs -recurse | % `
{ 
    <# For each file on the $target directory that matches the filter, let's call the Write-Header function defined above passing the file as parameter #> 
    Write-Header $_.PSPath.Split(":", 3)[2] 
} 

In order to get run the script during a build phase, Visual Studio needs permissions to run power shell commands (http://stackoverflow.com/questions/5006619/call-powershell-script-in-post-built-with-parameters?rq=1).  Run the following batch script:

REM This Script Must Be Run As An Administrator

%SystemRoot%\SysWOW64\WindowsPowerShell\v1.0\powershell.exe "Set-ExecutionPolicy Unrestricted"
%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe "Set-ExecutionPolicy Unrestricted"

Then add the following to Visual Studio pre-build event:

powershell.exe -file "$(SolutionDir)\scripts\AddCopyrightToAllClasses.ps1" -target $(ProjectDir)
(In this case, I have saved the power shell script above as AddCopyrightToAllClasses.ps1 and saved it in a directory called scripts.  The scripts directory is in the solution directory (not the project directory).

I originally found the links to the power shell script on stackoverflow: http://stackoverflow.com/questions/12199409/inserting-copyright-notice-banner-in-all-source-code-files-in-visual-studio-2012