AlanTsai
5/11/2013 - 12:53 AM

Powershell Scaffolding Example

Powershell Scaffolding Example

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{5FDF5393-022B-4F00-BF60-34A9A0D806DC}</ProjectGuid>
    <OutputType>Exe</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>ConsoleApplication1</RootNamespace>
    <AssemblyName>ConsoleApplication1</AssemblyName>
    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="Castle.Core">
      <HintPath>..\packages\Castle.Core.3.2.0\lib\net45\Castle.Core.dll</HintPath>
    </Reference>
    <Reference Include="Castle.Facilities.Logging">
      <HintPath>..\packages\Castle.LoggingFacility.3.2.0\lib\net45\Castle.Facilities.Logging.dll</HintPath>
    </Reference>
    <Reference Include="Castle.Services.Logging.NLogIntegration">
      <HintPath>..\packages\Castle.Core-NLog.3.2.0\lib\net40\Castle.Services.Logging.NLogIntegration.dll</HintPath>
    </Reference>
    <Reference Include="Castle.Windsor">
      <HintPath>..\packages\Castle.Windsor.3.2.0\lib\net45\Castle.Windsor.dll</HintPath>
    </Reference>
    <Reference Include="NLog">
      <HintPath>..\packages\NLog.2.0.1.2\lib\net45\NLog.dll</HintPath>
    </Reference>
    <Reference Include="System" />
    <Reference Include="System.Configuration" />
    <Reference Include="System.Core" />
    <Reference Include="System.Xml.Linq" />
    <Reference Include="System.Data.DataSetExtensions" />
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System.Data" />
    <Reference Include="System.Xml" />
    <Reference Include="Topshelf">
      <HintPath>..\packages\Topshelf.3.1.1\lib\net40-full\Topshelf.dll</HintPath>
    </Reference>
    <Reference Include="Topshelf.NLog">
      <HintPath>..\packages\Topshelf.NLog.3.1.1\lib\net40-full\Topshelf.NLog.dll</HintPath>
    </Reference>
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Properties\AssemblyInfo.cs" />
  </ItemGroup>
  <ItemGroup>
    <None Include="app.config" />
    <None Include="bin\Debug\ConsoleApplication1.exe.config" />
    <None Include="bin\Debug\ConsoleApplication1.vshost.exe.config" />
    <None Include="bin\Debug\ConsoleApplication1.vshost.exe.manifest" />
    <None Include="bin\Debug\NLog.config" />
    <None Include="bin\Debug\Templates.Service.exe.config" />
    <None Include="NLog.config">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>
    <None Include="packages.config" />
  </ItemGroup>
  <ItemGroup>
    <Content Include="bin\Debug\ConsoleApplication1.vshost.exe" />
  </ItemGroup>
  <ItemGroup>
    <Folder Include="bin\Release\" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
</Project>
function Insert-CompileNode { 
    param($dir, $file)
    $project = (gi ".\$mvc_project_directory\$mvc_project_directory.csproj").FullName
    $node = "<Compile Include='$dir\$file.cs' />"
    $doc = ([xml](Get-Content $project)) 
    $doc | `
        Select-Xml "//x:ItemGroup[x:Compile]" -Namespace @{"x"=$doc.Project.xmlns} | `
        Select-Object -ExpandProperty Node -First 1 | `
        % { $_.InnerXml += $node; $doc.Save($project) }
}

function New-Model {
@"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Oak;
 
namespace $mvc_project_directory.Models
{
    public class $name : DynamicModel
    {
        public $name(object dto) : base(dto) { }
        public $name() { }
        //IEnumerable<dynamic> Validates() { }
        //IEnumerable<dynamic> Associates() { }
    }
}
"@
}
Include ".\utilities.ps1"
properties {
    $config = &".\config.ps1"
    $config | %{ Set-Variable -Scope 1 -Name $_ -Value $config[$_] }

    $mvc_project_directory = $config.mvc_project

    # Provide a default (could be done in config.ps1) 
    # which can be overriden at command line by -Properties argument.
    $name = "Person"  
}

task model -depends setup `
    -description "adds a dynamic model class to your mvc project" `
{
    #error validation, did they pass the name argument?
    Assert ($name -ne $null) "name parameter required, usage: Invoke-Psake model @{`$n=`"Person`"}"

    #create the template, if it doesn't exist already
    $path = "$mvc_project_directory\Models\$name.cs"
    Assert ((Test-Path $path) -eq $false) "File already exists"
    New-Model | Set-Content $path

    #add class to cs project
    Insert-CompileNode Models $name
}

task clean {
    Remove-Item $mvc_project_directory -Recurse -Force -ErrorAction SilentlyContinue
}

task setup -depends clean { .{
    mkdir ".\$mvc_project_directory" 
    mkdir ".\$mvc_project_directory\Models" 
    cp ".\TestProject.csproj" "$mvc_project_directory\$mvc_project.csproj"
} | Out-Null}
@{
website_port = 80
website_deploy_directory = 'C:\inetpub\website'
solution_name = 'ASolution'
mvc_project = 'AProject'
database = '(local)\SQLEXPRESS'
} 

PowerShell Scaffolding

Amir's RRYN Version (RRYN == Ruby Rake Yaml Nokogiri)

Setup

First, assuming you've not done a bunch of PowerShell before, lets get you setup with the minimums (in my opinion)

  • Set your execution policy, if you haven't already. You can choose Unrestricted if you prefer, RemoteSigned is a minimum for PSGet.
Set-ExecutionPolicy RemoteSigned
(new-object Net.WebClient).DownloadString("http://psget.net/GetPsGet.ps1") | iex
  • Install PSake (pronounced Sake, like the rice-wine)
install-module psake
import-module psake
  • Personally I setup an alias for PSake
New-Alias psake Invoke-psake

PSake Commands

Run the model task, add a Person (which I made a default) :

psake model

Run the model task, add an AwesomeClass :

psake Model -properties @{name="AwesomeClass"}

Document all tasks:

psake .\default.ps1 -docs