Powershell AI写脚本

记录一次纯AI写脚本

之前收集过一个脚本,使用powershell调用iperf来运行网络带宽的检查,后来就懂了信息,想要搞一个检查云桌面RTT延迟的工具,这样用户说云桌面卡的时候就能很清晰的看到网络的情况,之前见过一个类似的工具,叫Nping,查了一圈还是国内的一个程序员写的,在了解了基本原理就是使用icmp协议来执行ping命令后,收集返回信息,然后图形化以后我就想能不能用powershell写一个类似的工具。

自己二把刀写powershell的水平,大概率又要烂尾,所以就干脆直接问通译千问算了,结果还成了,所以记录一下。

需求提交

先整理了一下这个脚本的需求,和实现的逻辑

然后提交给AI

1
2
3
4
5
6
7
8
9
10
11
#测试powershell版本

#检查powershell进程,如果有就先关掉,如果没有就进行执行

#创建进程

#执行命令,变量匹配UI的测试地址,变量匹配测试数量,变量匹配显示方式

#执行新打开窗口显示测试RTT效果,导出csvlog文件

#UI窗口,调用donet命令创建窗口,填写测试地址,勾选

然后收到了第一版本的脚本

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
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

# 创建窗体
$form = New-Object System.Windows.Forms.Form
$form.Text = "PowerShell ICMP Ping 工具"
$form.Size = New-Object System.Drawing.Size(600, 400)
$form.StartPosition = 'CenterScreen'

# 输入地址
$labelTarget = New-Object System.Windows.Forms.Label
$labelTarget.Location = New-Object System.Drawing.Point(20, 20)
$labelTarget.Text = "请输入目标地址:"
$form.Controls.Add($labelTarget)

$txtTarget = New-Object System.Windows.Forms.TextBox
$txtTarget.Location = New-Object System.Drawing.Point(150, 20)
$txtTarget.Size = New-Object System.Drawing.Size(300, 20)
$form.Controls.Add($txtTarget)

# 测试次数
$labelCount = New-Object System.Windows.Forms.Label
$labelCount.Location = New-Object System.Drawing.Point(20, 50)
$labelCount.Text = "请选择测试次数:"
$form.Controls.Add($labelCount)

$cboCount = New-Object System.Windows.Forms.ComboBox
$cboCount.Location = New-Object System.Drawing.Point(150, 50)
1..10 | ForEach-Object { $cboCount.Items.Add($_) } | Out-Null
$cboCount.SelectedItem = 3
$form.Controls.Add($cboCount)

# 开始按钮
$btnStart = New-Object System.Windows.Forms.Button
$btnStart.Location = New-Object System.Drawing.Point(20, 80)
$btnStart.Text = "开始测试"
$form.Controls.Add($btnStart)

# 结果输出 RichTextBox
$outputBox = New-Object System.Windows.Forms.RichTextBox
$outputBox.Location = New-Object System.Drawing.Point(20, 120)
$outputBox.Size = New-Object System.Drawing.Size(540, 200)
$outputBox.ReadOnly = $true
$form.Controls.Add($outputBox)

# 执行逻辑
$btnStart.Add_Click({
$target = $txtTarget.Text.Trim()
$count = $cboCount.SelectedItem

if (-not $target) {
[System.Windows.Forms.MessageBox]::Show("请输入目标地址!", "提示")
return
}

$outputBox.Clear()
$outputBox.AppendText("正在执行 ICMP Ping 测试...`n")

# 初始化结果集合
$results = @()

for ($i = 1; $i -le $count; $i++) {
try {
$ping = New-Object System.Net.NetworkInformation.Ping
$reply = $ping.Send($target, 1000) # 超时1秒
$status = $reply.Status
$rtt = if ($reply.RoundtripTime) { $reply.RoundtripTime } else { "N/A" }

$outputBox.AppendText("`n第 $i 次测试: 地址=$target, 状态=$status, RTT=$rtt ms")

$results += [PSCustomObject]@{
序号 = $i
地址 = $target
状态 = $status
RTT_ms = $rtt
时间戳 = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
}
} catch {
$outputBox.AppendText("`n第 $i 次测试失败: $_")
$results += [PSCustomObject]@{
序号 = $i
地址 = $target
状态 = "Error"
RTT_ms = "N/A"
时间戳 = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
}
}
}

# 显示在 GridView 中
$results | Out-GridView -Title "Ping 测试结果"

# 导出 CSV
$csvPath = Join-Path $env:USERPROFILE "ICMP_Ping_$(Get-Date -Format yyyyMMdd_HHmmss).csv"
$results | Export-Csv -Path $csvPath -NoTypeInformation -Encoding UTF8
$outputBox.AppendText("`n`n结果已导出到: $csvPath")
})

# 启动窗体
[System.Windows.Forms.Application]::EnableVisualStyles()
[System.Windows.Forms.Application]::Run($form)

执行了一次,还真能用

OK,我自己一行没写,实现了一个功能,还能筛选呢!,有点开心。

调试

第一轮调试 加数量控制

在实现了基本功能以后,熟话说饱暖思淫欲,我又有一个点子,能不能在这个测试的数量上增加一些

1
2
这个ping的数量我想要修改成自己填写(当然最大值是65535)这样就可以测试一段时间的网络情况

AI回复了

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
109
110
111
112
113
114
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

# 创建主窗体
$form = New-Object System.Windows.Forms.Form
$form.Text = "PowerShell ICMP Ping 工具"
$form.Size = New-Object System.Drawing.Size(600, 400)
$form.StartPosition = 'CenterScreen'

# 标签和地址输入框
$labelTarget = New-Object System.Windows.Forms.Label
$labelTarget.Location = New-Object System.Drawing.Point(20, 20)
$labelTarget.Text = "请输入目标地址:"
$form.Controls.Add($labelTarget)

$txtTarget = New-Object System.Windows.Forms.TextBox
$txtTarget.Location = New-Object System.Drawing.Point(150, 20)
$txtTarget.Size = New-Object System.Drawing.Size(300, 20)
$form.Controls.Add($txtTarget)

# 自定义次数输入框
$labelCount = New-Object System.Windows.Forms.Label
$labelCount.Location = New-Object System.Drawing.Point(20, 50)
$labelCount.Text = "请输入测试次数 (最大 65535):"
$form.Controls.Add($labelCount)

$txtCount = New-Object System.Windows.Forms.TextBox
$txtCount.Location = New-Object System.Drawing.Point(150, 50)
$txtCount.Size = New-Object System.Drawing.Size(100, 20)
$txtCount.Text = "10" # 默认值
$form.Controls.Add($txtCount)

# 开始按钮
$btnStart = New-Object System.Windows.Forms.Button
$btnStart.Location = New-Object System.Drawing.Point(20, 80)
$btnStart.Text = "开始测试"
$form.Controls.Add($btnStart)

# 结果显示 RichTextBox
$outputBox = New-Object System.Windows.Forms.RichTextBox
$outputBox.Location = New-Object System.Drawing.Point(20, 120)
$outputBox.Size = New-Object System.Drawing.Size(540, 200)
$outputBox.ReadOnly = $true
$form.Controls.Add($outputBox)

# 执行逻辑
$btnStart.Add_Click({
$target = $txtTarget.Text.Trim()
$countStr = $txtCount.Text.Trim()

if (-not $target) {
[System.Windows.Forms.MessageBox]::Show("请输入目标地址!", "提示")
return
}

if (-not ($countStr -match '^\d+$')) {
[System.Windows.Forms.MessageBox]::Show("请输入有效的数字作为测试次数!", "提示")
return
}

$count = [int]$countStr

if ($count -le 0 -or $count -gt 65535) {
[System.Windows.Forms.MessageBox]::Show("请输入 1 到 65535 之间的测试次数!", "提示")
return
}

$outputBox.Clear()
$outputBox.AppendText("正在执行 ICMP Ping 测试...`n")

# 初始化结果集合
$results = @()

for ($i = 1; $i -le $count; $i++) {
try {
$ping = New-Object System.Net.NetworkInformation.Ping
$reply = $ping.Send($target, 1000) # 超时1秒
$status = $reply.Status
$rtt = if ($reply.RoundtripTime) { $reply.RoundtripTime } else { "N/A" }

$outputBox.AppendText("`n第 $i 次测试: 地址=$target, 状态=$status, RTT=$rtt ms")

$results += [PSCustomObject]@{
序号 = $i
地址 = $target
状态 = $status
RTT_ms = $rtt
时间戳 = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
}
} catch {
$outputBox.AppendText("`n第 $i 次测试失败: $_")
$results += [PSCustomObject]@{
序号 = $i
地址 = $target
状态 = "Error"
RTT_ms = "N/A"
时间戳 = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
}
}
}

# 显示在 GridView 中
$results | Out-GridView -Title "Ping 测试结果"

# 导出 CSV
$csvPath = Join-Path $env:USERPROFILE "ICMP_Ping_$(Get-Date -Format yyyyMMdd_HHmmss).csv"
$results | Export-Csv -Path $csvPath -NoTypeInformation -Encoding UTF8
$outputBox.AppendText("`n`n结果已导出到: $csvPath")
})

# 启动窗体
[System.Windows.Forms.Application]::EnableVisualStyles()
[System.Windows.Forms.Application]::Run($form)

第二轮调试 加中断功能

到这里脚本还是正常的,我又想要加一个中断功能,可以填写一个很大的测试值,但是我随时都可以停止脚本执行的按键

1
在开始测试的旁边可以加一个停止的选项,可以直接结束并展示结果

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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

# 全局变量用于控制循环和存储结果
$script:cancelPing = $false
$script:results = @()

# 创建主窗体
$form = New-Object System.Windows.Forms.Form
$form.Text = "PowerShell ICMP Ping 工具"
$form.Size = New-Object System.Drawing.Size(600, 400)
$form.StartPosition = 'CenterScreen'

# 标签和地址输入框
$labelTarget = New-Object System.Windows.Forms.Label
$labelTarget.Location = New-Object System.Drawing.Point(20, 20)
$labelTarget.Text = "请输入目标地址:"
$form.Controls.Add($labelTarget)

$txtTarget = New-Object System.Windows.Forms.TextBox
$txtTarget.Location = New-Object System.Drawing.Point(150, 20)
$txtTarget.Size = New-Object System.Drawing.Size(300, 20)
$form.Controls.Add($txtTarget)

# 自定义次数输入框
$labelCount = New-Object System.Windows.Forms.Label
$labelCount.Location = New-Object System.Drawing.Point(20, 50)
$labelCount.Text = "请输入测试次数 (最大 65535):"
$form.Controls.Add($labelCount)

$txtCount = New-Object System.Windows.Forms.TextBox
$txtCount.Location = New-Object System.Drawing.Point(150, 50)
$txtCount.Size = New-Object System.Drawing.Size(100, 20)
$txtCount.Text = "10" # 默认值
$form.Controls.Add($txtCount)

# 开始按钮
$btnStart = New-Object System.Windows.Forms.Button
$btnStart.Location = New-Object System.Drawing.Point(20, 80)
$btnStart.Text = "开始测试"
$form.Controls.Add($btnStart)

# 停止按钮
$btnStop = New-Object System.Windows.Forms.Button
$btnStop.Location = New-Object System.Drawing.Point(120, 80)
$btnStop.Text = "停止测试"
$btnStop.Enabled = $false
$form.Controls.Add($btnStop)

# 结果显示 RichTextBox
$outputBox = New-Object System.Windows.Forms.RichTextBox
$outputBox.Location = New-Object System.Drawing.Point(20, 120)
$outputBox.Size = New-Object System.Drawing.Size(540, 200)
$outputBox.ReadOnly = $true
$form.Controls.Add($outputBox)

# 执行 Ping 的函数(可在后台线程中运行)
function Start-PingTest {
param(
[string]$target,
[int]$count
)

for ($i = 1; $i -le $count; $i++) {
if ($script:cancelPing) {
break
}

try {
$ping = New-Object System.Net.NetworkInformation.Ping
$reply = $ping.Send($target, 1000) # 超时1秒
$status = $reply.Status
$rtt = if ($reply.RoundtripTime) { $reply.RoundtripTime } else { "N/A" }

$line = "`n第 $i 次测试: 地址=$target, 状态=$status, RTT=$rtt ms"
$script:resultQueue.Enqueue($line)

$script:results += [PSCustomObject]@{
序号 = $i
地址 = $target
状态 = $status
RTT_ms = $rtt
时间戳 = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
}
} catch {
$line = "`n第 $i 次测试失败: $_"
$script:resultQueue.Enqueue($line)
$script:results += [PSCustomObject]@{
序号 = $i
地址 = $target
状态 = "Error"
RTT_ms = "N/A"
时间戳 = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
}
}

Start-Sleep -Milliseconds 100 # 可选:控制间隔时间
}

# 导出并提示
if ($script:results.Count -gt 0) {
$csvPath = Join-Path $env:USERPROFILE "ICMP_Ping_$(Get-Date -Format yyyyMMdd_HHmmss).csv"
$script:results | Export-Csv -Path $csvPath -NoTypeInformation -Encoding UTF8
$script:resultQueue.Enqueue("`n`n结果已导出到: $csvPath")
}

$script:resultQueue.Enqueue("###TEST_FINISHED###")
}

# 定时器用于更新 UI(防止阻塞主线程)
$timer = New-Object System.Windows.Forms.Timer
$timer.Interval = 200
$timer.Add_Tick({
while ($script:resultQueue.Count -gt 0) {
$msg = $script:resultQueue.Dequeue()
if ($msg -eq "###TEST_FINISHED###") {
$btnStart.Enabled = $true
$btnStop.Enabled = $false
$script:cancelPing = $false
return
}
$outputBox.AppendText($msg)
}
})
$timer.Start()

# 开始按钮点击事件
$btnStart.Add_Click({
$target = $txtTarget.Text.Trim()
$countStr = $txtCount.Text.Trim()

if (-not $target) {
[System.Windows.Forms.MessageBox]::Show("请输入目标地址!", "提示")
return
}

if (-not ($countStr -match '^\d+$')) {
[System.Windows.Forms.MessageBox]::Show("请输入有效的数字作为测试次数!", "提示")
return
}

$count = [int]$countStr

if ($count -le 0 -or $count -gt 65535) {
[System.Windows.Forms.MessageBox]::Show("请输入 1 到 65535 之间的测试次数!", "提示")
return
}

# 初始化变量
$script:results = @()
$script:resultQueue = [System.Collections.Queue]::new()
$script:cancelPing = $false

$outputBox.Clear()
$outputBox.AppendText("正在执行 ICMP Ping 测试...`n")

$btnStart.Enabled = $false
$btnStop.Enabled = $true

# 启动后台线程
$runspace = [RunspaceFactory]::CreateRunspace()
$runspace.ApartmentState = "STA"
$runspace.ThreadOptions = "ReuseThread"
$runspace.Open()

$ps = [PowerShell]::Create()
$ps.Runspace = $runspace
$ps.AddScript(${function:Start-PingTest}) | Out-Null
$ps.AddParameter("target", $target) | Out-Null
$ps.AddParameter("count", $count) | Out-Null

$async = $ps.BeginInvoke()
})

# 停止按钮点击事件
$btnStop.Add_Click({
$script:cancelPing = $true
$btnStop.Enabled = $false
$outputBox.AppendText("`n用户已手动停止测试。")
})

# 启动窗体
[System.Windows.Forms.Application]::EnableVisualStyles()
[System.Windows.Forms.Application]::Run($form)

放心,上面这个脚本已经挂了,执行了没结果的,感觉是执行了以后没有进入ping的逻辑,直接执行停止去了,接下来就是不断的调试,在这个过程中,我发现和AI调试,是有一些技巧的

因为对话的模型不是Agent的那种智能体,只能通过对话来了解我现在的界面情况,所以每次执行脚本后我就需要吧目前的结果情况反馈给AI,这样他就可以按照我的结果,去判断是不是脚本中的逻辑存在问题

经过多轮调试以后

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
109
110
111
112
113
114
115
116
117
118
119
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

# 全局变量
$script:target = ""
$script:count = 0
$script:index = 0
$script:canceled = $false
$script:timer = New-Object System.Windows.Forms.Timer
$script:timer.Interval = 200 # 每 200 毫秒执行一次 Ping

# 创建窗体
$form = New-Object System.Windows.Forms.Form
$form.Text = "ICMP Ping 工具 (定时器版)"
$form.Size = New-Object System.Drawing.Size(600, 400)

# 输入目标地址
$txtTarget = New-Object System.Windows.Forms.TextBox
$txtTarget.Location = New-Object System.Drawing.Point(20, 20)
$txtTarget.Width = 200
$txtTarget.Text = "www.baidu.com"
$form.Controls.Add($txtTarget)

# 输入次数
$txtCount = New-Object System.Windows.Forms.TextBox
$txtCount.Location = New-Object System.Drawing.Point(230, 20)
$txtCount.Width = 50
$txtCount.Text = "10"
$form.Controls.Add($txtCount)

# 开始按钮
$btnStart = New-Object System.Windows.Forms.Button
$btnStart.Location = New-Object System.Drawing.Point(290, 20)
$btnStart.Text = "开始测试"
$form.Controls.Add($btnStart)

# 停止按钮
$btnStop = New-Object System.Windows.Forms.Button
$btnStop.Location = New-Object System.Drawing.Point(370, 20)
$btnStop.Text = "停止测试"
$btnStop.Enabled = $false
$form.Controls.Add($btnStop)

# 输出区域
$outputBox = New-Object System.Windows.Forms.RichTextBox
$outputBox.Location = New-Object System.Drawing.Point(20, 60)
$outputBox.Size = New-Object System.Drawing.Size(540, 280)
$outputBox.ReadOnly = $true
$form.Controls.Add($outputBox)

# Timer Tick 事件:每次执行一次 Ping
$script:timer.Add_Tick({
if ($script:canceled) {
$this.Stop()
$btnStart.Enabled = $true
$btnStop.Enabled = $false
$outputBox.AppendText("`n🛑 测试已被用户中断。")
return
}

if ($script:index -ge $script:count) {
$this.Stop()
$btnStart.Enabled = $true
$btnStop.Enabled = $false
$outputBox.AppendText("`n✅ 测试已完成。")
return
}

$script:index++
try {
$ping = New-Object System.Net.NetworkInformation.Ping
$reply = $ping.Send($script:target, 1000)
$status = $reply.Status
$rtt = if ($reply.RoundtripTime) { $reply.RoundtripTime } else { "N/A" }

$outputBox.AppendText("`n第 $($script:index) 次测试: 地址=$($script:target), 状态=$status, RTT=$rtt ms")
} catch {
$outputBox.AppendText("`n第 $($script:index) 次测试失败: $_")
}
})

# 开始按钮点击事件
$btnStart.Add_Click({
$target = $txtTarget.Text.Trim()
$countStr = $txtCount.Text.Trim()

if ([string]::IsNullOrWhiteSpace($target)) {
[System.Windows.Forms.MessageBox]::Show("请输入目标地址!", "提示")
return
}

if (-not ($countStr -match '^\d+$') -or [int]$countStr -le 0 -or [int]$countStr -gt 65535) {
[System.Windows.Forms.MessageBox]::Show("请输入有效的次数(1-65535)", "提示")
return
}

$script:target = $target
$script:count = [int]$countStr
$script:index = 0
$script:canceled = $false

$outputBox.Clear()
$outputBox.AppendText("正在执行 ICMP 测试...")

$btnStart.Enabled = $false
$btnStop.Enabled = $true

$script:timer.Start()
})

# 停止按钮点击事件
$btnStop.Add_Click({
$script:canceled = $true
$outputBox.AppendText("`n🛑 正在请求中断...")
})

# 启动窗体
[System.Windows.Forms.Application]::EnableVisualStyles()
[System.Windows.Forms.Application]::Run($form)

这个时间用时一个小时,圆满实现我的需求

第三轮调试 加报表查看功能

我还是不满足,因为第一版它给我弹出了一个窗口,我这个能停止了但是没有弹出窗口了,本着既要又要的逻辑,我就想要一个查看RTT延迟的报表功能

1
#我想要RTT折线图,和第一版的脚本一样,可以在另一个窗口弹出来结果

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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
Add-Type -AssemblyName System.Windows.Forms.DataVisualization

# 全局变量
$script:target = ""
$script:count = 0
$script:index = 0
$script:canceled = $false
$script:rttData = @()
$script:timer = New-Object System.Windows.Forms.Timer
$script:timer.Interval = 200 # 每 200 毫秒执行一次 Ping

# 创建主窗体
$form = New-Object System.Windows.Forms.Form
$form.Text = "ICMP Ping 工具 (含图表)"
$form.Size = New-Object System.Drawing.Size(600, 400)

# 输入目标地址
$txtTarget = New-Object System.Windows.Forms.TextBox
$txtTarget.Location = New-Object System.Drawing.Point(20, 20)
$txtTarget.Width = 200
$txtTarget.Text = "www.baidu.com"
$form.Controls.Add($txtTarget)

# 输入次数
$txtCount = New-Object System.Windows.Forms.TextBox
$txtCount.Location = New-Object System.Drawing.Point(230, 20)
$txtCount.Width = 50
$txtCount.Text = "10"
$form.Controls.Add($txtCount)

# 开始按钮
$btnStart = New-Object System.Windows.Forms.Button
$btnStart.Location = New-Object System.Drawing.Point(290, 20)
$btnStart.Text = "开始测试"
$form.Controls.Add($btnStart)

# 停止按钮
$btnStop = New-Object System.Windows.Forms.Button
$btnStop.Location = New-Object System.Drawing.Point(370, 20)
$btnStop.Text = "停止测试"
$btnStop.Enabled = $false
$form.Controls.Add($btnStop)

# 查看图表按钮
$btnChart = New-Object System.Windows.Forms.Button
$btnChart.Location = New-Object System.Drawing.Point(450, 20)
$btnChart.Text = "查看图表"
$btnChart.Enabled = $false
$form.Controls.Add($btnChart)

# 输出区域
$outputBox = New-Object System.Windows.Forms.RichTextBox
$outputBox.Location = New-Object System.Drawing.Point(20, 60)
$outputBox.Size = New-Object System.Drawing.Size(540, 280)
$outputBox.ReadOnly = $true
$form.Controls.Add($outputBox)

# Timer Tick 事件:每次执行一次 Ping
$script:timer.Add_Tick({
if ($script:canceled) {
$this.Stop()
$btnStart.Enabled = $true
$btnStop.Enabled = $false
$btnChart.Enabled = $true
$outputBox.AppendText("`n🛑 测试已被用户中断。")
return
}

if ($script:index -ge $script:count) {
$this.Stop()
$btnStart.Enabled = $true
$btnStop.Enabled = $false
$btnChart.Enabled = $true
$outputBox.AppendText("`n✅ 测试已完成。")
return
}

$script:index++
try {
$ping = New-Object System.Net.NetworkInformation.Ping
$reply = $ping.Send($script:target, 1000)
$status = $reply.Status
$rtt = if ($reply.RoundtripTime) { $reply.RoundtripTime } else { 0 }

if ($status -eq 'Success') {
$script:rttData += [PSCustomObject]@{
Index = $script:index
RTT = $rtt
}
}

$outputBox.AppendText("`n第 $($script:index) 次测试: 地址=$($script:target), 状态=$status, RTT=$rtt ms")
} catch {
$outputBox.AppendText("`n第 $($script:index) 次测试失败: $_")
}
})

# 开始按钮点击事件
$btnStart.Add_Click({
$target = $txtTarget.Text.Trim()
$countStr = $txtCount.Text.Trim()

if ([string]::IsNullOrWhiteSpace($target)) {
[System.Windows.Forms.MessageBox]::Show("请输入目标地址!", "提示")
return
}

if (-not ($countStr -match '^\d+$') -or [int]$countStr -le 0 -or [int]$countStr -gt 65535) {
[System.Windows.Forms.MessageBox]::Show("请输入有效的次数(1-65535)", "提示")
return
}

$script:target = $target
$script:count = [int]$countStr
$script:index = 0
$script:canceled = $false
$script:rttData = @()

$outputBox.Clear()
$outputBox.AppendText("正在执行 ICMP 测试...")

$btnStart.Enabled = $false
$btnStop.Enabled = $true
$btnChart.Enabled = $false

$script:timer.Start()
})

# 停止按钮点击事件
$btnStop.Add_Click({
$script:canceled = $true
$outputBox.AppendText("`n🛑 正在请求中断...")
})

# 查看图表按钮点击事件
$btnChart.Add_Click({
if ($script:rttData.Count -eq 0) {
[System.Windows.Forms.MessageBox]::Show("没有可用数据,请先执行至少一次 Ping 测试。", "提示")
return
}

# 创建图表窗口
$chartForm = New-Object System.Windows.Forms.Form
$chartForm.Text = "RTT 折线图"
$chartForm.Size = New-Object System.Drawing.Size(800, 600)

# 创建 Chart 控件
$chart = New-Object System.Windows.Forms.DataVisualization.Charting.Chart
$chart.Size = New-Object System.Drawing.Size(780, 540)
$chartArea = New-Object System.Windows.Forms.DataVisualization.Charting.ChartArea
$chart.ChartAreas.Add($chartArea)

# 设置系列
$series = New-Object System.Windows.Forms.DataVisualization.Charting.Series
$series.ChartType = [System.Windows.Forms.DataVisualization.Charting.SeriesChartType]::Line
$series.BorderWidth = 2
$series.Color = [System.Drawing.Color]::Blue

foreach ($item in $script:rttData) {
$series.Points.AddXY($item.Index, $item.RTT)
}

$chart.Series.Add($series)

# 添加标题和轴标签
$chart.Titles.Add("RTT 变化趋势") | Out-Null
$chart.ChartAreas[0].AxisX.Title = "Ping 序号"
$chart.ChartAreas[0].AxisY.Title = "RTT (ms)"

$chartForm.Controls.Add($chart)
$chartForm.ShowDialog()
})

# 启动主窗体
[System.Windows.Forms.Application]::EnableVisualStyles()
[System.Windows.Forms.Application]::Run($form)

OK这个功能也能实现了

第四轮调试 加导出功能

在实际使用中,我们往往要通过邮件发送日志文件,所以我还想要一个log导出的功能,这个就需要每次写一个csv文件导出来

1
#我想要在图标界面增加一个导出的功能,可以导出为csv文件

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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
Add-Type -AssemblyName System.Windows.Forms.DataVisualization

# 全局变量
$script:target = ""
$script:count = 0
$script:index = 0
$script:canceled = $false
$script:rttData = @()
$script:timer = New-Object System.Windows.Forms.Timer
$script:timer.Interval = 200 # 每 200 毫秒执行一次 Ping

# 创建主窗体
$form = New-Object System.Windows.Forms.Form
$form.Text = "ICMP Ping 工具 (含时间戳)"
$form.Size = New-Object System.Drawing.Size(650, 400)

# 输入目标地址
$txtTarget = New-Object System.Windows.Forms.TextBox
$txtTarget.Location = New-Object System.Drawing.Point(20, 20)
$txtTarget.Width = 200
$txtTarget.Text = "www.baidu.com"
$form.Controls.Add($txtTarget)

# 输入次数
$txtCount = New-Object System.Windows.Forms.TextBox
$txtCount.Location = New-Object System.Drawing.Point(230, 20)
$txtCount.Width = 50
$txtCount.Text = "10"
$form.Controls.Add($txtCount)

# 开始按钮
$btnStart = New-Object System.Windows.Forms.Button
$btnStart.Location = New-Object System.Drawing.Point(290, 20)
$btnStart.Text = "开始测试"
$form.Controls.Add($btnStart)

# 停止按钮
$btnStop = New-Object System.Windows.Forms.Button
$btnStop.Location = New-Object System.Drawing.Point(370, 20)
$btnStop.Text = "停止测试"
$btnStop.Enabled = $false
$form.Controls.Add($btnStop)

# 查看图表按钮
$btnChart = New-Object System.Windows.Forms.Button
$btnChart.Location = New-Object System.Drawing.Point(450, 20)
$btnChart.Text = "查看图表"
$btnChart.Enabled = $false
$form.Controls.Add($btnChart)

# 导出按钮
$btnExport = New-Object System.Windows.Forms.Button
$btnExport.Location = New-Object System.Drawing.Point(530, 20)
$btnExport.Text = "导出结果"
$btnExport.Enabled = $false
$form.Controls.Add($btnExport)

# 输出区域
$outputBox = New-Object System.Windows.Forms.RichTextBox
$outputBox.Location = New-Object System.Drawing.Point(20, 60)
$outputBox.Size = New-Object System.Drawing.Size(590, 280)
$outputBox.ReadOnly = $true
$form.Controls.Add($outputBox)

# Timer Tick 事件:每次执行一次 Ping
$script:timer.Add_Tick({
if ($script:canceled) {
$this.Stop()
$btnStart.Enabled = $true
$btnStop.Enabled = $false
$btnChart.Enabled = $true
$btnExport.Enabled = $true
$outputBox.AppendText("`n🛑 测试已被用户中断。")
return
}

if ($script:index -ge $script:count) {
$this.Stop()
$btnStart.Enabled = $true
$btnStop.Enabled = $false
$btnChart.Enabled = $true
$btnExport.Enabled = $true
$outputBox.AppendText("`n✅ 测试已完成。")
return
}

$script:index++
try {
$timestamp = Get-Date -Format "HH:mm:ss"

$ping = New-Object System.Net.NetworkInformation.Ping
$reply = $ping.Send($script:target, 1000)
$status = $reply.Status
$rtt = if ($reply.RoundtripTime) { $reply.RoundtripTime } else { "N/A" }

if ($status -eq 'Success') {
$script:rttData += [PSCustomObject]@{
Index = $script:index
Timestamp = $timestamp
Target = $script:target
Status = $status
RTT = $rtt
}
} else {
$script:rttData += [PSCustomObject]@{
Index = $script:index
Timestamp = $timestamp
Target = $script:target
Status = $status
RTT = "N/A"
}
}

$outputBox.AppendText("`n[$timestamp] 第 $($script:index) 次测试: 地址=$($script:target), 状态=$status, RTT=$rtt ms")

} catch {
$timestamp = Get-Date -Format "HH:mm:ss"
$outputBox.AppendText("`n[$timestamp] 第 $($script:index) 次测试失败: $_")
}
})

# 开始按钮点击事件
$btnStart.Add_Click({
$target = $txtTarget.Text.Trim()
$countStr = $txtCount.Text.Trim()

if ([string]::IsNullOrWhiteSpace($target)) {
[System.Windows.Forms.MessageBox]::Show("请输入目标地址!", "提示")
return
}

if (-not ($countStr -match '^\d+$') -or [int]$countStr -le 0 -or [int]$countStr -gt 65535) {
[System.Windows.Forms.MessageBox]::Show("请输入有效的次数(1-65535)", "提示")
return
}

$script:target = $target
$script:count = [int]$countStr
$script:index = 0
$script:canceled = $false
$script:rttData = @()

$outputBox.Clear()
$outputBox.AppendText("正在执行 ICMP 测试...")

$btnStart.Enabled = $false
$btnStop.Enabled = $true
$btnChart.Enabled = $false
$btnExport.Enabled = $false

$script:timer.Start()
})

# 停止按钮点击事件
$btnStop.Add_Click({
$script:canceled = $true
$outputBox.AppendText("`n🛑 正在请求中断...")
})

# 查看图表按钮点击事件
$btnChart.Add_Click({
if ($script:rttData.Count -eq 0) {
[System.Windows.Forms.MessageBox]::Show("没有可用数据,请先执行至少一次 Ping 测试。", "提示")
return
}

# 创建图表窗口
$chartForm = New-Object System.Windows.Forms.Form
$chartForm.Text = "RTT 折线图"
$chartForm.Size = New-Object System.Drawing.Size(800, 600)

# 创建 Chart 控件
$chart = New-Object System.Windows.Forms.DataVisualization.Charting.Chart
$chart.Dock = 'Fill'
$chartArea = New-Object System.Windows.Forms.DataVisualization.Charting.ChartArea
$chart.ChartAreas.Add($chartArea)

# 设置系列
$series = New-Object System.Windows.Forms.DataVisualization.Charting.Series
$series.ChartType = [System.Windows.Forms.DataVisualization.Charting.SeriesChartType]::Line
$series.BorderWidth = 2
$series.Color = [System.Drawing.Color]::Blue

foreach ($item in $script:rttData | Where-Object { $_.RTT -ne "N/A" }) {
$series.Points.AddXY($item.Index, $item.RTT)
}

$chart.Series.Add($series)

# 添加标题和轴标签
$chart.Titles.Add("RTT 变化趋势") | Out-Null
$chart.ChartAreas[0].AxisX.Title = "Ping 序号"
$chart.ChartAreas[0].AxisY.Title = "RTT (ms)"

$chartForm.Controls.Add($chart)
$chartForm.ShowDialog()
})

# 导出按钮点击事件
$btnExport.Add_Click({
if ($script:rttData.Count -eq 0) {
[System.Windows.Forms.MessageBox]::Show("没有可用数据,请先执行至少一次 Ping 测试。", "提示")
return
}

$saveDialog = New-Object System.Windows.Forms.SaveFileDialog
$saveDialog.Filter = "CSV 文件 (*.csv)|*.csv"
$saveDialog.Title = "保存 Ping 测试结果"

if ($saveDialog.ShowDialog() -eq "OK") {
$filePath = $saveDialog.FileName
$script:rttData | Export-Csv -Path $filePath -NoTypeInformation -Encoding UTF8
[System.Windows.Forms.MessageBox]::Show("数据已成功导出到:`n$filePath", "导出完成")
}
})

# 启动窗体
[System.Windows.Forms.Application]::EnableVisualStyles()
[System.Windows.Forms.Application]::Run($form)

最后可以了

整个下来,我没写一行代码,实现了这个功能,后面再研究它的运行逻辑吧