-
-
Notifications
You must be signed in to change notification settings - Fork 3
/
wpf.ps1
108 lines (94 loc) · 4.02 KB
/
wpf.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
Add-Type -AssemblyName PresentationFramework
Add-Type -Path "$PSScriptRoot\WpfInPowerShell\Toolkit\bin\Debug\Toolkit.dll"
[WpfToolkit.ViewModelBase]::InvokeCommand = $ExecutionContext.InvokeCommand
[WpfToolkit.ViewModelBase]::InitScript = {
param($self, $PropertyName)
$self |
Add-Member -MemberType ScriptMethod -Name "Set$PropertyName" -Value ([ScriptBlock]::Create("
param(`$value)
`$this.'$PropertyName' = `$value
`$this.OnPropertyChanged('$PropertyName')
")) -PassThru |
Add-Member -MemberType ScriptMethod -Name "Get$PropertyName" -Value ([ScriptBlock]::Create("
`$this.'$PropertyName'
"))
}
[WpfToolkit.ViewModelBase]::BackgroundWorkScript = {
# gets invoked when a background command is called
# user passes two scriptblocks
param ($work, $callback)
$scriptRoot = $PSScriptRoot
{
param($this, $o)
function log ($string) {
$string | Out-File -FilePath "$PSScriptRoot\log.txt" -Append
}
try {
log "Invoking background task"
log "`$this: $($this | Out-String)"
log "`$o: $($o | Out-String)"
log "`$callback: { $($callback | Out-String) }"
# store view model into hashtable so we can access
# it in the target runspace
# also store the callback that we will invoke via
# dispatcher when the main work is done
$syncHash = [hashtable]::Synchronized(@{
This = $this
Work = $work
Object = $o
CallBack = $callback
Root = $scriptRoot
})
$psCmd = [powershell]::Create()
$newRunspace = [RunspaceFactory]::CreateRunspace()
$newRunspace.Open()
$newRunspace.SessionStateProxy.SetVariable('syncHash', $syncHash)
$psCmd.Runspace = $newRunspace
$sb = {
$o = $syncHash.Object
$this = $syncHash.This
$root = $syncHash.Root
function log ($string) {
$string | Out-File -FilePath "$root\log.txt" -Append
}
# unbind those scriptblocks otherwise they would get bound to the
# original scope and block the execution
$work = [ScriptBlock]::Create($syncHash.Work)
$callback = [ScriptBlock]::Create($syncHash.Callback)
# invoke the main work
try {
$functionsToDefine = @{
Log = {
param($string)
$string | Out-File -FilePath "$root\log.txt" -Append
}
Dispatch = {
param($ScriptBlock)
[System.Windows.Threading.Dispatcher]::CurrentDispatcher.Invoke($ScriptBlock)
}
}
$variablesToDefine = [Collections.Generic.List[psvariable]]@()
$variablesToDefine.Add((Get-Variable "Root"))
$arguments = [Object[]]@($this, $o)
$output = $work.InvokeWithContext($functionsToDefine, $variablesToDefine, $arguments)
}
catch {
log "Invoking work failed with error $($error | Out-String)"
}
try {
[System.Windows.Threading.Dispatcher]::CurrentDispatcher.Invoke({
&$callback $syncHash.This $output
})
}
catch {
log "Invoking callback failed with error $($error | Out-String)"
}
}.GetNewClosure()
$psCmd.AddScript($sb)
$psCmd.BeginInvoke()
}
catch {
log "Invoking background task failed with error $($error | Out-String)"
}
}.GetNewClosure()
}