c# - 你可以从 powershell 运行 Microsoft.VisualStudio.SlowCheetah 吗?
问题描述
我想运行一个 powershell 构建脚本,其中我有一些不是 app.config、appsettings.json 或 web.config 文件的配置文件 (xml/json),我想根据构建配置进行转换。完美的工具似乎是 VisualStudio.SlowCheetah,因为它同时支持 xml 和 json,并且它使用与 web.config 转换相同的底层技术(这也在我的项目中)。有没有办法从powershell运行这个工具,如果有相同的工具在解决方案中进行转换也对我的辅助文件进行转换,那会很好吗?
解决方案
所以这是我的概念证明:
我的文件夹包含 4 个文件:
- PerformTransform.ps1 - 将启动转换的构建脚本的替身
- Transform-Config.ps1 - 使用 SlowCheetah 执行转换的脚本
- Sample.config - 一个示例配置文件
- Sample.Prod.config - 一个示例 xml 转换文件
PerformTransform.ps1 看起来像:
cls
$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
# Temporarily adds the script folder to the path
# so that the Transform-Config command is available
if(($env:Path -split ';') -notcontains $scriptPath) {
$env:Path += ';' + $scriptPath
}
Transform-Config "$scriptPath\Sample.config" "$scriptPath\Sample.Prod.config" "$scriptPath\Sample.Transformed.config"
这是我的 Transform-Config.ps1:
#!/usr/bin/env powershell
<#
.SYNOPSIS
You can use this script to easly transform any XML file using XDT or JSON file using JDT.
To use this script you can just save it locally and execute it. The script
will download its dependencies automatically.
#>
[cmdletbinding()]
param(
[Parameter(
Mandatory=$true,
Position=0)]
$sourceFile,
[Parameter(
Mandatory=$true,
Position=1)]
$transformFile,
[Parameter(
Mandatory=$true,
Position=2)]
$destFile
)
$loggingStubSource = @"
using System;
namespace Microsoft.VisualStudio.SlowCheetah
{
public class LoggingStub : ITransformationLogger
{
public void LogError(string message, params object[] messageArgs) { }
public void LogError(string file, int lineNumber, int linePosition, string message, params object[] messageArgs) { }
public void LogErrorFromException(Exception ex) { }
public void LogErrorFromException(Exception ex, string file, int lineNumber, int linePosition) { }
public void LogMessage(LogMessageImportance importance, string message, params object[] messageArgs) { }
public void LogWarning(string message, params object[] messageArgs) { }
public void LogWarning(string file, int lineNumber, int linePosition, string message, params object[] messageArgs) { }
}
}
"@ # this here-string terminator needs to be at column zero
<#
.SYNOPSIS
If nuget is not in the tools
folder then it will be downloaded there.
#>
function Get-Nuget(){
[cmdletbinding()]
param(
$toolsDir = "$env:LOCALAPPDATA\NuGet\BuildTools\",
$nugetDownloadUrl = 'https://dist.nuget.org/win-x86-commandline/latest/nuget.exe'
)
process{
$nugetDestPath = Join-Path -Path $toolsDir -ChildPath nuget.exe
if(!(Test-Path $nugetDestPath)){
'Downloading nuget.exe' | Write-Verbose
# download nuget
$webclient = New-Object System.Net.WebClient
$webclient.DownloadFile($nugetDownloadUrl, $nugetDestPath)
# double check that is was written to disk
if(!(Test-Path $nugetDestPath)){
throw 'unable to download nuget'
}
}
# return the path of the file
$nugetDestPath
}
}
function Get-Nuget-Package(){
[cmdletbinding()]
param(
[Parameter(
Mandatory=$true,
Position=0)]
$packageName,
[Parameter(
Mandatory=$true,
Position=1)]
$toolFileName,
$toolsDir = "$env:LOCALAPPDATA\NuGet\BuildTools\",
$nugetDownloadUrl = 'https://dist.nuget.org/win-x86-commandline/latest/nuget.exe'
)
process{
if(!(Test-Path $toolsDir)){
New-Item -Path $toolsDir -ItemType Directory | Out-Null
}
$toolPath = (Get-ChildItem -Path $toolsDir -Include $toolFileName -Recurse) | Select-Object -First 1
if($toolPath){
return $toolPath
}
"Downloading package [$packageName] since it was not found in the tools folder [$toolsDir]" | Write-Verbose
$cmdArgs = @('install',$packageName,'-OutputDirectory',(Resolve-Path $toolsDir).ToString())
"Calling nuget.exe to download [$packageName] with the following args: [{0} {1}]" -f (Get-Nuget -toolsDir $toolsDir -nugetDownloadUrl $nugetDownloadUrl), ($cmdArgs -join ' ') | Write-Verbose
&(Get-Nuget -toolsDir $toolsDir -nugetDownloadUrl $nugetDownloadUrl) $cmdArgs | Out-Null
$toolPath = (Get-ChildItem -Path $toolsDir -Include $toolFileName -Recurse) | Select-Object -First 1
return $toolPath
}
}
function Transform-Config{
[cmdletbinding()]
param(
[Parameter(
Mandatory=$true,
Position=0)]
$sourceFile,
[Parameter(
Mandatory=$true,
Position=1)]
$transformFile,
[Parameter(
Mandatory=$true,
Position=2)]
$destFile,
$toolsDir = "$env:LOCALAPPDATA\NuGet\BuildTools\"
)
process{
$sourcePath = (Resolve-Path $sourceFile).ToString()
$transformPath = (Resolve-Path $transformFile).ToString()
$cheetahPath = Get-Nuget-Package -packageName 'Microsoft.VisualStudio.SlowCheetah' -toolFileName 'Microsoft.VisualStudio.SlowCheetah.dll' -toolsDir $toolsDir
if(!$cheetahPath){
throw ('Failed to download Slow Cheetah package')
}
if (-not ([System.Management.Automation.PSTypeName]'Microsoft.VisualStudio.SlowCheetah.LoggingStub').Type)
{
[Reflection.Assembly]::LoadFrom($cheetahPath.FullName) | Out-Null
Add-Type -TypeDefinition $loggingStubSource -Language CSharp -ReferencedAssemblies $cheetahPath.FullName
}
$logStub = New-Object Microsoft.VisualStudio.SlowCheetah.LoggingStub
$transformer = [Microsoft.VisualStudio.SlowCheetah.TransformerFactory]::GetTransformer($sourcePath, $logStub);
$success = $transformer.Transform($sourcePath, $transformPath, $destFile);
if(!$success){
throw ("Transform of file [] failed!!!!")
}
Write-Host "Transform successful."
}
}
Transform-Config -sourceFile $sourceFile -transformFile $transformFile -destFile $destFile
配置文件并不重要,您应该能够使用现有的 app.config 和 app.ENV.config 转换文件来使用它。
如果有更简单的方法可以做到这一点,请告诉我!
推荐阅读
- reactjs - 在 redux-toolkit 中使用 combine reducer 重置嵌套状态的最佳方法
- julia - Flux 中的自定义梯度下降算法
- python - 用诗歌运行一个包 pytest
- python - 将列表的空字符串转换为浮点数
- javascript - 为什么我需要@babel/polyfill,使用 Babel?
- ios - 将数据仅传递给 UINavigation 上的静态故事板嵌入式 tableview 控制器
- laravel - 如何使用自定义分页 laravel?
- spring - 在 Tomcat 启动时运行启用 Spring 的 @Component 方法
- r - 使用 R 中的 abline 函数具有不同颜色的直方图
- python - 如果字符串字符在同一个字符串中重复,相同的字符串字符是否具有相同的索引?