-
-
Notifications
You must be signed in to change notification settings - Fork 41
/
Xpand.VersionConverter.ps1
137 lines (131 loc) 路 6.47 KB
/
Xpand.VersionConverter.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
using namespace System
using namespace System.IO
using namespace System.IO.Compression
using namespace System.Reflection
using namespace System.Text.RegularExpressions
using namespace Mono.Cecil
using namespace Mono.Cecil.pdb
param(
# [parameter(Mandatory)]
[string]$projectFile = "C:\Work\eXpandFramework\expand\Xpand\Xpand.ExpressApp.Modules\ExcelImporter\Xpand.ExpressApp.ExcelImporter.csproj",
# [parameter(Mandatory)]
[string]$targetPath = "C:\Work\eXpandFramework\expand\Xpand.DLL\",
[string]$referenceFilter = "DevExpress*",
[string]$assemblyFilter = "Xpand.XAF.*"
)
# $VerbosePreference = "Continue"
$ErrorActionPreference = "Stop"
set-location $targetPath
function Using-Object {
[CmdletBinding()]
param (
[Object]$InputObject,
[Parameter(Mandatory = $true)]
[scriptblock]$ScriptBlock
)
try {
. $ScriptBlock
}
finally {
if ($null -ne $InputObject -and $InputObject -is [System.IDisposable]) {
$InputObject.Dispose()
}
}
}
Write-Verbose "Running Version Converter on project $projectFile with target $targetPath"
$projectFileInfo = Get-Item $projectFile
[xml]$csproj = Get-Content $projectFileInfo.FullName
$references = $csproj.Project.ItemGroup.Reference
$dxReferences = $references | Where-Object { $_.Include -like "$referenceFilter" }
$root = $PSScriptRoot
Write-Verbose "Loading Mono.Cecil"
$monoPath = "$root\mono.cecil.0.10.3\lib\net40"
if (!(Test-Path "$monoPath\Mono.Cecil.dll")) {
$client = New-Object System.Net.WebClient
$client.DownloadFile("https://www.nuget.org/api/v2/package/Mono.Cecil/0.10.3", "$root\mono.cecil.0.10.3.zip")
Add-Type -AssemblyName System.IO.Compression.FileSystem
[ZipFile]::ExtractToDirectory("$root\mono.cecil.0.10.3.zip", "$root\mono.cecil.0.10.3")
}
[Assembly]::Load([File]::ReadAllBytes("$monoPath\Mono.Cecil.dll")) | Out-Null
[Assembly]::Load([File]::ReadAllBytes("$monoPath\Mono.Cecil.pdb.dll")) | Out-Null
Add-Type @"
using Mono.Cecil;
public class MyDefaultAssemblyResolver : DefaultAssemblyResolver{
public override AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters){
try{
return base.Resolve(name, parameters);
}
catch (AssemblyResolutionException){
var assemblyDefinition = AssemblyDefinition.ReadAssembly(string.Format(@"$targetPath\{0}.dll", name.Name));
return assemblyDefinition;
}
}
}
"@ -ReferencedAssemblies @("$monoPath\Mono.Cecil.dll")
$devExpressAssemblyName = Invoke-Command {
Write-Verbose "Finding DX assembly name"
$dxAssemblyPath = Get-ChildItem $targetPath "$referenceFilter*.dll" | Select-Object -First 1
if ($dxAssemblyPath) {
$dxAssembly = [AssemblyDefinition]::ReadAssembly($dxAssemblyPath.FullName)
Write-Verbose "$($dxAssembly.Name.Name) found from $($dxAssemblyPath.FullName)"
$dxAssembly.Name
}
else {
$name = ($dxReferences | Where-Object { $_.Include -like "*Version*" } | Select-Object -First 1).Include
New-Object System.Reflection.AssemblyName($name)
}
} | Select-Object -last 1
if (!$devExpressAssemblyName) {
throw "Cannot find $referenceFilter version in $($projectFileInfo.Name)"
}
$references | Where-Object { $_.Include -like $assemblyFilter } | ForEach-Object {
"$targetPath\$([Path]::GetFileName($_.HintPath))", "$($projectFileInfo.DirectoryName)\$($_.HintPath)" | ForEach-Object {
if (Test-Path $_) {
$modulePath = (Get-Item $_).FullName
Write-Verbose "Checking $modulePath references.."
$readerParams = New-Object ReaderParameters
$readerParams.ReadWrite = $true
$readerParams.AssemblyResolver = New-Object MyDefaultAssemblyResolver
$readerParams.SymbolReaderProvider = New-Object PdbReaderProvider
$readerParams.ReadSymbols = $true
Using-Object ($moduleAssembly = [AssemblyDefinition]::ReadAssembly($modulePath, $readerParams)) {
$moduleAssembly.MainModule.AssemblyReferences.ToArray() | Write-Verbose
$needPatching = $false
$moduleAssembly.MainModule.AssemblyReferences.ToArray() | Where-Object { $_.FullName -like $referenceFilter } | ForEach-Object {
$nowReference = $_
Write-Verbose "Checking $_ reference..."
if ($nowReference.Version -ne $devExpressAssemblyName.Version) {
$moduleAssembly.MainModule.AssemblyReferences.Remove($nowReference)
$newMinor = "$($devExpressAssemblyName.Version.Major).$($devExpressAssemblyName.Version.Minor)"
$newName = [Regex]::Replace($nowReference.Name, ".(v[\d]{2}\.\d)", ".v$newMinor")
$regex = New-Object Regex("PublicKeyToken=([\w]*)")
$token = $regex.Match($nowReference).Groups[1].Value
$regex = New-Object Regex("Culture=([\w]*)")
$culture = $regex.Match($nowReference).Groups[1].Value
$newReference = [AssemblyNameReference]::Parse("$newName, Version=$($devExpressAssemblyName.Version), Culture=$culture, PublicKeyToken=$token")
$moduleAssembly.MainModule.AssemblyReferences.Add($newreference)
$moduleAssembly.MainModule.Types | ForEach-Object {
$moduleAssembly.MainModule.GetTypeReferences() | Where-Object { $_.Scope -eq $nowReference } | ForEach-Object {
$_.Scope = $newReference
}
}
Write-Verbose "$($_.Name) version changed from $($_.Version) to $($devExpressAssemblyName.Version)"
$needPatching = $true
}
else {
Write-Verbose "Versions ($($nowReference.Version)) matched nothing to do."
}
}
if ($needPatching) {
Write-Verbose "Patching $modulePath"
$writeParams = New-Object WriterParameters
$writeParams.WriteSymbols = $true
$key = [system.byte[]]::new(0)
$key = [System.IO.File]::ReadAllBytes("$root\Xpand.snk")
$writeParams.StrongNameKeyPair = [System.Reflection.StrongNameKeyPair]($key)
$moduleAssembly.Write($writeParams)
}
}
}
}
}