使用.VBS脚本发送Discord消息时触发语法错误求助
问题现象
计划编写VBS脚本实现多Discord账号快捷发消息功能(已知Discord自带多账号支持,本项目为个人挑战练习),在原有可正常运行的基础发送脚本上添加UI交互逻辑(面向法语用户设计,界面提示为法语)后,脚本启动报语法错误,错误指向原本可正常运行的消息发送函数。原始代码如下:
On Error Resume Next 'Token selector dialogue box account=InputBox("Merci d'indiquer le nom du compte ci-dessous","Discord CMD","") 'If user cancels, exit the program if IsEmpty(account) Then WScript.Quit end if 'Check if token is registered Const ForReading = 1 Dim File, content, FSO Set FSO = CreateObject("Scripting.FileSystemObject") Function FileExists(FilePath) If fso.FileExists(FilePath) Then FileExists=CBool(1) Else FileExists=CBool(0) End If End Function If FileExists("database\accounts\"+account+".bin") Then 'If the file exist, do nothing and continue the script WScript.Sleep(500) Else 'If the file doesn't exist, restart the script and display an error x=msgbox("This account has not be registered in the database. Please try again.", 0+16, "Error - Does not exist") CreateObject("WScript.Shell").Run "Chat.vbs" WScript.Quit End If 'Get the token related the account asked Set File = fso.OpenTextFile("database\accounts\"+account+".bin", ForReading) Token = File.ReadAll 'Loop Do 'Choose channel Echannel=InputBox("Merci d'indiquer l'identifiant du channel ci-dessous. Si il est identique, inscrivez 'Channel'","Discord CMD - " + account,"Channel") If (Echannel="Channel") Then 'If the channel is the same as before, then we don't change it in the code WScript.Sleep(500) Else 'If the channel is different, we change to the new value channels = Echannel End If 'If user cancels, restart the program if IsEmpty(account) Then CreateObject("WScript.Shell").Run "Chat.vbs" WScript.Quit end if 'The user enters his message text=InputBox("Merci d'indiquer le texte ci-dessous, faites OK pour l'envoyer","Discord CMD - " + account + " - Writing...","") 'If user cancels, restart the program if IsEmpty(account) Then CreateObject("WScript.Shell").Run "Chat.vbs" WScript.Quit end if 'We send the message Call commandeexercuter(channels,Token,text) Function commandeexercuter(channels,Token,text) Set objXmlHttp = CreateObject("Msxml2.ServerXMLHTTP") sRequest = "{" & Chr(34) & "content" & Chr(34) & ": " & Chr(34) & text & Chr(34) & "}" objXmlHttp.open "POST","https://discordapp.com/api/v6/channels/" & channels &"/messages", False objXmlHttp.setRequestHeader "Authorization", Token objXmlHttp.setRequestHeader "Content-Type", "application/json" objXmlHttp.send(sRequest) End Function 'We restart the loop Loop
错误原因
- 核心语法错误:VBScript明确要求所有
Function/Sub过程必须定义在代码顶层作用域,不能嵌套在Do...Loop循环、If...End If判断这类流程控制块内部。原始代码把commandeexercuter发送函数直接写在了Do...Loop循环体里,直接触发语法报错。 - 逻辑缺陷1:两处用户取消输入的判断逻辑写错,均判断了
account变量而非当前输入的Echannel(频道ID)、text(消息内容)变量,用户取消频道/消息输入时无法触发预期的重启逻辑。 - 逻辑缺陷2:
channels变量未做初始化,若用户首次运行直接保留频道输入框默认值Channel,会因变量未定义导致请求URL拼接失败。 - 潜在运行bug:读取账号token文件后未关闭文件句柄,可能触发文件占用问题;发送消息时未转义消息内容里的双引号,若消息包含双引号会导致JSON格式错误,消息发送失败。
修复方案
- 将
commandeexercuter消息发送函数移出循环块,放到所有流程控制结构外部的顶层作用域。 - 修正取消输入的判断逻辑,分别对
Echannel、text变量做空值判断。 - 初始化
channels变量,增加首次输入校验,避免空值发起无效请求。 - 补充文件句柄关闭逻辑、消息内双引号转义逻辑,增加空消息拦截避免发空内容。
修复后可正常运行的完整代码:
On Error Resume Next 'Token selector dialogue box account=InputBox("Merci d'indiquer le nom du compte ci-dessous","Discord CMD","") 'If user cancels, exit the program if IsEmpty(account) Then WScript.Quit end if 'Check if token is registered Const ForReading = 1 Dim File, content, FSO, channels Set FSO = CreateObject("Scripting.FileSystemObject") channels = "" '初始化频道变量 Function FileExists(FilePath) If fso.FileExists(FilePath) Then FileExists=CBool(1) Else FileExists=CBool(0) End If End Function If FileExists("database\accounts\"&account&".bin") Then WScript.Sleep(500) Else x=msgbox("This account has not be registered in the database. Please try again.", 0+16, "Error - Does not exist") CreateObject("WScript.Shell").Run "Chat.vbs" WScript.Quit End If 'Get the token related the account asked Set File = fso.OpenTextFile("database\accounts\"&account&".bin", ForReading) Token = File.ReadAll File.Close '关闭文件句柄避免占用 '消息发送函数 放在顶层作用域 Function commandeexercuter(channels,Token,text) Set objXmlHttp = CreateObject("Msxml2.ServerXMLHTTP") '转义消息内的双引号,避免JSON格式错误 sRequest = "{" & Chr(34) & "content" & Chr(34) & ": " & Chr(34) & Replace(text, Chr(34), "\"&Chr(34)) & Chr(34) & "}" objXmlHttp.open "POST","https://discordapp.com/api/v6/channels/" & channels &"/messages", False objXmlHttp.setRequestHeader "Authorization", Token objXmlHttp.setRequestHeader "Content-Type", "application/json" objXmlHttp.send(sRequest) End Function '主循环 Do 'Choose channel Echannel=InputBox("Merci d'indiquer l'identifiant du channel ci-dessous. Si il est identique, inscrivez 'Channel'","Discord CMD - " & account,"Channel") '修正取消判断逻辑 if IsEmpty(Echannel) Then CreateObject("WScript.Shell").Run "Chat.vbs" WScript.Quit end if If (Echannel<>"Channel") Then channels = Echannel End If '首次未输入频道ID时提示重输 If channels = "" Then MsgBox "Veuillez d'abord saisir l'identifiant du channel", vbExclamation, "Erreur" Loop End If '获取用户输入的消息 text=InputBox("Merci d'indiquer le texte ci-dessous, faites OK pour l'envoyer","Discord CMD - " & account & " - Writing...","") '修正取消判断逻辑 if IsEmpty(text) Then CreateObject("WScript.Shell").Run "Chat.vbs" WScript.Quit end if '空消息不发送 If Trim(text) <> "" Then Call commandeexercuter(channels,Token,text) End If Loop
内容的提问来源于stack exchange,提问作者Zorglub2506
相关产品推荐
相关产品推荐

