param( [Parameter(Mandatory=$true)][string]$Executable, [Parameter(Mandatory=$true)][string]$OutputDirectory ) $ErrorActionPreference='Stop' $exe=(Resolve-Path $Executable).Path if(Test-Path $OutputDirectory){throw 'Use a fresh evidence directory.'} $directory=(New-Item -ItemType Directory $OutputDirectory).FullName $doctor=(& $exe doctor | Out-String) | ConvertFrom-Json $doctorCode=$LASTEXITCODE $doctor | ConvertTo-Json -Depth 8 | Set-Content "$directory\doctor.json" -Encoding UTF8 if($doctor.InputDesktopAvailable -ne $false -or $doctor.Errors -notcontains 'SessionLocked'){ throw 'This negative test requires an already unavailable input desktop; it does not lock or disconnect it.' } Add-Type -AssemblyName UIAutomationClient Add-Type -AssemblyName UIAutomationTypes function Get-DraftDigest { $ae=[System.Windows.Automation.AutomationElement] $scope=[System.Windows.Automation.TreeScope]::Descendants $windows=$ae::RootElement.FindAll([System.Windows.Automation.TreeScope]::Children,[System.Windows.Automation.Condition]::TrueCondition) foreach($window in $windows){ $p=Get-Process -Id $window.Current.ProcessId -ErrorAction SilentlyContinue if($null -eq $p -or $p.ProcessName -ne 'Weixin'){continue} $view=$window.FindFirst($scope,(New-Object System.Windows.Automation.PropertyCondition($ae::AutomationIdProperty,'MainView'))) if($null -eq $view){continue} $input=$window.FindFirst($scope,(New-Object System.Windows.Automation.PropertyCondition($ae::AutomationIdProperty,'chat_input_field'))) $value=$input.GetCurrentPattern([System.Windows.Automation.ValuePattern]::Pattern).Current.Value $sha=[Security.Cryptography.SHA256]::Create() try{return [Convert]::ToBase64String($sha.ComputeHash([Text.Encoding]::UTF8.GetBytes($value)))}finally{$sha.Dispose()} } throw 'Cannot independently verify the draft; do not accept mutation protection as tested.' } $before=Get-DraftDigest & $exe inspect-ui --output "$directory\locked-ui.json" --timeout 20 | Out-Null $inspectCode=$LASTEXITCODE $smoke=(& $exe smoke --output "$directory\smoke-ui.json" --timeout 20 | Out-String) | ConvertFrom-Json $smokeCode=$LASTEXITCODE $sent=(& $exe chat send --text ('wx-agent-locked-'+[Guid]::NewGuid().ToString('N')) --timeout 20 | Out-String) | ConvertFrom-Json $sendCode=$LASTEXITCODE $listener=(& $exe chat monitor --seconds 1 --state-file "$directory\state.json" --timeout 5 | Out-String) | ConvertFrom-Json $listenerCode=$LASTEXITCODE $after=Get-DraftDigest $result=@{DoctorExit=$doctorCode;InputDesktopAvailable=$doctor.InputDesktopAvailable;InspectExit=$inspectCode; SmokeExit=$smokeCode;SmokeError=$smoke.error;SendExit=$sendCode;SendError=$sent.error; ListenerExit=$listenerCode;ListenerError=$listener.error;CheckpointCreated=(Test-Path "$directory\state.json");DraftUnchanged=($before -ceq $after); BinarySha256=(Get-FileHash $exe -Algorithm SHA256).Hash} $result.Success=($doctorCode -ne 0 -and $smokeCode -ne 0 -and $sendCode -ne 0 -and $listenerCode -ne 0 -and $smoke.error -eq 'SessionLocked' -and $sent.error -eq 'SessionLocked' -and $listener.error -eq 'SessionLocked' -and !$result.CheckpointCreated -and $result.DraftUnchanged) $result | ConvertTo-Json -Depth 5 | Set-Content "$directory\summary.json" -Encoding UTF8 if(!$result.Success){exit 1}