Implement PGO in pipelines for AMD64 architecture; supply training test scenarios (#10071)
Implement PGO in pipelines for AMD64 architecture; supply training test scenarios ## References - #3075 - Relevant to speed interests there and other linked issues. ## PR Checklist * [x] Closes #6963 * [x] I work here. * [x] New UIA Tests added and passed. Manual build runs also tested. ## Detailed Description of the Pull Request / Additional comments - Creates a new pipeline run for creating instrumented binaries for Profile Guided Optimization (PGO). - Creates a new suite of UIA tests on the full Windows Terminal app to run PGO training scenarios on instrumented binaries (and incidentally can be used to write other UIA tests later for the full Terminal app.) - Creates a new NuGet artifact to store trained PGO databases (PGD files) at `Microsoft.Internal.Windows.Terminal.PGODatabase` - Creates a new NuGet artifact to supply large-scale test content for automated tests at `Microsoft.Internal.Windows.Terminal.TestContent` - Adjusts the release pipeline to run binaries in PGO optimized mode where content from PGO databases is leveraged at link time to optimize the final release build The following binaries are trained: - OpenConsole.exe - WindowsTerminal.exe - TerminalApp.dll - TerminalConnection.dll - Microsoft.Terminal.Control.dll - Microsoft.Terminal.Remoting.dll - Microsoft.Terminal.Settings.Editor.dll - Microsoft.Terminal.Settings.Model.dll In the future, adding `<PgoTarget>true</PgoTarget>` to a new `vcxproj` file will automatically enroll the DLL/EXE for PGO instrumentation and optimization going forward. Two training test scenarios are implemented: - Smoke test the Terminal by just opening it and typing a bit of text then exiting. (Should help focus on the standard launch path.) - Optimize bulk text output by launching terminal, outputting `big.txt`, then exiting. Additional scenarios can be contributed to the `WindowsTerminal_UIATests` project with the `[TestProperty("IsPGO", "true")]` annotation to add them to the suite of scenarios for PGO. **NOTE:** There are currently no weights applied to the various test scenarios. We will revisit that in the future when/if necessary. ## Validation Steps Performed - [x] - Training run completed at https://dev.azure.com/ms/terminal/_build?definitionId=492&_a=summary - [x] - Optimization run completed locally (by forcing `PGOBuildMode` to `Optimize` on my local machine, manually retrieving the databases with NuGet, and building). - [x] - Validated locally that x86 and ARM64 do not get trained and automatically skip optimization as databases are not present for them. - [x] - Smoke tested optimized binary versus latest releases. `big.txt` output through CMD is ~11-12seconds prior to PGO and just over 8 seconds with PGO.
This commit is contained in:
parent
a3a2a4102d
commit
7dadde5dd6
|
@ -18,10 +18,10 @@ ACIOSS
|
|||
ACover
|
||||
actctx
|
||||
ACTCTXW
|
||||
actionmap
|
||||
activatable
|
||||
ACTIVEBORDER
|
||||
ACTIVECAPTION
|
||||
adaa
|
||||
ADDALIAS
|
||||
ADDB
|
||||
ADDREF
|
||||
|
@ -199,6 +199,7 @@ byref
|
|||
bytearray
|
||||
bytebuffer
|
||||
cac
|
||||
cacafire
|
||||
callee
|
||||
cang
|
||||
capslock
|
||||
|
@ -298,6 +299,8 @@ codepage
|
|||
codepath
|
||||
codepoint
|
||||
codeproject
|
||||
coffgroup
|
||||
coffgrp
|
||||
coinit
|
||||
COLLECTIONURI
|
||||
colorizing
|
||||
|
@ -487,6 +490,7 @@ dai
|
|||
DATABLOCK
|
||||
DATAVIEW
|
||||
DATAW
|
||||
datetime
|
||||
DBatch
|
||||
dbcs
|
||||
DBCSCHAR
|
||||
|
@ -676,6 +680,7 @@ dxgidwm
|
|||
dxinterop
|
||||
dxttbmp
|
||||
eachother
|
||||
eae
|
||||
eaf
|
||||
EASTEUROPE
|
||||
eb
|
||||
|
@ -698,6 +703,7 @@ elems
|
|||
elif
|
||||
elseif
|
||||
emacs
|
||||
emplate
|
||||
EMPTYBOX
|
||||
enabledelayedexpansion
|
||||
endian
|
||||
|
@ -761,6 +767,7 @@ fcb
|
|||
fcharset
|
||||
fclose
|
||||
fcntl
|
||||
fd
|
||||
fdc
|
||||
FDD
|
||||
fdopen
|
||||
|
@ -781,6 +788,7 @@ FILESYSPATH
|
|||
filesystem
|
||||
FILETIME
|
||||
FILETYPE
|
||||
fileurl
|
||||
FILEW
|
||||
FILLATTR
|
||||
FILLCONSOLEOUTPUT
|
||||
|
@ -846,6 +854,7 @@ fuzzwrapper
|
|||
fwdecl
|
||||
fwe
|
||||
fwlink
|
||||
Fx
|
||||
GAUSSIAN
|
||||
gb
|
||||
gci
|
||||
|
@ -854,6 +863,7 @@ gcy
|
|||
gdi
|
||||
gdip
|
||||
gdirenderer
|
||||
GENPROFILE
|
||||
geopol
|
||||
GETALIAS
|
||||
GETALIASES
|
||||
|
@ -973,6 +983,7 @@ hfont
|
|||
hglobal
|
||||
hh
|
||||
hhh
|
||||
HHmm
|
||||
hhook
|
||||
hhx
|
||||
HIBYTE
|
||||
|
@ -1003,6 +1014,7 @@ horiz
|
|||
HORZ
|
||||
hostable
|
||||
hostlib
|
||||
Hostx
|
||||
HPA
|
||||
HPAINTBUFFER
|
||||
hpcon
|
||||
|
@ -1129,6 +1141,7 @@ INPUTPROCESSORPROFILE
|
|||
inputrc
|
||||
Inputreadhandledata
|
||||
INSERTMODE
|
||||
installationpath
|
||||
intellisense
|
||||
INTERACTIVITYBASE
|
||||
INTERCEPTCOPYPASTE
|
||||
|
@ -1430,6 +1443,7 @@ mkdir
|
|||
MMBB
|
||||
mmcc
|
||||
MMCPL
|
||||
MMdd
|
||||
mmsystem
|
||||
MNC
|
||||
MNOPQ
|
||||
|
@ -1618,6 +1632,7 @@ numlock
|
|||
numpad
|
||||
NUMSCROLL
|
||||
nupkg
|
||||
nuspec
|
||||
NVIDIA
|
||||
NVR
|
||||
Nx
|
||||
|
@ -1760,7 +1775,11 @@ PFNCONSOLECREATEIOTHREAD
|
|||
PFONT
|
||||
PFONTENUMDATA
|
||||
PFS
|
||||
pgd
|
||||
pgdn
|
||||
pgorepro
|
||||
pgort
|
||||
PGU
|
||||
pguid
|
||||
pgup
|
||||
PHANDLE
|
||||
|
@ -1994,7 +2013,6 @@ Replymessage
|
|||
repositorypath
|
||||
rescap
|
||||
Resequence
|
||||
reserialize
|
||||
RESETCONTENT
|
||||
resheader
|
||||
resizable
|
||||
|
@ -2271,6 +2289,7 @@ STX
|
|||
stylecop
|
||||
SUA
|
||||
subcompartment
|
||||
subfolder
|
||||
subkey
|
||||
SUBLANG
|
||||
sublicensable
|
||||
|
@ -2521,7 +2540,7 @@ UNORM
|
|||
unparseable
|
||||
unpause
|
||||
Unregister
|
||||
Unregistering
|
||||
unregistering
|
||||
untests
|
||||
untextured
|
||||
untimes
|
||||
|
@ -2831,7 +2850,6 @@ xdy
|
|||
XEncoding
|
||||
xes
|
||||
Xes
|
||||
XES
|
||||
xff
|
||||
XFile
|
||||
XFORM
|
||||
|
@ -2879,6 +2897,7 @@ YVIRTUALSCREEN
|
|||
Yw
|
||||
YWalk
|
||||
yx
|
||||
yy
|
||||
YZ
|
||||
Zc
|
||||
ZCmd
|
||||
|
@ -2890,3 +2909,4 @@ zsh
|
|||
zu
|
||||
zxcvbnm
|
||||
zy
|
||||
zz
|
||||
|
|
16
NOTICE.md
16
NOTICE.md
|
@ -252,10 +252,26 @@ DEALINGS IN THE SOFTWARE.
|
|||
|
||||
```
|
||||
|
||||
# Microsoft Open Source
|
||||
|
||||
This product also incorporates source code from other Microsoft open source projects, all licensed under the MIT license.
|
||||
|
||||
## `GSL`
|
||||
|
||||
**Source**: [https://github.com/microsoft/GSL](https://github.com/microsoft/GSL)
|
||||
|
||||
## `Microsoft-UI-XAML`
|
||||
|
||||
**Source**: [https://github.com/microsoft/Microsoft-UI-XAML](https://github.com/microsoft/Microsoft-UI-XAML)
|
||||
|
||||
## `VirtualDesktopUtils`
|
||||
|
||||
**Source**: [https://github.com/microsoft/PowerToys](https://github.com/microsoft/PowerToys)
|
||||
|
||||
## `wil`
|
||||
|
||||
**Source**: [https://github.com/microsoft/wil](https://github.com/microsoft/wil)
|
||||
|
||||
### License
|
||||
|
||||
```
|
||||
|
|
|
@ -395,6 +395,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTests_Control", "src\ca
|
|||
{CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsTerminal.UIA.Tests", "src\cascadia\WindowsTerminal_UIATests\WindowsTerminal.UIA.Tests.csproj", "{F19DACD5-0C6E-40DC-B6E4-767A3200542C}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
AuditMode|Any CPU = AuditMode|Any CPU
|
||||
|
@ -3256,6 +3258,40 @@ Global
|
|||
{C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Release|x64.Build.0 = Release|x64
|
||||
{C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Release|x86.ActiveCfg = Release|Win32
|
||||
{C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B}.Release|x86.Build.0 = Release|Win32
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|Any CPU.ActiveCfg = Debug|Win32
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|ARM.ActiveCfg = Debug|Win32
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|ARM64.ActiveCfg = Debug|ARM64
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|DotNet_x64Test.ActiveCfg = Debug|x64
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|DotNet_x86Test.ActiveCfg = Debug|Win32
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|x64.ActiveCfg = Debug|x64
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.AuditMode|x86.ActiveCfg = Debug|Win32
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|ARM.ActiveCfg = Debug|Win32
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|DotNet_x64Test.ActiveCfg = Debug|x64
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|x64.Build.0 = Debug|x64
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Debug|x86.Build.0 = Debug|Win32
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|Any CPU.ActiveCfg = Debug|Win32
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|ARM.ActiveCfg = Debug|Win32
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|ARM64.ActiveCfg = Debug|ARM64
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|DotNet_x64Test.ActiveCfg = Debug|x64
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|DotNet_x86Test.ActiveCfg = Debug|Win32
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|x64.ActiveCfg = Debug|x64
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Fuzzing|x86.ActiveCfg = Debug|Win32
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|ARM.ActiveCfg = Release|Win32
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|DotNet_x64Test.ActiveCfg = Release|x64
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|DotNet_x86Test.ActiveCfg = Release|Win32
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|x64.ActiveCfg = Release|x64
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|x64.Build.0 = Release|x64
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|x86.ActiveCfg = Release|Win32
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -3353,6 +3389,7 @@ Global
|
|||
{9921CA0A-320C-4460-8623-3A3196E7F4CB} = {59840756-302F-44DF-AA47-441A9D673202}
|
||||
{05D9052F-D78F-478F-968A-2DE38A6DB996} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
|
||||
{C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E}
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {3140B1B7-C8EE-43D1-A772-D82A7061A271}
|
||||
|
|
|
@ -29,4 +29,147 @@ function GetQueryTestRunsUri
|
|||
$baseUri = GetAzureDevOpsBaseUri -CollectionUri $CollectionUri -TeamProject $TeamProject
|
||||
$queryUri = "$baseUri/_apis/test/runs?buildUri=$BuildUri$includeRunDetailsParameter&api-version=5.0"
|
||||
return $queryUri
|
||||
}
|
||||
|
||||
function Get-HelixJobTypeFromTestRun
|
||||
{
|
||||
Param ($testRun)
|
||||
|
||||
$testRunSingleResultUri = "$($testRun.url)/results?`$top=1&`$skip=0&api-version=5.1"
|
||||
$singleTestResult = Invoke-RestMethod -Uri $testRunSingleResultUri -Method Get -Headers $azureDevOpsRestApiHeaders
|
||||
$count = $singleTestResult.value.Length
|
||||
if($count -eq 0)
|
||||
{
|
||||
# If the count is 0, then results have not yet been reported for this run.
|
||||
# We only care about completed runs with results, so it is ok to just return 'UNKNOWN' for this run.
|
||||
return "UNKNOWN"
|
||||
}
|
||||
else
|
||||
{
|
||||
$info = ConvertFrom-Json $singleTestResult.value.comment
|
||||
$helixJobId = $info.HelixJobId
|
||||
$job = Invoke-RestMethodWithRetries "https://helix.dot.net/api/2019-06-17/jobs/${helixJobId}?access_token=${HelixAccessToken}"
|
||||
return $job.Type
|
||||
}
|
||||
}
|
||||
|
||||
function Append-HelixAccessTokenToUrl
|
||||
{
|
||||
Param ([string]$url, [string]$token)
|
||||
if($url.Contains("?"))
|
||||
{
|
||||
$url = "$($url)&access_token=$($token)"
|
||||
}
|
||||
else
|
||||
{
|
||||
$url = "$($url)?access_token=$($token)"
|
||||
}
|
||||
return $url
|
||||
}
|
||||
|
||||
|
||||
# The Helix Rest api is sometimes unreliable. So we call these apis with retry logic.
|
||||
# Note: The Azure DevOps apis are stable and do not need to be called with this retry logic.
|
||||
$helixApiRetries = 0
|
||||
$helixApiRetriesMax = 10
|
||||
|
||||
function Download-StringWithRetries
|
||||
{
|
||||
Param ([string]$fileName, [string]$url)
|
||||
|
||||
$result = ""
|
||||
$done = $false
|
||||
|
||||
while(!($done))
|
||||
{
|
||||
try
|
||||
{
|
||||
Write-Host "Downloading $fileName"
|
||||
$result = (New-Object System.Net.WebClient).DownloadString($url)
|
||||
$done = $true
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-Host "Failed to download $fileName $($PSItem.Exception)"
|
||||
|
||||
$helixApiRetries = $helixApiRetries + 1
|
||||
if($helixApiRetries -lt $helixApiRetriesMax)
|
||||
{
|
||||
Write-Host "Sleep and retry download of $fileName"
|
||||
Start-Sleep 60
|
||||
}
|
||||
else
|
||||
{
|
||||
throw "Failed to download $fileName"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result
|
||||
}
|
||||
|
||||
function Invoke-RestMethodWithRetries
|
||||
{
|
||||
Param ([string]$url,$Headers)
|
||||
|
||||
$result = @()
|
||||
$done = $false
|
||||
|
||||
while(!($done))
|
||||
{
|
||||
try
|
||||
{
|
||||
$result = Invoke-RestMethod -Uri $url -Method Get -Headers $Headers
|
||||
$done = $true
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-Host "Failed to invoke Rest method $($PSItem.Exception)"
|
||||
|
||||
$helixApiRetries = $helixApiRetries + 1
|
||||
if($helixApiRetries -lt $helixApiRetriesMax)
|
||||
{
|
||||
Write-Host "Sleep and retry invoke"
|
||||
Start-Sleep 60
|
||||
}
|
||||
else
|
||||
{
|
||||
throw "Failed to invoke Rest method"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result
|
||||
}
|
||||
|
||||
function Download-FileWithRetries
|
||||
{
|
||||
Param ([string]$fileurl, [string]$destination)
|
||||
|
||||
$done = $false
|
||||
|
||||
while(!($done))
|
||||
{
|
||||
try
|
||||
{
|
||||
Write-Host "Downloading $destination"
|
||||
$webClient.DownloadFile($fileurl, $destination)
|
||||
$done = $true
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-Host "Failed to download $destination $($PSItem.Exception)"
|
||||
|
||||
$helixApiRetries = $helixApiRetries + 1
|
||||
if($helixApiRetries -lt $helixApiRetriesMax)
|
||||
{
|
||||
Write-Host "Sleep and retry download of $destination"
|
||||
Start-Sleep 60
|
||||
}
|
||||
else
|
||||
{
|
||||
throw "Failed to download $destination"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,10 +20,12 @@ New-Item -ItemType Directory -Force -Path $payloadDir
|
|||
# Copy files from nuget packages
|
||||
Copy-Item "$nugetPackagesDir\microsoft.windows.apps.test.1.0.181203002\lib\netcoreapp2.1\*.dll" $payloadDir
|
||||
Copy-Item "$nugetPackagesDir\Microsoft.Taef.10.58.210305002\build\Binaries\$Platform\*" $payloadDir
|
||||
Copy-Item "$nugetPackagesDir\Microsoft.Taef.10.58.210305002\build\Binaries\$Platform\CoreClr\*" $payloadDir
|
||||
Copy-Item "$nugetPackagesDir\Microsoft.Taef.10.58.210305002\build\Binaries\$Platform\NetFx4.5\*" $payloadDir
|
||||
New-Item -ItemType Directory -Force -Path "$payloadDir\.NETCoreApp2.1\"
|
||||
Copy-Item "$nugetPackagesDir\runtime.win-$Platform.microsoft.netcore.app.2.1.0\runtimes\win-$Platform\lib\netcoreapp2.1\*" "$payloadDir\.NETCoreApp2.1\"
|
||||
Copy-Item "$nugetPackagesDir\runtime.win-$Platform.microsoft.netcore.app.2.1.0\runtimes\win-$Platform\native\*" "$payloadDir\.NETCoreApp2.1\"
|
||||
New-Item -ItemType Directory -Force -Path "$payloadDir\content\"
|
||||
Copy-Item "$nugetPackagesDir\Microsoft.Internal.Windows.Terminal.TestContent.1.0.1\content\*" "$payloadDir\content\"
|
||||
|
||||
function Copy-If-Exists
|
||||
{
|
||||
|
@ -52,3 +54,13 @@ Copy-Item "build\helix\HelixTestHelpers.cs" "$payloadDir"
|
|||
Copy-Item "build\helix\runtests.cmd" $payloadDir
|
||||
Copy-Item "build\helix\InstallTestAppDependencies.ps1" "$payloadDir"
|
||||
Copy-Item "build\Helix\EnsureMachineState.ps1" "$payloadDir"
|
||||
|
||||
# Copy the APPX package from the 'drop' artifact dir
|
||||
Copy-Item "$repoDirectory\Artifacts\$ArtifactName\appx\CascadiaPackage_0.0.1.0_$Platform.msix" $payloadDir\CascadiaPackage.zip
|
||||
|
||||
# Rename it to extension of ZIP because Expand-Archive is real sassy on the build machines
|
||||
# and refuses to unzip it because of its file extension while on a desktop, it just
|
||||
# does the job without complaining.
|
||||
|
||||
# Extract the APPX package
|
||||
Expand-Archive -LiteralPath $payloadDir\CascadiaPackage.zip -DestinationPath $payloadDir\appx
|
||||
|
|
|
@ -9,11 +9,6 @@ Param(
|
|||
|
||||
$helixLinkFile = "$OutputFolder\LinksToHelixTestFiles.html"
|
||||
|
||||
$accessTokenParam = ""
|
||||
if($HelixAccessToken)
|
||||
{
|
||||
$accessTokenParam = "?access_token=$HelixAccessToken"
|
||||
}
|
||||
|
||||
function Generate-File-Links
|
||||
{
|
||||
|
@ -45,66 +40,69 @@ $azureDevOpsRestApiHeaders = @{
|
|||
$queryUri = GetQueryTestRunsUri -CollectionUri $CollectionUri -TeamProject $TeamProject -BuildUri $BuildUri -IncludeRunDetails
|
||||
Write-Host "queryUri = $queryUri"
|
||||
|
||||
$testRuns = Invoke-RestMethod -Uri $queryUri -Method Get -Headers $azureDevOpsRestApiHeaders
|
||||
$testRuns = Invoke-RestMethodWithRetries $queryUri -Headers $azureDevOpsRestApiHeaders
|
||||
$webClient = New-Object System.Net.WebClient
|
||||
[System.Collections.Generic.List[string]]$workItems = @()
|
||||
|
||||
foreach ($testRun in $testRuns.value)
|
||||
{
|
||||
$testResults = Invoke-RestMethod -Uri "$($testRun.url)/results?api-version=5.0" -Method Get -Headers $azureDevOpsRestApiHeaders
|
||||
Write-Host "testRunUri = $testRun.url"
|
||||
$testResults = Invoke-RestMethodWithRetries "$($testRun.url)/results?api-version=5.0" -Headers $azureDevOpsRestApiHeaders
|
||||
$isTestRunNameShown = $false
|
||||
|
||||
foreach ($testResult in $testResults.value)
|
||||
{
|
||||
if ("comment" -in $testResult)
|
||||
$info = ConvertFrom-Json $testResult.comment
|
||||
$helixJobId = $info.HelixJobId
|
||||
$helixWorkItemName = $info.HelixWorkItemName
|
||||
|
||||
$workItem = "$helixJobId-$helixWorkItemName"
|
||||
|
||||
Write-Host "Helix Work Item = $workItem"
|
||||
|
||||
if (-not $workItems.Contains($workItem))
|
||||
{
|
||||
$info = ConvertFrom-Json $testResult.comment
|
||||
$helixJobId = $info.HelixJobId
|
||||
$helixWorkItemName = $info.HelixWorkItemName
|
||||
$workItems.Add($workItem)
|
||||
$filesQueryUri = "https://helix.dot.net/api/2019-06-17/jobs/$helixJobId/workitems/$helixWorkItemName/files$accessTokenParam"
|
||||
$files = Invoke-RestMethodWithRetries $filesQueryUri
|
||||
|
||||
$workItem = "$helixJobId-$helixWorkItemName"
|
||||
|
||||
if (-not $workItems.Contains($workItem))
|
||||
$screenShots = $files | where { $_.Name.EndsWith(".jpg") }
|
||||
$dumps = $files | where { $_.Name.EndsWith(".dmp") }
|
||||
$pgcFiles = $files | where { $_.Name.EndsWith(".pgc") }
|
||||
if ($screenShots.Count + $dumps.Count + $pgcFiles.Count -gt 0)
|
||||
{
|
||||
$workItems.Add($workItem)
|
||||
$filesQueryUri = "https://helix.dot.net/api/2019-06-17/jobs/$helixJobId/workitems/$helixWorkItemName/files$accessTokenParam"
|
||||
$files = Invoke-RestMethod -Uri $filesQueryUri -Method Get
|
||||
|
||||
$screenShots = $files | where { $_.Name.EndsWith(".jpg") }
|
||||
$dumps = $files | where { $_.Name.EndsWith(".dmp") }
|
||||
$pgcFiles = $files | where { $_.Name.EndsWith(".pgc") }
|
||||
if ($screenShots.Count + $dumps.Count + $pgcFiles.Count -gt 0)
|
||||
if(-Not $isTestRunNameShown)
|
||||
{
|
||||
if(-Not $isTestRunNameShown)
|
||||
Out-File -FilePath $helixLinkFile -Append -InputObject "<h2>$($testRun.name)</h2>"
|
||||
$isTestRunNameShown = $true
|
||||
}
|
||||
Out-File -FilePath $helixLinkFile -Append -InputObject "<h3>$helixWorkItemName</h3>"
|
||||
Generate-File-Links $screenShots "Screenshots"
|
||||
Generate-File-Links $dumps "CrashDumps"
|
||||
Generate-File-Links $pgcFiles "PGC files"
|
||||
$misc = $files | where { ($screenShots -NotContains $_) -And ($dumps -NotContains $_) -And ($visualTreeVerificationFiles -NotContains $_) -And ($pgcFiles -NotContains $_) }
|
||||
Generate-File-Links $misc "Misc"
|
||||
|
||||
foreach($pgcFile in $pgcFiles)
|
||||
{
|
||||
$flavorPath = $testResult.automatedTestName.Split('.')[0]
|
||||
$archPath = $testResult.automatedTestName.Split('.')[1]
|
||||
$fileName = $pgcFile.Name
|
||||
$fullPath = "$OutputFolder\PGO\$flavorPath\$archPath"
|
||||
$destination = "$fullPath\$fileName"
|
||||
|
||||
Write-Host "Copying $($pgcFile.Name) to $destination"
|
||||
|
||||
if (-Not (Test-Path $fullPath))
|
||||
{
|
||||
Out-File -FilePath $helixLinkFile -Append -InputObject "<h2>$($testRun.name)</h2>"
|
||||
$isTestRunNameShown = $true
|
||||
New-Item $fullPath -ItemType Directory
|
||||
}
|
||||
Out-File -FilePath $helixLinkFile -Append -InputObject "<h3>$helixWorkItemName</h3>"
|
||||
Generate-File-Links $screenShots "Screenshots"
|
||||
Generate-File-Links $dumps "CrashDumps"
|
||||
Generate-File-Links $pgcFiles "PGC files"
|
||||
$misc = $files | where { ($screenShots -NotContains $_) -And ($dumps -NotContains $_) -And ($visualTreeVerificationFiles -NotContains $_) -And ($pgcFiles -NotContains $_) }
|
||||
Generate-File-Links $misc "Misc"
|
||||
|
||||
foreach($pgcFile in $pgcFiles)
|
||||
{
|
||||
$flavorPath = $pgcFile.Name.Split('.')[0]
|
||||
$archPath = $pgcFile.Name.Split('.')[1]
|
||||
$fileName = $pgcFile.Name.Remove(0, $flavorPath.length + $archPath.length + 2)
|
||||
$fullPath = "$OutputFolder\PGO\$flavorPath\$archPath"
|
||||
$destination = "$fullPath\$fileName"
|
||||
$link = $pgcFile.Link
|
||||
|
||||
Write-Host "Copying $($pgcFile.Name) to $destination"
|
||||
Write-Host "Downloading $link to $destination"
|
||||
|
||||
if (-Not (Test-Path $fullPath))
|
||||
{
|
||||
New-Item $fullPath -ItemType Directory
|
||||
}
|
||||
|
||||
$link = "$($pgcFile.Link)$accessTokenParam"
|
||||
$webClient.DownloadFile($link, $destination)
|
||||
}
|
||||
Download-FileWithRetries $link $destination
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
</ItemGroup>
|
||||
|
||||
<!-- These .proj files are generated by the build machine prior to running tests via GenerateTestProjFile.ps1. -->
|
||||
<Import Project="$(ProjFilesPath)\RunTestsInHelix-TerminalAppLocalTests.proj" Condition=" '$(TestSuite)'=='DevTestSuite' " />
|
||||
<Import Project="$(ProjFilesPath)\RunTestsInHelix-HostTestsUIA.proj" Condition=" '$(TestSuite)'=='DevTestSuite' " />
|
||||
<Import Project="$(ProjFilesPath)\$(Configuration)\$(Platform)\RunTestsInHelix-TerminalAppLocalTests.proj" Condition=" '$(TestSuite)'=='DevTestSuite' " />
|
||||
<Import Project="$(ProjFilesPath)\$(Configuration)\$(Platform)\RunTestsInHelix-SettingsModelLocalTests.proj" Condition=" '$(TestSuite)'=='DevTestSuite' " />
|
||||
<Import Project="$(ProjFilesPath)\$(Configuration)\$(Platform)\RunTestsInHelix-HostTestsUIA.proj" Condition=" '$(TestSuite)'=='DevTestSuite' " />
|
||||
<Import Project="$(ProjFilesPath)\$(Configuration)\$(Platform)\RunTestsInHelix-WindowsTerminalUIATests.proj" Condition=" '$(TestSuite)'=='PgoInstrumentationSuite' " />
|
||||
</Project>
|
|
@ -1,6 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="MUXCustomBuildTasks" version="1.0.48" targetFramework="native" />
|
||||
<package id="Microsoft.Internal.Windows.Terminal.TestContent" version="1.0.1" />
|
||||
<package id="Microsoft.Taef" version="10.58.210305002" targetFramework="native" />
|
||||
<package id="microsoft.windows.apps.test" version="1.0.181203002" targetFramework="native" />
|
||||
<package id="runtime.win-x86.microsoft.netcore.app" version="2.1.0" targetFramework="native" />
|
||||
|
|
|
@ -28,7 +28,7 @@ echo %TIME%
|
|||
powershell -ExecutionPolicy Bypass .\InstallTestAppDependencies.ps1
|
||||
echo %TIME%
|
||||
|
||||
set testBinaryCandidates=TerminalApp.LocalTests.dll SettingsModel.LocalTests.dll Conhost.UIA.Tests.dll
|
||||
set testBinaryCandidates=TerminalApp.LocalTests.dll SettingsModel.LocalTests.dll Conhost.UIA.Tests.dll WindowsTerminal.UIA.Tests.dll
|
||||
set testBinaries=
|
||||
for %%B in (%testBinaryCandidates%) do (
|
||||
if exist %%B (
|
||||
|
@ -46,7 +46,6 @@ move te.wtl te_original.wtl
|
|||
|
||||
copy /y te_original.wtl %HELIX_WORKITEM_UPLOAD_ROOT%
|
||||
copy /y WexLogFileOutput\*.jpg %HELIX_WORKITEM_UPLOAD_ROOT%
|
||||
for /f "tokens=* delims=" %%a in ('dir /b *.pgc') do ren "%%a" "%testnameprefix%.%%~na.pgc"
|
||||
copy /y *.pgc %HELIX_WORKITEM_UPLOAD_ROOT%
|
||||
|
||||
set FailedTestQuery=
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
trigger: none
|
||||
pr: none
|
||||
|
||||
variables:
|
||||
- name: runCodesignValidationInjectionBG
|
||||
value: false
|
||||
|
||||
# 0.0.yyMM.dd##
|
||||
# 0.0.1904.0900
|
||||
name: 0.0.$(Date:yyMM).$(Date:dd)$(Rev:rr)
|
||||
|
||||
stages:
|
||||
- stage: Build_x64
|
||||
displayName: Build x64
|
||||
dependsOn: []
|
||||
condition: succeeded()
|
||||
jobs:
|
||||
- template: ./templates/build-console-pgo.yml
|
||||
parameters:
|
||||
platform: x64
|
||||
- stage: Publish_PGO_Databases
|
||||
displayName: Publish PGO databases
|
||||
dependsOn: ['Build_x64']
|
||||
jobs:
|
||||
- template: ./templates/pgo-build-and-publish-nuget-job.yml
|
||||
parameters:
|
||||
pgoArtifact: 'PGO'
|
|
@ -9,6 +9,7 @@ jobs:
|
|||
variables:
|
||||
BuildConfiguration: ${{ parameters.configuration }}
|
||||
BuildPlatform: ${{ parameters.platform }}
|
||||
PGOBuildMode: 'Optimize'
|
||||
|
||||
pool:
|
||||
name: Package ES Lab E
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
parameters:
|
||||
configuration: 'Release'
|
||||
platform: ''
|
||||
additionalBuildArguments: ''
|
||||
minimumExpectedTestsExecutedCount: 1 # Sanity check for minimum expected tests to be reported
|
||||
rerunPassesRequiredToAvoidFailure: 0
|
||||
|
||||
jobs:
|
||||
- job: Build${{ parameters.platform }}${{ parameters.configuration }}
|
||||
displayName: Build ${{ parameters.platform }} ${{ parameters.configuration }}
|
||||
variables:
|
||||
BuildConfiguration: ${{ parameters.configuration }}
|
||||
BuildPlatform: ${{ parameters.platform }}
|
||||
PGOBuildMode: 'Instrument'
|
||||
pool: "windevbuildagents"
|
||||
# The public pool is also an option!
|
||||
# pool: { vmImage: windows-2019 }
|
||||
|
||||
steps:
|
||||
- template: build-console-steps.yml
|
||||
parameters:
|
||||
additionalBuildArguments: ${{ parameters.additionalBuildArguments }}
|
||||
|
||||
- template: helix-runtests-job.yml
|
||||
parameters:
|
||||
name: 'RunTestsInHelix'
|
||||
dependsOn: Build${{ parameters.platform }}${{ parameters.configuration }}
|
||||
condition: succeeded()
|
||||
testSuite: 'PgoInstrumentationSuite'
|
||||
taefQuery: '@IsPgo=true'
|
||||
configuration: ${{ parameters.configuration }}
|
||||
platform: ${{ parameters.platform }}
|
||||
rerunPassesRequiredToAvoidFailure: ${{ parameters.rerunPassesRequiredToAvoidFailure }}
|
||||
|
||||
- template: helix-processtestresults-job.yml
|
||||
parameters:
|
||||
name: 'ProcessTestResults'
|
||||
pgoArtifact: 'PGO'
|
||||
dependsOn:
|
||||
- RunTestsInHelix
|
||||
condition: succeededOrFailed()
|
||||
rerunPassesRequiredToAvoidFailure: ${{ parameters.rerunPassesRequiredToAvoidFailure }}
|
||||
minimumExpectedTestsExecutedCount: ${{ parameters.minimumExpectedTestsExecutedCount }}
|
||||
|
||||
- template: pgo-merge-pgd-job.yml
|
||||
parameters:
|
||||
name: 'MergePGD'
|
||||
dependsOn:
|
||||
- ProcessTestResults
|
||||
pgoArtifact: 'PGO'
|
||||
platform: ${{ parameters.platform }}
|
|
@ -32,6 +32,29 @@ steps:
|
|||
restoreSolution: build/packages.config
|
||||
restoreDirectory: '$(Build.SourcesDirectory)\packages'
|
||||
|
||||
# The environment variable VCToolsInstallDir isn't defined on lab machines, so we need to retrieve it ourselves.
|
||||
- script: |
|
||||
"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -Latest -requires Microsoft.Component.MSBuild -property InstallationPath > %TEMP%\vsinstalldir.txt
|
||||
set /p _VSINSTALLDIR15=<%TEMP%\vsinstalldir.txt
|
||||
del %TEMP%\vsinstalldir.txt
|
||||
call "%_VSINSTALLDIR15%\Common7\Tools\VsDevCmd.bat"
|
||||
echo VCToolsInstallDir = %VCToolsInstallDir%
|
||||
echo ##vso[task.setvariable variable=VCToolsInstallDir]%VCToolsInstallDir%
|
||||
displayName: 'Retrieve VC tools directory'
|
||||
|
||||
- task: CmdLine@1
|
||||
displayName: 'Display build machine environment variables'
|
||||
inputs:
|
||||
filename: 'set'
|
||||
|
||||
- task: powershell@2
|
||||
displayName: 'Restore PGO database'
|
||||
condition: eq(variables['PGOBuildMode'], 'Optimize')
|
||||
inputs:
|
||||
targetType: filePath
|
||||
workingDirectory: $(Build.SourcesDirectory)\tools\PGODatabase
|
||||
filePath: $(Build.SourcesDirectory)\tools\PGODatabase\restore-pgodb.ps1
|
||||
|
||||
- task: VSBuild@1
|
||||
displayName: 'Build solution **\OpenConsole.sln'
|
||||
inputs:
|
||||
|
@ -45,6 +68,9 @@ steps:
|
|||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Check MSIX for common regressions'
|
||||
# PGO runtime needs its own CRT and it's in the package for convenience.
|
||||
# That will make this script mad so skip since we're not shipping the PGO Instrumentation one anyway.
|
||||
condition: ne(variables['PGOBuildMode'], 'Instrument')
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: |
|
||||
|
@ -53,6 +79,7 @@ steps:
|
|||
|
||||
- task: powershell@2
|
||||
displayName: 'Source Index PDBs'
|
||||
condition: ne(variables['PGOBuildMode'], 'Instrument')
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: build\scripts\Index-Pdbs.ps1
|
||||
|
@ -68,13 +95,25 @@ steps:
|
|||
If ($Arch -Eq "x86") { $Arch = "Win32" }
|
||||
Write-Host "##vso[task.setvariable variable=RationalizedBuildPlatform]${Arch}"
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Validate binaries are optimized'
|
||||
condition: eq(variables['pgoBuildMode'], 'Optimize')
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: |
|
||||
$Binaries = 'OpenConsole.exe', 'WindowsTerminal.exe', 'TerminalApp.dll', 'TerminalConnection.dll', 'Microsoft.Terminal.Control.dll', 'Microsoft.Terminal.Remoting.dll', 'Microsoft.Terminal.Settings.Editor.dll', 'Microsoft.Terminal.Settings.Model.dll'
|
||||
foreach ($BinFile in $Binaries)
|
||||
{
|
||||
& "$(Build.SourcesDirectory)\tools\PGODatabase\verify-pgo.ps1" "$(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/$BinFile"
|
||||
}
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Run Unit Tests'
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: build\scripts\Run-Tests.ps1
|
||||
arguments: -MatchPattern '*unit.test*.dll' -Platform '$(RationalizedBuildPlatform)' -Configuration '$(BuildConfiguration)' -LogPath '${{ parameters.testLogPath }}'
|
||||
condition: and(succeeded(), or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86')))
|
||||
condition: and(and(succeeded(), ne(variables['PGOBuildMode'], 'Instrument')), or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86')))
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Run Feature Tests (x64 only)'
|
||||
|
@ -82,7 +121,7 @@ steps:
|
|||
targetType: filePath
|
||||
filePath: build\scripts\Run-Tests.ps1
|
||||
arguments: -MatchPattern '*feature.test*.dll' -Platform '$(RationalizedBuildPlatform)' -Configuration '$(BuildConfiguration)' -LogPath '${{ parameters.testLogPath }}'
|
||||
condition: and(succeeded(), eq(variables['BuildPlatform'], 'x64'))
|
||||
condition: and(and(succeeded(), ne(variables['PGOBuildMode'], 'Instrument')), eq(variables['BuildPlatform'], 'x64'))
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Convert Test Logs from WTL to xUnit format'
|
||||
|
@ -90,10 +129,11 @@ steps:
|
|||
targetType: filePath
|
||||
filePath: build\Helix\ConvertWttLogToXUnit.ps1
|
||||
arguments: -WttInputPath '${{ parameters.testLogPath }}' -WttSingleRerunInputPath 'unused.wtl' -WttMultipleRerunInputPath 'unused2.wtl' -XUnitOutputPath 'onBuildMachineResults.xml' -TestNamePrefix '$(BuildConfiguration).$(BuildPlatform)'
|
||||
condition: or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86'))
|
||||
condition: and(ne(variables['PGOBuildMode'], 'Instrument'),or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86')))
|
||||
|
||||
- task: PublishTestResults@2
|
||||
displayName: 'Upload converted test logs'
|
||||
condition: ne(variables['PGOBuildMode'], 'Instrument')
|
||||
inputs:
|
||||
testResultsFormat: 'xUnit' # Options: JUnit, NUnit, VSTest, xUnit, cTest
|
||||
testResultsFiles: '**/onBuildMachineResults.xml'
|
||||
|
@ -127,24 +167,47 @@ steps:
|
|||
TargetFolder: '$(Build.ArtifactStagingDirectory)/appx'
|
||||
OverWrite: true
|
||||
flattenFolders: true
|
||||
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))
|
||||
condition: succeeded()
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Copy outputs needed for test runs to Artifacts'
|
||||
inputs:
|
||||
Contents: |
|
||||
$(Build.SourcesDirectory)/bin/$(BuildPlatform)/$(BuildConfiguration)/*.exe
|
||||
$(Build.SourcesDirectory)/bin/$(BuildPlatform)/$(BuildConfiguration)/*.dll
|
||||
$(Build.SourcesDirectory)/bin/$(BuildPlatform)/$(BuildConfiguration)/*.xml
|
||||
$(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/*.exe
|
||||
$(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/*.dll
|
||||
$(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/*.xml
|
||||
**/Microsoft.VCLibs.*.appx
|
||||
**/TestHostApp/*
|
||||
**/TestHostApp/*.exe
|
||||
**/TestHostApp/*.dll
|
||||
**/TestHostApp/*.xml
|
||||
!**/*.pdb
|
||||
!**/*.ipdb
|
||||
!**/*.obj
|
||||
!**/*.pch
|
||||
TargetFolder: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/$(BuildPlatform)/test'
|
||||
OverWrite: true
|
||||
flattenFolders: true
|
||||
condition: and(and(succeeded(), eq(variables['BuildPlatform'], 'x64')), ne(variables['Build.Reason'], 'PullRequest'))
|
||||
condition: succeeded()
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish All Build Artifacts'
|
||||
inputs:
|
||||
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
|
||||
ArtifactName: 'drop'
|
||||
ArtifactName: 'drop'
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Copy PGO databases needed for PGO instrumentation run'
|
||||
inputs:
|
||||
Contents: |
|
||||
**/*.pgd
|
||||
TargetFolder: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/PGO/$(BuildPlatform)'
|
||||
OverWrite: true
|
||||
flattenFolders: true
|
||||
condition: and(succeeded(), eq(variables['PGOBuildMode'], 'Instrument'))
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish All PGO Artifacts'
|
||||
inputs:
|
||||
PathtoPublish: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/PGO'
|
||||
ArtifactName: 'PGO'
|
||||
condition: and(succeeded(), eq(variables['PGOBuildMode'], 'Instrument'))
|
||||
|
|
|
@ -12,4 +12,4 @@ steps:
|
|||
inputs:
|
||||
targetType: filePath
|
||||
filePath: build\Helix\GenerateTestProjFile.ps1
|
||||
arguments: -TestFile '${{ parameters.testFilePath }}' -OutputProjFile '$(Build.ArtifactStagingDirectory)\${{ parameters.outputProjFileName }}' -JobTestSuiteName '${{ parameters.testSuite }}' -TaefPath '$(Build.SourcesDirectory)\build\Helix\packages\Microsoft.Taef.10.58.210305002\build\Binaries\x86' -TaefQuery '${{ parameters.taefQuery }}'
|
||||
arguments: -TestFile '${{ parameters.testFilePath }}' -OutputProjFile '$(Build.ArtifactStagingDirectory)\$(BuildConfiguration)\$(BuildPlatform)\${{ parameters.outputProjFileName }}' -JobTestSuiteName '${{ parameters.testSuite }}' -TaefPath '$(Build.SourcesDirectory)\build\Helix\packages\Microsoft.Taef.10.58.210305002\build\Binaries\x86' -TaefQuery '${{ parameters.taefQuery }}'
|
|
@ -10,19 +10,11 @@ parameters:
|
|||
maxParallel: 4
|
||||
rerunPassesRequiredToAvoidFailure: 5
|
||||
taefQuery: ''
|
||||
configuration: ''
|
||||
platform: ''
|
||||
# if 'useBuildOutputFromBuildId' is set, we will default to using a build from this pipeline:
|
||||
useBuildOutputFromPipeline: $(System.DefinitionId)
|
||||
matrix:
|
||||
# Release_x86:
|
||||
# buildPlatform: 'x86'
|
||||
# buildConfiguration: 'release'
|
||||
# openHelixTargetQueues: 'windows.10.amd64.client19h1.open.xaml'
|
||||
# closedHelixTargetQueues: 'windows.10.amd64.client19h1.xaml'
|
||||
Release_x64:
|
||||
buildPlatform: 'x64'
|
||||
buildConfiguration: 'release'
|
||||
openHelixTargetQueues: 'windows.10.amd64.client19h1.open.xaml'
|
||||
closedHelixTargetQueues: 'windows.10.amd64.client19h1.xaml'
|
||||
openHelixTargetQueues: 'windows.10.amd64.client19h1.open.xaml'
|
||||
|
||||
jobs:
|
||||
- job: ${{ parameters.name }}
|
||||
|
@ -33,8 +25,10 @@ jobs:
|
|||
timeoutInMinutes: 120
|
||||
strategy:
|
||||
maxParallel: ${{ parameters.maxParallel }}
|
||||
matrix: ${{ parameters.matrix }}
|
||||
variables:
|
||||
buildConfiguration: ${{ parameters.configuration }}
|
||||
buildPlatform: ${{ parameters.platform }}
|
||||
openHelixTargetQueues: ${{ parameters.openHelixTargetQueues }}
|
||||
artifactsDir: $(Build.SourcesDirectory)\Artifacts
|
||||
taefPath: $(Build.SourcesDirectory)\build\Helix\packages\Microsoft.Taef.10.58.210305002\build\Binaries\$(buildPlatform)
|
||||
helixCommonArgs: '/binaryLogger:$(Build.SourcesDirectory)/${{parameters.name}}.$(buildPlatform).$(buildConfiguration).binlog /p:HelixBuild=$(Build.BuildId).$(buildPlatform).$(buildConfiguration) /p:Platform=$(buildPlatform) /p:Configuration=$(buildConfiguration) /p:HelixType=${{parameters.helixType}} /p:TestSuite=${{parameters.testSuite}} /p:ProjFilesPath=$(Build.ArtifactStagingDirectory) /p:rerunPassesRequiredToAvoidFailure=${{parameters.rerunPassesRequiredToAvoidFailure}}'
|
||||
|
@ -97,9 +91,17 @@ jobs:
|
|||
filename: 'dir'
|
||||
arguments: '/s $(Build.SourcesDirectory)\HelixPayload'
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Make artifact directories'
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: |
|
||||
New-Item -ItemType Directory -Force -Path "$(Build.ArtifactStagingDirectory)\$(BuildConfiguration)\"
|
||||
New-Item -ItemType Directory -Force -Path "$(Build.ArtifactStagingDirectory)\$(BuildConfiguration)\$(BuildPlatform)\"
|
||||
|
||||
- template: helix-createprojfile-steps.yml
|
||||
parameters:
|
||||
condition: and(succeeded(),ne('${{ parameters.testSuite }}','NugetTestSuite'))
|
||||
condition: and(succeeded(),eq('${{ parameters.testSuite }}','DevTestSuite'))
|
||||
testFilePath: '$(artifactsDir)\${{ parameters.artifactName }}\$(buildConfiguration)\$(buildPlatform)\Test\TerminalApp.LocalTests.dll'
|
||||
outputProjFileName: 'RunTestsInHelix-TerminalAppLocalTests.proj'
|
||||
testSuite: '${{ parameters.testSuite }}'
|
||||
|
@ -107,7 +109,7 @@ jobs:
|
|||
|
||||
- template: helix-createprojfile-steps.yml
|
||||
parameters:
|
||||
condition: and(succeeded(),ne('${{ parameters.testSuite }}','NugetTestSuite'))
|
||||
condition: and(succeeded(),eq('${{ parameters.testSuite }}','DevTestSuite'))
|
||||
testFilePath: '$(artifactsDir)\${{ parameters.artifactName }}\$(buildConfiguration)\$(buildPlatform)\Test\SettingsModel.LocalTests.dll'
|
||||
outputProjFileName: 'RunTestsInHelix-SettingsModelLocalTests.proj'
|
||||
testSuite: '${{ parameters.testSuite }}'
|
||||
|
@ -116,12 +118,20 @@ jobs:
|
|||
|
||||
- template: helix-createprojfile-steps.yml
|
||||
parameters:
|
||||
condition: and(succeeded(),ne('${{ parameters.testSuite }}','NugetTestSuite'))
|
||||
condition: and(succeeded(),eq('${{ parameters.testSuite }}','DevTestSuite'))
|
||||
testFilePath: '$(artifactsDir)\${{ parameters.artifactName }}\$(buildConfiguration)\$(buildPlatform)\Test\Conhost.UIA.Tests.dll'
|
||||
outputProjFileName: 'RunTestsInHelix-HostTestsUIA.proj'
|
||||
testSuite: '${{ parameters.testSuite }}'
|
||||
taefQuery: ${{ parameters.taefQuery }}
|
||||
|
||||
- template: helix-createprojfile-steps.yml
|
||||
parameters:
|
||||
condition: and(succeeded(),or(eq('${{ parameters.testSuite }}','PgoInstrumentationSuite'),eq('${{ parameters.testSuite }}','DevTestSuite')))
|
||||
testFilePath: '$(artifactsDir)\${{ parameters.artifactName }}\$(buildConfiguration)\$(buildPlatform)\Test\WindowsTerminal.UIA.Tests.dll'
|
||||
outputProjFileName: 'RunTestsInHelix-WindowsTerminalUIATests.proj'
|
||||
testSuite: '${{ parameters.testSuite }}'
|
||||
taefQuery: ${{ parameters.taefQuery }}
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish generated .proj files'
|
||||
inputs:
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
# From our friends at MUX: https://github.com/microsoft/microsoft-ui-xaml/blob/main/build/AzurePipelinesTemplates/MUX-BuildAndPublishPGONuGet-Job.yml
|
||||
|
||||
parameters:
|
||||
dependsOn: ''
|
||||
pgoArtifact: PGO
|
||||
|
||||
jobs:
|
||||
- job: BuildAndPublishPGONuGet
|
||||
dependsOn: ${{ parameters.dependsOn }}
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
variables:
|
||||
artifactsPath: $(Build.SourcesDirectory)\Artifacts
|
||||
pgoToolsPath: $(Build.SourcesDirectory)\tools\PGODatabase
|
||||
nuspecPath: $(pgoToolsPath)\NuSpecs
|
||||
nuspecFilename: PGO.nuspec
|
||||
|
||||
steps:
|
||||
- task: DownloadBuildArtifacts@0
|
||||
inputs:
|
||||
artifactName: ${{ parameters.pgoArtifact }}
|
||||
downloadPath: $(artifactsPath)
|
||||
|
||||
- task: NuGetToolInstaller@0
|
||||
displayName: 'Use NuGet 5.2.0'
|
||||
inputs:
|
||||
versionSpec: 5.2.0
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Copy pgd files to NuGet build directory'
|
||||
inputs:
|
||||
sourceFolder: $(artifactsPath)\${{ parameters.pgoArtifact }}
|
||||
contents: '**\*.pgd'
|
||||
targetFolder: $(nuspecPath)\tools
|
||||
|
||||
- task: powershell@2
|
||||
displayName: 'Generate NuSpec file'
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: $(pgoToolsPath)\generate-nuspec.ps1
|
||||
workingDirectory: $(pgoToolsPath)
|
||||
arguments: $(nuspecPath)\$(nuspecFilename).template $(nuspecPath)\$(nuspecFilename)
|
||||
|
||||
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
|
||||
displayName: 'NuGet pack'
|
||||
inputs:
|
||||
command: pack
|
||||
packagesToPack: '$(nuspecPath)\$(nuspecFilename)'
|
||||
basePath: '$(nuspecPath)'
|
||||
packDestination: '$(Build.ArtifactStagingDirectory)'
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
inputs:
|
||||
pathToPublish: $(Build.ArtifactStagingDirectory)
|
||||
artifactName: ${{ parameters.pgoArtifact }}
|
||||
|
||||
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
|
||||
displayName: 'NuGet push'
|
||||
inputs:
|
||||
command: push
|
||||
publishVstsFeed: Terminal/TerminalDependencies
|
||||
packagesToPush: $(Build.ArtifactStagingDirectory)/*.nupkg
|
|
@ -0,0 +1,90 @@
|
|||
parameters:
|
||||
dependsOn: ''
|
||||
pgoArtifact: PGO
|
||||
platform: ''
|
||||
|
||||
jobs:
|
||||
- job: MergePGD
|
||||
dependsOn: ${{ parameters.dependsOn }}
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
variables:
|
||||
artifactsPath: $(Build.SourcesDirectory)\Artifacts
|
||||
pgoArtifactsPath: $(artifactsPath)\${{ parameters.pgoArtifact }}
|
||||
buildPlatform: ${{ parameters.platform }}
|
||||
|
||||
steps:
|
||||
# The environment variable VCToolsInstallDir isn't defined on lab machines, so we need to retrieve it ourselves.
|
||||
- script: |
|
||||
"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -Latest -requires Microsoft.Component.MSBuild -property InstallationPath > %TEMP%\vsinstalldir.txt
|
||||
set /p _VSINSTALLDIR15=<%TEMP%\vsinstalldir.txt
|
||||
del %TEMP%\vsinstalldir.txt
|
||||
call "%_VSINSTALLDIR15%\Common7\Tools\VsDevCmd.bat"
|
||||
echo VCToolsInstallDir = %VCToolsInstallDir%
|
||||
echo ##vso[task.setvariable variable=VCToolsInstallDir]%VCToolsInstallDir%
|
||||
displayName: 'Retrieve VC tools directory'
|
||||
|
||||
- task: DownloadBuildArtifacts@0
|
||||
inputs:
|
||||
artifactName: ${{ parameters.pgoArtifact }}
|
||||
downloadPath: $(artifactsPath)
|
||||
|
||||
- script: |
|
||||
cd $(buildPlatform)
|
||||
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge WindowsTerminal*.pgc WindowsTerminal.pgd
|
||||
displayName: 'Merge Terminal pgc files into pgd'
|
||||
workingDirectory: $(pgoArtifactsPath)
|
||||
|
||||
- script: |
|
||||
cd $(buildPlatform)
|
||||
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge OpenConsole*.pgc OpenConsole.pgd
|
||||
displayName: 'Merge OpenConsole pgc files into pgd'
|
||||
workingDirectory: $(pgoArtifactsPath)
|
||||
|
||||
- script: |
|
||||
cd $(buildPlatform)
|
||||
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge Microsoft.Terminal.Control*.pgc Microsoft.Terminal.Control.pgd
|
||||
displayName: 'Merge Microsoft.Terminal.Control pgc files into pgd'
|
||||
workingDirectory: $(pgoArtifactsPath)
|
||||
|
||||
- script: |
|
||||
cd $(buildPlatform)
|
||||
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge Microsoft.Terminal.Remoting*.pgc Microsoft.Terminal.Remoting.pgd
|
||||
displayName: 'Merge Microsoft.Terminal.Remoting pgc files into pgd'
|
||||
workingDirectory: $(pgoArtifactsPath)
|
||||
|
||||
- script: |
|
||||
cd $(buildPlatform)
|
||||
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge Microsoft.Terminal.Settings.Editor*.pgc Microsoft.Terminal.Settings.Editor.pgd
|
||||
displayName: 'Merge Microsoft.Terminal.Settings.Editor pgc files into pgd'
|
||||
workingDirectory: $(pgoArtifactsPath)
|
||||
|
||||
- script: |
|
||||
cd $(buildPlatform)
|
||||
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge Microsoft.Terminal.Settings.Model*.pgc Microsoft.Terminal.Settings.Model.pgd
|
||||
displayName: 'Merge Microsoft.Terminal.Settings.Model pgc files into pgd'
|
||||
workingDirectory: $(pgoArtifactsPath)
|
||||
|
||||
- script: |
|
||||
cd $(buildPlatform)
|
||||
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge TerminalApp*.pgc TerminalApp.pgd
|
||||
displayName: 'Merge TerminalApp pgc files into pgd'
|
||||
workingDirectory: $(pgoArtifactsPath)
|
||||
|
||||
- script: |
|
||||
cd $(buildPlatform)
|
||||
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge TerminalConnection*.pgc TerminalConnection.pgd
|
||||
displayName: 'Merge TerminalConnection pgc files into pgd'
|
||||
workingDirectory: $(pgoArtifactsPath)
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Copy merged pgd to artifact staging'
|
||||
inputs:
|
||||
sourceFolder: $(pgoArtifactsPath)
|
||||
contents: '**\$(buildPlatform)\*.pgd'
|
||||
targetFolder: $(Build.ArtifactStagingDirectory)
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
inputs:
|
||||
pathToPublish: $(Build.ArtifactStagingDirectory)
|
||||
artifactName: ${{ parameters.pgoArtifact }}
|
|
@ -10,6 +10,7 @@
|
|||
<SubSystem>Console</SubSystem>
|
||||
<!-- sets a bunch of Windows Universal properties -->
|
||||
<OpenConsoleUniversalApp>true</OpenConsoleUniversalApp>
|
||||
<PgoTarget>true</PgoTarget>
|
||||
</PropertyGroup>
|
||||
<Import Project="..\..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
|
||||
|
@ -61,8 +62,8 @@
|
|||
<Link>
|
||||
<AdditionalDependencies>User32.lib;WindowsApp.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<!-- Our lib contains a DllMain that we need to force the use of. -->
|
||||
<AdditionalOptions Condition="'$(Platform)'=='Win32'">/INCLUDE:_DllMain@12</AdditionalOptions>
|
||||
<AdditionalOptions Condition="'$(Platform)'!='Win32'">/INCLUDE:DllMain</AdditionalOptions>
|
||||
<AdditionalOptions Condition="'$(Platform)'=='Win32'">/INCLUDE:_DllMain@12 %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalOptions Condition="'$(Platform)'!='Win32'">/INCLUDE:DllMain %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
<Reference>
|
||||
<!-- Do not propagate microsoft.ui.xaml upwards as a private dependency. -->
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
<SubSystem>Console</SubSystem>
|
||||
<!-- sets a bunch of Windows Universal properties -->
|
||||
<OpenConsoleUniversalApp>true</OpenConsoleUniversalApp>
|
||||
<PgoTarget>true</PgoTarget>
|
||||
</PropertyGroup>
|
||||
<Import Project="..\..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
|
||||
|
@ -105,8 +106,8 @@
|
|||
<Link>
|
||||
<AdditionalDependencies>User32.lib;WindowsApp.lib;shell32.lib;WinMM.Lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<!-- TerminalAppLib contains a DllMain that we need to force the use of. -->
|
||||
<AdditionalOptions Condition="'$(Platform)'=='Win32'">/INCLUDE:_DllMain@12</AdditionalOptions>
|
||||
<AdditionalOptions Condition="'$(Platform)'!='Win32'">/INCLUDE:DllMain</AdditionalOptions>
|
||||
<AdditionalOptions Condition="'$(Platform)'=='Win32'">/INCLUDE:_DllMain@12 %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalOptions Condition="'$(Platform)'!='Win32'">/INCLUDE:DllMain %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<OpenConsoleUniversalApp>true</OpenConsoleUniversalApp>
|
||||
<PgoTarget>true</PgoTarget>
|
||||
</PropertyGroup>
|
||||
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
|
||||
|
@ -87,4 +88,4 @@
|
|||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
<SubSystem>Console</SubSystem>
|
||||
<!-- sets a bunch of Windows Universal properties -->
|
||||
<OpenConsoleUniversalApp>true</OpenConsoleUniversalApp>
|
||||
<PgoTarget>true</PgoTarget>
|
||||
|
||||
<!-- C++/WinRT sets the depth to 1 if there is a XAML file in the project
|
||||
Unfortunately for us, we need it to be 3. When the namespace merging
|
||||
|
@ -87,8 +88,8 @@
|
|||
If you don't have this, then you'll see an error like
|
||||
"(init.obj) : error LNK2005: DllMain already defined in MSVCRTD.lib(dll_dllmain_stub.obj)"
|
||||
-->
|
||||
<AdditionalOptions Condition="'$(Platform)'=='Win32'">/INCLUDE:_DllMain@12</AdditionalOptions>
|
||||
<AdditionalOptions Condition="'$(Platform)'!='Win32'">/INCLUDE:DllMain</AdditionalOptions>
|
||||
<AdditionalOptions Condition="'$(Platform)'=='Win32'">/INCLUDE:_DllMain@12 %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalOptions Condition="'$(Platform)'!='Win32'">/INCLUDE:DllMain %(AdditionalOptions)</AdditionalOptions>
|
||||
|
||||
<Reference>
|
||||
<!-- Do not propagate microsoft.ui.xaml upwards as a private dependency. -->
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
<SubSystem>Console</SubSystem>
|
||||
<!-- sets a bunch of Windows Universal properties -->
|
||||
<OpenConsoleUniversalApp>true</OpenConsoleUniversalApp>
|
||||
<PgoTarget>true</PgoTarget>
|
||||
<!-- C++/WinRT sets the depth to 1 if there is a XAML file in the project
|
||||
Unfortunately for us, we need it to be 3. When the namespace merging
|
||||
depth is 1, Microsoft.Terminal.Control becomes "Microsoft",
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
<SubSystem>Console</SubSystem>
|
||||
<!-- sets a bunch of Windows Universal properties -->
|
||||
<OpenConsoleUniversalApp>true</OpenConsoleUniversalApp>
|
||||
<PgoTarget>true</PgoTarget>
|
||||
</PropertyGroup>
|
||||
<Import Project="..\..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
|
||||
|
@ -115,8 +116,8 @@
|
|||
<Link>
|
||||
<AdditionalDependencies>User32.lib;WindowsApp.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<!-- TSM Lib contains a DllMain that we need to force the use of. -->
|
||||
<AdditionalOptions Condition="'$(Platform)'=='Win32'">/INCLUDE:_DllMain@12</AdditionalOptions>
|
||||
<AdditionalOptions Condition="'$(Platform)'!='Win32'">/INCLUDE:DllMain</AdditionalOptions>
|
||||
<AdditionalOptions Condition="'$(Platform)'=='Win32'">/INCLUDE:_DllMain@12 %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalOptions Condition="'$(Platform)'!='Win32'">/INCLUDE:DllMain %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
<Reference>
|
||||
<!-- Do not propagate microsoft.ui.xaml upwards as a private dependency. -->
|
||||
|
|
|
@ -17,11 +17,12 @@
|
|||
<!-- IMPORTANT! cppwinrt.pre.props specifies 17134 -->
|
||||
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
|
||||
<TargetPlatformIdentifier>Windows</TargetPlatformIdentifier>
|
||||
<PgoTarget>true</PgoTarget>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
|
||||
|
||||
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
|
@ -170,7 +171,6 @@
|
|||
</ItemGroup>
|
||||
<!-- **END VC LIBS HACK** -->
|
||||
</Target>
|
||||
|
||||
<Import Project="$(OpenConsoleDir)\build\rules\GenerateSxsManifestsFromWinmds.targets" />
|
||||
<Import Project="..\..\..\packages\Terminal.ThemeHelpers.0.2.200324001\build\native\Terminal.ThemeHelpers.targets" Condition="Exists('..\..\..\packages\Terminal.ThemeHelpers.0.2.200324001\build\native\Terminal.ThemeHelpers.targets')" />
|
||||
</Project>
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="Globals.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
// <summary>Windows Terminal UI Automation global settings</summary>
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
namespace WindowsTerminal.UIA.Tests.Common
|
||||
{
|
||||
using System;
|
||||
using WEX.TestExecution.Markup;
|
||||
|
||||
public static class Globals
|
||||
{
|
||||
public const int Timeout = 50; // in milliseconds
|
||||
public const int LongTimeout = 5000; // in milliseconds
|
||||
public const int AppCreateTimeout = 3000; // in milliseconds
|
||||
|
||||
public static void WaitForTimeout()
|
||||
{
|
||||
System.Threading.Thread.Sleep(Globals.Timeout);
|
||||
}
|
||||
|
||||
public static void WaitForLongTimeout()
|
||||
{
|
||||
System.Threading.Thread.Sleep(Globals.LongTimeout);
|
||||
}
|
||||
|
||||
|
||||
static string[] modules =
|
||||
{
|
||||
"WindowsTerminal.exe",
|
||||
"OpenConsole.exe",
|
||||
"Microsoft.Terminal.Control.dll",
|
||||
"Microsoft.Terminal.Remoting.dll",
|
||||
"Microsoft.Terminal.Settings.Editor.dll",
|
||||
"Microsoft.Terminal.Settings.Model.dll",
|
||||
"TerminalApp.dll",
|
||||
"TerminalConnection.dll"
|
||||
};
|
||||
|
||||
public static void SweepAllModules(TestContext context)
|
||||
{
|
||||
foreach (var mod in modules)
|
||||
{
|
||||
PgoManager.PgoSweepIfInstrumented(context, mod);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,861 @@
|
|||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="NativeMethods.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
// <summary>Wrapper class for storing P/Invoke and COM Interop definitions.</summary>
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace WindowsTerminal.UIA.Tests.Common.NativeMethods
|
||||
{
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
using Microsoft.Win32;
|
||||
using WEX.TestExecution;
|
||||
using WEX.Logging.Interop;
|
||||
|
||||
// Small extension method helpers to make C# feel closer to native.
|
||||
public static class NativeExtensions
|
||||
{
|
||||
public static int LoWord(this int val)
|
||||
{
|
||||
return val & 0xffff;
|
||||
}
|
||||
|
||||
public static int HiWord(this int val)
|
||||
{
|
||||
return (val >> 16) & 0xffff;
|
||||
}
|
||||
}
|
||||
|
||||
public static class NativeMethods
|
||||
{
|
||||
public static void Win32BoolHelper(bool result, string actionMessage)
|
||||
{
|
||||
if (!result)
|
||||
{
|
||||
string errorMsg = string.Format("Win32 error occurred: 0x{0:X}", Marshal.GetLastWin32Error());
|
||||
Log.Comment(errorMsg);
|
||||
}
|
||||
|
||||
Verify.IsTrue(result, actionMessage);
|
||||
}
|
||||
|
||||
public static void Win32NullHelper(IntPtr result, string actionMessage)
|
||||
{
|
||||
if (result == IntPtr.Zero)
|
||||
{
|
||||
string errorMsg = string.Format("Win32 error occurred: 0x{0:X}", Marshal.GetLastWin32Error());
|
||||
Log.Comment(errorMsg);
|
||||
}
|
||||
|
||||
Verify.IsNotNull(result, actionMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public static class WinCon
|
||||
{
|
||||
[Flags()]
|
||||
public enum CONSOLE_SELECTION_INFO_FLAGS : uint
|
||||
{
|
||||
CONSOLE_NO_SELECTION = 0x0,
|
||||
CONSOLE_SELECTION_IN_PROGRESS = 0x1,
|
||||
CONSOLE_SELECTION_NOT_EMPTY = 0x2,
|
||||
CONSOLE_MOUSE_SELECTION = 0x4,
|
||||
CONSOLE_MOUSE_DOWN = 0x8
|
||||
}
|
||||
|
||||
public enum CONSOLE_STD_HANDLE : int
|
||||
{
|
||||
STD_INPUT_HANDLE = -10,
|
||||
STD_OUTPUT_HANDLE = -11,
|
||||
STD_ERROR_HANDLE = -12
|
||||
}
|
||||
|
||||
public enum CONSOLE_ATTRIBUTES : ushort
|
||||
{
|
||||
FOREGROUND_BLUE = 0x1,
|
||||
FOREGROUND_GREEN = 0x2,
|
||||
FOREGROUND_RED = 0x4,
|
||||
FOREGROUND_INTENSITY = 0x8,
|
||||
FOREGROUND_YELLOW = FOREGROUND_RED | FOREGROUND_GREEN,
|
||||
FOREGROUND_CYAN = FOREGROUND_GREEN | FOREGROUND_BLUE,
|
||||
FOREGROUND_MAGENTA = FOREGROUND_RED | FOREGROUND_BLUE,
|
||||
FOREGROUND_COLORS = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN,
|
||||
FOREGROUND_ALL = FOREGROUND_COLORS | FOREGROUND_INTENSITY,
|
||||
BACKGROUND_BLUE = 0x10,
|
||||
BACKGROUND_GREEN = 0x20,
|
||||
BACKGROUND_RED = 0x40,
|
||||
BACKGROUND_INTENSITY = 0x80,
|
||||
BACKGROUND_YELLOW = BACKGROUND_RED | BACKGROUND_GREEN,
|
||||
BACKGROUND_CYAN = BACKGROUND_GREEN | BACKGROUND_BLUE,
|
||||
BACKGROUND_MAGENTA = BACKGROUND_RED | BACKGROUND_BLUE,
|
||||
BACKGROUND_COLORS = BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN,
|
||||
BACKGROUND_ALL = BACKGROUND_COLORS | BACKGROUND_INTENSITY,
|
||||
COMMON_LVB_LEADING_BYTE = 0x100,
|
||||
COMMON_LVB_TRAILING_BYTE = 0x200,
|
||||
COMMON_LVB_GRID_HORIZONTAL = 0x400,
|
||||
COMMON_LVB_GRID_LVERTICAL = 0x800,
|
||||
COMMON_LVB_GRID_RVERTICAL = 0x1000,
|
||||
COMMON_LVB_REVERSE_VIDEO = 0x4000,
|
||||
COMMON_LVB_UNDERSCORE = 0x8000
|
||||
}
|
||||
|
||||
public enum CONSOLE_OUTPUT_MODES : uint
|
||||
{
|
||||
ENABLE_PROCESSED_OUTPUT = 0x1,
|
||||
ENABLE_WRAP_AT_EOL_OUTPUT = 0x2,
|
||||
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x4
|
||||
}
|
||||
|
||||
//CHAR_INFO struct, which was a union in the old days
|
||||
// so we want to use LayoutKind.Explicit to mimic it as closely
|
||||
// as we can
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct CHAR_INFO
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
internal char UnicodeChar;
|
||||
[FieldOffset(0)]
|
||||
internal char AsciiChar;
|
||||
[FieldOffset(2)] //2 bytes seems to work properly
|
||||
internal CONSOLE_ATTRIBUTES Attributes;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct COORD
|
||||
{
|
||||
public short X;
|
||||
public short Y;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("(X:{0} Y:{1})", X, Y);
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct SMALL_RECT
|
||||
{
|
||||
public short Left;
|
||||
public short Top;
|
||||
public short Right;
|
||||
public short Bottom;
|
||||
|
||||
public short Width
|
||||
{
|
||||
get
|
||||
{
|
||||
// The API returns bottom/right as the inclusive lower-right
|
||||
// corner, so we need +1 for the true width
|
||||
return (short)(this.Right - this.Left + 1);
|
||||
}
|
||||
}
|
||||
|
||||
public short Height
|
||||
{
|
||||
get
|
||||
{
|
||||
// The API returns bottom/right as the inclusive lower-right
|
||||
// corner, so we need +1 for the true height
|
||||
return (short)(this.Bottom - this.Top + 1);
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("(L:{0} T:{1} R:{2} B:{3})", Left, Top, Right, Bottom);
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct CONSOLE_CURSOR_INFO
|
||||
{
|
||||
public uint dwSize;
|
||||
public bool bVisible;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct CONSOLE_FONT_INFO
|
||||
{
|
||||
public int nFont;
|
||||
public COORD dwFontSize;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct CONSOLE_SELECTION_INFO
|
||||
{
|
||||
public CONSOLE_SELECTION_INFO_FLAGS Flags;
|
||||
public COORD SelectionAnchor;
|
||||
public SMALL_RECT Selection;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("Flags:{0:X} Anchor:{1} Selection:{2}", Flags, SelectionAnchor, Selection);
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct CONSOLE_SCREEN_BUFFER_INFO
|
||||
{
|
||||
public COORD dwSize;
|
||||
public COORD dwCursorPosition;
|
||||
public CONSOLE_ATTRIBUTES wAttributes;
|
||||
public SMALL_RECT srWindow;
|
||||
public COORD dwMaximumWindowSize;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct CONSOLE_SCREEN_BUFFER_INFO_EX
|
||||
{
|
||||
public uint cbSize;
|
||||
public COORD dwSize;
|
||||
public COORD dwCursorPosition;
|
||||
public CONSOLE_ATTRIBUTES wAttributes;
|
||||
public SMALL_RECT srWindow;
|
||||
public COORD dwMaximumWindowSize;
|
||||
|
||||
public CONSOLE_ATTRIBUTES wPopupAttributes;
|
||||
public bool bFullscreenSupported;
|
||||
|
||||
internal COLORREF black;
|
||||
internal COLORREF darkBlue;
|
||||
internal COLORREF darkGreen;
|
||||
internal COLORREF darkCyan;
|
||||
internal COLORREF darkRed;
|
||||
internal COLORREF darkMagenta;
|
||||
internal COLORREF darkYellow;
|
||||
internal COLORREF gray;
|
||||
internal COLORREF darkGray;
|
||||
internal COLORREF blue;
|
||||
internal COLORREF green;
|
||||
internal COLORREF cyan;
|
||||
internal COLORREF red;
|
||||
internal COLORREF magenta;
|
||||
internal COLORREF yellow;
|
||||
internal COLORREF white;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct COLORREF
|
||||
{
|
||||
internal uint ColorDWORD;
|
||||
|
||||
public COLORREF(Color color)
|
||||
{
|
||||
ColorDWORD = (uint)color.R + (((uint)color.G) << 8) + (((uint)color.B) << 16);
|
||||
}
|
||||
|
||||
public COLORREF(uint r, uint g, uint b)
|
||||
{
|
||||
ColorDWORD = r + (g << 8) + (b << 16);
|
||||
}
|
||||
|
||||
public Color GetColor()
|
||||
{
|
||||
return Color.FromArgb((int)(0x000000FFU & ColorDWORD),
|
||||
(int)(0x0000FF00U & ColorDWORD) >> 8, (int)(0x00FF0000U & ColorDWORD) >> 16);
|
||||
}
|
||||
|
||||
public void SetColor(Color color)
|
||||
{
|
||||
ColorDWORD = (uint)color.R + (((uint)color.G) << 8) + (((uint)color.B) << 16);
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern IntPtr GetStdHandle(CONSOLE_STD_HANDLE nStdHandle);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern bool AttachConsole(UInt32 dwProcessId);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern bool FreeConsole();
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
public static extern bool SetConsoleTitle(string ConsoleTitle);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern bool GetConsoleMode(IntPtr hConsoleOutputHandle, out CONSOLE_OUTPUT_MODES lpMode);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
public static extern uint GetConsoleTitle(StringBuilder lpConsoleTitle, int nSize);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern IntPtr GetConsoleWindow();
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern bool GetConsoleSelectionInfo(out CONSOLE_SELECTION_INFO lpConsoleSelectionInfo);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern bool SetConsoleWindowInfo(IntPtr hConsoleOutput, bool bAbsolute, [In] ref SMALL_RECT lpConsoleWindow);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern bool GetConsoleCursorInfo(IntPtr hConsoleOutput, out CONSOLE_CURSOR_INFO lpConsoleCursorInfo);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern bool GetConsoleScreenBufferInfo(IntPtr hConsoleOutput, out CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern bool GetConsoleScreenBufferInfoEx(IntPtr hConsoleOutput, ref CONSOLE_SCREEN_BUFFER_INFO_EX ConsoleScreenBufferInfo);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern bool SetConsoleScreenBufferInfoEx(IntPtr ConsoleOutput, ref CONSOLE_SCREEN_BUFFER_INFO_EX ConsoleScreenBufferInfoEx);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern bool GetCurrentConsoleFont(IntPtr hConsoleOutput, bool bMaximumWindow, out CONSOLE_FONT_INFO lpConsoleCurrentFont);
|
||||
|
||||
[DllImport("kernel32.dll", EntryPoint = "ReadConsoleOutputW", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
public static extern bool ReadConsoleOutput(
|
||||
IntPtr hConsoleOutput,
|
||||
/* This pointer is treated as the origin of a two-dimensional array of CHAR_INFO structures
|
||||
whose size is specified by the dwBufferSize parameter.*/
|
||||
[MarshalAs(UnmanagedType.LPArray), Out] CHAR_INFO[,] lpBuffer,
|
||||
COORD dwBufferSize,
|
||||
COORD dwBufferCoord,
|
||||
ref SMALL_RECT lpReadRegion);
|
||||
|
||||
[DllImport("kernel32.dll", EntryPoint = "WriteConsoleOutputCharacterW", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
public static extern bool WriteConsoleOutputCharacter(
|
||||
IntPtr hConsoleOutput,
|
||||
string lpCharacter,
|
||||
UInt32 nLength,
|
||||
COORD dwWriteCoord,
|
||||
ref UInt32 lpNumberOfCharsWritten);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The definitions within this file match the winconp.h file that is generated from wincon.w
|
||||
/// Please see /windows/published/main/wincon.w
|
||||
/// </summary>
|
||||
public static class WinConP
|
||||
{
|
||||
private static readonly Guid PKEY_Console_FormatId = new Guid(0x0C570607, 0x0396, 0x43DE, new byte[] { 0x9D, 0x61, 0xE3, 0x21, 0xD7, 0xDF, 0x50, 0x26 });
|
||||
|
||||
public static readonly Wtypes.PROPERTYKEY PKEY_Console_ForceV2 = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 1 };
|
||||
public static readonly Wtypes.PROPERTYKEY PKEY_Console_WrapText = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 2 };
|
||||
public static readonly Wtypes.PROPERTYKEY PKEY_Console_FilterOnPaste = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 3 };
|
||||
public static readonly Wtypes.PROPERTYKEY PKEY_Console_CtrlKeysDisabled = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 4 };
|
||||
public static readonly Wtypes.PROPERTYKEY PKEY_Console_LineSelection = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 5 };
|
||||
public static readonly Wtypes.PROPERTYKEY PKEY_Console_WindowTransparency = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 6 };
|
||||
public static readonly Wtypes.PROPERTYKEY PKEY_Console_TrimZeros = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 7 };
|
||||
public static readonly Wtypes.PROPERTYKEY PKEY_Console_CursorType = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 8 };
|
||||
public static readonly Wtypes.PROPERTYKEY PKEY_Console_CursorColor = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 9 };
|
||||
public static readonly Wtypes.PROPERTYKEY PKEY_Console_InterceptCopyPaste = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 10 };
|
||||
public static readonly Wtypes.PROPERTYKEY PKEY_Console_DefaultForeground = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 11 };
|
||||
public static readonly Wtypes.PROPERTYKEY PKEY_Console_DefaultBackground = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 12 };
|
||||
public static readonly Wtypes.PROPERTYKEY PKEY_Console_TerminalScrolling = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 13 };
|
||||
|
||||
public static readonly uint NT_CONSOLE_PROPS_SIG = 0xA0000002;
|
||||
public static readonly uint NT_FE_CONSOLE_PROPS_SIG = 0xA0000004;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public struct NT_CONSOLE_PROPS
|
||||
{
|
||||
public Shell32.DATABLOCK_HEADER dbh;
|
||||
public short wFillAttribute;
|
||||
public short wPopupFillAttribute;
|
||||
public WinCon.COORD dwScreenBufferSize;
|
||||
public WinCon.COORD dwWindowSize;
|
||||
public WinCon.COORD dwWindowOrigin;
|
||||
public int nFont;
|
||||
public int nInputBufferSize;
|
||||
public WinCon.COORD dwFontSize;
|
||||
public uint uFontFamily;
|
||||
public uint uFontWeight;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
|
||||
public string FaceName;
|
||||
public uint uCursorSize;
|
||||
public int bFullScreen;
|
||||
public int bQuickEdit;
|
||||
public int bInsertMode;
|
||||
public int bAutoPosition;
|
||||
public uint uHistoryBufferSize;
|
||||
public uint uNumberOfHistoryBuffers;
|
||||
public int bHistoryNoDup;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
|
||||
public int[] ColorTable;
|
||||
public uint CursorType;
|
||||
public WinCon.COLORREF CursorColor;
|
||||
public bool InterceptCopyPaste;
|
||||
public WinCon.COLORREF DefaultForeground;
|
||||
public WinCon.COLORREF DefaultBackground;
|
||||
public bool TerminalScrolling;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct NT_FE_CONSOLE_PROPS
|
||||
{
|
||||
Shell32.DATABLOCK_HEADER dbh;
|
||||
uint uCodePage;
|
||||
}
|
||||
}
|
||||
|
||||
public static class User32
|
||||
{
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd162897(v=vs.85).aspx
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct RECT
|
||||
{
|
||||
public Int32 left;
|
||||
public Int32 top;
|
||||
public Int32 right;
|
||||
public Int32 bottom;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct POINT
|
||||
{
|
||||
public Int32 x;
|
||||
public Int32 y;
|
||||
}
|
||||
|
||||
public const int WHEEL_DELTA = 120;
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
|
||||
|
||||
public const int GWL_STYLE = (-16);
|
||||
public const int GWL_EXSTYLE = (-20);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool AdjustWindowRectEx(ref RECT lpRect, int dwStyle, bool bMenu, int dwExStyle);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool ClientToScreen(IntPtr hWnd, ref POINT lpPoint);
|
||||
|
||||
public enum WindowMessages : UInt32
|
||||
{
|
||||
WM_KEYDOWN = 0x0100,
|
||||
WM_KEYUP = 0x0101,
|
||||
WM_CHAR = 0x0102,
|
||||
WM_MOUSEWHEEL = 0x020A,
|
||||
WM_MOUSEHWHEEL = 0x020E,
|
||||
WM_USER = 0x0400,
|
||||
CM_SET_KEY_STATE = WM_USER + 18
|
||||
}
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
||||
public static extern IntPtr SendMessage(IntPtr hWnd, WindowMessages Msg, Int32 wParam, IntPtr lParam);
|
||||
|
||||
public enum SPI : uint
|
||||
{
|
||||
SPI_GETWHEELSCROLLLINES = 0x0068,
|
||||
SPI_GETWHEELSCROLLCHARACTERS = 0x006C
|
||||
}
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
||||
public static extern bool SystemParametersInfo(SPI uiAction, uint uiParam, ref uint pvParam, uint fWinIni);
|
||||
|
||||
|
||||
public enum WinEventId : uint
|
||||
{
|
||||
EVENT_CONSOLE_CARET = 0x4001,
|
||||
EVENT_CONSOLE_UPDATE_REGION = 0x4002,
|
||||
EVENT_CONSOLE_UPDATE_SIMPLE = 0x4003,
|
||||
EVENT_CONSOLE_UPDATE_SCROLL = 0x4004,
|
||||
EVENT_CONSOLE_LAYOUT = 0x4005,
|
||||
EVENT_CONSOLE_START_APPLICATION = 0x4006,
|
||||
EVENT_CONSOLE_END_APPLICATION = 0x4007
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum WinEventFlags : uint
|
||||
{
|
||||
WINEVENT_OUTOFCONTEXT = 0x0000, // Events are ASYNC
|
||||
WINEVENT_SKIPOWNTHREAD = 0x0001, // Don't call back for events on installer's thread
|
||||
WINEVENT_SKIPOWNPROCESS = 0x0002, // Don't call back for events on installer's process
|
||||
WINEVENT_INCONTEXT = 0x0004, // Events are SYNC, this causes your dll to be injected into every process
|
||||
}
|
||||
|
||||
public delegate void WinEventDelegate(IntPtr hWinEventHook, WinEventId eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
public static extern IntPtr SetWinEventHook(WinEventId eventMin, WinEventId eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, WinEventFlags dwFlags);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool UnhookWinEvent(IntPtr hWinEventHook);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
|
||||
|
||||
public struct MSG
|
||||
{
|
||||
public IntPtr hwnd;
|
||||
public uint message;
|
||||
public IntPtr wParam;
|
||||
public IntPtr lParam;
|
||||
public uint time;
|
||||
public POINT pt;
|
||||
}
|
||||
|
||||
public enum PM : uint
|
||||
{
|
||||
PM_NOREMOVE = 0x0000,
|
||||
PM_REMOVE = 0x0001,
|
||||
PM_NOYIELD = 0x0002,
|
||||
}
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool PeekMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax, PM wRemoveMsg);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
public static extern int GetMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
public static extern IntPtr DispatchMessage(ref MSG lpmsg);
|
||||
}
|
||||
|
||||
public static class Shell32
|
||||
{
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb773249(v=vs.85).aspx
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct DATABLOCK_HEADER
|
||||
{
|
||||
public int cbSize;
|
||||
public int dwSignature;
|
||||
}
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb774944(v=vs.85).aspx
|
||||
// http://pinvoke.net/default.aspx/Enums/SLGP_FLAGS.html
|
||||
/// <summary>IShellLink.GetPath fFlags: Flags that specify the type of path information to retrieve</summary>
|
||||
[Flags()]
|
||||
public enum SLGP_FLAGS
|
||||
{
|
||||
/// <summary>Retrieves the standard short (8.3 format) file name</summary>
|
||||
SLGP_SHORTPATH = 0x1,
|
||||
/// <summary>Retrieves the Universal Naming Convention (UNC) path name of the file</summary>
|
||||
SLGP_UNCPRIORITY = 0x2,
|
||||
/// <summary>Retrieves the raw path name. A raw path is something that might not exist and may include environment variables that need to be expanded</summary>
|
||||
SLGP_RAWPATH = 0x4
|
||||
}
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb774952(v=vs.85).aspx
|
||||
// http://pinvoke.net/default.aspx/Enums/SLR_FLAGS.html
|
||||
/// <summary>IShellLink.Resolve fFlags</summary>
|
||||
[Flags()]
|
||||
public enum SLR_FLAGS
|
||||
{
|
||||
/// <summary>
|
||||
/// Do not display a dialog box if the link cannot be resolved. When SLR_NO_UI is set,
|
||||
/// the high-order word of fFlags can be set to a time-out value that specifies the
|
||||
/// maximum amount of time to be spent resolving the link. The function returns if the
|
||||
/// link cannot be resolved within the time-out duration. If the high-order word is set
|
||||
/// to zero, the time-out duration will be set to the default value of 3,000 milliseconds
|
||||
/// (3 seconds). To specify a value, set the high word of fFlags to the desired time-out
|
||||
/// duration, in milliseconds.
|
||||
/// </summary>
|
||||
SLR_NO_UI = 0x1,
|
||||
/// <summary>Obsolete and no longer used</summary>
|
||||
SLR_ANY_MATCH = 0x2,
|
||||
/// <summary>If the link object has changed, update its path and list of identifiers.
|
||||
/// If SLR_UPDATE is set, you do not need to call IPersistFile::IsDirty to determine
|
||||
/// whether or not the link object has changed.</summary>
|
||||
SLR_UPDATE = 0x4,
|
||||
/// <summary>Do not update the link information</summary>
|
||||
SLR_NOUPDATE = 0x8,
|
||||
/// <summary>Do not execute the search heuristics</summary>
|
||||
SLR_NOSEARCH = 0x10,
|
||||
/// <summary>Do not use distributed link tracking</summary>
|
||||
SLR_NOTRACK = 0x20,
|
||||
/// <summary>Disable distributed link tracking. By default, distributed link tracking tracks
|
||||
/// removable media across multiple devices based on the volume name. It also uses the
|
||||
/// Universal Naming Convention (UNC) path to track remote file systems whose drive letter
|
||||
/// has changed. Setting SLR_NOLINKINFO disables both types of tracking.</summary>
|
||||
SLR_NOLINKINFO = 0x40,
|
||||
/// <summary>Call the Microsoft Windows Installer</summary>
|
||||
SLR_INVOKE_MSI = 0x80
|
||||
}
|
||||
|
||||
[ComImport, Guid("00021401-0000-0000-C000-000000000046")]
|
||||
public class ShellLink
|
||||
{
|
||||
// Making new of this class will call CoCreate e.g. new ShellLink();
|
||||
// Cast to one of the interfaces below will QueryInterface. e.g. (IPersistFile)new ShellLink();
|
||||
}
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb774950(v=vs.85).aspx
|
||||
// http://pinvoke.net/default.aspx/Interfaces/IShellLinkW.html
|
||||
/// <summary>The IShellLink interface allows Shell links to be created, modified, and resolved</summary>
|
||||
[ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("000214F9-0000-0000-C000-000000000046")]
|
||||
public interface IShellLinkW
|
||||
{
|
||||
/// <summary>Retrieves the path and file name of a Shell link object</summary>
|
||||
void GetPath([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, out WinBase.WIN32_FIND_DATAW pfd, SLGP_FLAGS fFlags);
|
||||
/// <summary>Retrieves the list of item identifiers for a Shell link object</summary>
|
||||
void GetIDList(out IntPtr ppidl);
|
||||
/// <summary>Sets the pointer to an item identifier list (PIDL) for a Shell link object.</summary>
|
||||
void SetIDList(IntPtr pidl);
|
||||
/// <summary>Retrieves the description string for a Shell link object</summary>
|
||||
void GetDescription([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cchMaxName);
|
||||
/// <summary>Sets the description for a Shell link object. The description can be any application-defined string</summary>
|
||||
void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
|
||||
/// <summary>Retrieves the name of the working directory for a Shell link object</summary>
|
||||
void GetWorkingDirectory([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath);
|
||||
/// <summary>Sets the name of the working directory for a Shell link object</summary>
|
||||
void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
|
||||
/// <summary>Retrieves the command-line arguments associated with a Shell link object</summary>
|
||||
void GetArguments([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath);
|
||||
/// <summary>Sets the command-line arguments for a Shell link object</summary>
|
||||
void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
|
||||
/// <summary>Retrieves the hot key for a Shell link object</summary>
|
||||
void GetHotkey(out short pwHotkey);
|
||||
/// <summary>Sets a hot key for a Shell link object</summary>
|
||||
void SetHotkey(short wHotkey);
|
||||
/// <summary>Retrieves the show command for a Shell link object</summary>
|
||||
void GetShowCmd(out int piShowCmd);
|
||||
/// <summary>Sets the show command for a Shell link object. The show command sets the initial show state of the window.</summary>
|
||||
void SetShowCmd(int iShowCmd);
|
||||
/// <summary>Retrieves the location (path and index) of the icon for a Shell link object</summary>
|
||||
void GetIconLocation([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath,
|
||||
int cchIconPath, out int piIcon);
|
||||
/// <summary>Sets the location (path and index) of the icon for a Shell link object</summary>
|
||||
void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
|
||||
/// <summary>Sets the relative path to the Shell link object</summary>
|
||||
void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, int dwReserved);
|
||||
/// <summary>Attempts to find the target of a Shell link, even if it has been moved or renamed</summary>
|
||||
void Resolve(IntPtr hwnd, SLR_FLAGS fFlags);
|
||||
/// <summary>Sets the path and file name of a Shell link object</summary>
|
||||
void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
|
||||
}
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb774916(v=vs.85).aspx
|
||||
// http://pinvoke.net/default.aspx/Interfaces/IShellLonkDataList.html
|
||||
[ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("45e2b4ae-b1c3-11d0-b92f-00a0c90312e1")]
|
||||
public interface IShellLinkDataList
|
||||
{
|
||||
void AddDataBlock(IntPtr pDataBlock);
|
||||
void CopyDataBlock(uint dwSig, out IntPtr ppDataBlock);
|
||||
void RemoveDataBlock(uint dwSig);
|
||||
void GetFlags(out uint pdwFlags);
|
||||
void SetFlags(uint dwFlags);
|
||||
}
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms688695(v=vs.85).aspx
|
||||
// http://pinvoke.net/default.aspx/Interfaces/IPersist.html
|
||||
[ComImport, Guid("0000010c-0000-0000-c000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IPersist
|
||||
{
|
||||
[PreserveSig]
|
||||
void GetClassID(out Guid pClassID);
|
||||
}
|
||||
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms687223(v=vs.85).aspx
|
||||
// http://www.pinvoke.net/default.aspx/Interfaces/IPersistFile.html
|
||||
[ComImport, Guid("0000010b-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IPersistFile : IPersist
|
||||
{
|
||||
new void GetClassID(out Guid pClassID);
|
||||
|
||||
[PreserveSig]
|
||||
int IsDirty();
|
||||
|
||||
[PreserveSig]
|
||||
void Load([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName, uint dwMode);
|
||||
|
||||
[PreserveSig]
|
||||
void Save([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName,
|
||||
[In, MarshalAs(UnmanagedType.Bool)] bool fRemember);
|
||||
|
||||
[PreserveSig]
|
||||
void SaveCompleted([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName);
|
||||
|
||||
[PreserveSig]
|
||||
void GetCurFile([In, MarshalAs(UnmanagedType.LPWStr)] string ppszFileName);
|
||||
}
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb761474(v=vs.85).aspx
|
||||
// http://www.pinvoke.net/default.aspx/Interfaces/IPropertyStore.html
|
||||
[ComImport, Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IPropertyStore
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
|
||||
void GetCount([Out] out uint cProps);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
|
||||
void GetAt([In] uint iProp, out Wtypes.PROPERTYKEY pkey);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
|
||||
void GetValue([In] ref Wtypes.PROPERTYKEY key, out object pv);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
|
||||
void SetValue([In] ref Wtypes.PROPERTYKEY key, [In] ref object pv);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
|
||||
void Commit();
|
||||
}
|
||||
}
|
||||
|
||||
public static class WinBase
|
||||
{
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa365740(v=vs.85).aspx
|
||||
// http://www.pinvoke.net/default.aspx/Structures/WIN32_FIND_DATA.html
|
||||
// The CharSet must match the CharSet of the corresponding PInvoke signature
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public struct WIN32_FIND_DATAW
|
||||
{
|
||||
public uint dwFileAttributes;
|
||||
public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
|
||||
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
|
||||
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
|
||||
public uint nFileSizeHigh;
|
||||
public uint nFileSizeLow;
|
||||
public uint dwReserved0;
|
||||
public uint dwReserved1;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
|
||||
public string cFileName;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
|
||||
public string cAlternateFileName;
|
||||
}
|
||||
|
||||
public enum STARTF : Int32
|
||||
{
|
||||
STARTF_TITLEISLINKNAME = 0x00000800
|
||||
}
|
||||
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public struct STARTUPINFO
|
||||
{
|
||||
public Int32 cb;
|
||||
public string lpReserved;
|
||||
public string lpDesktop;
|
||||
public string lpTitle;
|
||||
public Int32 dwX;
|
||||
public Int32 dwY;
|
||||
public Int32 dwXSize;
|
||||
public Int32 dwYSize;
|
||||
public Int32 dwXCountChars;
|
||||
public Int32 dwYCountChars;
|
||||
public Int32 dwFillAttribute;
|
||||
public STARTF dwFlags;
|
||||
public Int16 wShowWindow;
|
||||
public Int16 cbReserved2;
|
||||
public IntPtr lpReserved2;
|
||||
public IntPtr hStdInput;
|
||||
public IntPtr hStdOutput;
|
||||
public IntPtr hStdError;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct PROCESS_INFORMATION
|
||||
{
|
||||
public IntPtr hProcess;
|
||||
public IntPtr hThread;
|
||||
public int dwProcessId;
|
||||
public int dwThreadId;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public struct STARTUPINFOEX
|
||||
{
|
||||
public STARTUPINFO StartupInfo;
|
||||
public IntPtr lpAttributeList;
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum CP_CreationFlags : uint
|
||||
{
|
||||
CREATE_SUSPENDED = 0x4,
|
||||
CREATE_NEW_CONSOLE = 0x10,
|
||||
}
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
||||
public static extern bool CreateProcess(string lpApplicationName,
|
||||
string lpCommandLine,
|
||||
IntPtr lpProcessAttributes,
|
||||
IntPtr lpThreadAttributes,
|
||||
bool bInheritHandles,
|
||||
CP_CreationFlags dwCreationFlags,
|
||||
IntPtr lpEnvironment,
|
||||
string lpCurrentDirectory,
|
||||
[In] ref STARTUPINFO lpStartupInfo,
|
||||
out PROCESS_INFORMATION lpProcessInformation);
|
||||
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr CreateJobObject(IntPtr lpJobAttributes, IntPtr lpName);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool TerminateJobObject(IntPtr hJob, uint uExitCode);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern bool AssignProcessToJobObject(IntPtr hJob, IntPtr hProcess);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern int ResumeThread(IntPtr hThread);
|
||||
|
||||
public enum JOBOBJECTINFOCLASS : uint
|
||||
{
|
||||
JobObjectBasicProcessIdList = 3
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct JOBOBJECT_BASIC_PROCESS_ID_LIST
|
||||
{
|
||||
public uint NumberOfAssignedProcesses;
|
||||
public uint NumberOfProcessIdsInList;
|
||||
public IntPtr ProcessId;
|
||||
public IntPtr ProcessId2;
|
||||
}
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool QueryInformationJobObject(IntPtr hJob,
|
||||
JOBOBJECTINFOCLASS JobObjectInformationClass,
|
||||
IntPtr lpJobObjectInfo,
|
||||
int cbJobObjectInfoLength,
|
||||
IntPtr lpReturnLength);
|
||||
}
|
||||
|
||||
public static class Wtypes
|
||||
{
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb773381(v=vs.85).aspx
|
||||
// http://pinvoke.net/default.aspx/Structures/PROPERTYKEY.html
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
||||
public struct PROPERTYKEY
|
||||
{
|
||||
public Guid fmtid;
|
||||
public uint pid;
|
||||
}
|
||||
}
|
||||
|
||||
public static class ObjBase
|
||||
{
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa380337(v=vs.85).aspx
|
||||
// http://www.pinvoke.net/default.aspx/Enums/StgmConstants.html
|
||||
[Flags]
|
||||
public enum STGM
|
||||
{
|
||||
STGM_READ = 0x0,
|
||||
STGM_WRITE = 0x1,
|
||||
STGM_READWRITE = 0x2,
|
||||
STGM_SHARE_DENY_NONE = 0x40,
|
||||
STGM_SHARE_DENY_READ = 0x30,
|
||||
STGM_SHARE_DENY_WRITE = 0x20,
|
||||
STGM_SHARE_EXCLUSIVE = 0x10,
|
||||
STGM_PRIORITY = 0x40000,
|
||||
STGM_CREATE = 0x1000,
|
||||
STGM_CONVERT = 0x20000,
|
||||
STGM_FAILIFTHERE = 0x0,
|
||||
STGM_DIRECT = 0x0,
|
||||
STGM_TRANSACTED = 0x10000,
|
||||
STGM_NOSCRATCH = 0x100000,
|
||||
STGM_NOSNAPSHOT = 0x200000,
|
||||
STGM_SIMPLE = 0x8000000,
|
||||
STGM_DIRECT_SWMR = 0x400000,
|
||||
STGM_DELETEONRELEASE = 0x4000000
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using WEX.Logging.Interop;
|
||||
using WEX.TestExecution.Markup;
|
||||
|
||||
namespace WindowsTerminal.UIA.Tests.Common
|
||||
{
|
||||
public static class PgoManager
|
||||
{
|
||||
public static void PgoSweepIfInstrumented(TestContext context, string assemblyName)
|
||||
{
|
||||
#if PGO_INSTRUMENT
|
||||
string pgcFileName = context.TestName;
|
||||
Log.Comment($"Running pgosweep on '{assemblyName}' for test: {pgcFileName}");
|
||||
try
|
||||
{
|
||||
var startInfo = new ProcessStartInfo() {
|
||||
FileName = Path.GetFullPath(Path.Combine(context.TestDeploymentDir, "pgosweep.exe")),
|
||||
Arguments = $"{assemblyName} {assemblyName}-{pgcFileName}.pgc",
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true
|
||||
};
|
||||
using (var process = Process.Start(startInfo))
|
||||
{
|
||||
var output = new StringBuilder();
|
||||
while (!process.HasExited)
|
||||
{
|
||||
Log.Comment(process.StandardOutput.ReadToEnd());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Comment("Failed trying to pgosweep. " + ex.ToString());
|
||||
throw;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,176 @@
|
|||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="TerminalApp.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
// <summary>Helper and wrapper for generating the base test application and its UI Root node.</summary>
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
namespace WindowsTerminal.UIA.Tests.Elements
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using WindowsTerminal.UIA.Tests.Common;
|
||||
using WindowsTerminal.UIA.Tests.Common.NativeMethods;
|
||||
|
||||
using OpenQA.Selenium.Remote;
|
||||
using OpenQA.Selenium.Appium;
|
||||
using OpenQA.Selenium.Appium.iOS;
|
||||
using OpenQA.Selenium.Interactions;
|
||||
|
||||
using WEX.Logging.Interop;
|
||||
using WEX.TestExecution;
|
||||
using WEX.TestExecution.Markup;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Principal;
|
||||
using OpenQA.Selenium;
|
||||
|
||||
public class TerminalApp : IDisposable
|
||||
{
|
||||
protected const string AppDriverUrl = "http://127.0.0.1:4723";
|
||||
|
||||
private IntPtr job;
|
||||
|
||||
public IOSDriver<IOSElement> Session { get; private set; }
|
||||
public Actions Actions { get; private set; }
|
||||
public AppiumWebElement UIRoot { get; private set; }
|
||||
|
||||
private bool isDisposed = false;
|
||||
|
||||
private TestContext context;
|
||||
|
||||
public string ContentPath { get; private set; }
|
||||
public string GetFullTestContentPath(string filename)
|
||||
{
|
||||
return Path.GetFullPath(Path.Combine(ContentPath, filename));
|
||||
}
|
||||
|
||||
public TerminalApp(TestContext context, string shellToLaunch = "powershell.exe")
|
||||
{
|
||||
this.context = context;
|
||||
|
||||
// If running locally, set WTPath to where we can find a loose deployment of Windows Terminal
|
||||
// On the build machines, the scripts lay it out at the appx\ subfolder of the test deployment directory
|
||||
string path = Path.GetFullPath(Path.Combine(context.TestDeploymentDir, @"appx\WindowsTerminal.exe"));
|
||||
if (context.Properties.Contains("WTPath"))
|
||||
{
|
||||
path = (string)context.Properties["WTPath"];
|
||||
}
|
||||
Log.Comment($"Windows Terminal will be launched from '{path}'");
|
||||
|
||||
// Same goes for the content directory. Set WTTestContent for where the content files are
|
||||
// for running tests.
|
||||
// On the build machines, the scripts lay it out at the content\ subfolder.
|
||||
ContentPath = @"content";
|
||||
if (context.Properties.Contains("WTTestContent"))
|
||||
{
|
||||
ContentPath = (string)context.Properties["WTTestContent"];
|
||||
}
|
||||
Log.Comment($"Test Content will be loaded from '{Path.GetFullPath(ContentPath)}'");
|
||||
|
||||
this.CreateProcess(path, shellToLaunch);
|
||||
}
|
||||
|
||||
~TerminalApp()
|
||||
{
|
||||
this.Dispose(false);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
this.Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public AppiumWebElement GetRoot()
|
||||
{
|
||||
return this.UIRoot;
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!this.isDisposed)
|
||||
{
|
||||
// ensure we're exited when this is destroyed or disposed of explicitly
|
||||
this.ExitProcess();
|
||||
|
||||
this.isDisposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateProcess(string path, string shellToLaunch)
|
||||
{
|
||||
string WindowTitleToFind = "WindowsTerminal.UIA.Tests";
|
||||
|
||||
job = WinBase.CreateJobObject(IntPtr.Zero, IntPtr.Zero);
|
||||
NativeMethods.Win32NullHelper(job, "Creating job object to hold binaries under test.");
|
||||
|
||||
Log.Comment("Attempting to launch command-line application at '{0}'", path);
|
||||
|
||||
string binaryToRunPath = path;
|
||||
string args = $"new-tab --title \"{WindowTitleToFind}\" --suppressApplicationTitle \"{shellToLaunch}\"";
|
||||
|
||||
string launchArgs = $"{binaryToRunPath} {args}";
|
||||
|
||||
WinBase.STARTUPINFO si = new WinBase.STARTUPINFO();
|
||||
si.cb = Marshal.SizeOf(si);
|
||||
|
||||
WinBase.PROCESS_INFORMATION pi = new WinBase.PROCESS_INFORMATION();
|
||||
|
||||
NativeMethods.Win32BoolHelper(WinBase.CreateProcess(null,
|
||||
launchArgs,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
false,
|
||||
WinBase.CP_CreationFlags.CREATE_SUSPENDED,
|
||||
IntPtr.Zero,
|
||||
null,
|
||||
ref si,
|
||||
out pi),
|
||||
"Attempting to create child host window process.");
|
||||
|
||||
Log.Comment($"Host window PID: {pi.dwProcessId}");
|
||||
|
||||
NativeMethods.Win32BoolHelper(WinBase.AssignProcessToJobObject(job, pi.hProcess), "Assigning new host window (suspended) to job object.");
|
||||
NativeMethods.Win32BoolHelper(-1 != WinBase.ResumeThread(pi.hThread), "Resume host window process now that it is attached and its launch of the child application will be caught in the job object.");
|
||||
|
||||
Globals.WaitForTimeout();
|
||||
|
||||
DesiredCapabilities appCapabilities = new DesiredCapabilities();
|
||||
appCapabilities.SetCapability("app", @"Root");
|
||||
Session = new IOSDriver<IOSElement>(new Uri(AppDriverUrl), appCapabilities);
|
||||
|
||||
Verify.IsNotNull(Session);
|
||||
Actions = new Actions(Session);
|
||||
Verify.IsNotNull(Session);
|
||||
|
||||
Globals.WaitForLongTimeout();
|
||||
|
||||
UIRoot = Session.FindElementByName(WindowTitleToFind);
|
||||
|
||||
// Set the timeout to 15 seconds after we found the initial window.
|
||||
Session.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(15);
|
||||
}
|
||||
|
||||
private bool IsRunningAsAdmin()
|
||||
{
|
||||
return new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
|
||||
}
|
||||
|
||||
private void ExitProcess()
|
||||
{
|
||||
Globals.SweepAllModules(this.context);
|
||||
|
||||
// Release attachment to the child process console.
|
||||
WinCon.FreeConsole();
|
||||
|
||||
this.UIRoot = null;
|
||||
|
||||
if (this.job != IntPtr.Zero)
|
||||
{
|
||||
WinBase.TerminateJobObject(this.job, 0);
|
||||
}
|
||||
this.job = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="ExperimentalTabTests.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
// </copyright>
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using WEX.Logging.Interop;
|
||||
using WEX.TestExecution.Markup;
|
||||
|
||||
namespace Host.Tests.UIA
|
||||
{
|
||||
[TestClass]
|
||||
class Init
|
||||
{
|
||||
static Process appDriver;
|
||||
|
||||
[AssemblyInitialize]
|
||||
public static void SetupAll(TestContext context)
|
||||
{
|
||||
Log.Comment("Searching for WinAppDriver in the same directory where this test was launched from...");
|
||||
string winAppDriver = Path.Combine(context.TestDeploymentDir, "WinAppDriver.exe");
|
||||
|
||||
Log.Comment($"Attempting to launch WinAppDriver at: {winAppDriver}");
|
||||
Log.Comment($"Working directory: {Environment.CurrentDirectory}");
|
||||
|
||||
appDriver = Process.Start(winAppDriver);
|
||||
}
|
||||
|
||||
[AssemblyCleanup]
|
||||
public static void CleanupAll()
|
||||
{
|
||||
try
|
||||
{
|
||||
appDriver.Kill();
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// <copyright file="SmokeTests.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
// </copyright>
|
||||
// <summary>UI Automation tests for verifying the basic opening/closing of the Terminal.</summary>
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace WindowsTerminal.UIA.Tests
|
||||
{
|
||||
using OpenQA.Selenium;
|
||||
using WEX.TestExecution.Markup;
|
||||
|
||||
using WindowsTerminal.UIA.Tests.Common;
|
||||
using WindowsTerminal.UIA.Tests.Elements;
|
||||
|
||||
[TestClass]
|
||||
public class SmokeTests
|
||||
{
|
||||
public TestContext TestContext { get; set; }
|
||||
|
||||
[TestMethod]
|
||||
[TestProperty("IsPGO", "true")]
|
||||
public void StartTerminal()
|
||||
{
|
||||
using (TerminalApp app = new TerminalApp(TestContext))
|
||||
{
|
||||
var root = app.GetRoot();
|
||||
root.SendKeys("Hello smoke test!");
|
||||
Globals.WaitForLongTimeout();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestProperty("IsPGO", "true")]
|
||||
public void RunBigTextPowershell()
|
||||
{
|
||||
using (TerminalApp app = new TerminalApp(TestContext))
|
||||
{
|
||||
var root = app.GetRoot();
|
||||
var contentPath = app.GetFullTestContentPath("big.txt");
|
||||
root.SendKeys($"cat \"{contentPath}\"");
|
||||
root.SendKeys(Keys.Enter);
|
||||
System.Threading.Thread.Sleep(25000);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestProperty("IsPGO", "true")]
|
||||
public void RunBigTextPowershellBulk ()
|
||||
{
|
||||
using (TerminalApp app = new TerminalApp(TestContext))
|
||||
{
|
||||
var root = app.GetRoot();
|
||||
var contentPath = app.GetFullTestContentPath("big.txt");
|
||||
root.SendKeys($"Get-Content -ReadCount 0 \"{contentPath}\" | Out-Default");
|
||||
root.SendKeys(Keys.Enter);
|
||||
System.Threading.Thread.Sleep(25000);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestProperty("IsPGO", "true")]
|
||||
public void RunBigTextCmd()
|
||||
{
|
||||
using (TerminalApp app = new TerminalApp(TestContext, "cmd.exe"))
|
||||
{
|
||||
var root = app.GetRoot();
|
||||
var contentPath = app.GetFullTestContentPath("big.txt");
|
||||
root.SendKeys($"type \"{contentPath}\"");
|
||||
root.SendKeys(Keys.Enter);
|
||||
System.Threading.Thread.Sleep(25000);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestProperty("IsPGO", "true")]
|
||||
public void RunCmatrixCmd()
|
||||
{
|
||||
using (TerminalApp app = new TerminalApp(TestContext, "cmd.exe"))
|
||||
{
|
||||
var root = app.GetRoot();
|
||||
root.SendKeys("chcp 65001" + Keys.Enter); // This output needs UTF-8
|
||||
var contentPath = app.GetFullTestContentPath("cmatrix.txt");
|
||||
root.SendKeys($"type \"{contentPath}\"");
|
||||
root.SendKeys(Keys.Enter);
|
||||
System.Threading.Thread.Sleep(10000);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestProperty("IsPGO", "true")]
|
||||
public void RunCacafireCmd()
|
||||
{
|
||||
using (TerminalApp app = new TerminalApp(TestContext, "cmd.exe"))
|
||||
{
|
||||
var root = app.GetRoot();
|
||||
root.SendKeys("chcp 65001" + Keys.Enter); // This output needs UTF-8
|
||||
var contentPath = app.GetFullTestContentPath("cacafire.txt");
|
||||
root.SendKeys($"type \"{contentPath}\"");
|
||||
root.SendKeys(Keys.Enter);
|
||||
System.Threading.Thread.Sleep(25000);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestProperty("IsPGO", "true")]
|
||||
public void RunChafaCmd()
|
||||
{
|
||||
using (TerminalApp app = new TerminalApp(TestContext, "cmd.exe"))
|
||||
{
|
||||
var root = app.GetRoot();
|
||||
root.SendKeys("chcp 65001" + Keys.Enter); // This output needs UTF-8
|
||||
var contentPath = app.GetFullTestContentPath("chafa.txt");
|
||||
root.SendKeys($"type \"{contentPath}\"");
|
||||
root.SendKeys(Keys.Enter);
|
||||
System.Threading.Thread.Sleep(10000);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestProperty("IsPGO", "true")]
|
||||
public void RunMakeKillPanes()
|
||||
{
|
||||
using (TerminalApp app = new TerminalApp(TestContext))
|
||||
{
|
||||
var root = app.GetRoot();
|
||||
|
||||
root.SendKeys(Keys.LeftAlt + Keys.LeftShift + "+");
|
||||
Globals.WaitForTimeout();
|
||||
root.SendKeys(Keys.LeftAlt + Keys.LeftShift + "+");
|
||||
Globals.WaitForTimeout();
|
||||
root.SendKeys(Keys.LeftAlt + Keys.LeftShift + "-");
|
||||
Globals.WaitForTimeout();
|
||||
root.SendKeys(Keys.LeftAlt + Keys.LeftShift + "-");
|
||||
Globals.WaitForTimeout();
|
||||
root.SendKeys(Keys.LeftControl + Keys.LeftShift + "W");
|
||||
Globals.WaitForTimeout();
|
||||
root.SendKeys(Keys.LeftControl + Keys.LeftShift + "W");
|
||||
Globals.WaitForTimeout();
|
||||
root.SendKeys(Keys.LeftControl + Keys.LeftShift + "W");
|
||||
Globals.WaitForTimeout();
|
||||
root.SendKeys(Keys.LeftControl + Keys.LeftShift + "W");
|
||||
Globals.WaitForTimeout();
|
||||
|
||||
Globals.WaitForLongTimeout();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestProperty("IsPGO", "true")]
|
||||
public void RunMakeKillTabs()
|
||||
{
|
||||
using (TerminalApp app = new TerminalApp(TestContext))
|
||||
{
|
||||
var root = app.GetRoot();
|
||||
|
||||
root.SendKeys(Keys.LeftAlt + Keys.LeftShift + "T");
|
||||
Globals.WaitForTimeout();
|
||||
root.SendKeys(Keys.LeftAlt + Keys.LeftShift + "T");
|
||||
Globals.WaitForTimeout();
|
||||
root.SendKeys(Keys.LeftAlt + Keys.LeftShift + "T");
|
||||
Globals.WaitForTimeout();
|
||||
root.SendKeys(Keys.LeftAlt + Keys.LeftShift + "T");
|
||||
Globals.WaitForTimeout();
|
||||
root.SendKeys(Keys.LeftControl + Keys.LeftShift + "W");
|
||||
Globals.WaitForTimeout();
|
||||
root.SendKeys(Keys.LeftControl + Keys.LeftShift + "W");
|
||||
Globals.WaitForTimeout();
|
||||
root.SendKeys(Keys.LeftControl + Keys.LeftShift + "W");
|
||||
Globals.WaitForTimeout();
|
||||
root.SendKeys(Keys.LeftControl + Keys.LeftShift + "W");
|
||||
Globals.WaitForTimeout();
|
||||
|
||||
Globals.WaitForLongTimeout();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{F19DACD5-0C6E-40DC-B6E4-767A3200542C}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>WindowsTerminal.UIA.Tests</RootNamespace>
|
||||
<AssemblyName>WindowsTerminal.UIA.Tests</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
|
||||
<IsCodedUITest>False</IsCodedUITest>
|
||||
<TestProjectType>UnitTest</TestProjectType>
|
||||
<OutputPath>$(SolutionDir)\bin\$(Platform)\$(Configuration)</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Platform)' == 'ARM64'">
|
||||
<PlatformTarget>ARM64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Platform)' == 'x64'">
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Platform)' == 'Win32'">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<DefineConstants Condition="'$(PGOBuildMode)' == 'Instrument'">$(DefineConstants);PGO_INSTRUMENT</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="appium-dotnet-driver, Version=3.0.0.2, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\..\packages\Appium.WebDriver.3.0.0.2\lib\net45\appium-dotnet-driver.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Castle.Core, Version=4.1.1.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\..\packages\Castle.Core.4.1.1\lib\net45\Castle.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="TE.Managed, Version=10.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\..\packages\Microsoft.Taef.10.58.210305002\lib\net45\TE.Managed.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="TE.Model.Managed, Version=10.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\..\packages\Microsoft.Taef.10.58.210305002\lib\net45\TE.Model.Managed.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UIAutomationClient" />
|
||||
<Reference Include="UIAutomationTypes" />
|
||||
<Reference Include="WebDriver, Version=3.5.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\..\packages\Selenium.WebDriver.3.5.0\lib\net40\WebDriver.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="WebDriver.Support, Version=3.5.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\..\packages\Selenium.Support.3.5.0\lib\net40\WebDriver.Support.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Wex.Common.Managed, Version=10.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\..\packages\Microsoft.Taef.10.58.210305002\lib\net45\Wex.Common.Managed.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Wex.Logger.Interop, Version=10.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\..\packages\Microsoft.Taef.10.58.210305002\lib\net45\Wex.Logger.Interop.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="WindowsBase" />
|
||||
</ItemGroup>
|
||||
<Choose>
|
||||
<When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
|
||||
</ItemGroup>
|
||||
</When>
|
||||
<Otherwise>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework" />
|
||||
</ItemGroup>
|
||||
</Otherwise>
|
||||
</Choose>
|
||||
<ItemGroup>
|
||||
<Compile Include="Common\Globals.cs" />
|
||||
<Compile Include="Common\NativeMethods.cs" />
|
||||
<Compile Include="Common\PgoManager.cs" />
|
||||
<Compile Include="Elements\TerminalApp.cs" />
|
||||
<Compile Include="Init.cs" />
|
||||
<Compile Include="SmokeTests.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Choose>
|
||||
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.CodedUITestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Extension, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITesting, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
</When>
|
||||
</Choose>
|
||||
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>copy $(SolutionDir)\dep\WinAppDriver\* $(OutDir)\</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<Import Project="..\..\..\packages\Microsoft.Taef.10.58.210305002\build\Microsoft.Taef.targets" Condition="Exists('..\..\..\packages\Microsoft.Taef.10.58.210305002\build\Microsoft.Taef.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Taef.10.58.210305002\build\Microsoft.Taef.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Taef.10.58.210305002\build\Microsoft.Taef.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Castle.Core" publicKeyToken="407dd0808d44fbdc" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Appium.WebDriver" version="3.0.0.2" targetFramework="net45" />
|
||||
<package id="Castle.Core" version="4.1.1" targetFramework="net45" />
|
||||
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net45" />
|
||||
<package id="Selenium.Support" version="3.5.0" targetFramework="net45" />
|
||||
<package id="Selenium.WebDriver" version="3.5.0" targetFramework="net45" />
|
||||
<package id="Microsoft.Taef" version="10.58.210305002" targetFramework="net45" />
|
||||
</packages>
|
|
@ -33,6 +33,10 @@
|
|||
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
||||
<!-- PGO -->
|
||||
<Import Condition="'$(PgoTarget)' == 'true' And '$(PGOBuildMode)' == 'Optimize'" Project="$(SolutionDir)packages\$(PGODatabaseId).$(PGODatabaseVersion)\build\PGO.targets" />
|
||||
<Import Condition="'$(PgoTarget)' == 'true' And '$(PGOBuildMode)' == 'Instrument'" Project="$(SolutionDir)\src\common.pgo.runtime.props" />
|
||||
|
||||
<!-- Exclude our dependencies from static analysis. CAExcludePath can only be
|
||||
set after we've imported Microsoft.Cpp.targets -->
|
||||
<PropertyGroup>
|
||||
|
|
|
@ -156,6 +156,9 @@
|
|||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<Import Condition="'$(PgoTarget)' == 'true' And '$(Configuration)' == 'Release'" Project="$(SolutionDir)\src\common.pgo.compile.props" />
|
||||
<Import Condition="'$(PgoTarget)' == 'true' And '$(PGOBuildMode)' == 'Optimize'" Project="$(SolutionDir)\tools\PGODatabase\PGO.version.props" />
|
||||
|
||||
<!-- For Win32 (x86) ONLY ... we use all defaults for AMD64. No def for those. -->
|
||||
<ItemDefinitionGroup Condition="'$(Platform)'=='Win32'">
|
||||
<ClCompile>
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- From our friends at MUX: https://github.com/microsoft/microsoft-ui-xaml/blob/main/PGO.compile.props -->
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition="'$(PGOBuildMode)' == 'Instrument'">
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Enable PGO optimization only for Release builds. -->
|
||||
<ItemDefinitionGroup Condition="'$(PGOBuildMode)' == 'Instrument'">
|
||||
<Link>
|
||||
<AdditionalOptions>/GENPROFILE %(AdditionalOptions)</AdditionalOptions>
|
||||
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
||||
<AdditionalDependencies Condition="'$(Platform)'=='ARM'">$(VC_ReferencesPath_VC_ARM)\pgort.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies Condition="'$(Platform)'=='ARM64'">$(VC_ReferencesPath_VC_ARM64)\pgort.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies Condition="'$(Platform)'=='Win32'">$(VC_ReferencesPath_VC_x86)\pgort.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies Condition="'$(Platform)'=='x64'">$(VC_ReferencesPath_VC_x64)\pgort.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
</Project>
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- From our friends at MUX: https://github.com/microsoft/microsoft-ui-xaml/blob/main/PGO.runtime.props -->
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<PlatformShortName Condition="'$(PlatformShortName)'==''">$(Platform)</PlatformShortName>
|
||||
<PlatformShortName Condition="'$(PlatformShortName)'=='Win32'">x86</PlatformShortName>
|
||||
<PlatformShortName Condition="'$(PlatformShortName)'=='AnyCPU' and '$(Prefer32Bit)'==''">x64</PlatformShortName>
|
||||
<PlatformShortName Condition="'$(PlatformShortName)'=='AnyCPU' and '$(Prefer32Bit)'=='true'">x64</PlatformShortName>
|
||||
<PlatformShortName Condition="'$(PlatformShortName)'=='AnyCPU' and '$(Prefer32Bit)'=='false'">x64</PlatformShortName>
|
||||
<HostFolderName Condition="'$(VCToolArchitecture)'=='Native32Bit'">Hostx86</HostFolderName>
|
||||
<HostFolderName Condition="'$(VCToolArchitecture)'=='Native64Bit'">Hostx64</HostFolderName>
|
||||
<PGOFilesDir>$(VCToolsInstallDir)bin\$(HostFolderName)\$(PlatformShortName)</PGOFilesDir>
|
||||
<PGOFilesDir Condition="'$(PlatformShortName)'=='ARM' or '$(PlatformShortName)'=='ARM64'">$(VCToolsInstallDir)bin\$(PlatformShortName)</PGOFilesDir>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="$(PGOFilesDir)\pgort140.dll">
|
||||
<Link>%(Filename)%(Extension)</Link>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(PGOFilesDir)\pgosweep.exe">
|
||||
<Link>%(Filename)%(Extension)</Link>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(PGOFilesDir)\vcruntime140.dll" Condition="Exists('$(PGOFilesDir)\vcruntime140.dll')">
|
||||
<Link>%(Filename)%(Extension)</Link>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -7,7 +7,9 @@
|
|||
<ProjectName>Host.EXE</ProjectName>
|
||||
<TargetName>OpenConsole</TargetName>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PgoTarget>true</PgoTarget>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(SolutionDir)common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
<Import Project="$(SolutionDir)src\common.build.pre.props" />
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\precomp.h" />
|
||||
|
@ -90,5 +92,5 @@
|
|||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<!-- Careful reordering these. Some default props (contained in these files) are order sensitive. -->
|
||||
<Import Project="..\..\common.build.post.props" />
|
||||
</Project>
|
||||
<Import Project="$(SolutionDir)src\common.build.post.props" />
|
||||
</Project>
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>$id</id>
|
||||
<version>$version</version>
|
||||
<title>PGO Database</title>
|
||||
<authors>Microsoft</authors>
|
||||
<owners>Microsoft</owners>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<description>PGO Database</description>
|
||||
<releaseNotes>Initial release</releaseNotes>
|
||||
<copyright>Copyright 2021</copyright>
|
||||
</metadata>
|
||||
<files>
|
||||
<file target="build\PGO.targets" src="build\PGO.targets"/>
|
||||
<file target="tools\x64\" src="tools\x64\*.pgd"/>
|
||||
</files>
|
||||
</package>
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. See LICENSE in the project root for license information. -->
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<PlatformShortName Condition="'$(PlatformShortName)'==''">$(Platform)</PlatformShortName>
|
||||
<PlatformShortName Condition="'$(PlatformShortName)'=='Win32'">x86</PlatformShortName>
|
||||
<PlatformShortName Condition="'$(PlatformShortName)'=='AnyCPU' and '$(Prefer32Bit)'==''">x64</PlatformShortName>
|
||||
<PlatformShortName Condition="'$(PlatformShortName)'=='AnyCPU' and '$(Prefer32Bit)'=='true'">x64</PlatformShortName>
|
||||
<PlatformShortName Condition="'$(PlatformShortName)'=='AnyCPU' and '$(Prefer32Bit)'=='false'">x64</PlatformShortName>
|
||||
<ProfileGuidedDatabaseFileName>$(MSBuildThisFileDirectory)..\tools\$(PlatformShortName)\$(TargetName).pgd</ProfileGuidedDatabaseFileName>
|
||||
</PropertyGroup>
|
||||
<!-- Enable PGO optimization only for if the pgds file exists. -->
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)' == 'Release' and '$(PGOBuildMode)' == 'Optimize' and Exists('$(ProfileGuidedDatabaseFileName)')">
|
||||
<Link>
|
||||
<LinkTimeCodeGeneration>PGUpdate</LinkTimeCodeGeneration>
|
||||
<ProfileGuidedDatabase>$(ProfileGuidedDatabaseFileName)</ProfileGuidedDatabase>
|
||||
<AdditionalOptions>/force:pgorepro %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
</Project>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. See LICENSE in the project root for license information. -->
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Globals">
|
||||
<PGODatabaseId>$id</PGODatabaseId>
|
||||
<PGODatabaseVersion>$version</PGODatabaseVersion>
|
||||
</PropertyGroup>
|
||||
</Project>
|
|
@ -0,0 +1,7 @@
|
|||
$pgoBranch = "main"
|
||||
$packageId = "Microsoft.Internal.Windows.Terminal.PGODatabase"
|
||||
|
||||
# Get release version
|
||||
[xml] $customProps = ( Get-Content "..\..\custom.props" )
|
||||
$releaseVersionMajor = ( [int]::Parse( $customProps.GetElementsByTagName("VersionMajor").'#text' ) )
|
||||
$releaseVersionMinor = ( [int]::Parse( $customProps.GetElementsByTagName("VersionMinor").'#text' ) )
|
|
@ -0,0 +1,11 @@
|
|||
Param(
|
||||
[Parameter(Mandatory = $true, Position = 1)] [string] $templatePath,
|
||||
[Parameter(Mandatory = $true, Position = 2)] [string] $outputPath)
|
||||
|
||||
. .\version.ps1
|
||||
. .\template.ps1
|
||||
. .\config.ps1
|
||||
|
||||
$version = FormatVersion ( MakeVersion $releaseVersionMajor $releaseVersionMinor ( GetDatetimeStamp $pgoBranch ) )
|
||||
Write-Host ( "PGO INSTRUMENT: generating {0} version {1}" -f $packageId, $version )
|
||||
FillOut-Template $templatePath $outputPath @{ "version" = $version; "id" = $packageId }
|
|
@ -0,0 +1,49 @@
|
|||
# Profile Guided Optimization
|
||||
|
||||
**NOTE: All PGO work builds on work from Microsoft/Microsoft-UI-XAML**
|
||||
|
||||
## Description
|
||||
|
||||
We generate PGO database NuGet package which is versioned based on product release version and branch name/time stamp of the code that was used for instrumentation and training. In CI/release builds an initialization step enumerates all available versions, filters out those for other releases and branches. Given a list of applicable versions, it will find the one that is closest (BEFORE) the time-stamp of the last commit or a fork-point from instrumented branch. That package version will be installed and version references will be updated. The PGO branch is determined by variable $pgoBranch in tools/PGODatabase/config.ps1. It will need to be updated if a forked branch should be PGO'd.
|
||||
|
||||
## Scenarios
|
||||
|
||||
For the purpose of illustration, let’s assume the following is a chronological list of check-ins to two branches (main and release/2.4). Some of them have had instrumentation/training run done on them and have generated PGO NuGets (version numbers in parentheses). To simplify, let’s assume that release major and minor versions are the same for all check-in as they merely act as filters for what versions are considered to be available.
|
||||
|
||||
1b27fd5f -- main --
|
||||
7b303f74 -- main --
|
||||
930ff585 -- main -- 2.4.2001312227-main
|
||||
63948a75 -- main --
|
||||
0d379b51 -- main --
|
||||
f23f1fad -- main -- 2.4.2001312205-main
|
||||
bcf9adaa -- main --
|
||||
6ef44a23 -- main --
|
||||
310bc133 -- release/2.4 --
|
||||
80a4ab55 -- release/2.4 -- 2.4.2001312054-release_2_4
|
||||
18b956f6 -- release/2.4 --
|
||||
4abd4d54 -- main -- 2.4.2001312033-main
|
||||
d150eae0 -- main -- 2.4.2001312028-main
|
||||
|
||||
### Optimizing on PGO’d branch
|
||||
|
||||
If we are building on main (which in this example is PGO’d), the version picked will be the one that has the same major and minor versions AND branch name and is the same or is right before the SHA being built.
|
||||
|
||||
E.g.
|
||||
|
||||
1b27fd5f -- 2.4.2001312227-main
|
||||
f23f1fad -- 2.4.2001312205-main
|
||||
bcf9adaa -- 2.4.2001312033-main
|
||||
|
||||
### Optimizing release branch
|
||||
|
||||
A branch which will be PGO’d requires a slightly different handling. Let’s say release/2.4 forked from main on commit 4abd4d54. Initially, it will be configured to track main and 18b956f6 will be optimized with 2.4.2001312033-main. When the configuration is changed to start tracking release/2.4 (change branch name $pgoBranch in tools/PGODatabase/config.ps1 script), it will start tracking its own branch.
|
||||
|
||||
E.g.
|
||||
|
||||
18b956f6 -- if tracking main -> 2.4.2001312033-main,
|
||||
if tracking release/2.4 -> ERROR (no database exists)
|
||||
310bc133 -- 2.4.2001312054-release_2_4
|
||||
|
||||
### Optimizing topic branch
|
||||
|
||||
Assuming topic branch will not have a training run done, it can still use database from branch it was forked from. Let’s say we have a branch which was forked from main on 4abd4d54. If we don’t change which branch it’s tracking, it will keep using 2.4.2001312033-main. Merging main on f23f1fad into topic branch, will change used database to 2.4.2001312205-main.
|
|
@ -0,0 +1,47 @@
|
|||
. .\version.ps1
|
||||
. .\template.ps1
|
||||
. .\config.ps1
|
||||
|
||||
$feedUri = "https://pkgs.dev.azure.com/ms/terminal/_packaging/TerminalDependencies/nuget/v2"
|
||||
|
||||
$currentVersion = MakeVersion $releaseVersionMajor $releaseVersionMinor ( GetDatetimeStamp $pgoBranch )
|
||||
|
||||
Write-Host ( "PGO OPTIMIZE: requesting {0} version {1}" -f $packageId, ( FormatVersion $currentVersion ) )
|
||||
|
||||
$packageSource = Register-PackageSource -ForceBootstrap -Name TerminalDependencies -Location $feedUri -ProviderName NuGet -Trusted
|
||||
$packages = ( Find-Package $packageId -Source TerminalDependencies -AllowPrereleaseVersions -AllVersions ) | Sort-Object -Property Version -Descending
|
||||
|
||||
$best = $null
|
||||
|
||||
foreach ( $existing in $packages )
|
||||
{
|
||||
$existingVersion = MakeVersionFromString $existing.Version
|
||||
|
||||
if ( ( CompareBranches $existingVersion $currentVersion ) -eq $False -or
|
||||
( CompareReleases $existingVersion $currentVersion ) -ne 0 )
|
||||
{
|
||||
# If this is different release or branch, then skip it.
|
||||
continue
|
||||
}
|
||||
|
||||
if ( ( CompareRevisions $existingVersion $currentVersion ) -le 0 )
|
||||
{
|
||||
# Version are sorted in descending order, the first one less than or equal to the current is the one we want.
|
||||
# NOTE: at this point the only difference between versions will be revision (date-time stamp)
|
||||
# which is formatted as a fixed-length string, so string comparison WILL sort it correctly.
|
||||
$best = $existing
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if ( $best -eq $null )
|
||||
{
|
||||
throw "Appropriate database cannot be found"
|
||||
}
|
||||
|
||||
Write-Host ( "PGO OPTIMIZE: picked {0} version {1}" -f $packageId, $best.Version )
|
||||
|
||||
$best | Install-Package -Destination ..\..\packages -Force
|
||||
$packageSource | Unregister-PackageSource
|
||||
|
||||
FillOut-Template "PGO.version.props.template" "PGO.version.props" @{ "version" = $best.Version; "id" = $packageId }
|
|
@ -0,0 +1,16 @@
|
|||
function Replace-Many ( $string, $dictionary )
|
||||
{
|
||||
foreach ( $key in $dictionary.Keys )
|
||||
{
|
||||
$field = '$' + $key.ToString()
|
||||
$string = $string.Replace( $field, $dictionary[$key].ToString() )
|
||||
}
|
||||
|
||||
return $string
|
||||
}
|
||||
|
||||
function FillOut-Template ( $inputPath, $outputPath, $dictionary )
|
||||
{
|
||||
$replaced = Replace-Many ( Get-Content $inputPath ) $dictionary
|
||||
Write-Output $replaced | Set-Content $outputPath -Force | Out-Null
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
Param(
|
||||
[Parameter(Mandatory = $true, Position = 1)]
|
||||
[string] $module)
|
||||
|
||||
if ( !( Test-Path $module ) )
|
||||
{
|
||||
throw "File does not exist $module"
|
||||
}
|
||||
|
||||
$vsPath = &(Join-Path ${env:ProgramFiles(x86)} "\Microsoft Visual Studio\Installer\vswhere.exe") -property installationpath
|
||||
Import-Module (Get-ChildItem $vsPath -Recurse -File -Filter Microsoft.VisualStudio.DevShell.dll).FullName
|
||||
Enter-VsDevShell -VsInstallPath $vsPath -SkipAutomaticLocation
|
||||
|
||||
$output = ( & link.exe /dump /headers /coffgroup $module )
|
||||
|
||||
$regex1 = [regex] '^\s*[A-F0-9]+ coffgrp(\s+[A-F0-9]+){4} \(PGU\)$'
|
||||
$regex2 = [regex] '^\s*([A-F0-9]+\s+){2}\.text\$zz$'
|
||||
|
||||
$matchFlags = 0
|
||||
|
||||
foreach ( $line in $output )
|
||||
{
|
||||
if ( $line -match $regex1 )
|
||||
{
|
||||
$matchFlags = $matchFlags -bor 1
|
||||
}
|
||||
|
||||
if ( $line -match $regex2 )
|
||||
{
|
||||
$matchFlags = $matchFlags -bor 2
|
||||
}
|
||||
}
|
||||
|
||||
$optimized = $matchFlags -eq 3
|
||||
|
||||
$message = "$module is $( if ( $optimized ) { "optimized" } else { "not optimized" } )"
|
||||
|
||||
if ( -not $optimized )
|
||||
{
|
||||
throw $message
|
||||
}
|
||||
else
|
||||
{
|
||||
write-host $message
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
function MakeVersion ( $major, $minor, $datetimeStamp )
|
||||
{
|
||||
$revision, $branch = $datetimeStamp.Split("-")
|
||||
|
||||
if ( $branch -eq $null )
|
||||
{
|
||||
$branch = ""
|
||||
}
|
||||
|
||||
return [PSCustomObject] @{
|
||||
Major = $major
|
||||
Minor = $minor
|
||||
Revision = $revision
|
||||
Branch = $branch
|
||||
}
|
||||
}
|
||||
|
||||
function MakeVersionFromString ( $str )
|
||||
{
|
||||
$parts = $str.Split(".")
|
||||
return MakeVersion ( [int]::Parse($parts[0]) ) ( [int]::Parse($parts[1]) ) $parts[2]
|
||||
}
|
||||
|
||||
function FormatVersion ( $version )
|
||||
{
|
||||
$branch = ""
|
||||
|
||||
if ( $version.Branch -ne "" )
|
||||
{
|
||||
$branch = "-{0}" -f $version.Branch
|
||||
}
|
||||
|
||||
return "{0}.{1}.{2}{3}" -f $version.Major, $version.Minor, $version.Revision, $branch
|
||||
}
|
||||
|
||||
function CompareReleases ( $version1, $version2 )
|
||||
{
|
||||
$cmpMajor = [Math]::Sign($version1.Major - $version2.Major)
|
||||
|
||||
if ( $cmpMajor -ne 0 )
|
||||
{
|
||||
return $cmpMajor
|
||||
}
|
||||
|
||||
return [Math]::Sign($version1.Minor - $version2.Minor)
|
||||
}
|
||||
|
||||
function CompareRevisions ( $version1, $version2 )
|
||||
{
|
||||
return [Math]::Sign($version1.Revision - $version2.Revision)
|
||||
}
|
||||
|
||||
function CompareBranches ( $version1, $version2 )
|
||||
{
|
||||
return $version1.Branch -eq $version2.Branch
|
||||
}
|
||||
|
||||
function GetDatetimeStamp ( $pgoBranch )
|
||||
{
|
||||
$forkSHA = $( git merge-base origin/$pgoBranch HEAD )
|
||||
|
||||
if ( $LastExitCode -ne 0 )
|
||||
{
|
||||
throw "FAILED: git merge-base"
|
||||
}
|
||||
|
||||
$forkDate = ( Get-Date -Date $( git log -1 $forkSHA --date=iso --pretty=format:"%ad" ) ).ToUniversalTime().ToString("yyMMddHHmm")
|
||||
|
||||
if ( $LastExitCode -ne 0 )
|
||||
{
|
||||
throw "FAILED: Get forkDate"
|
||||
}
|
||||
|
||||
return $forkDate + "-" + $pgoBranch.Replace("/", "_").Replace("-", "_").Replace(".", "_")
|
||||
}
|
Loading…
Reference in New Issue