├── .gitattributes ├── .gitignore ├── Bin ├── LICENSE ├── cygcrypto-3.dll ├── cygwin1.dll ├── cygz.dll ├── iperf2.exe └── iperf3.exe ├── Examples ├── Example1.png ├── Example2.png └── Example3.png ├── LICENSE ├── PPerf.ps1 └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | 38 | # Directories potentially created on remote AFP share 39 | .AppleDB 40 | .AppleDesktop 41 | Network Trash Folder 42 | Temporary Items 43 | .apdisk 44 | PPerf.history.zip 45 | -------------------------------------------------------------------------------- /Bin/LICENSE: -------------------------------------------------------------------------------- 1 | "iperf, Copyright (c) 2014-2024, The Regents of the University of California, 2 | through Lawrence Berkeley National Laboratory (subject to receipt of any 3 | required approvals from the U.S. Dept. of Energy). All rights reserved." 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | (1) Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | (2) Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation and/ 13 | or other materials provided with the distribution. 14 | 15 | (3) Neither the name of the University of California, Lawrence Berkeley 16 | National Laboratory, U.S. Dept. of Energy nor the names of its contributors may 17 | be used to endorse or promote products derived from this software without 18 | specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 21 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 24 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 27 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | You are under no obligation whatsoever to provide any bug fixes, patches, or 32 | upgrades to the features, functionality or performance of the source code 33 | ("Enhancements") to anyone; however, if you choose to make your Enhancements 34 | available either publicly, or directly to Lawrence Berkeley National 35 | Laboratory, without imposing a separate written license agreement for such 36 | Enhancements, then you hereby grant the following license: a non-exclusive, 37 | royalty-free perpetual license to install, use, modify, prepare derivative 38 | works, incorporate into other computer software, distribute, and sublicense 39 | such enhancements or derivative works thereof, in binary and source code form. 40 | 41 | ===== 42 | 43 | This software contains source code (src/cjson.{c,h}) that is: 44 | 45 | Copyright (c) 2009-2017 Dave Gamble and cJSON contributors 46 | 47 | Permission is hereby granted, free of charge, to any person obtaining a copy 48 | of this software and associated documentation files (the "Software"), to deal 49 | in the Software without restriction, including without limitation the rights 50 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 51 | copies of the Software, and to permit persons to whom the Software is 52 | furnished to do so, subject to the following conditions: 53 | 54 | The above copyright notice and this permission notice shall be included in 55 | all copies or substantial portions of the Software. 56 | 57 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 58 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 59 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 60 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 61 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 62 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 63 | THE SOFTWARE. 64 | 65 | ===== 66 | 67 | This software contains source code (src/net.{c,h}) that is: 68 | 69 | This software was developed as part of a project at MIT. 70 | 71 | Copyright (c) 2005-2007 Russ Cox, 72 | Massachusetts Institute of Technology 73 | 74 | Permission is hereby granted, free of charge, to any person obtaining 75 | a copy of this software and associated documentation files (the 76 | "Software"), to deal in the Software without restriction, including 77 | without limitation the rights to use, copy, modify, merge, publish, 78 | distribute, sublicense, and/or sell copies of the Software, and to 79 | permit persons to whom the Software is furnished to do so, subject to 80 | the following conditions: 81 | 82 | The above copyright notice and this permission notice shall be 83 | included in all copies or substantial portions of the Software. 84 | 85 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 88 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 89 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 90 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 91 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 92 | 93 | === 94 | 95 | Contains parts of an earlier library that has: 96 | 97 | /* 98 | * The authors of this software are Rob Pike, Sape Mullender, and Russ Cox 99 | * Copyright (c) 2003 by Lucent Technologies. 100 | * Permission to use, copy, modify, and distribute this software for any 101 | * purpose without fee is hereby granted, provided that this entire notice 102 | * is included in all copies of any software which is or includes a copy 103 | * or modification of this software and in all copies of the supporting 104 | * documentation for such software. 105 | * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED 106 | * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY 107 | * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY 108 | * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. 109 | */ 110 | 111 | ===== 112 | 113 | This software contains source code (src/net.c) that is: 114 | 115 | /* 116 | * Copyright (c) 2001 Eric Jackson 117 | * 118 | * Redistribution and use in source and binary forms, with or without 119 | * modification, are permitted provided that the following conditions 120 | * are met: 121 | * 122 | * 1. Redistributions of source code must retain the above copyright 123 | * notice, this list of conditions and the following disclaimer. 124 | * 2. Redistributions in binary form must reproduce the above copyright 125 | * notice, this list of conditions and the following disclaimer in the 126 | * documentation and/or other materials provided with the distribution. 127 | * 3. The name of the author may not be used to endorse or promote products 128 | * derived from this software without specific prior written permission. 129 | * 130 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 131 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 132 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 133 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 134 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 135 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 136 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 137 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 138 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 139 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 140 | */ 141 | 142 | ===== 143 | 144 | This software contains source code (src/queue.h) that is: 145 | 146 | /* 147 | * Copyright (c) 1991, 1993 148 | * The Regents of the University of California. All rights reserved. 149 | * 150 | * Redistribution and use in source and binary forms, with or without 151 | * modification, are permitted provided that the following conditions 152 | * are met: 153 | * 1. Redistributions of source code must retain the above copyright 154 | * notice, this list of conditions and the following disclaimer. 155 | * 2. Redistributions in binary form must reproduce the above copyright 156 | * notice, this list of conditions and the following disclaimer in the 157 | * documentation and/or other materials provided with the distribution. 158 | * 3. Neither the name of the University nor the names of its contributors 159 | * may be used to endorse or promote products derived from this software 160 | * without specific prior written permission. 161 | * 162 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 163 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 164 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 165 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 166 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 167 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 168 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 169 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 170 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 171 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 172 | * SUCH DAMAGE. 173 | * 174 | * @(#)queue.h 8.5 (Berkeley) 8/20/94 175 | */ 176 | 177 | ===== 178 | 179 | This software contains source code (src/units.{c.h}) that is: 180 | 181 | /*--------------------------------------------------------------- 182 | * Copyright (c) 1999,2000,2001,2002,2003 183 | * The Board of Trustees of the University of Illinois 184 | * All Rights Reserved. 185 | *--------------------------------------------------------------- 186 | * Permission is hereby granted, free of charge, to any person 187 | * obtaining a copy of this software (Iperf) and associated 188 | * documentation files (the "Software"), to deal in the Software 189 | * without restriction, including without limitation the 190 | * rights to use, copy, modify, merge, publish, distribute, 191 | * sublicense, and/or sell copies of the Software, and to permit 192 | * persons to whom the Software is furnished to do 193 | * so, subject to the following conditions: 194 | * 195 | * 196 | * Redistributions of source code must retain the above 197 | * copyright notice, this list of conditions and 198 | * the following disclaimers. 199 | * 200 | * 201 | * Redistributions in binary form must reproduce the above 202 | * copyright notice, this list of conditions and the following 203 | * disclaimers in the documentation and/or other materials 204 | * provided with the distribution. 205 | * 206 | * 207 | * Neither the names of the University of Illinois, NCSA, 208 | * nor the names of its contributors may be used to endorse 209 | * or promote products derived from this Software without 210 | * specific prior written permission. 211 | * 212 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 213 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 214 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 215 | * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT 216 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 217 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 218 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE 219 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 220 | * ________________________________________________________________ 221 | * National Laboratory for Applied Network Research 222 | * National Center for Supercomputing Applications 223 | * University of Illinois at Urbana-Champaign 224 | * http://www.ncsa.uiuc.edu 225 | * ________________________________________________________________ 226 | * 227 | * stdio.c 228 | * by Mark Gates 229 | * and Ajay Tirumalla 230 | * ------------------------------------------------------------------- 231 | * input and output numbers, converting with kilo, mega, giga 232 | * ------------------------------------------------------------------- */ 233 | 234 | ===== 235 | 236 | This software contains source code (src/portable_endian.h) that is: 237 | 238 | // "License": Public Domain 239 | // I, Mathias Panzenböck, place this file hereby into the public domain. Use it at your own risk for whatever you like. 240 | 241 | ===== 242 | 243 | 244 | 245 | -------------------------------------------------------------------------------- /Bin/cygcrypto-3.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ili101/PPerf/f3afd6bf56c4d8a02b742560193757ed1bf4837c/Bin/cygcrypto-3.dll -------------------------------------------------------------------------------- /Bin/cygwin1.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ili101/PPerf/f3afd6bf56c4d8a02b742560193757ed1bf4837c/Bin/cygwin1.dll -------------------------------------------------------------------------------- /Bin/cygz.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ili101/PPerf/f3afd6bf56c4d8a02b742560193757ed1bf4837c/Bin/cygz.dll -------------------------------------------------------------------------------- /Bin/iperf2.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ili101/PPerf/f3afd6bf56c4d8a02b742560193757ed1bf4837c/Bin/iperf2.exe -------------------------------------------------------------------------------- /Bin/iperf3.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ili101/PPerf/f3afd6bf56c4d8a02b742560193757ed1bf4837c/Bin/iperf3.exe -------------------------------------------------------------------------------- /Examples/Example1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ili101/PPerf/f3afd6bf56c4d8a02b742560193757ed1bf4837c/Examples/Example1.png -------------------------------------------------------------------------------- /Examples/Example2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ili101/PPerf/f3afd6bf56c4d8a02b742560193757ed1bf4837c/Examples/Example2.png -------------------------------------------------------------------------------- /Examples/Example3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ili101/PPerf/f3afd6bf56c4d8a02b742560193757ed1bf4837c/Examples/Example3.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 ili101 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PPerf.ps1: -------------------------------------------------------------------------------- 1 | #requires -Version 5 2 | param($Work) 3 | 4 | # restart PowerShell with -noexit, the same script, and 1 5 | if ((!$Work) -and ($host.name -eq 'ConsoleHost')) 6 | { 7 | powershell.exe -noexit -file $MyInvocation.MyCommand.Path 1 8 | return 9 | } 10 | 11 | # Set Variables 12 | $SyncHash = [hashtable]::Synchronized(@{}) 13 | $SyncHash.Host = $host 14 | $SyncHash.IperfFolder = $PSScriptRoot + '\Bin' 15 | 16 | # UI Runspace 17 | $UiRunspace = [runspacefactory]::CreateRunspace() 18 | $UiRunspace.ApartmentState = 'STA' 19 | $UiRunspace.ThreadOptions = 'ReuseThread' 20 | $UiRunspace.Open() 21 | $UiRunspace.SessionStateProxy.SetVariable('syncHash',$SyncHash) 22 | 23 | # UI Script 24 | $UiPowerShell = [PowerShell]::Create().AddScript( 25 | { 26 | $SyncHash.host.ui.WriteVerboseLine(' UI Script Started') 27 | trap {$SyncHash.host.ui.WriteErrorLine("$_`nError was in Line {0}`n{1}" -f ($_.InvocationInfo.ScriptLineNumber, $_.InvocationInfo.Line))} 28 | 29 | function Write-Status 30 | { 31 | [CmdletBinding()] 32 | param 33 | ( 34 | [Parameter(Mandatory=$true, Position=0)] 35 | [String]$Text, 36 | 37 | [Parameter(Mandatory=$true, Position=1)] 38 | [String]$Colore 39 | ) 40 | $syncHash.Form.Dispatcher.invoke([action]{ 41 | if (![string]::IsNullOrWhitespace([System.Windows.Documents.TextRange]::new($SyncHash.IperfJobOutputTextBox.Document.ContentStart, $SyncHash.IperfJobOutputTextBox.Document.ContentEnd).Text)) 42 | { 43 | $SyncHash.IperfJobOutputTextBox.AppendText("`r") 44 | } 45 | 46 | $TextRange = [System.Windows.Documents.TextRange]::new($SyncHash.IperfJobOutputTextBox.Document.ContentEnd, $SyncHash.IperfJobOutputTextBox.Document.ContentEnd) 47 | $TextRange.Text = $Text 48 | $TextRange.ApplyPropertyValue([System.Windows.Documents.TextElement]::ForegroundProperty, [System.Windows.Media.Brushes]::$Colore) 49 | $SyncHash.IperfJobOutputTextBox.ScrollToEnd() 50 | }) 51 | } 52 | 53 | function Start-Iperf 54 | { 55 | $SyncHash.host.ui.WriteVerboseLine('Start-Iperf') 56 | if ($SyncHash.IperfJobMonitorRunspace.RunspaceStateInfo.State -eq 'Opened') 57 | { 58 | Write-Status -Text 'Iperf Already Running' -Colore 'Orange' 59 | } 60 | else 61 | { 62 | 63 | #Get-Job | Remove-Job -Force 64 | #$SyncHash.Remove('IperfJob') 65 | 66 | # Iperf Job Monitor with Register-ObjectEvent in Runspace 67 | $InitialSessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault() 68 | $InitialSessionState.Commands.Add((New-Object System.Management.Automation.Runspaces.SessionStateFunctionEntry -ArgumentList 'Stop-Iperf', (Get-Content Function:\Stop-Iperf))) 69 | $InitialSessionState.Commands.Add((New-Object System.Management.Automation.Runspaces.SessionStateFunctionEntry -ArgumentList 'Write-Status', (Get-Content Function:\Write-Status))) 70 | $SyncHash.IperfJobMonitorRunspace = [runspacefactory]::CreateRunspace($InitialSessionState) 71 | $SyncHash.IperfJobMonitorRunspace.ApartmentState = 'STA' 72 | $SyncHash.IperfJobMonitorRunspace.ThreadOptions = 'ReuseThread' 73 | $SyncHash.IperfJobMonitorRunspace.Open() 74 | $SyncHash.IperfJobMonitorRunspace.SessionStateProxy.SetVariable('syncHash',$SyncHash) 75 | $SyncHash.IperfJobMonitorRunspace.SessionStateProxy.SetVariable('CsvFilePath',$SyncHash.CsvFilePathTextBox.Text) 76 | $SyncHash.IperfJobMonitorRunspace.SessionStateProxy.SetVariable('Command',$SyncHash.CommandTextBox.Text) 77 | $SyncHash.IperfJobMonitorRunspace.SessionStateProxy.SetVariable('IperfVersion',$IperfVersion) 78 | $SyncHash.IperfJobMonitorRunspace.SessionStateProxy.SetVariable('IperfExe',$IperfExe) 79 | $SyncHash.IperfJobMonitorPowerShell = [PowerShell]::Create().AddScript( 80 | { 81 | trap {$SyncHash.host.ui.WriteErrorLine("$_`nError was in Line {0}`n{1}" -f ($_.InvocationInfo.ScriptLineNumber, $_.InvocationInfo.Line))} 82 | trap [System.Management.Automation.PipelineStoppedException] {$SyncHash.host.ui.WriteVerboseLine($_)} 83 | 84 | $SyncHash.host.ui.WriteVerboseLine('Start-Iperf Running') 85 | Set-Location -Path $SyncHash.IperfFolder 86 | 87 | try 88 | { 89 | $ErrorActionPreferenceOrg = $ErrorActionPreference 90 | if ($IperfVersion -eq 2) 91 | { 92 | 'Time,localIp,localPort,RemoteIp,RemotePort,Id,Interval,Transfer,Bitrate' | Out-File -FilePath $CsvFilePath 93 | Write-Status -Text ((Invoke-Expression -Command "$IperfExe -v") 2>&1) -Colore 'Blue' 94 | $ErrorActionPreference = 'stop' 95 | Invoke-Expression -Command $Command | Out-File -FilePath $CsvFilePath -Append 96 | } 97 | else 98 | { 99 | Set-Content -Path $CsvFilePath -Value $null 100 | #Write-Status -Text ((Invoke-Expression -Command "$IperfExe -v") -join ' ') -Colore 'Blue' 101 | Invoke-Expression -Command $Command 102 | 103 | if ($ErrorOut = Get-Content -Tail 5 -Path $CsvFilePath | Select-String -Pattern 'iperf3: error') 104 | { 105 | Write-Error -Message $ErrorOut -ErrorAction Stop 106 | } 107 | } 108 | } 109 | catch 110 | { 111 | Write-Status -Text $_ -Colore 'Red' 112 | Stop-Iperf 113 | } 114 | $ErrorActionPreference = $ErrorActionPreferenceOrg 115 | Write-Status -Text 'Iperf Finished' -Colore 'Green' 116 | Stop-Iperf 117 | 118 | #Get-EventSubscriber | Unregister-Event 119 | #$SyncHash.Remove('IperfJobMonitor') 120 | }) 121 | $SyncHash.IperfJobMonitorPowerShell.Runspace = $SyncHash.IperfJobMonitorRunspace 122 | $SyncHash.IperfJobMonitorHandle = $SyncHash.IperfJobMonitorPowerShell.BeginInvoke() 123 | } 124 | } 125 | 126 | function Stop-Iperf 127 | { 128 | $SyncHash.host.ui.WriteVerboseLine('Stop-Iperf') 129 | if ($SyncHash.IperfJobMonitorRunspace.RunspaceStateInfo.State -eq 'Opened') 130 | { 131 | $SyncHash.host.ui.WriteVerboseLine('Stop-Iperf Running') 132 | #$SyncHash.IperfJobMonitorPowerShell.EndInvoke($SyncHash.IperfJobMonitorHandle) 133 | $SyncHash.IperfJobMonitorRunspace.Close() 134 | $SyncHash.IperfJobMonitorPowerShell.Dispose() 135 | } 136 | } 137 | 138 | function Start-Analyzer 139 | { 140 | $SyncHash.host.ui.WriteVerboseLine('Start-Analyzer') 141 | if (!(Test-Path -Path $SyncHash.CsvFilePathTextBox.Text)) 142 | { 143 | Write-Status -Text 'File not found' -Colore 'Red' 144 | } 145 | elseif ($SyncHash.AnalyzerRunspace.RunspaceStateInfo.State -eq 'Opened') 146 | { 147 | Write-Status -Text 'Analyzer Already Running' -Colore 'Orange' 148 | } 149 | else 150 | { 151 | # Analyzer Runspace 152 | $InitialSessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault() 153 | $InitialSessionState.Commands.Add((New-Object System.Management.Automation.Runspaces.SessionStateFunctionEntry -ArgumentList 'Stop-Analyzer', (Get-Content Function:\Stop-Analyzer))) 154 | $InitialSessionState.Commands.Add((New-Object System.Management.Automation.Runspaces.SessionStateFunctionEntry -ArgumentList 'Write-Status', (Get-Content Function:\Write-Status))) 155 | $SyncHash.AnalyzerRunspace = [runspacefactory]::CreateRunspace($InitialSessionState) 156 | $SyncHash.AnalyzerRunspace.ApartmentState = 'STA' 157 | $SyncHash.AnalyzerRunspace.ThreadOptions = 'ReuseThread' 158 | $SyncHash.AnalyzerRunspace.Open() 159 | $SyncHash.AnalyzerRunspace.SessionStateProxy.SetVariable('syncHash',$SyncHash) 160 | $SyncHash.AnalyzerRunspace.SessionStateProxy.SetVariable('CsvFilePath',$SyncHash.CsvFilePathTextBox.Text) 161 | $SyncHash.AnalyzerRunspace.SessionStateProxy.SetVariable('LastX',$SyncHash.LastXTextBox.Text) 162 | $SyncHash.AnalyzerRunspace.SessionStateProxy.SetVariable('IperfVersion',$IperfVersion) 163 | $SyncHash.AnalyzerPowerShell = [powershell]::Create() 164 | $SyncHash.AnalyzerPowerShell.Runspace = $SyncHash.AnalyzerRunspace 165 | $null = $SyncHash.AnalyzerPowerShell.AddScript($AnalyzerScript) 166 | $SyncHash.AnalyzerHandle = $SyncHash.AnalyzerPowerShell.BeginInvoke() 167 | } 168 | } 169 | 170 | # Analyzer Runspace Script 171 | $AnalyzerScript = 172 | { 173 | $SyncHash.host.ui.WriteVerboseLine('Start-Analyzer Running') 174 | trap {$SyncHash.host.ui.WriteErrorLine("$_`nError was in Line {0}`n{1}" -f ($_.InvocationInfo.ScriptLineNumber, $_.InvocationInfo.Line))} 175 | trap [System.Management.Automation.PipelineStoppedException] {$SyncHash.host.ui.WriteVerboseLine($_)} 176 | 177 | $First = $true 178 | $Header = $null 179 | $AnalyzerDataLength = 0 180 | 181 | $ChartDataAction0 = [Action]{ 182 | $SyncHash.Chart.Series['Bitrate (Mbits/sec)'].Points.Clear() 183 | $SyncHash.Chart.Series['Transfer (MBytes)'].Points.Clear() 184 | $SyncHash.host.ui.WriteVerboseLine('Clear Data: ' + ($SyncHash.Chart.Series['Transfer (MBytes)'].Points.Count | Out-String)) 185 | } 186 | $SyncHash.Chart.Invoke($ChartDataAction0) 187 | 188 | Get-Content -Path $CsvFilePath -ReadCount 0 -Wait | ForEach-Object { 189 | trap {$SyncHash.host.ui.WriteErrorLine("$_`nError was in Line {0}`n{1}" -f ($_.InvocationInfo.ScriptLineNumber, $_.InvocationInfo.Line))} 190 | #$SyncHash.host.ui.WriteVerboseLine('Loop Data: ' + ($_ | Out-String)) ### 191 | $AnalyzerData = New-Object -TypeName System.Collections.Generic.List[System.Object] 192 | 193 | if ($IperfVersion -eq 2) 194 | { 195 | foreach ($Line in $_) 196 | { 197 | if ($Line -like '*Bitrate*') 198 | { 199 | $Header = $Line -split ',' 200 | } 201 | else 202 | { 203 | if ($First -and !$Header) 204 | { 205 | Write-Status -Text 'CSV Error' -Colore 'Red' 206 | Stop-Analyzer 207 | } 208 | else 209 | { 210 | $First = $false 211 | } 212 | 213 | $CsvLine = $Line | ConvertFrom-Csv -Header $Header 214 | $CsvLine.Bitrate = $CsvLine.Bitrate /1Mb 215 | $CsvLine.Transfer = $CsvLine.Transfer /1Mb 216 | if (!($CsvLine.Interval).StartsWith('0.0-') -or ($CsvLine.Interval -eq '0.0-1.0')) 217 | { 218 | $AnalyzerData.add($CsvLine) 219 | } 220 | else 221 | { 222 | $SyncHash.host.ui.WriteVerboseLine('Remove Total Line: ' + $CsvLine.Time) 223 | } 224 | } 225 | } 226 | } 227 | else 228 | { 229 | $Csv = $_ | Where-Object {$_ -match '\[...\]'} 230 | #$Csv = $a | Select-String -Pattern '\[...\]' 231 | foreach ($Line in $Csv) 232 | { 233 | $Line = $Line -replace '[][]' 234 | if ($Line -like ' ID *') 235 | { 236 | $Header = ($Line = $Line -replace 'Total Datagram','Total-Datagram' -replace 'Lost/Total Datagrams','Lost/Total-Datagrams') -split '\s+' | Where-Object {$_} 237 | $HeaderIndex = @() 238 | foreach ($Head in $Header) 239 | { 240 | $HeaderIndex += $Line.IndexOf($Head) 241 | } 242 | } 243 | elseif ($Header -and $Line -notlike '*connected to*' -and $Line -notlike '*sender*' -and $Line -notlike '*receiver*' -and $Line -cnotlike '*datagrams*') 244 | { 245 | $i=0 246 | $CsvLine = New-Object System.Object 247 | foreach ($Head in $Header) 248 | { 249 | if ($i -lt $HeaderIndex.Length-1) 250 | { 251 | $Cell = $Line.Substring($HeaderIndex[$i],$HeaderIndex[$i + 1] - $HeaderIndex[$i]) 252 | } 253 | else 254 | { 255 | $Cell = $Line.Substring($HeaderIndex[$i]) 256 | } 257 | 258 | if ($Head -eq 'Transfer') 259 | { 260 | $TransferData = $Cell.Trim() -split '\s+' 261 | if ($TransferData[1] -eq 'KBytes') 262 | { 263 | $Cell = $TransferData[0] /1kb 264 | } 265 | elseif ($TransferData[1] -eq 'GBytes') 266 | { 267 | $Cell = $TransferData[0] *1kb 268 | } 269 | } 270 | 271 | $i++ 272 | Add-Member -InputObject $CsvLine -NotePropertyName $Head -NotePropertyValue ("$Cell".Trim() -split '\s+')[0] 273 | } 274 | $AnalyzerData.add($CsvLine) 275 | } 276 | } 277 | } 278 | 279 | if ($AnalyzerData.Count -gt $LastX -and $LastX -gt 0) 280 | { 281 | $SyncHash.host.ui.WriteVerboseLine('Trim Data 1') 282 | $AnalyzerData = $AnalyzerData.GetRange($AnalyzerData.Count - $LastX, $LastX) 283 | } 284 | $SyncHash.host.ui.WriteVerboseLine('New Points: ' + $AnalyzerData.Count) 285 | 286 | if ($AnalyzerData.Count -gt 0) 287 | { 288 | if ($AnalyzerDataLength -eq 0 -and $AnalyzerData.Count -gt 1) 289 | { 290 | $ChartDataAction1 = [Action]{ 291 | $SyncHash.Chart.Series['Bitrate (Mbits/sec)'].Points.DataBindXY($AnalyzerData.Interval, $AnalyzerData.Bitrate) 292 | $SyncHash.Chart.Series['Transfer (MBytes)'].Points.DataBindXY($AnalyzerData.Interval, $AnalyzerData.Transfer) 293 | $SyncHash.host.ui.WriteVerboseLine('Show Data: ' + ($SyncHash.Chart.Series['Transfer (MBytes)'].Points.Count | Out-String)) 294 | } 295 | $SyncHash.Chart.Invoke($ChartDataAction1) 296 | } 297 | else 298 | { 299 | $ChartDataAction2 = [Action]{ 300 | while ($AnalyzerDataLength + $AnalyzerData.Count -gt $LastX -and $LastX -gt 0) 301 | { 302 | $SyncHash.Chart.Series['Bitrate (Mbits/sec)'].Points.RemoveAt(0) 303 | $SyncHash.Chart.Series['Transfer (MBytes)'].Points.RemoveAt(0) 304 | $Global:AnalyzerDataLength -- 305 | } 306 | foreach ($Point in $AnalyzerData) 307 | { 308 | $SyncHash.Chart.Series['Bitrate (Mbits/sec)'].Points.AddXY($Point.Interval, $Point.Bitrate) 309 | $SyncHash.Chart.Series['Transfer (MBytes)'].Points.AddXY($Point.Interval, $Point.Transfer) 310 | $SyncHash.host.ui.WriteVerboseLine('Add Data Point: ' + ($SyncHash.Chart.Series['Transfer (MBytes)'].Points.Count | Out-String)) 311 | } 312 | } 313 | $SyncHash.Chart.Invoke($ChartDataAction2) 314 | } 315 | $AnalyzerDataLength += $AnalyzerData.Count 316 | } 317 | else 318 | { 319 | $SyncHash.host.ui.WriteVerboseLine('Point Skipped') 320 | } 321 | $SyncHash.host.ui.WriteVerboseLine('Analyzer Loop End: ' + ($AnalyzerDataLength | Out-String)) 322 | } 323 | } 324 | 325 | function Stop-Analyzer 326 | { 327 | $SyncHash.host.ui.WriteVerboseLine('Stop-Analyzer') 328 | if ($SyncHash.AnalyzerRunspace.RunspaceStateInfo.State -eq 'Opened') 329 | { 330 | $SyncHash.host.ui.WriteVerboseLine('Stop-Analyzer Running') 331 | $SyncHash.AnalyzerRunspace.Close() 332 | $SyncHash.AnalyzerPowerShell.Dispose() 333 | } 334 | } 335 | 336 | function Set-IperfCommand 337 | { 338 | if ($SyncHash.ClientRadio.IsChecked) 339 | { 340 | $IperfMode = ' -c ' + $SyncHash.IpTextBox.Text 341 | $SyncHash.IpTextBox.IsEnabled = $true 342 | $IperfTime = ' -t ' + $SyncHash.TimeTextBox.Text 343 | $SyncHash.TimeTextBox.IsEnabled = $true 344 | } 345 | else 346 | { 347 | $IperfMode = ' -s' 348 | $SyncHash.IpTextBox.IsEnabled = $false 349 | $IperfTime = $null 350 | $SyncHash.TimeTextBox.IsEnabled = $false 351 | } 352 | 353 | if ($SyncHash.Version2Radio.IsChecked) 354 | { 355 | $IperfVersionParams = ' -y c' 356 | $Global:IperfVersion = 2 357 | $Global:IperfExe = '.\iperf2.exe' 358 | } 359 | else 360 | { 361 | $IperfVersionParams = ' -f m --logfile ' + $SyncHash.CsvFilePathTextBox.Text 362 | $Global:IperfVersion = 3 363 | $Global:IperfExe = '.\iperf3.exe' 364 | } 365 | 366 | $SyncHash.CommandTextBox.Text = $IperfExe + $IperfMode + $IperfTime + $IperfVersionParams + ' -i 1' 367 | } 368 | 369 | # UI 370 | $InputXml = @" 371 | 381 | 382 | 383 | 384 |