【问题标题】:Create Visual Studio .NET solution using a shell script?使用 shell 脚本创建 Visual Studio .NET 解决方案?
【发布时间】:2019-02-03 14:10:43
【问题描述】:

我从事的大量项目都是从相同的基本布局开始的。我想知道是否有一种方法可以自动化项目的初始创建。我想用脚本创建一个解决方案和所有内部项目。最重要的是,我希望能够为这个项目创建 git 存储库。

我希望有一种方法可以在 shell 脚本或类似的东西中制作这个项目。如果这不可能,有没有办法制作可用于创建解决方案的模板?

我进行了大量搜索,但要么我不知道如何正确地用词搜索,要么我什么也找不到。我在 IntelliJ 中看到了与此类似的东西。

【问题讨论】:

标签: c# .net visual-studio powershell templates


【解决方案1】:

这里有一些东西可以帮助您入门。它仅适用于 C# 项目并重命名现有解决方案的所有命名空间。您可以克隆一个目录,它会进行简单的搜索和替换。您还应该重命名项目 guid。

<#
.SYNOPSIS
  Renames all the filenames and namespaces of an existing solution or project

.DESCRIPTION
  When a new visual studio solution is cloned, the namespaces usually need
  to be changed, as well as the filenames.

  This script does all that on an existing solution directory.

.PARAMETER Path
  Path to the solution file e.g. MyCompany.MyApp\MyCompany.MyApp.sln

.PARAMETER OldNamespace
  Original namespace of the solution e.g. MyCompany.MyApp

.PARAMETER NewNamespace
  New namespace to replace the original namespace with e.g. MyCompany.NewApp

.INPUTS
  <Inputs if any, otherwise state None>

.OUTPUTS
  <Outputs if any, otherwise state None - example: Log file stored in C:\Windows\Temp\<name>.log>

.NOTES
  Version:        1.0
  Author:         Chui Tey
  Creation Date:  15-08-2018
  Purpose/Change: Initial script development

.EXAMPLE
  .\Rename-Solution.ps1 -Path .\MyCompany.MyApp\MyCompany.MyApp.sln MyCompany.OldApp MyCompany.MyApp [-Verbose]
#>

[CmdletBinding(SupportsShouldProcess)]
param
(
    [Parameter(Mandatory)]
    [string]
    $Path,

    [Parameter(Mandatory)]
    $OldNamespace,

    [Parameter(Mandatory)]
    $NewNamespace
)

#---------------------------------------------------------[Initialisations]--------------------------------------------------------

$ErrorActionPreference = "Stop"

$SolutionPath = $Path
$SolutionDirectory = (Get-Item $SolutionPath).DirectoryName

Write-Verbose "`$SolutionPath=`"$SolutionPath`""
Write-Verbose "`$SolutionDirectory=`"$SolutionDirectory`""

If (-Not (Test-Path $SolutionPath -PathType Leaf))
{
    Write-Error "SolutionPath $SolutionPath not present"
}

If (-Not $SolutionPath.EndsWith(".sln"))
{
    Write-Error "SolutionPath must end with '.sln'"
}

If ($OldNamespace -cnotlike "*.*")
{
    Write-Error "OldNamespace parameter must contain period e.g. 'MyCompany.MyApp'"
}

If ($NewNamespace -cnotlike "*.*")
{
    Write-Error "NewNamespace parameter must contain period e.g. 'MyCompany.MyApp'"
}

#-----------------------------------------------------------[Functions]------------------------------------------------------------


Function Rename-Namespaces
{
    [CmdletBinding(SupportsShouldProcess=$true)]
    param(
        [Parameter(ValueFromPipeline=$True, Mandatory)] $Item,
        [string] $OldNamespace,
        [string] $NewNamespace
    )

    Process
    {
        $OldContent = (Get-Content -Path $item.FullName -Raw)
        If ($OldContent -cmatch $OldNamespace)
        {
            If ($PSCmdlet.ShouldProcess($item.FullName, "Rename-Namespaces"))
            {
                Write-Verbose "Rename-Namespace $($item.FullName)"
                $NewContent = $OldContent -creplace $OldNamespace,$NewNamespace

                # Don't use Set-Content as it appends a new line
                #Set-Content -Path $Item.FullName -Value $NewContent
                [System.IO.File]::WriteAllText($Item.FullName, $NewContent)
            }
        }
    }
}

Function Get-FilesToRenameNamespace
{
    $items = Get-ChildItem -Path $SolutionDirectory -Recurse -File -Filter "*.csproj" 
    $items

    $items = Get-ChildItem -Path $SolutionDirectory -Recurse -File -Filter "*.cs" 
    $items

    $items = Get-ChildItem -Path $SolutionDirectory -Recurse -File -Filter "*.asax" 
    $items

    $items = Get-ChildItem -Path $SolutionDirectory -Recurse -File -Filter "*.cshtml" 
    $items

    $items = Get-ChildItem -Path $SolutionDirectory -Recurse -File -Filter "*.config" 
    $items

    $items = Get-ChildItem -Path $SolutionDirectory -Recurse -File -Filter "*.targets" 
    $items
}

Function Rename-Project($SolutionDirectory, $OldNamespace, $NewNamespace)
{
    Write-Verbose "Renaming csproj"
    Get-ChildItem -ErrorAction SilentlyContinue -File -Recurse -Path $SolutionDirectory -Filter "*$OldNamespace*.csproj" `
    | ForEach-Object {
        $NewName = $_.Name -replace $OldNamespace,$NewNamespace
        Rename-Item -Path $_.FullName $NewName
    }

    Write-Verbose "Renaming directories"
    Get-ChildItem -ErrorAction SilentlyContinue -Directory -Recurse -Path $SolutionDirectory -Filter "*$OldNamespace*" `
    | ForEach-Object {
        $NewName = $_.Name -replace $OldNamespace,$NewNamespace
        Rename-Item -Path $_.FullName $NewName
    }

    Write-Verbose "Renaming project names in sln"
    $OldContent = Get-Content $SolutionPath
    $NewContent = $OldContent -replace $OldNamespace,$NewNamespace
    Set-Content -Path $SolutionPath -Value $NewContent
}


Function Rename-Solution($SolutionDirectory, $OldNamespace, $NewNamespace)
{
    Get-ChildItem -ErrorAction SilentlyContinue -File -Path $SolutionDirectory -Filter "*$OldNamespace*.sln" `
    | ForEach-Object {
        $NewName = $_.Name -replace $OldNamespace,$NewNamespace
        Rename-Item -Path $_.FullName $NewName
    }
}

#-----------------------------------------------------------[Execution]------------------------------------------------------------

Get-FilesToRenameNamespace | Rename-Namespaces -OldNamespace $OldNamespace -NewNamespace $NewNamespace

Rename-Project $SolutionDirectory $OldNamespace $NewNamespace
Rename-Solution $SolutionDirectory $OldNamespace $NewNamespace


Write-Output "End of script"

重命名项目 guid 的脚本。

<#
.SYNOPSIS
  Renames all the project guids in a solution so that they are unique

.DESCRIPTION
  When a new visual studio solution is cloned, project guids need to change as well.

.PARAMETER Path
  Path to the solution file e.g. MyCompany.MyApp\MyCompany.MyApp.sln

.INPUTS
  <Inputs if any, otherwise state None>

.OUTPUTS
  <Outputs if any, otherwise state None - example: Log file stored in C:\Windows\Temp\<name>.log>

.NOTES
  Version:        1.0
  Author:         Chui Tey
  Creation Date:  15-08-2018
  Purpose/Change: Initial script development

.EXAMPLE
  .\Rename-Solution.ps1 -Path .\MyCompany.MyApp [-Verbose]
#>

[CmdletBinding(SupportsShouldProcess)]
param
(
    [Parameter(Mandatory)]
    [string]
    $Path
)

#---------------------------------------------------------[Initialisations]--------------------------------------------------------

$ErrorActionPreference = "Stop"

$SolutionPath = $Path
$SolutionDirectory = (Get-Item $SolutionPath).DirectoryName

Write-Verbose "`$SolutionPath=`"$SolutionPath`""
Write-Verbose "`$SolutionDirectory=`"$SolutionDirectory`""

If (-Not (Test-Path $SolutionPath -PathType Leaf))
{
    Write-Error "SolutionPath $SolutionPath not present"
}

If (-Not $SolutionPath.EndsWith(".sln"))
{
    Write-Error "SolutionPath must end with '.sln'"
}

#-----------------------------------------------------------[Functions]------------------------------------------------------------

Function Get-ProjectGuid($SolutionPath)
{
    Get-Content $SolutionPath `
    | Where-Object { $_ -match "Project.+ `"(.+)`", `"{([0123456789ABCDEF-]+)}`"" } `
    | ForEach-Object { New-Object PsObject -Property @{ File = $Matches[1]; Guid = $Matches[2] } } `
    | Where-Object { Test-Path -PathType Leaf (Join-Path $SolutionDirectory $_.File) }
}

Function New-Type3Guid([string] $src)
{
    If ($src.Length -eq 0 -or $src -eq $null)
    {
        Write-Error "New-Type3Guid $src must not be empty"
    }

    $md5 = [System.Security.Cryptography.MD5]::Create()
    $hash = $md5.ComputeHash([System.Text.Encoding]::Default.GetBytes($src))
    $md5.Dispose()

    $newGuid = [System.Guid]::new($hash)
    Write-Verbose "New-Type3Guid $src => $newGuid"
    Return $newGuid
}

Function New-ProjectGuidMapping
{
    param
    (
        [Parameter(Mandatory)]
        [string]
        $SolutionPath
    )

    $ProjectGuidMapping = @{}
    Get-ProjectGuid $SolutionPath `
    | ForEach-Object {
        $filename = $_.File
        Write-Verbose "Calling New-Type3Guid $filename"
        $guid = New-Type3Guid $filename
        $ProjectGuidMapping[$_.Guid] = $guid.ToString().ToUpper() 
    }
    Return $ProjectGuidMapping
}

Function Rename-ProjectGuid
{
    [CmdletBinding(SupportsShouldProcess)]
    param ($ProjectGuidMapping)

    $projects = [PSObject[]] (Get-ChildItem -Recurse -File -Path $SolutionDirectory -Filter "*.csproj")
    $solutions = [PSObject[]] (Get-ChildItem -Recurse -File -Path $SolutionDirectory -Filter "*.sln")

    $items = $projects + $solutions
    ForEach ($item in $items)
    {
        $OldContent = Get-Content -Path $item.FullName

        ForEach ($Key in $ProjectGuidMapping.Keys)
        {
            Write-Verbose "Checking key $Key"
            If ($OldContent -cmatch $Key)
            {
                Write-Verbose "Matched $Key in $($Item.FullName)"
                If ($PSCmdlet.ShouldProcess($item.FullName, "Rename-ProjectGuids"))
                {
                    Write-Verbose "Rename-ProjectGuids $($item.FullName) $Key to $($ProjectGuidMapping[$Key])"
                    $NewContent = $OldContent -creplace $Key,$ProjectGuidMapping[$Key]
                    Set-Content -Path $Item.FullName -Value $NewContent
                    $OldContent = $NewContent
                }
            }
        }
    }
}

$ProjectGuidMapping = New-ProjectGuidMapping $SolutionPath
Rename-ProjectGuid $ProjectGuidMapping

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多