Fixes line endings, hopefully for the last time.
This commit is contained in:
Родитель
edddb53760
Коммит
a7632a05d5
|
@ -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("<root><description /><contact /><path /><region>AOC</region></root>")
|
||||
$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("<root><description /><contact /><path /><region>AOC</region></root>")
|
||||
$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 '
|
||||
')"
|
||||
}
|
||||
}
|
|
@ -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("<root><description /><contact /><path /><region>AOC</region></root>")
|
||||
$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("<root><description /><contact /><path /><region>AOC</region></root>")
|
||||
$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 '
|
||||
')"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
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
|
||||
}
|
||||
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
|
||||
}
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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"=-
|
||||
|
||||
|
|
|
@ -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"=-
|
||||
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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<Screen> 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<Screen> 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<Screen> 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<Screen> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче