Mineplex2018-withcommit/Website/packages/MvcScaffolding.1.0.7/tools/registerWithMvcTooling.ps1
Jonathan Williams 3fb52c5c71 Initial Commit
2013-08-27 08:14:08 -07:00

145 lines
8.3 KiB
PowerShell

# Ensure we're on the right version of the tooling. If not, there's nothing for us to do here.
$toolingExists = [System.AppDomain]::CurrentDomain.GetAssemblies() | ?{ $_.GetType("Microsoft.VisualStudio.Web.Mvc.Scaffolding.ScaffolderProviders") }
if (!$toolingExists) { return }
# Todo: Scope the following to this module if possible
function global:MvcScaffoldingHashTableToPsObject($hashOfScriptMethods) {
$result = New-Object PSObject
$hashOfScriptMethods.Keys | %{ Add-Member -InputObject $result -Member ScriptMethod -Name $_ -Value $hashOfScriptMethods[$_] }
$result
}
function global:MvcScaffoldingInvokeViaScriptExecutor($scriptToExecute) {
$completeScript = @"
try {
# Activate output pane
`$packageManagerOutputPaneGuid = "{CEC55EC8-CC51-40E7-9243-57B87A6F6BEB}"
`$dteService = [NuGet.VisualStudio.ServiceLocator].GetMethods() | ?{ `$_.Name -eq 'GetInstance' } | %{ `$_.MakeGenericMethod([Microsoft.VisualStudio.Shell.Interop.SDTE]).Invoke(`$null, [Array]`$null) }
`$outputWindow = `$dteService.Windows.Item([EnvDTE.Constants]::vsWindowKindOutput)
`$packageManagerOutputPane = `$outputWindow.Object.OutputWindowPanes.Item(`$packageManagerOutputPaneGuid)
`$packageManagerOutputPane.Clear()
`$packageManagerOutputPane.Activate()
`$outputWindow.Activate()
# Invoke requested script
$scriptToExecute
} catch {
[System.Windows.Forms.MessageBox]::Show("An error occurred during scaffolding:`n`n`$(`$_.Exception.ToString())`n`nYou may need to upgrade to a newer version of MvcScaffolding.", "Scaffolding error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error) | Out-Null
}
"@
try {
# Write the script to disk
$tempDir = Join-Path $env:Temp ([System.Guid]::NewGuid())
$tempScriptFilename = Join-Path $tempDir "tools\tempScript.ps1"
md $tempdir
md ([System.IO.Path]::GetDirectoryName($tempScriptFilename))
Set-Content -Path $tempScriptFilename -Value $completeScript
# Ensure we're on the right NuGet version
$scriptExecutorExists = [System.AppDomain]::CurrentDomain.GetAssemblies() | ?{ $_.GetType("NuGet.VisualStudio.IScriptExecutor") }
if (!$scriptExecutorExists) {
[System.Windows.Forms.MessageBox]::Show("Sorry, this operation requires NuGet 1.2 or later.", "Scaffolding error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error) | Out-Null
return
}
# Invoke via IScriptExecutor, then clean up
$scriptExecutor = [NuGet.VisualStudio.ServiceLocator].GetMethods() | ?{ $_.Name -eq 'GetInstance' } | %{ $_.MakeGenericMethod([NuGet.VisualStudio.IScriptExecutor]).Invoke($null, [Array]$null) }
$scriptExecutor.Execute($tempDir, "tempScript.ps1", $null, $null, (New-Object NuGet.NullLogger))
rmdir $tempdir -Force -Recurse
} catch {
[System.Windows.Forms.MessageBox]::Show("An error occurred during scaffolding:`n`n$($_.Exception.ToString())`n`nYou may need to upgrade to a newer version of MvcScaffolding.", "Scaffolding error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error) | Out-Null
}
}
$mvcScaffoldingProvider = global:MvcScaffoldingHashTableToPsObject @{
ID = { "{9EC893D9-B925-403C-B785-A50545149521}" };
GetControllerScaffolders = {
param($project)
$allControllerScaffolders = Get-Scaffolder -Project $project.Name -IncludeHidden | ?{ $_.ScaffolderAttribute -is [T4Scaffolding.ControllerScaffolderAttribute] }
if (!$allControllerScaffolders) { return @() }
$result = $allControllerScaffolders | %{
global:MvcScaffoldingHashTableToPsObject @{
ID = { $_.Name }.GetNewClosure();
DisplayName = { "MvcScaffolding: " + $_.ScaffolderAttribute.DisplayName }.GetNewClosure();
SupportsModelType = { $_.ScaffolderAttribute.SupportsModelType }.GetNewClosure();
SupportsDataContextType = { $_.ScaffolderAttribute.SupportsDataContextType }.GetNewClosure();
ViewsScaffolders = {
if (!$_.ScaffolderAttribute.SupportsViewScaffolder) { return @() }
$viewScaffolderSelector = $_.ScaffolderAttribute.ViewScaffolderSelector
if (!$viewScaffolderSelector) { $viewScaffolderSelector = [T4Scaffolding.ViewScaffolderAttribute] }
$viewScaffolders = Get-Scaffolder -Project $project.Name -IncludeHidden | ?{ $viewScaffolderSelector.IsAssignableFrom($_.ScaffolderAttribute.GetType()) }
# Put default view engine at the top of the list so it's the default selection until you choose otherwise
$defaultViewScaffolder = (Get-DefaultScaffolder View).ScaffolderName
$viewScaffolders = $viewScaffolders | Sort-Object { if($_.Name -eq $defaultViewScaffolder) { "" } else { $_.Name } }
$result = $viewScaffolders | %{
global:MvcScaffoldingHashTableToPsObject @{
ID = { $_.Name }.GetNewClosure();
DisplayName = { $_.ScaffolderAttribute.DisplayName }.GetNewClosure();
LayoutPageFilter = { $_.ScaffolderAttribute.LayoutPageFilter }.GetNewClosure();
}
}
return ,[Array]$result
}.GetNewClosure();
Execute = {
param($container, $controllerName, $modelType, $dataContextType, $viewsScaffolder, $options)
# Infer possible area name from container location
$areaName = $null
if ($container -is [EnvDTE.ProjectItem]) {
$containerNamespace = $container.Properties.Item("DefaultNamespace").Value
$areaMatch = [System.Text.RegularExpressions.Regex]::Match($containerNamespace, "(^|\.)Areas\.(.*)\.Controllers($|\.)")
$areaName = if ($areaMatch.Success) { $areaMatch.Groups[2].Value }
}
$scriptToExecute = @"
# These are all the args we may pass to the target scaffolder...
`$possibleArgs = @{
ControllerName = `"$controllerName`";
ModelType = `"$modelType`";
DbContextType = `"$dataContextType`";
Project = `"$($project.Name)`";
Area = $(if($areaName) { "`"" + $areaName + "`"" } else { "`$null" });
ViewScaffolder = $(if($viewsScaffolder) { "`"" + $viewsScaffolder.ID + "`"" } else { "`$null" });
Force = $(if($options.OverwriteViews -or $options.OverwriteController) { "`$true" } else { "`$false" });
ForceMode = $(if($options.OverwriteViews -and $options.OverwriteController) { "`$null" } else { if($options.OverwriteViews) { "`"PreserveController`"" } else { "`"ControllerOnly`"" } });
Layout = $(if($options.UseLayout) { "`"" + $options.Layout + "`"" } else { "`$null" });
PrimarySectionName = $(if($options.PrimarySectionName) { "`"" + $options.PrimarySectionName + "`"" } else { "`$null" });
ReferenceScriptLibraries = $(if($options.ReferenceScriptLibraries) { "`$true" } else { "`$false" });
}
# ... but we only pass the ones it actually accepts
`$actualArgs = @{}
`$acceptedParameterNames = (Get-Command Invoke-Scaffolder -ArgumentList @(`"$($_.Name)`")).Parameters.Keys
`$acceptedParameterNames | ?{ `$possibleArgs.ContainsKey(`"`$_`") } | %{ `$actualArgs.Add(`$_, `$possibleArgs[`$_]) }
Invoke-Scaffolder `"$($_.Name)`" @actualArgs
"@
global:MvcScaffoldingInvokeViaScriptExecutor $scriptToExecute | Out-Null
# Trick PowerShell into not unrolling the return collection by wrapping it in a further collection
$result = [System.Activator]::CreateInstance(([System.Collections.Generic.List``1].MakeGenericType([System.Object])))
$result.Add(([System.Activator]::CreateInstance(([System.Collections.Generic.List``1].MakeGenericType([EnvDTE.ProjectItem])))))
return $result
}.GetNewClosure();
}
}
return ,[Array]$result
}
}
# Need to register with each ScaffolderProviders type
# There can be multiple, one per loaded ASP.NET MVC tooling DLL, if your VS instance has multiple versions of ASP.NET MVC tooling loaded
$scaffolderProviderTypes = [System.AppDomain]::CurrentDomain.GetAssemblies() | %{ $_.GetType("Microsoft.VisualStudio.Web.Mvc.Scaffolding.ScaffolderProviders") } | ?{ $_ }
$scaffolderProviderTypes | %{
$allProviders = $_.GetProperty("Providers").GetValue($null, $null)
# Remove existing MvcScaffolding providers
$existingMvcScaffoldingProviders = $allProviders | ?{ $_.ID -eq $mvcScaffoldingProvider.ID() }
$existingMvcScaffoldingProviders | %{ $allProviders.Remove($_) } | Out-Null
# Add new provider
$powerShellScaffolderProviderType = $_.Assembly.GetType("Microsoft.VisualStudio.Web.Mvc.Scaffolding.PowerShell.PowerShellScaffolderProvider")
$newProvider = New-Object $powerShellScaffolderProviderType($mvcScaffoldingProvider)
$allProviders.Add($newProvider) | Out-Null
}