Last active
April 2, 2025 23:01
-
-
Save romero126/8d178f82a162dae067a759963d41c96e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="800" Height="600" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,0,0,0" Background="#35333a" BorderThickness="0" BorderBrush="#666374" Foreground="#514e5d" OpacityMask="#5b586d" Name="LoginPageWPF" WindowStartupLocation="CenterScreen" ResizeMode="CanResizeWithGrip" Title="TEAMS MIGRATION TOOL" WindowChrome.IsHitTestVisibleInChrome="True"> | |
<Window.Resources> | |
<ResourceDictionary> | |
<Style TargetType="Button" x:Key="TabButton"> | |
<Setter Property="Background" Value="#E0E0E2"/> | |
<Setter Property="Foreground" Value="#000000"/> | |
<Setter Property="BorderThickness" Value="0"/> | |
<Setter Property="FontWeight" Value="Bold"/> | |
<Setter Property="FontSize" Value="13"/> | |
<Setter Property="TextBlock.TextAlignment" Value="Center"/> | |
<Style.Resources> | |
<Style TargetType="Border"> | |
<Setter Property="CornerRadius" Value="7"/> | |
</Style> | |
</Style.Resources> | |
</Style> | |
<Style TargetType="TextBox" x:Key="TBOX"> | |
<Setter Property="Background" Value="#ffffff"/> | |
<Setter Property="Foreground" Value="#000000"/> | |
<Setter Property="FontSize" Value="13"/> | |
<Setter Property="BorderThickness" Value=".7"/> | |
<Style.Resources> | |
<Style TargetType="Border"> | |
<Setter Property="CornerRadius" Value="7"/> | |
</Style> | |
</Style.Resources> | |
</Style> | |
<Style TargetType="PasswordBox" x:Key="PBOX"> | |
<Setter Property="Background" Value="#ffffff"/> | |
<Setter Property="Foreground" Value="#000000"/> | |
<Setter Property="BorderThickness" Value=".7"/> | |
<Style.Resources> | |
<Style TargetType="Border"> | |
<Setter Property="CornerRadius" Value="7"/> | |
</Style> | |
</Style.Resources> | |
</Style> | |
</ResourceDictionary> | |
</Window.Resources> | |
<Grid Background="#ffffff" ShowGridLines="False" Name="MainGrid" Margin="0,-1,0,1"> | |
<Grid.RowDefinitions> | |
<RowDefinition Height="25"/> | |
<RowDefinition Height="150*"/> | |
<RowDefinition Height="5"/> | |
<RowDefinition Height="300*"/> | |
</Grid.RowDefinitions> | |
<Grid.ColumnDefinitions> | |
<ColumnDefinition Width="25"/> | |
<ColumnDefinition Width="*"/> | |
<ColumnDefinition Width="25"/> | |
</Grid.ColumnDefinitions> | |
<Button Name="ColorBT" Content="☀" Background="#ffffff" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" BorderThickness="0" Width="20" Height="20" Margin="0" Grid.Row="0" Grid.Column="2"/> | |
<Button Name="LeftBT" Content="◀" Grid.Row="1" Grid.Column="0" Background="#ffffff" Foreground="#B78CDE" BorderThickness="0" HorizontalAlignment="Left" VerticalAlignment="Center" Width="20" Margin="0" Height="20"/> | |
<Button Name="RightBT" Content="▶" Grid.Row="1" Grid.Column="2" Background="#ffffff" Foreground="#B78CDE" BorderThickness="0" HorizontalAlignment="Right" VerticalAlignment="Center" Width="20" Margin="2" Height="20"/> | |
<TabControl Name="TabNav" Grid.Row="1" Grid.Column="1" SelectedIndex="1" Padding="-1"> | |
<TabItem Name="ConnectGraphTab" Header="Tab 1" Visibility="Collapsed"> | |
<Grid Name="ConnectGraphGrid" Background="#ffffff" Margin="0"> | |
<Grid.ColumnDefinitions> | |
<ColumnDefinition Width="50*"/> | |
<ColumnDefinition Width="50*"/> | |
</Grid.ColumnDefinitions> | |
<Button Name="SelectSourceTenantBT" Grid.Column="0" Style="{StaticResource TabButton}" Content="Select Source" Margin="0,0,0,40" Height="24" Width="200" IsDefault="True" VerticalAlignment="Top"/> | |
<TextBlock Name="OR1" Foreground="#000000" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Top" Text="-OR-" FontSize="12" Height="18" Margin="0,22,0,0"/> | |
<Button Name="AddSourceTenantBT" Grid.Column="0" Style="{StaticResource TabButton}" Content="Add Source" Margin="0,40,0,0" Height="24" Width="200" IsDefault="True" VerticalAlignment="Top"/> | |
<Button Name="SelectDestTenantBT" Grid.Column="1" Style="{StaticResource TabButton}" Content="Select Destination" Margin="0,0,0,40" Height="24" Width="200" IsDefault="True" VerticalAlignment="Top"/> | |
<TextBlock Name="OR2" Foreground="#000000" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Top" Text="-OR-" FontSize="12" Height="18" Margin="0,22,0,0"/> | |
<Button Name="AddDestTenantBT" Grid.Column="1" Style="{StaticResource TabButton}" Content="Add Destination" Margin="0,40,0,0" Height="24" Width="200" IsDefault="True" VerticalAlignment="Top"/> | |
<Button Name="ConnectGraphBT" Grid.Column="0" Grid.ColumnSpan="2" Style="{StaticResource TabButton}" Content="Connect Graph" Margin="0,80,0,0" Height="24" Width="200" IsDefault="True" VerticalAlignment="Top"/> | |
</Grid> | |
</TabItem> | |
<TabItem Name="SelectSourceTab" Grid.Row="1" Header="Tab 2" Visibility="Collapsed"> | |
<Grid Name="SelectSourceGrid" Background="#ffffff" Margin="0"> | |
<Button Name="SelectSourceBT" Style="{StaticResource TabButton}" Content="Select source teams" Height="25" Width="200" Margin="0,0,0,0"/> | |
<TextBlock Name="SelectSourceTB" FontStyle="Italic" Foreground="#3dfc03" HorizontalAlignment="Center" VerticalAlignment="Bottom" Text=" " FontSize="14" Height="21"/> | |
</Grid> | |
</TabItem> | |
<TabItem Name="ViewTeamTab" Grid.Row="1" Header="Tab 3" Visibility="Collapsed"> | |
<Grid Name="ViewTeamGrid" Background="#ffffff" Margin="0"> | |
<Button Name="ViewTeamBT" Style="{StaticResource TabButton}" Content="View selected teams" Height="25" Width="200" Margin="0,0,0,0"/> | |
<TextBlock Name="ViewTeamTB" FontStyle="Italic" Foreground="#3dfc03" HorizontalAlignment="Center" VerticalAlignment="Bottom" Text=" " FontSize="14" Height="21"/> | |
</Grid> | |
</TabItem> | |
<TabItem Name="CloneTeamTab" Grid.Row="1" Header="Tab 4" Visibility="Collapsed"> | |
<Grid Name="CloneTeamGrid" Background="#ffffff" Margin="0"> | |
<Button Name="CloneTeamBT" Style="{StaticResource TabButton}" Content="Clone teams" Height="25" Width="200" Margin="0,0,0,0"/> | |
<TextBlock Name="CloneTeamTB" FontStyle="Italic" Foreground="#3dfc03" HorizontalAlignment="Center" VerticalAlignment="Bottom" Text=" " FontSize="14" Height="21"/> | |
</Grid> | |
</TabItem> | |
<TabItem Name="SnapFileTab" Grid.Row="1" Header="Tab 5" Visibility="Collapsed"> | |
<Grid Name="SnapFileGrid" Background="#ffffff" Margin="0"> | |
<Button Name="SnapFileBT" Style="{StaticResource TabButton}" Content="Backup team files" Height="25" Width="200" Margin="0,0,0,0"/> | |
<TextBlock Name="SnapFileTB" FontStyle="Italic" Foreground="#3dfc03" HorizontalAlignment="Center" VerticalAlignment="Bottom" Text=" " FontSize="14" Height="21"/> | |
</Grid> | |
</TabItem> | |
<TabItem Name="CloneChatTab" Grid.Row="1" Header="Tab 6" Visibility="Collapsed"> | |
<Grid Name="CloneChatGrid" Background="#ffffff" Margin="0"> | |
<Button Name="CloneChatBT" Style="{StaticResource TabButton}" Content="Clone chat messages" Height="25" Width="200" Margin="0,0,0,0"/> | |
<TextBlock Name="CloneChatTB" FontStyle="Italic" Foreground="#3dfc03" HorizontalAlignment="Center" VerticalAlignment="Bottom" Text=" " FontSize="14" Height="21"/> | |
</Grid> | |
</TabItem> | |
<TabItem Name="MigrateFileTab" Grid.Row="1" Header="Tab 7" Visibility="Collapsed"> | |
<Grid Name="MigrateFileGrid" Background="#ffffff" Margin="0"> | |
<Button Name="MigrateFileBT" Style="{StaticResource TabButton}" Content="Migrate files" Height="25" Width="200" Margin="0,0,0,0"/> | |
<TextBlock Name="MigrateFileTB" FontStyle="Italic" Foreground="#3dfc03" HorizontalAlignment="Center" VerticalAlignment="Bottom" Text=" " FontSize="14" Height="21"/> | |
</Grid> | |
</TabItem> | |
</TabControl> | |
<Button Name="Circle1" Style="{StaticResource TabButton}" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Bottom" Height="10" Width="10" Margin="0,0,120,0"/> | |
<Button Name="Circle2" Style="{StaticResource TabButton}" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Bottom" Height="10" Width="10" Margin="0,0,80,0"/> | |
<Button Name="Circle3" Style="{StaticResource TabButton}" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Bottom" Height="10" Width="10" Margin="0,0,40,0"/> | |
<Button Name="Circle4" Style="{StaticResource TabButton}" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Bottom" Height="10" Width="10" Margin="0,0,0,0"/> | |
<Button Name="Circle5" Style="{StaticResource TabButton}" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Bottom" Height="10" Width="10" Margin="40,0,0,0"/> | |
<Button Name="Circle6" Style="{StaticResource TabButton}" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Bottom" Height="10" Width="10" Margin="80,0,0,0"/> | |
<Button Name="Circle7" Style="{StaticResource TabButton}" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Bottom" Height="10" Width="10" Margin="120,0,0,0"/> | |
<GridSplitter Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="3" Height="5" Background="#ffffff" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/> | |
<DataGrid Name="DataGrid" ScrollViewer.PanningMode="None" ItemsSource="{Binding gridData}" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="3" Background="#FFFFFF" Margin="0,0,0,0" AlternatingRowBackground="LightBlue" AlternationCount="2" HorizontalGridLinesBrush="#FFBBBBBB" VerticalGridLinesBrush="#FFBBBBBB" HorizontalScrollBarVisibility="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/> | |
</Grid> | |
</Window> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Import-Module "$PSScriptRoot\..\Module\WindowsPresentationFramework" -Force | |
. "$PSScriptRoot\WindowsPresentationFramework.ps1" | |
#Region ThreadSafe | |
# Bind Variables | |
[WindowsPresentationFrameworkThreadSafe()] | |
[PSObject] $Variable = "Herro World from Proxy Scope" | |
[WindowsPresentationFrameworkThreadSafe()] | |
$Sync = [hashtable]::Synchronized(@{}) | |
[WindowsPresentationFrameworkThreadSafe()] | |
[PSCustomObject] $State = [PSCustomObject]@{} | |
# Fastest State | |
[WindowsPresentationFrameworkThreadSafe()] | |
[System.Collections.ObjectModel.ObservableCollection[Object]] $Log = [System.Collections.ObjectModel.ObservableCollection[Object]]::new() | |
function Write-Log | |
{ | |
[WindowsPresentationFrameworkThreadSafe()] | |
[CmdletBinding()] | |
param( | |
[Parameter(Mandatory)] | |
[string] $Message | |
) | |
$item = [PSCustomObject]@{ | |
Id = [Guid]::NewGuid().Guid | |
TimeStamp = [DateTime]::Now | |
Message = $Message | |
IsAsync = $false | |
} | |
if ([Runspace]::DefaultRunspace.Name -ne "AsyncOperation") | |
{ | |
$Log.Add($item) | |
} | |
else { | |
$item.IsAsync = $true | |
Start-Dispatch -Sender $Log -Event $item -ScriptBlock { | |
param($sender, $event) | |
[void]$sender.Add($event) | |
} | |
} | |
} | |
#EndRegion ThreadSafe | |
$Script:PSTeamsMigratePath = Join-Path -Path $Env:USERPROFILE -ChildPath '.PSTeamsMigrate' | |
$Script:ConfigPath = Join-Path -Path $PSTeamsMigratePath -ChildPath 'Configurations' | |
$Script:TenantPath = Join-Path -Path $ConfigPath -ChildPath 'Tenants' | |
if (-not ($null = Test-Path $TenantPath)) { | |
$ItemSplat = @{ | |
Type = 'Directory' | |
Force = $true | |
ErrorAction = 'SilentlyContinue' | |
} | |
$null = New-Item $PSTeamsMigratePath @ItemSplat | |
$null = New-Item $ConfigPath @ItemSplat | |
$null = New-Item $TenantPath @ItemSplat | |
} | |
function Select-Tenant { | |
(Get-ChildItem $TenantPath -Directory | Where-Object { | |
$_.Name -ne 'Files' | |
} | Select-Object Name | Out-GridView -Title 'Select the tenant and click OK' -OutputMode Single).name | |
} | |
function Select-Source | |
{ | |
[WindowsPresentationFrameworkEventBinding("SelectSourceTenantBT", "Click")] | |
[CmdletBinding()] | |
param($sender, $event) | |
Write-Host "Click from", $sender.Name | |
#$Script:SourceConnect = Select-Tenant | |
#$Script:SourceConfig = Join-Path $TenantPath -ChildPath "$SourceConnect\Config.xml" | |
#$Script:SourceCred = Join-Path $TenantPath -ChildPath "$SourceConnect\Cred.xml" | |
#$State.AppHash['SourceConnect'] = $SourceConnect | |
#$State.AppHash['SourceConfig'] = $SourceConfig | |
#$State.AppHash['SourceCred'] = $SourceCred | |
async -Passthru { | |
$variable = [Guid]::NewGuid().Guid | |
$sync.Value = "Rubbish" | |
} | await | Out-Host | Write-Host | |
$variable | out-host | |
$sync | Out-Host | |
} | |
function Add-Source | |
{ | |
[WindowsPresentationFrameworkEventBinding("AddSourceTenantBT", "Click")] | |
[CmdletBinding()] | |
param($sender, $event) | |
Write-Host "Click from", $sender.Name | |
# This is fast | |
async { | |
$ts = [DateTime]::Now | |
foreach ($i in 0..1000) | |
{ | |
Write-Log -Message "* Long running Asyncronous Loop" | |
#Start-Sleep -Milliseconds 20 | |
} | |
$longTask = [DateTime]::Now - $ts | |
#Write-Log -Message "Finished at $ts" | |
Write-Log -Message "Duration was $LongTask" | |
} | |
} | |
function Select-Destination | |
{ | |
[WindowsPresentationFrameworkEventBinding("SelectDestTenantBT", "Click")] | |
[CmdletBinding()] | |
param($sender, $event) | |
$Script:DestConnect = Select-Tenant | |
$Script:DestConfig = Join-Path $TenantPath -ChildPath "$DestConnect\Config.xml" | |
$Script:DestCred = Join-Path $TenantPath -ChildPath "$DestConnect\Cred.xml" | |
$State.AppHash['DestConnect'] = $DestConnect | |
$State.AppHash['DestConfig'] = $DestConfig | |
$State.AppHash['DestCred'] = $DestCred | |
} | |
function Add-Destination | |
{ | |
[WindowsPresentationFrameworkEventBinding("AddDestTenantBT", "Click")] | |
[CmdletBinding()] | |
param($sender, $event) | |
Register-TeamsGraphApplication | |
} | |
function Connect-SourceAndDestination | |
{ | |
[WindowsPresentationFrameworkEventBinding("ConnectGraphBT", "Click")] | |
[CmdletBinding()] | |
param($sender, $event) | |
Start-Async { | |
Connect-GTeams | |
}} | |
function Get-Source | |
{ | |
[WindowsPresentationFrameworkEventBinding("SelectSourceBT", "Click")] | |
[CmdletBinding()] | |
param($sender, $event) | |
$State.AppHash['PSTeamsMigratePath'] = $PSTeamsMigratePath | |
$State.AppHash['ConfigPath'] = $ConfigPath | |
$State.AppHash['TenantPath'] = $TenantPath | |
Get-SourceTeam | |
Get-SourceChannel | |
} | |
function Start-GetMap | |
{ | |
[WindowsPresentationFrameworkEventBinding("ViewTeamBT", "Click")] | |
[CmdletBinding()] | |
param($sender, $event) | |
Get-Map | Out-GridView -Title 'Current mapping between source and target' | |
} | |
function Start-Clone | |
{ | |
[WindowsPresentationFrameworkEventBinding("CloneTeamBT", "Click")] | |
[CmdletBinding()] | |
param($sender, $event) | |
Get-Dupe | |
Write-TargetTeamsAndChannels | |
Start-Sleep -Seconds 20 # this could probably be shorter now that we've identified the provisioning issue. Commenting for later | |
Get-DriveID | |
} | |
function Circle_Click { | |
#function Set-Circle { | |
[WindowsPresentationFrameworkEventBinding("Circle1", "Click")] | |
[WindowsPresentationFrameworkEventBinding("Circle2", "Click")] | |
[WindowsPresentationFrameworkEventBinding("Circle3", "Click")] | |
[WindowsPresentationFrameworkEventBinding("Circle4", "Click")] | |
[WindowsPresentationFrameworkEventBinding("Circle5", "Click")] | |
[WindowsPresentationFrameworkEventBinding("Circle6", "Click")] | |
[WindowsPresentationFrameworkEventBinding("Circle7", "Click")] | |
[CmdletBinding()] | |
param($sender, $event) | |
$controlList = $Circle1, $Circle2, $Circle3, $Circle4, $Circle5, $Circle6, $Circle7 | |
$tabNavList = $ConnectGraphTab, $SelectSourceTab, $ViewTeamTab, $CloneTeamTab, $SnapFileTab, $CloneChatTab, $MigrateFileTab | |
foreach ($control in $controlList) { | |
if ($control -eq $sender) { | |
$sender.Height = 15 | |
$sender.Width = 15 | |
$sender.Background = "#B78CDE" | |
continue | |
} | |
$control.Height = 10 | |
$control.Width = 10 | |
$control.Background = "#E0E0E2" | |
} | |
# Set Tab to be visible | |
$tabIndex = $controlList.IndexOf($sender) | |
$TabNav.SelectedItem = $tabNavList[$tabIndex] | |
} | |
function LeftRightBT_Click { | |
[WindowsPresentationFrameworkEventBinding("LeftBT", "Click")] | |
[WindowsPresentationFrameworkEventBinding("RightBT", "Click")] | |
[CmdletBinding()] | |
param($sender, $event) | |
$controlList = $Circle1, $Circle2, $Circle3, $Circle4, $Circle5, $Circle6, $Circle7 | |
$tabNavList = $ConnectGraphTab, $SelectSourceTab, $ViewTeamTab, $CloneTeamTab, $SnapFileTab, $CloneChatTab, $MigrateFileTab | |
$circle = $controlList.Where({ | |
$_.Height -eq 15 -and | |
$_.Width -eq 15 | |
}) | |
$pos = $controlList.IndexOf($circle[0]) | |
switch ($sender.Name) | |
{ | |
"LeftBT" { $pos = $pos - 1 } | |
"RightBT" { $pos = $pos + 1 } | |
} | |
if ($pos -lt 0) { | |
$pos = $controlList.Count - 1 | |
} | |
elseif ($pos -ge $controlList.Count) { | |
$pos = 0 | |
} | |
Circle_Click $controlList[$pos] | |
} | |
function DataGrid_ScrollEventChanged | |
{ | |
[WindowsPresentationFrameworkEventBinding("DataGrid", "System.Windows.Controls.ScrollViewer", "ScrollChangedEvent")] | |
[CmdletBinding()] | |
param($sender, $event) | |
if ($DataGrid.Items.Count -eq 0) { return } | |
$DataGrid.ScrollIntoView( | |
$DataGrid.Items[$DataGrid.Items.Count - 1] | |
); | |
} | |
function LoginPageWPF_Loaded { | |
[WindowsPresentationFrameworkEventBinding("LoginPageWPF", "Loaded")] | |
[CmdletBinding()] | |
param($sender, $event) | |
$sender.Activate() | |
$sender.Focus() | |
Circle_Click $Circle1 | |
# Set Binding | |
# This should Syncronize across different locations | |
$DataGrid.ItemsSource = $Log | |
Write-Log -Message "Initial Thread" | |
# async { | |
# $ts = [DateTime]::Now | |
# foreach ($i in 0..500) | |
# { | |
# Write-Log -Message "* Long running Asyncronous Loop" | |
# } | |
# $longTask = $ts - [DateTime]::Now | |
# Write-Log -Message "Finished at $ts" | |
# Write-Log -Message "Duration was $LongTask" | |
# | |
# } | |
Write-Log -Message "* Current Thread Called" | |
async { | |
# This fires but fails as Write-Log does not exist in the Dispatchers context | |
Start-Dispatch { | |
Write-Log "Async/Dispatch/Log" | |
} | |
} | |
} | |
Import-Window -Path $PSScriptRoot\KevWindow.xaml -ShowDialog |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add-Type -AssemblyName PresentationCore, PresentationFramework | |
function Import-Window { | |
[CmdletBinding()] | |
param( | |
[Parameter(Mandatory)] | |
[System.IO.FileInfo]$Path, | |
[Parameter()] | |
[switch] $ShowDialog, | |
[object] $Type | |
) | |
begin { | |
if (-not $Path.Exists) { | |
Write-Error -Message "Path to xml does not exist" -Category OpenError -ErrorAction Stop | |
} | |
$PathScript = [System.IO.FileInfo]("{0}.ps1" -f $Path.FullName) | |
if (-not $PathScript.Exists) { | |
Write-Error -Message "Path to ps1 does not exist" -Category OpenError -ErrorAction Stop | |
} | |
} | |
process { | |
$xamlRaw = Get-Content $Path -Raw | |
$xaml = [xml]$xamlRaw | |
#https://github.com/GetFunctional/DillyDally/blob/6a9f6cd5fc5be5282602cb3fc38d5d2c90622bfb/GF.DillyDally.Wpf/GF.DillyDally.Wpf.Client/Core/DataTemplates/DataTemplateFactory.cs | |
# SetApp | |
# $xamlTypeMapper = [System.Windows.Markup.XamlTypeMapper]::new($type.Assembly.FullName) | |
# Build Parser Context for XMLNS | |
# Quick Notes: This allows you to specify a xmlnamespace like x:name="value" | |
$windowParserContext = New-Object System.Windows.Markup.ParserContext | |
$xmlNamespaceManager = [System.Xml.XmlNamespaceManager]::new($xaml.NameTable) | |
foreach ($attribute in $xaml.Window.Attributes) | |
{ | |
if ($attribute.Name.StartsWith("xmlns")) | |
{ | |
# The commented out section is for adding a mapping to the XamlTypeMapper However it does not work properly | |
$contextName = $attribute.LocalName | |
if ($attribute.LocalName -eq "xmlns") { | |
$contextName = "" | |
} | |
$type = $null | |
if ($attribute.Value -match "clr-namespace:") { | |
# Note: This will only work types created in an assembly that is currently loaded in the AppDomain | |
# This will not resolve PowerShell class objects as they are not bound to an assembly inside the TypeName lookup in the AppDomain | |
$typeName = $attribute.Value.Replace("clr-namespace:", "") | |
$type = [System.Reflection.TypeInfo]::GetType($typeName) | |
if ($type -ne $null) { | |
Write-Verbose -Message "Resolved type $typeName to be bound to window" -Category ObjectNotFound -ErrorAction Stop | |
[void]$xamlTypeMapper.AddMappingProcessingInstruction($contextName, $type.NameSpace, $type.Assembly.GetName().FullName) | |
} else { | |
Write-Verbose -Message "Could not resolve type $typeName to be bound to window" -Category ObjectNotFound -ErrorAction Stop | |
} | |
} | |
[void]$windowParserContext.XmlnsDictionary.Add($contextName, $attribute.Value) | |
[void]$xmlNamespaceManager.AddNameSpace($contextName, $attribute.Value) | |
} | |
} | |
$windowParserContext.XamlTypeMapper = $xamlTypeMapper | |
[WindowsPresentationFrameworkThreadSafe()]$Window = [Windows.Markup.XamlReader]::Parse($xamlRaw, $windowParserContext) | |
Set-Variable -Name Window -Value $Window -Scope 1 | |
if ($Window.Name -ne $null) { | |
Set-Variable -Name $Window.Name -Value $Window -Scope 1 | |
} | |
$resolvedNodes = @{} | |
foreach ($namespace in $xmlNamespaceManager.ForEach({$_})) | |
{ | |
$nodeQuery = "{0}:Name" -f $namespace | |
if ([string]::IsNullOrEmpty($namespace)) { $nodeQuery = "Name" } | |
foreach ($node in $xaml.SelectNodes("//*[@$nodeQuery]", $xmlNamespaceManager)) | |
{ | |
# Set the node in the Script Scope | |
$nodeName = $node.Name | |
$nodeValue = $Window.FindName($node.Name) | |
#[void]$resolvedNodes.Add($nodeName, $nodeValue) | |
$resolvedNodes[$nodeName] = $nodeValue | |
$variable = Set-Variable -Passthru -Name $nodeName -Value $nodeValue # -Scope 2 | |
$variable.Attributes.Add( [WindowsPresentationFrameworkThreadSafeAttribute]::new()) | |
} | |
} | |
# Get-Command is too slow for this operation, we need to find a way to optimize this | |
#$commands = Get-Command -CommandType Function | |
$commands = Get-ChildItem Function: | |
foreach ($command in $commands) { | |
if ($null -eq $command.ScriptBlock.Attributes) { continue } | |
$isBinding = $command.ScriptBlock.Attributes.FindAll( | |
{ | |
$args[0].TypeId.Name -eq "WindowsPresentationFrameworkEventBindingAttribute" | |
} | |
) | |
if (-not $isBinding) { | |
continue | |
} | |
# Apply Bindings to the Window | |
foreach ($binding in $isBinding) { | |
try { | |
if ($binding.isSimple) { | |
$control = $resolvedNodes.Item( $binding.Name ) | |
if ($control -ne $null) { | |
$null = $control."Add_$($binding.EventName)"( $command.ScriptBlock ) | |
} | |
} | |
else { | |
$control = $window.FindName($binding.Name) | |
if ($control -ne $null) { | |
$handlerEvent = ($binding.ControlName -as [Type])::$($binding.EventName) | |
$control.AddHandler( | |
$handlerEvent, | |
$command.ScriptBlock -as ($handlerEvent.Handlertype) | |
) | |
} | |
} | |
} | |
catch { | |
$exceptionMessage = "Canning bind {0} to control {1} with the event {2}" -f $command.Name, $binding.Name, $binding.EventName | |
throw $_ | |
#$exceptionMessage | |
} | |
} | |
} | |
# Bind SessionState Variables | |
[void]$Window.Focus() | |
if ($ShowDialog) { | |
return $Window.ShowDialog() | |
} | |
$Window | |
} | |
end { | |
} | |
} | |
function Start-Async { | |
[CmdletBinding()] | |
[Alias("Async")] | |
param( | |
[Parameter(Mandatory)] | |
[ScriptBlock] $ScriptBlock, | |
[Parameter()] | |
[PSObject] $InputObject, | |
[switch] $Passthru | |
) | |
# Cleanup all completed runspaces | |
$AllRunspaces = Get-Runspace -Name AsyncOperation | |
$AllRunspaces.Where({ $_.RunspaceAvailability -eq "Available" }).ForEach({$_.Dispose() }) | |
if (-not $Script:Async) { | |
$Global:Async = @{} | |
$Global:Async.Pool = [RunspaceFactory]::CreateRunspacePool(1, [int]$env:NUMBER_OF_PROCESSORS+1) | |
$Global:Async.Pool.ApartmentState = "MTA" | |
$Global:Async.Pool.Open() | |
$Global:Async.Runspaces = New-Object "System.Collections.Generic.List[PSObject]" | |
} | |
$initialSessionState = [initialsessionstate]::CreateDefault() | |
$PSCallStack = (Get-PSCallStack)[1] | |
$result = (New-Object PSCustomObject @{ | |
Command = $PSCallStack.Command | |
Pipeline = $null | |
Output = [System.Collections.Arraylist]::new() | |
Status = $null | |
# DataAddedAction = $null | |
Index = $Global:Async.Runspaces.Count | |
}) | |
$runspace = [RunspaceFactory]::CreateRunspace($initialSessionState) | |
$runspace.ApartmentState = 'STA' | |
$runspace.ThreadOptions = 'ReuseThread' | |
$runspace.Open() | |
$runspace.Name = "AsyncOperation" | |
# Bind Functions to SessionState | |
$commands = $ExecutionContext.SessionState.InvokeCommand.GetCommands("*", [System.Management.Automation.CommandTypes]::Function, $true) | |
foreach ($command in $commands) { | |
if ($null -eq $command.ScriptBlock.Attributes) { continue } | |
$isBinding = $command.ScriptBlock.Attributes.FindAll({ $args[0].TypeId.Name -eq "WindowsPresentationFrameworkThreadSafeAttribute" }) | |
if (-not $isBinding) { continue } | |
#$initialSessionState.Commands.Add( | |
# (New-Object -TypeName System.Management.Automation.Runspaces.SessionStateFunctionEntry -ArgumentList $command.Name, $command.ScriptBlock.ToString().Replace("[WindowsPresentationFrameworkThreadSafe()]", "")) | |
#) | |
$runspace.SessionStateProxy.SetVariable("function:$($Command.Name)", $command.ScriptBlock.ToString().Replace("[WindowsPresentationFrameworkThreadSafe()]", "")) | |
} | |
# Bind Variables to SessionState | |
$variables = Get-Variable | |
foreach ($variable in $variables) | |
{ | |
$isBinding = $variable.Attributes.Where({$_.TypeId.Name -eq "WindowsPresentationFrameworkThreadSafeAttribute"}) | |
if (-not $isBinding) { continue; } | |
$runspace.SessionStateProxy.SetVariable($variable.Name, $variable.Value) | |
} | |
# Create Pipeline | |
$pipeline = [PowerShell]::Create() | |
$pipeline.Runspace = $runspace | |
$null = $pipeline.AddScript($ScriptBlock) | |
$null = $pipeline.AddArgument($InputObject) | |
# Attach hooks | |
$StreamCallback = { | |
param( $value, $sender ) | |
$index = {0} | |
$Global:Async.Runspaces[$index].Output.Add($value[$sender.Index]) | |
} | |
$StreamCallBack = $StreamCallBack.ToString().Replace("{0}", $Global:Async.Runspaces.Count) | |
$StreamCallBack = [ScriptBlock]::Create($StreamCallback).GetNewClosure() | |
if (-not $Passthru) { | |
return [void]$pipeline.BeginInvoke() | |
} | |
$pipeline.Streams.Error.Add_DataAdded( $StreamCallback ) | |
# $pipeline.Streams.Progress.Add_DataAdded( $StreamCallback ) | |
$pipeline.Streams.Verbose.Add_DataAdded( $StreamCallback ) | |
$pipeline.Streams.Debug.Add_DataAdded( $StreamCallback ) | |
$pipeline.Streams.Warning.Add_DataAdded( $StreamCallback ) | |
$pipeline.Streams.Information.Add_DataAdded( $StreamCallback ) | |
#Bind Variables to SessionState | |
$result.Pipeline = $pipeline | |
$result.Status = $pipeline.BeginInvoke() | |
if ($Passthru) { | |
$Global:Async.Runspaces.Add( | |
$result | |
) | |
return $result | |
} | |
} | |
function Start-Dispatch { | |
[CmdletBinding()] | |
[WindowsPresentationFrameworkThreadSafe()] | |
[Alias("DAsync")] | |
param( | |
[Parameter(Mandatory)] | |
[ScriptBlock] $ScriptBlock, | |
[Parameter()] | |
[System.Windows.Threading.DispatcherPriority] $Priority = [System.Windows.Threading.DispatcherPriority]::Normal, | |
[Parameter()] | |
[object] $Sender = $null, | |
[Parameter()] | |
[object] $Event = $null | |
) | |
[void]$Window.Dispatcher.BeginInvoke( | |
$Priority, | |
[action[object, object]] $ScriptBlock.Ast.GetScriptBlock(), | |
$sender, | |
$event | |
) | |
} | |
function Wait-Async { | |
[CmdletBinding()] | |
[Alias("await")] | |
param( | |
[Parameter(Mandatory, ValueFromPipeline)] | |
[PSCustomObject] $InputObject | |
) | |
if (-not $InputObject) { return } | |
do { | |
if ($Window) { | |
# [void]$Window.Dispatcher.Invoke({ }, "Render") | |
# $Window.UpdateLayout() | |
} | |
Start-Sleep -Milliseconds 5 | |
} until ($InputObject.Status.IsCompleted -eq $true) | |
# Receive Jobs we waited for. | |
$InputObject.Pipeline.EndInvoke($InputObject.Status) | |
$InputObject.Output | |
# Cleanup runspaces | |
$InputObject.Pipeline.Runspace.Close() | |
$InputObject.Pipeline.Runspace.Dispose() | |
} | |
class WindowsPresentationFrameworkEventBindingAttribute : System.Attribute { | |
[string] $Name | |
[string] $EventName | |
[string] $ControlName | |
[bool] $isSimple = $false | |
WindowsPresentationFrameworkEventBindingAttribute([string]$Name, [string]$EventName) { | |
$this.isSimple = $true | |
$this.Name = $Name | |
$this.EventName = $EventName | |
} | |
WindowsPresentationFrameworkEventBindingAttribute([string]$Name, [string] $ControlName, [string] $EventName) { | |
$this.isSimple = $false | |
$this.Name = $Name | |
$this.ControlName = $ControlName | |
$this.EventName = $EventName | |
} | |
} | |
class WindowsPresentationFrameworkThreadSafeAttribute : System.Attribute { } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment