diff --git a/.gitattributes b/.gitattributes
index 7003c01..3b18559 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -15,7 +15,7 @@
LICENSE text
# Projects and solutions
-*.sln text
+*.sln binary
*.csproj text
*.wixproj text
diff --git a/.hgeol b/.hgeol
index 67fdd71..5d5447a 100644
--- a/.hgeol
+++ b/.hgeol
@@ -1,37 +1,8 @@
[patterns]
-# Non human-editable files are binary
-
-**.dsp = BIN
-**.dsw = BIN
-**.mk = BIN
**.sln = BIN
-**.vcproj = BIN
-**.vsprops = BIN
-
-**.aif = BIN
-**.aifc = BIN
-**.aiff = BIN
-**.au = BIN
-**.bmp = BIN
-**.db = BIN
-**.exe = BIN
-**.icns = BIN
-**.gif = BIN
**.ico = BIN
-**.info = BIN
-**.jpg = BIN
-**.pck = BIN
-**.png = BIN
-**.psd = BIN
-**.tar = BIN
-**.wav = BIN
-**.whl = BIN
-**.xar = BIN
-**.zip = BIN
-
-# Windows batch files work best with CRLF, there can be subtle problems with LF
-**.bat = CRLF
+**.snk = BIN
# All other files (which presumably are human-editable) are "native".
# This must be the last rule!
diff --git a/Build/BuildReleaseHelpers.psm1 b/Build/BuildReleaseHelpers.psm1
index 82a8829..e663a83 100644
--- a/Build/BuildReleaseHelpers.psm1
+++ b/Build/BuildReleaseHelpers.psm1
@@ -1,240 +1,240 @@
-function submit_symbols {
- param($buildname, $buildid, $filetype, $sourcedir, $contacts)
-
- $request = `
- "BuildId=$buildid $filetype
- BuildLabPhone=7058786
- BuildRemark=$buildname
- ContactPeople=$contacts
- Directory=$sourcedir
- Project=TechnicalComputing
- Recursive=yes
- StatusMail=$contacts
- UserName=$env:username"
-
- Write-Output "*** Symbol Submission Text ***
-$request"
-
- $request | Out-File -Encoding ascii -FilePath request_$filetype.txt
- \\symbols\tools\createrequest.cmd -i request_$filetype.txt -d .\SymSrvRequestLogs -c -s
-}
-
-function _find_sdk_tool {
- param($tool)
-
- $_tool_item = ""
- foreach ($ver in ("v8.1A", "v8.0A")) {
- foreach ($kit in ("WinSDK-NetFx40Tools-x64", "WinSDK-NetFx40Tools-x86", "WinSDK-NetFx40Tools")) {
- $_kit_path = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Microsoft SDKs\Windows\$ver\$kit" -EA 0)
- if (-not $_kit_path) {
- $_kit_path = (Get-ItemProperty "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\$ver\$kit" -EA 0)
- }
-
- if ($_kit_path -and (Test-Path $_kit_path.InstallationFolder)) {
- $_tool_item = Get-Item "$($_kit_path.InstallationFolder)\$tool.exe" -EA 0
- if (-not (Test-Path alias:\$tool) -and $_tool_item) {
- Set-Alias -Name $tool -Value $_tool_item.FullName -Scope Global
- return
- }
- }
- }
- }
- foreach ($ver in ("KitsRoot81", "KitsRoot")) {
- $_kit_path = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots" -Name $ver -EA 0).$ver
- if (-not $_kit_path) {
- $_kit_path = (Get-ItemProperty "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows Kits\Installed Roots" -Name $ver -EA 0).$ver
- }
-
- foreach ($kit in ("x64", "x86")) {
- if ($_kit_path -and (Test-Path "$_kit_path\bin\$kit")) {
- $_tool_item = Get-Item "$_kit_path\bin\$kit\$tool.exe" -EA 0
- if (-not (Test-Path alias:\$tool) -and $_tool_item) {
- Set-Alias -Name $tool -Value $_tool_item.FullName -Scope Global
- return
- }
- }
- }
- }
-}
-
-function begin_sign_files {
- param($files, $outdir, $approvers, $projectName, $projectUrl, $jobDescription, $jobKeywords, $certificates, [switch] $delaysigned)
-
- if ($files.Count -eq 0) {
- return
- }
-
- if ($delaysigned) {
- # Ensure that all files are delay-signed
- # "sn -q -v ..." is true if the assembly has strong name and skip verification
- _find_sdk_tool "sn"
- if (Test-Path alias:\sn) {
- $not_delay_signed = $files | %{ gi $_.path } | ?{ sn -q -v $_ }
- if ($not_delay_signed) {
- Throw "Delay-signed check failed: $($not_delay_signed.Name -join '
-')"
- }
- }
- }
-
- [Reflection.Assembly]::Load("CODESIGN.Submitter, Version=3.0.0.6, Culture=neutral, PublicKeyToken=3d8252bd1272440d, processorArchitecture=MSIL") | Out-Null
- [Reflection.Assembly]::Load("CODESIGN.PolicyManager, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3d8252bd1272440d, processorArchitecture=MSIL") | Out-Null
-
- while ($True) {
- try {
- $job = [CODESIGN.Submitter.Job]::Initialize("codesign.gtm.microsoft.com", 9556, $True)
- $job.Description = $jobDescription
- $job.Keywords = $jobKeywords
-
- if ($certificates -match "authenticode") {
- $job.SelectCertificate("10006") # Authenticode
- }
- if ($certificates -match "strongname") {
- $job.SelectCertificate("67") # StrongName key
- }
- if ($certificates -match "opc") {
- $job.SelectCertificate("160") # Microsoft OPC Publisher (VSIX)
- }
-
- foreach ($approver in $approvers) {
- $job.AddApprover($approver)
- }
-
- foreach ($file in $files) {
- $job.AddFile($file.path, $file.name, $projectUrl, [CODESIGN.JavaPermissionsTypeEnum]::None)
- }
-
- $job.Send()
- return @{job=$job; description=$jobDescription; filecount=$($files.Count); outdir=$outdir}
- } catch [Exception] {
- echo $_.Exception.Message
- sleep 60
- }
- }
-}
-
-function end_sign_files {
- param($jobs)
-
- if ($jobs.Count -eq 0) {
- return
- }
-
- foreach ($jobinfo in $jobs) {
- $job = $jobinfo.job
- if($job -eq $null) {
- throw "jobinfo in unexpected format $jobinfo"
- }
- $filecount = $jobinfo.filecount
- $outdir = $jobinfo.outdir
- $activity = "Processing $($jobinfo.description) (Job ID $($job.JobID))"
- $percent = 0
- $jobCompletionPath = $job.JobCompletionPath
-
- if([string]::IsNullOrWhiteSpace($jobCompletionPath)) {
- throw "job.JobCompletionPath is not valid: $job.JobCompletionPath"
- }
-
- do {
- $files = dir $jobCompletionPath
- Write-Progress -activity $activity -status "Waiting for completion: $jobCompletionPath" -percentcomplete $percent;
- $percent = ($percent + 1) % 100
- sleep -seconds 5
- } while(-not $files -or $files.Count -ne $filecount);
-
- mkdir $outdir -EA 0 | Out-Null
- Write-Progress -Activity $activity -Completed
-
- Write-Output "Copying from $jobCompletionPath to $outdir"
- $retries = 9
- $delay = 2
- $copied = $null
- while ($retries) {
- try {
- $copied = (Copy-Item -path $jobCompletionPath\* -dest $outdir -Force -PassThru)
- break
- } catch {
- if ($retries -eq 0) {
- break
- }
- Write-Warning "Failed to copy - retrying in $delay seconds ($retries tries remaining)"
- Sleep -seconds $delay
- --$retries
- $delay += $delay
- }
- }
- if (-not $copied) {
- Throw "Failed to copy $jobCompletionPath to $outdir"
- } else {
- Write-Output "Copied $($copied.Count) files"
- }
- }
-}
-
-function start_virus_scan {
- param($description, $contact, $path)
-
- $xml = New-Object XML
- $xml.LoadXml("AOC")
- $xml.root.description = $description
- $xml.root.contact = $contact
- $xml.root.path = $path
-
- Invoke-WebRequest "http://vcs/process.asp" -Method Post -Body $xml -ContentType "text/xml" -UseDefaultCredentials -UseBasicParsing
-}
-
-function check_signing {
- param($outdir)
-
- _find_sdk_tool "signtool"
-
- $unsigned = @()
-
- $msis = gci $outdir\*.msi
- foreach ($m in $msis) {
- Write-Host "Checking signatures for $m"
- & signtool verify /pa "$m" 2>&1 | Out-Null
- if (-not $?) {
- $unsigned += "$m"
- }
-
- $dir = mkdir -fo "${env:TEMP}\msi_test"
- & msiexec /q /a "$m" TARGETDIR="$dir" | Out-Null
-
- foreach ($f in (gci $dir\*.exe, $dir\*.dll -r)) {
- & signtool verify /pa "$f" 2>&1 | Out-Null
- if (-not $?) {
- $unsigned += "$m - $($f.Name)"
- }
- }
-
- rmdir -r -fo $dir
- }
-
- Add-Type -assembly "System.IO.Compression.FileSystem"
- $zips = gci $outdir\*.vsix
- foreach ($m in $zips) {
- Write-Host "Checking signatures for $m"
- $dir = mkdir -fo "${env:TEMP}\msi_test"
- [IO.Compression.ZipFile]::ExtractToDirectory($m, $dir)
-
- if (-not (Test-Path "$dir\package\services\digital-signature\xml-signature")) {
- $unsigned += "$m"
- }
-
- foreach ($f in (gci $dir\*.exe, $dir\*.dll -r)) {
- & signtool verify /pa "$f" 2>&1 | Out-Null
- if (-not $?) {
- $unsigned += "$m - $($f.Name)"
- }
- }
-
- rmdir -r -fo $dir
- }
-
- if ($unsigned) {
- throw "Following files have invalid signatures:
-$(($unsigned | select -unique) -join '
-')"
- }
+function submit_symbols {
+ param($buildname, $buildid, $filetype, $sourcedir, $contacts)
+
+ $request = `
+ "BuildId=$buildid $filetype
+ BuildLabPhone=7058786
+ BuildRemark=$buildname
+ ContactPeople=$contacts
+ Directory=$sourcedir
+ Project=TechnicalComputing
+ Recursive=yes
+ StatusMail=$contacts
+ UserName=$env:username"
+
+ Write-Output "*** Symbol Submission Text ***
+$request"
+
+ $request | Out-File -Encoding ascii -FilePath request_$filetype.txt
+ \\symbols\tools\createrequest.cmd -i request_$filetype.txt -d .\SymSrvRequestLogs -c -s
+}
+
+function _find_sdk_tool {
+ param($tool)
+
+ $_tool_item = ""
+ foreach ($ver in ("v8.1A", "v8.0A")) {
+ foreach ($kit in ("WinSDK-NetFx40Tools-x64", "WinSDK-NetFx40Tools-x86", "WinSDK-NetFx40Tools")) {
+ $_kit_path = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Microsoft SDKs\Windows\$ver\$kit" -EA 0)
+ if (-not $_kit_path) {
+ $_kit_path = (Get-ItemProperty "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\$ver\$kit" -EA 0)
+ }
+
+ if ($_kit_path -and (Test-Path $_kit_path.InstallationFolder)) {
+ $_tool_item = Get-Item "$($_kit_path.InstallationFolder)\$tool.exe" -EA 0
+ if (-not (Test-Path alias:\$tool) -and $_tool_item) {
+ Set-Alias -Name $tool -Value $_tool_item.FullName -Scope Global
+ return
+ }
+ }
+ }
+ }
+ foreach ($ver in ("KitsRoot81", "KitsRoot")) {
+ $_kit_path = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots" -Name $ver -EA 0).$ver
+ if (-not $_kit_path) {
+ $_kit_path = (Get-ItemProperty "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows Kits\Installed Roots" -Name $ver -EA 0).$ver
+ }
+
+ foreach ($kit in ("x64", "x86")) {
+ if ($_kit_path -and (Test-Path "$_kit_path\bin\$kit")) {
+ $_tool_item = Get-Item "$_kit_path\bin\$kit\$tool.exe" -EA 0
+ if (-not (Test-Path alias:\$tool) -and $_tool_item) {
+ Set-Alias -Name $tool -Value $_tool_item.FullName -Scope Global
+ return
+ }
+ }
+ }
+ }
+}
+
+function begin_sign_files {
+ param($files, $outdir, $approvers, $projectName, $projectUrl, $jobDescription, $jobKeywords, $certificates, [switch] $delaysigned)
+
+ if ($files.Count -eq 0) {
+ return
+ }
+
+ if ($delaysigned) {
+ # Ensure that all files are delay-signed
+ # "sn -q -v ..." is true if the assembly has strong name and skip verification
+ _find_sdk_tool "sn"
+ if (Test-Path alias:\sn) {
+ $not_delay_signed = $files | %{ gi $_.path } | ?{ sn -q -v $_ }
+ if ($not_delay_signed) {
+ Throw "Delay-signed check failed: $($not_delay_signed.Name -join '
+')"
+ }
+ }
+ }
+
+ [Reflection.Assembly]::Load("CODESIGN.Submitter, Version=3.0.0.6, Culture=neutral, PublicKeyToken=3d8252bd1272440d, processorArchitecture=MSIL") | Out-Null
+ [Reflection.Assembly]::Load("CODESIGN.PolicyManager, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3d8252bd1272440d, processorArchitecture=MSIL") | Out-Null
+
+ while ($True) {
+ try {
+ $job = [CODESIGN.Submitter.Job]::Initialize("codesign.gtm.microsoft.com", 9556, $True)
+ $job.Description = $jobDescription
+ $job.Keywords = $jobKeywords
+
+ if ($certificates -match "authenticode") {
+ $job.SelectCertificate("10006") # Authenticode
+ }
+ if ($certificates -match "strongname") {
+ $job.SelectCertificate("67") # StrongName key
+ }
+ if ($certificates -match "opc") {
+ $job.SelectCertificate("160") # Microsoft OPC Publisher (VSIX)
+ }
+
+ foreach ($approver in $approvers) {
+ $job.AddApprover($approver)
+ }
+
+ foreach ($file in $files) {
+ $job.AddFile($file.path, $file.name, $projectUrl, [CODESIGN.JavaPermissionsTypeEnum]::None)
+ }
+
+ $job.Send()
+ return @{job=$job; description=$jobDescription; filecount=$($files.Count); outdir=$outdir}
+ } catch [Exception] {
+ echo $_.Exception.Message
+ sleep 60
+ }
+ }
+}
+
+function end_sign_files {
+ param($jobs)
+
+ if ($jobs.Count -eq 0) {
+ return
+ }
+
+ foreach ($jobinfo in $jobs) {
+ $job = $jobinfo.job
+ if($job -eq $null) {
+ throw "jobinfo in unexpected format $jobinfo"
+ }
+ $filecount = $jobinfo.filecount
+ $outdir = $jobinfo.outdir
+ $activity = "Processing $($jobinfo.description) (Job ID $($job.JobID))"
+ $percent = 0
+ $jobCompletionPath = $job.JobCompletionPath
+
+ if([string]::IsNullOrWhiteSpace($jobCompletionPath)) {
+ throw "job.JobCompletionPath is not valid: $job.JobCompletionPath"
+ }
+
+ do {
+ $files = dir $jobCompletionPath
+ Write-Progress -activity $activity -status "Waiting for completion: $jobCompletionPath" -percentcomplete $percent;
+ $percent = ($percent + 1) % 100
+ sleep -seconds 5
+ } while(-not $files -or $files.Count -ne $filecount);
+
+ mkdir $outdir -EA 0 | Out-Null
+ Write-Progress -Activity $activity -Completed
+
+ Write-Output "Copying from $jobCompletionPath to $outdir"
+ $retries = 9
+ $delay = 2
+ $copied = $null
+ while ($retries) {
+ try {
+ $copied = (Copy-Item -path $jobCompletionPath\* -dest $outdir -Force -PassThru)
+ break
+ } catch {
+ if ($retries -eq 0) {
+ break
+ }
+ Write-Warning "Failed to copy - retrying in $delay seconds ($retries tries remaining)"
+ Sleep -seconds $delay
+ --$retries
+ $delay += $delay
+ }
+ }
+ if (-not $copied) {
+ Throw "Failed to copy $jobCompletionPath to $outdir"
+ } else {
+ Write-Output "Copied $($copied.Count) files"
+ }
+ }
+}
+
+function start_virus_scan {
+ param($description, $contact, $path)
+
+ $xml = New-Object XML
+ $xml.LoadXml("AOC")
+ $xml.root.description = $description
+ $xml.root.contact = $contact
+ $xml.root.path = $path
+
+ Invoke-WebRequest "http://vcs/process.asp" -Method Post -Body $xml -ContentType "text/xml" -UseDefaultCredentials -UseBasicParsing
+}
+
+function check_signing {
+ param($outdir)
+
+ _find_sdk_tool "signtool"
+
+ $unsigned = @()
+
+ $msis = gci $outdir\*.msi
+ foreach ($m in $msis) {
+ Write-Host "Checking signatures for $m"
+ & signtool verify /pa "$m" 2>&1 | Out-Null
+ if (-not $?) {
+ $unsigned += "$m"
+ }
+
+ $dir = mkdir -fo "${env:TEMP}\msi_test"
+ & msiexec /q /a "$m" TARGETDIR="$dir" | Out-Null
+
+ foreach ($f in (gci $dir\*.exe, $dir\*.dll -r)) {
+ & signtool verify /pa "$f" 2>&1 | Out-Null
+ if (-not $?) {
+ $unsigned += "$m - $($f.Name)"
+ }
+ }
+
+ rmdir -r -fo $dir
+ }
+
+ Add-Type -assembly "System.IO.Compression.FileSystem"
+ $zips = gci $outdir\*.vsix
+ foreach ($m in $zips) {
+ Write-Host "Checking signatures for $m"
+ $dir = mkdir -fo "${env:TEMP}\msi_test"
+ [IO.Compression.ZipFile]::ExtractToDirectory($m, $dir)
+
+ if (-not (Test-Path "$dir\package\services\digital-signature\xml-signature")) {
+ $unsigned += "$m"
+ }
+
+ foreach ($f in (gci $dir\*.exe, $dir\*.dll -r)) {
+ & signtool verify /pa "$f" 2>&1 | Out-Null
+ if (-not $?) {
+ $unsigned += "$m - $($f.Name)"
+ }
+ }
+
+ rmdir -r -fo $dir
+ }
+
+ if ($unsigned) {
+ throw "Following files have invalid signatures:
+$(($unsigned | select -unique) -join '
+')"
+ }
}
\ No newline at end of file
diff --git a/Build/BuildReleaseMockHelpers.psm1 b/Build/BuildReleaseMockHelpers.psm1
index 7293654..abe9f97 100644
--- a/Build/BuildReleaseMockHelpers.psm1
+++ b/Build/BuildReleaseMockHelpers.psm1
@@ -1,277 +1,277 @@
-function submit_symbols {
- param($buildname, $buildid, $filetype, $sourcedir, $contacts)
-
- Write-Debug "*** Symbol Submission Text ***
- BuildId=$buildid $filetype
- BuildLabPhone=7058786
- BuildRemark=$buildname
- ContactPeople=$contacts
- Directory=$sourcedir
- Project=TechnicalComputing
- Recursive=yes
- StatusMail=$contacts
- UserName=$env:username"
-}
-
-function _find_sdk_tool {
- param($tool)
-
- $_tool_item = ""
- foreach ($ver in ("v8.1A", "v8.0A")) {
- foreach ($kit in ("WinSDK-NetFx40Tools-x64", "WinSDK-NetFx40Tools-x86", "WinSDK-NetFx40Tools")) {
- $_kit_path = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Microsoft SDKs\Windows\$ver\$kit" -EA 0)
- if (-not $_kit_path) {
- $_kit_path = (Get-ItemProperty "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\$ver\$kit" -EA 0)
- }
-
- if ($_kit_path -and (Test-Path $_kit_path.InstallationFolder)) {
- $_tool_item = Get-Item "$($_kit_path.InstallationFolder)\$tool.exe" -EA 0
- if (-not (Test-Path alias:\$tool) -and $_tool_item) {
- Set-Alias -Name $tool -Value $_tool_item.FullName -Scope Global
- }
- }
- }
- }
- foreach ($ver in ("KitsRoot81", "KitsRoot")) {
- $_kit_path = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots" -Name $ver -EA 0).$ver
- if (-not $_kit_path) {
- $_kit_path = (Get-ItemProperty "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows Kits\Installed Roots" -Name $ver -EA 0).$ver
- }
-
- foreach ($kit in ("x64", "x86")) {
- if ($_kit_path -and (Test-Path "$_kit_path\bin\$kit")) {
- $_tool_item = Get-Item "$_kit_path\bin\$kit\$tool.exe" -EA 0
- if (-not (Test-Path alias:\$tool) -and $_tool_item) {
- Set-Alias -Name $tool -Value $_tool_item.FullName -Scope Global
- return
- }
- }
- }
- }
-}
-
-function begin_sign_files {
- param($files, $outdir, $approvers, $projectName, $projectUrl, $jobDescription, $jobKeywords, $certificates, [switch] $delaysigned)
-
- if ($files.Count -eq 0) {
- return
- }
-
- if ($delaysigned) {
- # Ensure that all files are delay-signed
- # "sn -q -v ..." is true if the assembly has strong name and skip verification
- _find_sdk_tool "sn"
- if (Test-Path alias:\sn) {
- $not_delay_signed = $files | %{ gi $_.path } | ?{ sn -q -v $_ }
- if ($not_delay_signed) {
- Throw "Delay-signed check failed: $($not_delay_signed.Name -join '
-')
-You may need to skip strong name verification on this machine."
- }
- }
- }
-
- [Reflection.Assembly]::Load("CODESIGN.Submitter, Version=3.0.0.6, Culture=neutral, PublicKeyToken=3d8252bd1272440d, processorArchitecture=MSIL") | Out-Null
- [Reflection.Assembly]::Load("CODESIGN.PolicyManager, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3d8252bd1272440d, processorArchitecture=MSIL") | Out-Null
-
- $job = [CODESIGN.Submitter.Job]::Initialize("codesign.gtm.microsoft.com", 9556, $True)
- $msg = "*** Signing Job Details ***
-job.Description: $jobDescription
-job.Keywords: $jobKeywords"
- $job.Description = $jobDescription
- $job.Keywords = $jobKeywords
-
- if ($certificates -match "authenticode") {
- $msg = "$msg
-job.SelectCertificate(10006)"
- $job.SelectCertificate("10006") # Authenticode
- }
- if ($certificates -match "strongname") {
- $msg = "$msg
-job.SelectCertificate(67)"
- $job.SelectCertificate("67") # StrongName key
- }
- if ($certificates -match "opc") {
- $job.SelectCertificate("160") # Microsoft OPC Publisher (VSIX)
- }
-
- foreach ($approver in $approvers) {
- $msg = "$msg
-job.AddApprover($approver)"
- $job.AddApprover($approver)
- }
-
- foreach ($file in $files) {
- $msg = "$msg
-job.AddFile($($file.path), $($file.name), $projectUrl, None)"
- $job.AddFile($file.path, $file.name, $projectUrl, [CODESIGN.JavaPermissionsTypeEnum]::None)
- }
-
- $msg = "$msg
-Returning @{filecount=$($files.Count); outdir=$outdir}"
- Write-Debug $msg
-
- $uniqueJobFolderID = ((Get-Date -format "yyyyMMdd-HHmmss").ToString() + "-" + (Get-Date).Millisecond.ToString())
-
- $folder = ((Get-Item $($files[0].path)).DirectoryName.ToString() + "\MockSigned")
-
- $mockJob = New-Object PSObject
- $mockJob | Add-Member NoteProperty JobID $uniqueJobFolderID
- $mockJob | Add-Member NoteProperty JobMockFolder $folder
- $mockJob | Add-Member NoteProperty JobCompletionPath $folder\$uniqueJobFolderID
-
- $mockFolderPath = $mockJob.JobCompletionPath
- mkdir $mockFolderPath -EA 0 | Out-Null
-
- foreach($file in $files) {
- $destPath = "$($mockFolderPath)\$($fileInfo.Name)"
- copy -path $($file.path) -dest $destPath
- if (-not $?) {
- Write-Output "Failed to copy $($file.path) to $destPath"
- }
- }
-
- return @{rjob=$job; job=$mockJob; description=$jobDescription; filecount=$($files.Count); outdir=$outdir}
-}
-
-function end_sign_files {
- param($jobs)
-
- if ($jobs.Count -eq 0) {
- return
- }
-
- foreach ($jobinfo in $jobs) {
- $job = $jobinfo.job
- if($job -eq $null) {
- throw "jobinfo in unexpected format $jobinfo"
- }
- $filecount = $jobinfo.filecount
- $outdir = $jobinfo.outdir
- $activity = "Processing $($jobinfo.description) (Job ID $($job.JobID))"
- $percent = 0
- $jobCompletionPath = $job.JobCompletionPath
-
- if([string]::IsNullOrWhiteSpace($jobCompletionPath)) {
- throw "job.JobCompletionPath is not valid: $($job.JobCompletionPath)"
- }
-
- do {
- $files = @()
- Write-Progress -activity $activity -status "Waiting for completion: $jobCompletionPath" -percentcomplete $percent;
- $percent = ($percent + 1) % 100
- if ($percent -eq 90) {
- $files = dir $jobCompletionPath
- }
- sleep -Milliseconds 50
- } while(-not $files -or $files.Count -ne $filecount);
-
- mkdir $outdir -EA 0 | Out-Null
- Write-Progress -Activity $activity -Completed
-
- Write-Output "Copying from $jobCompletionPath to $outdir"
- $retries = 9
- $delay = 2
- $copied = $null
- while ($retries) {
- try {
- $copied = (Copy-Item -path $jobCompletionPath\* -dest $outdir -Force -PassThru)
- break
- } catch {
- if ($retries -eq 0) {
- break
- }
- Write-Warning "Failed to copy - retrying in $delay seconds ($retries tries remaining)"
- Sleep -seconds $delay
- --$retries
- $delay += $delay
- }
- }
- if (-not $copied) {
- Throw "Failed to copy $jobCompletionPath to $outdir"
- } else {
- Write-Output "Copied $($copied.Count) files"
- }
-
- #Get rid of the MockSigned directory
- Remove-Item -Recurse $jobCompletionPath\*
- Remove-Item -Recurse $jobCompletionPath
-
- if((Get-Item $($job.JobMockFolder)).GetDirectories().Count -eq 0) {
- Remove-Item -Recurse $($job.JobMockFolder)
- }
- }
-}
-
-function start_virus_scan {
- param($description, $contact, $path)
-
- $xml = New-Object XML
- $xml.LoadXml("AOC")
- $xml.root.description = $description
- $xml.root.contact = $contact
- $xml.root.path = $path
-
- Write-Debug "Posting to http://vcs/process.asp:
-$($xml.OuterXml)"
-}
-
-function check_signing {
- param($outdir)
-
- _find_sdk_tool "signtool"
-
- $unsigned = @()
-
- $msis = gci $outdir\*.msi
- foreach ($m in $msis) {
- Write-Host "Checking signatures for $m"
- & signtool verify /pa "$m" 2>&1 | Out-Null
- # All files should be unsigned
- if ($?) {
- $unsigned += "$m"
- }
-
- $dir = mkdir -fo "${env:TEMP}\msi_test"
- & msiexec /q /a "$m" TARGETDIR="$dir" | Out-Null
-
- foreach ($f in (gci $dir\*.exe, $dir\*.dll -r)) {
- & signtool verify /pa "$f" 2>&1 | Out-Null
- # All files should be unsigned
- if ($?) {
- $unsigned += "$m - $($f.Name)"
- }
- }
-
- rmdir -r -fo $dir
- }
-
- Add-Type -assembly "System.IO.Compression.FileSystem"
- $zips = gci $outdir\*.vsix
- foreach ($m in $zips) {
- Write-Host "Checking signatures for $m"
- $dir = mkdir -fo "${env:TEMP}\msi_test"
- [IO.Compression.ZipFile]::ExtractToDirectory($m, $dir)
-
- # All files should be unsigned
- if ((Test-Path "$dir\package\services\digital-signature\xml-signature")) {
- $unsigned += "$m"
- }
-
- foreach ($f in (gci $dir\*.exe, $dir\*.dll -r)) {
- & signtool verify /pa "$f" 2>&1 | Out-Null
- # All files should be unsigned
- if ($?) {
- $unsigned += "$m - $($f.Name)"
- }
- }
-
- rmdir -r -fo $dir
- }
-
- if ($unsigned) {
- throw "Following files have invalid signatures:
-$(($unsigned | select -unique) -join '
-')"
- }
-}
+function submit_symbols {
+ param($buildname, $buildid, $filetype, $sourcedir, $contacts)
+
+ Write-Debug "*** Symbol Submission Text ***
+ BuildId=$buildid $filetype
+ BuildLabPhone=7058786
+ BuildRemark=$buildname
+ ContactPeople=$contacts
+ Directory=$sourcedir
+ Project=TechnicalComputing
+ Recursive=yes
+ StatusMail=$contacts
+ UserName=$env:username"
+}
+
+function _find_sdk_tool {
+ param($tool)
+
+ $_tool_item = ""
+ foreach ($ver in ("v8.1A", "v8.0A")) {
+ foreach ($kit in ("WinSDK-NetFx40Tools-x64", "WinSDK-NetFx40Tools-x86", "WinSDK-NetFx40Tools")) {
+ $_kit_path = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Microsoft SDKs\Windows\$ver\$kit" -EA 0)
+ if (-not $_kit_path) {
+ $_kit_path = (Get-ItemProperty "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\$ver\$kit" -EA 0)
+ }
+
+ if ($_kit_path -and (Test-Path $_kit_path.InstallationFolder)) {
+ $_tool_item = Get-Item "$($_kit_path.InstallationFolder)\$tool.exe" -EA 0
+ if (-not (Test-Path alias:\$tool) -and $_tool_item) {
+ Set-Alias -Name $tool -Value $_tool_item.FullName -Scope Global
+ }
+ }
+ }
+ }
+ foreach ($ver in ("KitsRoot81", "KitsRoot")) {
+ $_kit_path = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots" -Name $ver -EA 0).$ver
+ if (-not $_kit_path) {
+ $_kit_path = (Get-ItemProperty "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows Kits\Installed Roots" -Name $ver -EA 0).$ver
+ }
+
+ foreach ($kit in ("x64", "x86")) {
+ if ($_kit_path -and (Test-Path "$_kit_path\bin\$kit")) {
+ $_tool_item = Get-Item "$_kit_path\bin\$kit\$tool.exe" -EA 0
+ if (-not (Test-Path alias:\$tool) -and $_tool_item) {
+ Set-Alias -Name $tool -Value $_tool_item.FullName -Scope Global
+ return
+ }
+ }
+ }
+ }
+}
+
+function begin_sign_files {
+ param($files, $outdir, $approvers, $projectName, $projectUrl, $jobDescription, $jobKeywords, $certificates, [switch] $delaysigned)
+
+ if ($files.Count -eq 0) {
+ return
+ }
+
+ if ($delaysigned) {
+ # Ensure that all files are delay-signed
+ # "sn -q -v ..." is true if the assembly has strong name and skip verification
+ _find_sdk_tool "sn"
+ if (Test-Path alias:\sn) {
+ $not_delay_signed = $files | %{ gi $_.path } | ?{ sn -q -v $_ }
+ if ($not_delay_signed) {
+ Throw "Delay-signed check failed: $($not_delay_signed.Name -join '
+')
+You may need to skip strong name verification on this machine."
+ }
+ }
+ }
+
+ [Reflection.Assembly]::Load("CODESIGN.Submitter, Version=3.0.0.6, Culture=neutral, PublicKeyToken=3d8252bd1272440d, processorArchitecture=MSIL") | Out-Null
+ [Reflection.Assembly]::Load("CODESIGN.PolicyManager, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3d8252bd1272440d, processorArchitecture=MSIL") | Out-Null
+
+ $job = [CODESIGN.Submitter.Job]::Initialize("codesign.gtm.microsoft.com", 9556, $True)
+ $msg = "*** Signing Job Details ***
+job.Description: $jobDescription
+job.Keywords: $jobKeywords"
+ $job.Description = $jobDescription
+ $job.Keywords = $jobKeywords
+
+ if ($certificates -match "authenticode") {
+ $msg = "$msg
+job.SelectCertificate(10006)"
+ $job.SelectCertificate("10006") # Authenticode
+ }
+ if ($certificates -match "strongname") {
+ $msg = "$msg
+job.SelectCertificate(67)"
+ $job.SelectCertificate("67") # StrongName key
+ }
+ if ($certificates -match "opc") {
+ $job.SelectCertificate("160") # Microsoft OPC Publisher (VSIX)
+ }
+
+ foreach ($approver in $approvers) {
+ $msg = "$msg
+job.AddApprover($approver)"
+ $job.AddApprover($approver)
+ }
+
+ foreach ($file in $files) {
+ $msg = "$msg
+job.AddFile($($file.path), $($file.name), $projectUrl, None)"
+ $job.AddFile($file.path, $file.name, $projectUrl, [CODESIGN.JavaPermissionsTypeEnum]::None)
+ }
+
+ $msg = "$msg
+Returning @{filecount=$($files.Count); outdir=$outdir}"
+ Write-Debug $msg
+
+ $uniqueJobFolderID = ((Get-Date -format "yyyyMMdd-HHmmss").ToString() + "-" + (Get-Date).Millisecond.ToString())
+
+ $folder = ((Get-Item $($files[0].path)).DirectoryName.ToString() + "\MockSigned")
+
+ $mockJob = New-Object PSObject
+ $mockJob | Add-Member NoteProperty JobID $uniqueJobFolderID
+ $mockJob | Add-Member NoteProperty JobMockFolder $folder
+ $mockJob | Add-Member NoteProperty JobCompletionPath $folder\$uniqueJobFolderID
+
+ $mockFolderPath = $mockJob.JobCompletionPath
+ mkdir $mockFolderPath -EA 0 | Out-Null
+
+ foreach($file in $files) {
+ $destPath = "$($mockFolderPath)\$($fileInfo.Name)"
+ copy -path $($file.path) -dest $destPath
+ if (-not $?) {
+ Write-Output "Failed to copy $($file.path) to $destPath"
+ }
+ }
+
+ return @{rjob=$job; job=$mockJob; description=$jobDescription; filecount=$($files.Count); outdir=$outdir}
+}
+
+function end_sign_files {
+ param($jobs)
+
+ if ($jobs.Count -eq 0) {
+ return
+ }
+
+ foreach ($jobinfo in $jobs) {
+ $job = $jobinfo.job
+ if($job -eq $null) {
+ throw "jobinfo in unexpected format $jobinfo"
+ }
+ $filecount = $jobinfo.filecount
+ $outdir = $jobinfo.outdir
+ $activity = "Processing $($jobinfo.description) (Job ID $($job.JobID))"
+ $percent = 0
+ $jobCompletionPath = $job.JobCompletionPath
+
+ if([string]::IsNullOrWhiteSpace($jobCompletionPath)) {
+ throw "job.JobCompletionPath is not valid: $($job.JobCompletionPath)"
+ }
+
+ do {
+ $files = @()
+ Write-Progress -activity $activity -status "Waiting for completion: $jobCompletionPath" -percentcomplete $percent;
+ $percent = ($percent + 1) % 100
+ if ($percent -eq 90) {
+ $files = dir $jobCompletionPath
+ }
+ sleep -Milliseconds 50
+ } while(-not $files -or $files.Count -ne $filecount);
+
+ mkdir $outdir -EA 0 | Out-Null
+ Write-Progress -Activity $activity -Completed
+
+ Write-Output "Copying from $jobCompletionPath to $outdir"
+ $retries = 9
+ $delay = 2
+ $copied = $null
+ while ($retries) {
+ try {
+ $copied = (Copy-Item -path $jobCompletionPath\* -dest $outdir -Force -PassThru)
+ break
+ } catch {
+ if ($retries -eq 0) {
+ break
+ }
+ Write-Warning "Failed to copy - retrying in $delay seconds ($retries tries remaining)"
+ Sleep -seconds $delay
+ --$retries
+ $delay += $delay
+ }
+ }
+ if (-not $copied) {
+ Throw "Failed to copy $jobCompletionPath to $outdir"
+ } else {
+ Write-Output "Copied $($copied.Count) files"
+ }
+
+ #Get rid of the MockSigned directory
+ Remove-Item -Recurse $jobCompletionPath\*
+ Remove-Item -Recurse $jobCompletionPath
+
+ if((Get-Item $($job.JobMockFolder)).GetDirectories().Count -eq 0) {
+ Remove-Item -Recurse $($job.JobMockFolder)
+ }
+ }
+}
+
+function start_virus_scan {
+ param($description, $contact, $path)
+
+ $xml = New-Object XML
+ $xml.LoadXml("AOC")
+ $xml.root.description = $description
+ $xml.root.contact = $contact
+ $xml.root.path = $path
+
+ Write-Debug "Posting to http://vcs/process.asp:
+$($xml.OuterXml)"
+}
+
+function check_signing {
+ param($outdir)
+
+ _find_sdk_tool "signtool"
+
+ $unsigned = @()
+
+ $msis = gci $outdir\*.msi
+ foreach ($m in $msis) {
+ Write-Host "Checking signatures for $m"
+ & signtool verify /pa "$m" 2>&1 | Out-Null
+ # All files should be unsigned
+ if ($?) {
+ $unsigned += "$m"
+ }
+
+ $dir = mkdir -fo "${env:TEMP}\msi_test"
+ & msiexec /q /a "$m" TARGETDIR="$dir" | Out-Null
+
+ foreach ($f in (gci $dir\*.exe, $dir\*.dll -r)) {
+ & signtool verify /pa "$f" 2>&1 | Out-Null
+ # All files should be unsigned
+ if ($?) {
+ $unsigned += "$m - $($f.Name)"
+ }
+ }
+
+ rmdir -r -fo $dir
+ }
+
+ Add-Type -assembly "System.IO.Compression.FileSystem"
+ $zips = gci $outdir\*.vsix
+ foreach ($m in $zips) {
+ Write-Host "Checking signatures for $m"
+ $dir = mkdir -fo "${env:TEMP}\msi_test"
+ [IO.Compression.ZipFile]::ExtractToDirectory($m, $dir)
+
+ # All files should be unsigned
+ if ((Test-Path "$dir\package\services\digital-signature\xml-signature")) {
+ $unsigned += "$m"
+ }
+
+ foreach ($f in (gci $dir\*.exe, $dir\*.dll -r)) {
+ & signtool verify /pa "$f" 2>&1 | Out-Null
+ # All files should be unsigned
+ if ($?) {
+ $unsigned += "$m - $($f.Name)"
+ }
+ }
+
+ rmdir -r -fo $dir
+ }
+
+ if ($unsigned) {
+ throw "Following files have invalid signatures:
+$(($unsigned | select -unique) -join '
+')"
+ }
+}
diff --git a/Build/GetWix.ps1 b/Build/GetWix.ps1
deleted file mode 100644
index 2834c65..0000000
--- a/Build/GetWix.ps1
+++ /dev/null
@@ -1,15 +0,0 @@
-function Get-Wix {
- param($target)
-
- Write-Output "Downloading Wix to $target"
-
- $file = [IO.Path]::GetTempFileName()
- Write-Output " - temporary storage: $file"
-
- Invoke-WebRequest "https://wix.codeplex.com/downloads/get/1421697" -UseBasicParsing -OutFile $file
-
- [Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem') | Out-Null
- [System.IO.Compression.ZipFile]::ExtractToDirectory($file, $target)
-
- del $file
-}
diff --git a/Build/NuGet.exe b/Build/NuGet.exe
new file mode 100644
index 0000000..324daa8
Binary files /dev/null and b/Build/NuGet.exe differ
diff --git a/BuildVSTestHost.ps1 b/BuildVSTestHost.ps1
index 0f523fe..3a166cd 100644
--- a/BuildVSTestHost.ps1
+++ b/BuildVSTestHost.ps1
@@ -18,16 +18,15 @@ if (-not $outdir) {
}
Write-Output "Writing output MSIs to $outdir"
+pushd (Join-Path $projectDir Installer)
+..\Build\nuget.exe restore packages.config -PackagesDirectory (Join-Path $projectDir packages)
+popd
+
$originalbuildtarget = $buildtarget
if ($sign -or $mocksign) {
$buildtarget = "BuildVSTestHost"
}
-if (-not (Test-Path $projectDir\Build\Wix\wix.targets)) {
- Import-Module $projectDir\Build\GetWix.ps1 -Force
- Get-Wix (mkdir -Force "$projectDir\Build\Wix") -EA Stop
-}
-
msbuild $projectDir\Installer\Installer.wixproj `
/fl /flp:logfile="$projectDir\VSTestHost.build.log" `
/v:m `
diff --git a/DeveloperGuide.md b/DeveloperGuide.md
index 2c8952e..3d77774 100644
--- a/DeveloperGuide.md
+++ b/DeveloperGuide.md
@@ -83,7 +83,7 @@ follows:
| VSApplication | The registry key name, like "VisualStudio" or "WDExpress" |
| VSExecutable | The executable name, like "devenv" or "wdexpress" |
| VSVersion | The version number, like "12.0" or "14.0" |
-| VSHive [optional] | The hive name, like "Exp" |
+| VSHive | The hive name, like "Exp" or "Default" |
| VSLaunchTimeoutInSeconds [opt] | The number of seconds to wait for launch |
| VSDebugMixedMode | True to use mixed-mode debugging for tests |
| ScreenCapture [opt] | Relative path to capture screenshots to |
diff --git a/DisableSkipVerification.reg b/DisableSkipVerification.reg
index ff25f0a..c99c0bf 100644
--- a/DisableSkipVerification.reg
+++ b/DisableSkipVerification.reg
@@ -1,10 +1,10 @@
-Windows Registry Editor Version 5.00
-
-[-HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.10.0,B03F5F7F11D50A3A]
-[-HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.11.0,B03F5F7F11D50A3A]
-[-HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.12.0,B03F5F7F11D50A3A]
-[-HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.14.0,B03F5F7F11D50A3A]
-[-HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.10.0,B03F5F7F11D50A3A]
-[-HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.11.0,B03F5F7F11D50A3A]
-[-HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.12.0,B03F5F7F11D50A3A]
-[-HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.14.0,B03F5F7F11D50A3A]
+Windows Registry Editor Version 5.00
+
+[-HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.10.0,B03F5F7F11D50A3A]
+[-HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.11.0,B03F5F7F11D50A3A]
+[-HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.12.0,B03F5F7F11D50A3A]
+[-HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.14.0,B03F5F7F11D50A3A]
+[-HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.10.0,B03F5F7F11D50A3A]
+[-HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.11.0,B03F5F7F11D50A3A]
+[-HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.12.0,B03F5F7F11D50A3A]
+[-HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.14.0,B03F5F7F11D50A3A]
diff --git a/DisableVSTestHost12.0.reg b/DisableVSTestHost12.0.reg
index 6256e19..53fa451 100644
--- a/DisableVSTestHost12.0.reg
+++ b/DisableVSTestHost12.0.reg
@@ -1,6 +1,6 @@
-Windows Registry Editor Version 5.00
-
-[-HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\VisualStudio\12.0\EnterpriseTools\QualityTools\HostAdapters\VSTestHost]
-[HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\VisualStudio\12.0\EnterpriseTools\QualityTools\TestTypes\{13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b}\SupportedHostAdapters]
-"VSTestHost"=-
-
+Windows Registry Editor Version 5.00
+
+[-HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\VisualStudio\12.0\EnterpriseTools\QualityTools\HostAdapters\VSTestHost]
+[HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\VisualStudio\12.0\EnterpriseTools\QualityTools\TestTypes\{13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b}\SupportedHostAdapters]
+"VSTestHost"=-
+
diff --git a/DisableVSTestHost14.0.reg b/DisableVSTestHost14.0.reg
index 7a81668..b9f0b80 100644
--- a/DisableVSTestHost14.0.reg
+++ b/DisableVSTestHost14.0.reg
@@ -1,6 +1,6 @@
-Windows Registry Editor Version 5.00
-
-[-HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\VisualStudio\14.0\EnterpriseTools\QualityTools\HostAdapters\VSTestHost]
-[HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\VisualStudio\14.0\EnterpriseTools\QualityTools\TestTypes\{13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b}\SupportedHostAdapters]
-"VSTestHost"=-
-
+Windows Registry Editor Version 5.00
+
+[-HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\VisualStudio\14.0\EnterpriseTools\QualityTools\HostAdapters\VSTestHost]
+[HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\VisualStudio\14.0\EnterpriseTools\QualityTools\TestTypes\{13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b}\SupportedHostAdapters]
+"VSTestHost"=-
+
diff --git a/EnableSkipVerification.reg b/EnableSkipVerification.reg
index 878908d..7a0a11a 100644
--- a/EnableSkipVerification.reg
+++ b/EnableSkipVerification.reg
@@ -1,10 +1,10 @@
-Windows Registry Editor Version 5.00
-
-[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.10.0,B03F5F7F11D50A3A]
-[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.11.0,B03F5F7F11D50A3A]
-[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.12.0,B03F5F7F11D50A3A]
-[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.14.0,B03F5F7F11D50A3A]
-[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.10.0,B03F5F7F11D50A3A]
-[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.11.0,B03F5F7F11D50A3A]
-[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.12.0,B03F5F7F11D50A3A]
-[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.14.0,B03F5F7F11D50A3A]
+Windows Registry Editor Version 5.00
+
+[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.10.0,B03F5F7F11D50A3A]
+[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.11.0,B03F5F7F11D50A3A]
+[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.12.0,B03F5F7F11D50A3A]
+[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.14.0,B03F5F7F11D50A3A]
+[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.10.0,B03F5F7F11D50A3A]
+[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.11.0,B03F5F7F11D50A3A]
+[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.12.0,B03F5F7F11D50A3A]
+[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\StrongName\Verification\Microsoft.VisualStudioTools.VSTestHost.14.0,B03F5F7F11D50A3A]
diff --git a/EnableVSTestHost12.0.reg b/EnableVSTestHost12.0.reg
index ce67acc..e96baac 100644
--- a/EnableVSTestHost12.0.reg
+++ b/EnableVSTestHost12.0.reg
@@ -1,10 +1,10 @@
-Windows Registry Editor Version 5.00
-
-[HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\VisualStudio\12.0\EnterpriseTools\QualityTools\HostAdapters\VSTestHost]
-"Type"="Microsoft.VisualStudioTools.VSTestHost.TesterTestAdapter, Microsoft.VisualStudioTools.VSTestHost.12.0, Version=12.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
-"EditorType"="Microsoft.VisualStudioTools.VSTestHost.TesterTestControl, Microsoft.VisualStudioTools.VSTestHost.12.0, Version=12.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
-[HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\VisualStudio\12.0\EnterpriseTools\QualityTools\HostAdapters\VSTestHost\SupportedTestTypes]
-"{13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b}"="Unit Test"
-[HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\VisualStudio\12.0\EnterpriseTools\QualityTools\TestTypes\{13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b}\SupportedHostAdapters]
-"VSTestHost"="VS Test Host Adapter"
-
+Windows Registry Editor Version 5.00
+
+[HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\VisualStudio\12.0\EnterpriseTools\QualityTools\HostAdapters\VSTestHost]
+"Type"="Microsoft.VisualStudioTools.VSTestHost.TesterTestAdapter, Microsoft.VisualStudioTools.VSTestHost.12.0, Version=12.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
+"EditorType"="Microsoft.VisualStudioTools.VSTestHost.TesterTestControl, Microsoft.VisualStudioTools.VSTestHost.12.0, Version=12.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
+[HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\VisualStudio\12.0\EnterpriseTools\QualityTools\HostAdapters\VSTestHost\SupportedTestTypes]
+"{13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b}"="Unit Test"
+[HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\VisualStudio\12.0\EnterpriseTools\QualityTools\TestTypes\{13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b}\SupportedHostAdapters]
+"VSTestHost"="VS Test Host Adapter"
+
diff --git a/EnableVSTestHost14.0.reg b/EnableVSTestHost14.0.reg
index 2785ffa..3ef15bd 100644
--- a/EnableVSTestHost14.0.reg
+++ b/EnableVSTestHost14.0.reg
@@ -1,10 +1,10 @@
-Windows Registry Editor Version 5.00
-
-[HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\VisualStudio\14.0\EnterpriseTools\QualityTools\HostAdapters\VSTestHost]
-"Type"="Microsoft.VisualStudioTools.VSTestHost.TesterTestAdapter, Microsoft.VisualStudioTools.VSTestHost.14.0, Version=14.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
-"EditorType"="Microsoft.VisualStudioTools.VSTestHost.TesterTestControl, Microsoft.VisualStudioTools.VSTestHost.14.0, Version=14.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
-[HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\VisualStudio\14.0\EnterpriseTools\QualityTools\HostAdapters\VSTestHost\SupportedTestTypes]
-"{13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b}"="Unit Test"
-[HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\VisualStudio\14.0\EnterpriseTools\QualityTools\TestTypes\{13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b}\SupportedHostAdapters]
-"VSTestHost"="VS Test Host Adapter"
-
+Windows Registry Editor Version 5.00
+
+[HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\VisualStudio\14.0\EnterpriseTools\QualityTools\HostAdapters\VSTestHost]
+"Type"="Microsoft.VisualStudioTools.VSTestHost.TesterTestAdapter, Microsoft.VisualStudioTools.VSTestHost.14.0, Version=14.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
+"EditorType"="Microsoft.VisualStudioTools.VSTestHost.TesterTestControl, Microsoft.VisualStudioTools.VSTestHost.14.0, Version=14.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
+[HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\VisualStudio\14.0\EnterpriseTools\QualityTools\HostAdapters\VSTestHost\SupportedTestTypes]
+"{13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b}"="Unit Test"
+[HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\VisualStudio\14.0\EnterpriseTools\QualityTools\TestTypes\{13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b}\SupportedHostAdapters]
+"VSTestHost"="VS Test Host Adapter"
+
diff --git a/Installer/Installer.wixproj b/Installer/Installer.wixproj
index eb497f8..7242818 100644
--- a/Installer/Installer.wixproj
+++ b/Installer/Installer.wixproj
@@ -1,5 +1,6 @@
+
Debug
x86
@@ -9,8 +10,6 @@
VSTestHost
Package
false
- $(MSBuildThisFileDirectory)\..\Build\Wix
- $(WixInstallPath)\Wix.targets
Build
11;12;14
@@ -79,4 +78,11 @@
+
+
+
+ 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}.
+
+
+
\ No newline at end of file
diff --git a/Installer/Product.wxs b/Installer/Product.wxs
index 1e2b3de..c5d1b08 100644
--- a/Installer/Product.wxs
+++ b/Installer/Product.wxs
@@ -3,7 +3,7 @@
diff --git a/Installer/packages.config b/Installer/packages.config
new file mode 100644
index 0000000..ff1106d
--- /dev/null
+++ b/Installer/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index 3490170..6d2473b 100644
--- a/README.md
+++ b/README.md
@@ -42,7 +42,7 @@ These settings should be specified in a `.testsettings` file or with the `TestPr
| VSApplication | The registry key name | "VisualStudio", "WDExpress", "VWDExpress", "Mock" |
| VSExecutable | The executable name | "devenv", "wdexpress", "vwdexpress" |
| VSVersion | The version number | "11.0", "12.0", "14.0" or blank (match tester) |
-| VSHive | The hive name | "Exp" or blank |
+| VSHive | The hive name | "Exp" or "Default" |
| VSLaunchTimeoutInSeconds | The number of seconds to wait for launch | Any number, or blank (30s) |
| VSDebugMixedMode | Use native debugging for tests | "True", "False" or blank |
| ScreenCapture | Directory to capture screenshots into | Blank (do not capture) or a relative path |
diff --git a/VSTestHost/Resources.Designer.cs b/VSTestHost/Resources.Designer.cs
index 6e76fff..56e7827 100644
--- a/VSTestHost/Resources.Designer.cs
+++ b/VSTestHost/Resources.Designer.cs
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
//
// This code was generated by a tool.
-// Runtime Version:4.0.30319.0
+// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -191,6 +191,15 @@ internal static string VSFailedToLaunch {
}
}
+ ///
+ /// Looks up a localized string similar to Launching {0}: "...\Microsoft Visual Studio {2}\Common7\IDE\{1}{3}".
+ ///
+ internal static string VSLaunchMessage {
+ get {
+ return ResourceManager.GetString("VSLaunchMessage", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Visual Studio failed to start within {0} seconds..
///
@@ -199,5 +208,14 @@ internal static string VSLaunchTimeout {
return ResourceManager.GetString("VSLaunchTimeout", resourceCulture);
}
}
+
+ ///
+ /// Looks up a localized string similar to Reusing {0}: "...\Microsoft Visual Studio {2}\Common7\IDE\{1}{3}".
+ ///
+ internal static string VSReuseMessage {
+ get {
+ return ResourceManager.GetString("VSReuseMessage", resourceCulture);
+ }
+ }
}
}
diff --git a/VSTestHost/Resources.resx b/VSTestHost/Resources.resx
index 52f76d4..b50f9b3 100644
--- a/VSTestHost/Resources.resx
+++ b/VSTestHost/Resources.resx
@@ -165,7 +165,13 @@
Failed to launch {1} ({0}, {2}{3})
application, executable, version, hive
+
+ Launching {0}: "...\Microsoft Visual Studio {2}\Common7\IDE\{1}{3}"
+
Visual Studio failed to start within {0} seconds.
+
+ Reusing {0}: "...\Microsoft Visual Studio {2}\Common7\IDE\{1}{3}"
+
\ No newline at end of file
diff --git a/VSTestHost/ScreenRecorder.cs b/VSTestHost/ScreenRecorder.cs
index db9d36d..6f04e65 100644
--- a/VSTestHost/ScreenRecorder.cs
+++ b/VSTestHost/ScreenRecorder.cs
@@ -12,246 +12,246 @@
*
* ***************************************************************************/
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Drawing;
-using System.Drawing.Imaging;
-using System.IO;
-using System.Linq;
-using System.Threading;
-using System.Windows.Forms;
-using Microsoft.VisualStudioTools.VSTestHost.Internal;
-
-namespace Microsoft.VisualStudioTools.VSTestHost {
- sealed class ScreenRecorder : IDisposable {
- private readonly System.Threading.Timer _timer;
- private readonly DirectoryInfo _output;
- private Bitmap _latestImage;
- private DateTime _latestImageTime;
- private TimeSpan _interval;
- private bool _isDisposed = false;
-
- public ScreenRecorder(string outputPath) {
- _timer = new System.Threading.Timer(Timer_Callback);
- _output = Directory.CreateDirectory(outputPath);
- }
-
- public void Dispose() {
- if (!_isDisposed) {
- _isDisposed = true;
- _timer.Dispose();
-
- var latestImage = _latestImage;
- _latestImage = null;
- if (latestImage != null) {
- latestImage.Dispose();
- }
- }
- }
-
- public string Failure { get; private set; }
-
- public TimeSpan Interval {
- get {
- return _interval;
- }
- set {
- _interval = value;
- try {
- _timer.Change((int)_interval.TotalMilliseconds, -1);
- } catch (ObjectDisposedException) {
- }
- }
- }
-
- private void Timer_Callback(object state) {
- if (_isDisposed) {
- return;
- }
-
- try {
- NextCapture();
- } catch (Exception ex) {
- if (ex is OutOfMemoryException || ex is ThreadAbortException || ex is AccessViolationException) {
- throw;
- }
- Failure = ex.ToString();
- }
- }
-
- private void NextCapture() {
- var bmp = Capture(Screen.AllScreens);
- var time = DateTime.Now;
-
- var lastImage = _latestImage;
- if (!AreSame(lastImage, bmp)) {
- _latestImage = bmp;
- _latestImageTime = time;
- if (lastImage != null) {
- lastImage.Dispose();
- }
-
- var nameFormat = time.ToString("s").Replace(":", "") + "{0}.png";
- using (var stream = OpenUniquelyNamedFile(_output.FullName, nameFormat)) {
- bmp.Save(stream, ImageFormat.Png);
- }
- } else {
- bmp.Dispose();
- }
-
- try {
- _timer.Change((int)Interval.TotalMilliseconds, -1);
- } catch (ObjectDisposedException) {
- }
- }
-
-
-
- private static Stream OpenUniquelyNamedFile(string directory, string format) {
- string path = format;
- try {
- path = Path.Combine(directory, string.Format(format, ""));
- return new FileStream(
- path,
- FileMode.CreateNew,
- FileAccess.Write,
- FileShare.Read
- );
- } catch (IOException) {
- } catch (UnauthorizedAccessException) {
- } catch (NotSupportedException ex) {
- throw new NotSupportedException(path, ex);
- }
-
- // Try with an additional index
- for (int i = 0; i < 0x100; ++i) {
- try {
- path = Path.Combine(directory, string.Format(format, string.Format("_{0}", i)));
- return new FileStream(
- path,
- FileMode.CreateNew,
- FileAccess.Write,
- FileShare.Read
- );
- } catch (IOException) {
- } catch (UnauthorizedAccessException) {
- } catch (NotSupportedException ex) {
- throw new NotSupportedException(path, ex);
- }
- }
-
- // If we can't find an index, try a guid. If we still can't create
- // the file, let the exception out so the user hears about it.
- try {
- path = Path.Combine(directory, string.Format(format, string.Format("_{0:N}", Guid.NewGuid())));
- return new FileStream(
- path,
- FileMode.CreateNew,
- FileAccess.Write,
- FileShare.Read
- );
- } catch (NotSupportedException ex) {
- throw new NotSupportedException(path, ex);
- }
- }
-
- private static Bitmap Capture(IList screens) {
- if (screens.Count == 0) {
- return null;
- }
-
- Rectangle bounds = GetScreensBounds(screens);
-
- var bmp = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format32bppArgb);
- try {
- using (var g = Graphics.FromImage(bmp)) {
- g.Clear(Color.Black);
- foreach (var s in screens) {
- var d = s.Bounds.Location;
- d.Offset(-bounds.X, -bounds.Y);
- if (d.X < 0 || d.Y < 0) {
- throw new InvalidOperationException(Resources.InvalidScreenBounds);
- }
- g.CopyFromScreen(s.Bounds.Location, d, s.Bounds.Size);
- }
- }
-
- var res = bmp;
- bmp = null;
- return res;
- } finally {
- if (bmp != null) {
- bmp.Dispose();
- }
- }
- }
-
- private static Rectangle GetScreensBounds(IList screens) {
- var bounds = screens[0].Bounds;
- foreach (var s in screens.Skip(1)) {
- if (s.Bounds.X < bounds.X) {
- bounds.X = s.Bounds.X;
- }
- if (s.Bounds.Y < bounds.Y) {
- bounds.Y = s.Bounds.Y;
- }
- if (s.Bounds.Right > bounds.Right) {
- bounds.Width = s.Bounds.Right - bounds.Left;
- if (bounds.Right != s.Bounds.Right) {
- throw new InvalidOperationException(Resources.InvalidScreenBounds);
- }
- }
- if (s.Bounds.Bottom > bounds.Bottom) {
- bounds.Height = s.Bounds.Bottom - bounds.Top;
- if (bounds.Bottom != s.Bounds.Bottom) {
- throw new InvalidOperationException(Resources.InvalidScreenBounds);
- }
- }
- }
-
- return bounds;
- }
-
- private static unsafe bool AreSame(Bitmap x, Bitmap y) {
- if (x == null || y == null) {
- return x == null && y == null;
- }
- if (x.Width != y.Width || x.Height != y.Height) {
- return false;
- }
-
- var bounds = new Rectangle(Point.Empty, x.Size);
- BitmapData bdX = null, bdY = null;
- try {
- bdX = x.LockBits(bounds, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
- bdY = y.LockBits(bounds, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
-
- var pX = (UInt32*)bdX.Scan0.ToPointer();
- var pY = (UInt32*)bdY.Scan0.ToPointer();
- int count = bdX.Width * bdX.Height;
- if (count != bdY.Width * bdY.Height) {
- // Should have already returned earlier in this case
- Debug.Fail("Bitmap sizes must match");
- return false;
- }
- for (; count > 0; --count) {
- if (*pX != *pY) {
- return false;
- }
- pX += 1;
- pY += 1;
- }
-
- return true;
- } finally {
- if (bdX != null) {
- x.UnlockBits(bdX);
- }
- if (bdY != null) {
- y.UnlockBits(bdY);
- }
- }
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Windows.Forms;
+using Microsoft.VisualStudioTools.VSTestHost.Internal;
+
+namespace Microsoft.VisualStudioTools.VSTestHost {
+ sealed class ScreenRecorder : IDisposable {
+ private readonly System.Threading.Timer _timer;
+ private readonly DirectoryInfo _output;
+ private Bitmap _latestImage;
+ private DateTime _latestImageTime;
+ private TimeSpan _interval;
+ private bool _isDisposed = false;
+
+ public ScreenRecorder(string outputPath) {
+ _timer = new System.Threading.Timer(Timer_Callback);
+ _output = Directory.CreateDirectory(outputPath);
+ }
+
+ public void Dispose() {
+ if (!_isDisposed) {
+ _isDisposed = true;
+ _timer.Dispose();
+
+ var latestImage = _latestImage;
+ _latestImage = null;
+ if (latestImage != null) {
+ latestImage.Dispose();
+ }
+ }
+ }
+
+ public string Failure { get; private set; }
+
+ public TimeSpan Interval {
+ get {
+ return _interval;
+ }
+ set {
+ _interval = value;
+ try {
+ _timer.Change((int)_interval.TotalMilliseconds, -1);
+ } catch (ObjectDisposedException) {
+ }
+ }
+ }
+
+ private void Timer_Callback(object state) {
+ if (_isDisposed) {
+ return;
+ }
+
+ try {
+ NextCapture();
+ } catch (Exception ex) {
+ if (ex is OutOfMemoryException || ex is ThreadAbortException || ex is AccessViolationException) {
+ throw;
+ }
+ Failure = ex.ToString();
+ }
+ }
+
+ private void NextCapture() {
+ var bmp = Capture(Screen.AllScreens);
+ var time = DateTime.Now;
+
+ var lastImage = _latestImage;
+ if (!AreSame(lastImage, bmp)) {
+ _latestImage = bmp;
+ _latestImageTime = time;
+ if (lastImage != null) {
+ lastImage.Dispose();
+ }
+
+ var nameFormat = time.ToString("s").Replace(":", "") + "{0}.png";
+ using (var stream = OpenUniquelyNamedFile(_output.FullName, nameFormat)) {
+ bmp.Save(stream, ImageFormat.Png);
+ }
+ } else {
+ bmp.Dispose();
+ }
+
+ try {
+ _timer.Change((int)Interval.TotalMilliseconds, -1);
+ } catch (ObjectDisposedException) {
+ }
+ }
+
+
+
+ private static Stream OpenUniquelyNamedFile(string directory, string format) {
+ string path = format;
+ try {
+ path = Path.Combine(directory, string.Format(format, ""));
+ return new FileStream(
+ path,
+ FileMode.CreateNew,
+ FileAccess.Write,
+ FileShare.Read
+ );
+ } catch (IOException) {
+ } catch (UnauthorizedAccessException) {
+ } catch (NotSupportedException ex) {
+ throw new NotSupportedException(path, ex);
+ }
+
+ // Try with an additional index
+ for (int i = 0; i < 0x100; ++i) {
+ try {
+ path = Path.Combine(directory, string.Format(format, string.Format("_{0}", i)));
+ return new FileStream(
+ path,
+ FileMode.CreateNew,
+ FileAccess.Write,
+ FileShare.Read
+ );
+ } catch (IOException) {
+ } catch (UnauthorizedAccessException) {
+ } catch (NotSupportedException ex) {
+ throw new NotSupportedException(path, ex);
+ }
+ }
+
+ // If we can't find an index, try a guid. If we still can't create
+ // the file, let the exception out so the user hears about it.
+ try {
+ path = Path.Combine(directory, string.Format(format, string.Format("_{0:N}", Guid.NewGuid())));
+ return new FileStream(
+ path,
+ FileMode.CreateNew,
+ FileAccess.Write,
+ FileShare.Read
+ );
+ } catch (NotSupportedException ex) {
+ throw new NotSupportedException(path, ex);
+ }
+ }
+
+ private static Bitmap Capture(IList screens) {
+ if (screens.Count == 0) {
+ return null;
+ }
+
+ Rectangle bounds = GetScreensBounds(screens);
+
+ var bmp = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format32bppArgb);
+ try {
+ using (var g = Graphics.FromImage(bmp)) {
+ g.Clear(Color.Black);
+ foreach (var s in screens) {
+ var d = s.Bounds.Location;
+ d.Offset(-bounds.X, -bounds.Y);
+ if (d.X < 0 || d.Y < 0) {
+ throw new InvalidOperationException(Resources.InvalidScreenBounds);
+ }
+ g.CopyFromScreen(s.Bounds.Location, d, s.Bounds.Size);
+ }
+ }
+
+ var res = bmp;
+ bmp = null;
+ return res;
+ } finally {
+ if (bmp != null) {
+ bmp.Dispose();
+ }
+ }
+ }
+
+ private static Rectangle GetScreensBounds(IList screens) {
+ var bounds = screens[0].Bounds;
+ foreach (var s in screens.Skip(1)) {
+ if (s.Bounds.X < bounds.X) {
+ bounds.X = s.Bounds.X;
+ }
+ if (s.Bounds.Y < bounds.Y) {
+ bounds.Y = s.Bounds.Y;
+ }
+ if (s.Bounds.Right > bounds.Right) {
+ bounds.Width = s.Bounds.Right - bounds.Left;
+ if (bounds.Right != s.Bounds.Right) {
+ throw new InvalidOperationException(Resources.InvalidScreenBounds);
+ }
+ }
+ if (s.Bounds.Bottom > bounds.Bottom) {
+ bounds.Height = s.Bounds.Bottom - bounds.Top;
+ if (bounds.Bottom != s.Bounds.Bottom) {
+ throw new InvalidOperationException(Resources.InvalidScreenBounds);
+ }
+ }
+ }
+
+ return bounds;
+ }
+
+ private static unsafe bool AreSame(Bitmap x, Bitmap y) {
+ if (x == null || y == null) {
+ return x == null && y == null;
+ }
+ if (x.Width != y.Width || x.Height != y.Height) {
+ return false;
+ }
+
+ var bounds = new Rectangle(Point.Empty, x.Size);
+ BitmapData bdX = null, bdY = null;
+ try {
+ bdX = x.LockBits(bounds, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
+ bdY = y.LockBits(bounds, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
+
+ var pX = (UInt32*)bdX.Scan0.ToPointer();
+ var pY = (UInt32*)bdY.Scan0.ToPointer();
+ int count = bdX.Width * bdX.Height;
+ if (count != bdY.Width * bdY.Height) {
+ // Should have already returned earlier in this case
+ Debug.Fail("Bitmap sizes must match");
+ return false;
+ }
+ for (; count > 0; --count) {
+ if (*pX != *pY) {
+ return false;
+ }
+ pX += 1;
+ pY += 1;
+ }
+
+ return true;
+ } finally {
+ if (bdX != null) {
+ x.UnlockBits(bdX);
+ }
+ if (bdY != null) {
+ y.UnlockBits(bdY);
+ }
+ }
+ }
+ }
+}
diff --git a/VSTestHost/TesterTestAdapter.cs b/VSTestHost/TesterTestAdapter.cs
index 4516597..ae6863b 100644
--- a/VSTestHost/TesterTestAdapter.cs
+++ b/VSTestHost/TesterTestAdapter.cs
@@ -48,19 +48,38 @@ private async Task Connect(
string executable,
Version version,
string hive,
+ IRunContext runContext,
+ ITestElement currentTest,
CancellationToken cancel
) {
+ var hiveOption = string.IsNullOrEmpty(hive) ? "" : (" /rootSuffix " + hive);
+
if (_ide != null &&
_remote != null &&
application == _currentApplication &&
executable == _currentExecutable &&
version == _currentVersion &&
hive == _currentHive) {
+ if (runContext != null) {
+ SendMessage(
+ runContext,
+ string.Format(Resources.VSReuseMessage, application, executable, version, hiveOption),
+ currentTest
+ );
+ }
return;
}
Close();
+ if (runContext != null) {
+ SendMessage(
+ runContext,
+ string.Format(Resources.VSLaunchMessage, application, executable, version, hiveOption),
+ currentTest
+ );
+ }
+
Internal.VisualStudio ide = null;
try {
ide = await Internal.VisualStudio.LaunchAsync(application, executable, version, hive, cancel);
@@ -141,7 +160,11 @@ private bool IsClientAlive() {
///
/// The context for the current test run.
///
- private async Task InitializeWorker(TestProperties vars) {
+ private async Task InitializeWorker(
+ TestProperties vars,
+ IRunContext runContext,
+ ITestElement currentTest = null
+ ) {
string application, executable, versionString, hive;
Version version;
string launchTimeoutInSecondsString;
@@ -165,7 +188,7 @@ private async Task InitializeWorker(TestProperties vars) {
}
// VSHive is the optional hive like 'Exp'
- hive = vars[VSTestProperties.VSHive.Key] ?? VSTestProperties.VSHive.Exp;
+ hive = vars[VSTestProperties.VSHive.Key];
if (!vars.TryGetValue(VSTestProperties.VSLaunchTimeoutInSeconds.Key, out launchTimeoutInSecondsString) ||
!int.TryParse(launchTimeoutInSecondsString, out launchTimeoutInSeconds)) {
@@ -178,7 +201,7 @@ private async Task InitializeWorker(TestProperties vars) {
application ?? "(null)",
executable ?? "(null)",
version != null ? version.ToString() : "(null)",
- hive ?? "(null)"
+ hive ?? "(default)"
));
}
@@ -205,7 +228,7 @@ private async Task InitializeWorker(TestProperties vars) {
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(launchTimeoutInSeconds));
try {
- await Connect(application, executable, version, hive, cts.Token);
+ await Connect(application, executable, version, hive, runContext, currentTest, cts.Token);
} catch (OperationCanceledException ex) {
throw new TimeoutException(string.Format(Resources.VSLaunchTimeout, launchTimeoutInSeconds), ex);
} catch (Exception ex) {
@@ -216,8 +239,8 @@ private async Task InitializeWorker(TestProperties vars) {
}
}
- private static TestRunTextResultMessage GetFailure(Exception ex, Guid runId) {
- var res = new TestRunTextResultMessage(runId, ex.Message);
+ private static TextTestResultMessage GetFailure(Exception ex, Guid runId, ITestElement currentTest) {
+ var res = new TextTestResultMessage(runId, currentTest, ex.Message);
#if DEBUG
if (ex.InnerException != null) {
res.SystemException = ex.InnerException;
@@ -228,25 +251,22 @@ private static TestRunTextResultMessage GetFailure(Exception ex, Guid runId) {
private bool InitializeForTest(ITestElement testElement, IRunContext runContext) {
var runId = runContext.RunConfig.TestRun.Id;
- TestRunTextResultMessage failure = null;
+ TestResultMessage failure = null;
- try {
+ try {
var vars = new TestProperties(testElement, runContext.RunConfig.TestRun.RunConfiguration);
- InitializeWorker(vars).GetAwaiter().GetResult();
+ InitializeWorker(vars, runContext, testElement).GetAwaiter().GetResult();
_remote.Initialize(_runContext);
AttachDebuggerIfNeeded(runContext, _ide, vars);
} catch (ArgumentException ex) {
- failure = GetFailure(ex, runId);
+ failure = GetFailure(ex, runId, testElement);
} catch (TimeoutException ex) {
- failure = GetFailure(ex, runId);
+ failure = GetFailure(ex, runId, testElement);
} catch (InvalidOperationException ex) {
- failure = GetFailure(ex, runId);
+ failure = GetFailure(ex, runId, testElement);
} catch (Exception ex) {
- failure = new TestRunTextResultMessage(
- runId,
- string.Format("{0}: {1}{2}{3}", ex.GetType().Name, ex.Message, Environment.NewLine, ex)
- );
+ failure = GetFailure(ex, runId, testElement);
failure.SystemException = ex;
}
@@ -261,7 +281,7 @@ private bool InitializeForTest(ITestElement testElement, IRunContext runContext)
private void AttachDebuggerIfNeeded(IRunContext runContext, Internal.VisualStudio ide, TestProperties vars) {
var config = runContext.RunConfig.TestRun.RunConfiguration;
if (!config.IsExecutedUnderDebugger || ide == null) {
- return;
+ return;
}
// If we're debugging, tell our host VS to attach to the new VS
diff --git a/VSTestHost/VSTestHostPackage.cs b/VSTestHost/VSTestHostPackage.cs
index 54fa762..aa9e278 100644
--- a/VSTestHost/VSTestHostPackage.cs
+++ b/VSTestHost/VSTestHostPackage.cs
@@ -30,7 +30,7 @@
namespace Microsoft.VisualStudioTools.VSTestHost.Internal {
[PackageRegistration(UseManagedResourcesOnly = true, RegisterUsing=RegistrationMethod.Assembly)]
- [InstalledProductRegistration("#110", "#112", "1.0.2", IconResourceID = 400)]
+ [InstalledProductRegistration("#110", "#112", "1.0.3", IconResourceID = 400)]
[ProvideAutoLoad(VSConstants.UICONTEXT.NoSolution_string)]
[ProvideAutoLoad(VSConstants.UICONTEXT.SolutionExists_string)]
[RegisterHostAdapter("VSTestHost", typeof(TesterTestAdapter), typeof(TesterTestControl))]
@@ -84,13 +84,13 @@ protected override void Initialize() {
typeof(TesterDebugAttacher),
"debug",
WellKnownObjectMode.SingleCall
- );
-
- // Register for notifications when we start debugging. This is used
- // so we can start listening for incoming calls to DebugAttacher
- // only when necessary.
- UIContext.FromUIContextGuid(new Guid(UIContextGuids.Debugging)).UIContextChanged += DebuggingChanged;
-
+ );
+
+ // Register for notifications when we start debugging. This is used
+ // so we can start listening for incoming calls to DebugAttacher
+ // only when necessary.
+ UIContext.FromUIContextGuid(new Guid(UIContextGuids.Debugging)).UIContextChanged += DebuggingChanged;
+
base.Initialize();
}
@@ -119,8 +119,8 @@ async void DebuggingChanged(object sender, UIContextChangedEventArgs e) {
// Abort waiting in case we stopped within the timeout
TesterDebugAttacherShared.CancelWait();
}
- }
-
+ }
+
public static string GetChannelName(Process process) {
return string.Format("VSTestHost_{0}_{1:X8}_06420E12_C5A1_4EEF_B604_406E6A139737",
process.MainModule.ModuleName.ToLowerInvariant(),
diff --git a/VSTestHost/source.extension.vsixmanifest b/VSTestHost/source.extension.vsixmanifest
index 72f0fd2..4f4044e 100644
--- a/VSTestHost/source.extension.vsixmanifest
+++ b/VSTestHost/source.extension.vsixmanifest
@@ -1,7 +1,7 @@
-
+
VSTestHost
Allows UI testing of the Visual Studio IDE.