积极答复者
在执行Invoke出现"索引超出了数组界限。"

问题
-
public static class PublicData { public static class Behavior { public const string Delay = "delay"; public const string Click = "click"; public const string ifexist = "ifexist"; public const string ifnotexist = "ifnotexist"; public const string exist = "exist"; } public static class ElementSearchType { public const string ID = "id"; public const string InnerText = "innertext"; public const string OuterText = "outertext"; public const string OuterHtml = "outerhtml"; } public static class RegString { public const string sRegDelay = @"^delay[\p{Z}]+(?<Time>\d+)$"; public const string sRegClick = @"^click[\p{Z}]+(?<SearchType>id|innertext|outertext|outerhtml)[\p{Z}]+(?<SearchContent>[\S\p{Z}]+)$"; public const string sRegIfGoto = @"^(?<IfType>ifexist|ifnotexist)[\p{Z}]+(?<Condition>[\S\p{Z}]+)[\p{Z}]+goto[\p{Z}]+(?<label>\S+)$"; public const string sRegLabel = @"^(?<Label>\S+):$"; public const string sRegExist = @"^(?<SearchType>id|innertext|outertext|outerhtml)[\p{Z}]+(?<SearchContent>[\S\p{Z}]+)$"; public const string sRegRandomGoto = @"^random[\p{Z}]+(?<Ratio>\d+(\.\d+)?)[\p{Z}]+goto[\p{Z}]+(?<Label>\S+)$"; } } /// <summary> /// 游戏管控 /// </summary> public class GameController { private delegate void StatementExecuseHandle(string Statement); int iIndex; bool blIsAutoAttack = false; System.Threading.Thread thrdAutoAttack; string[] sScriptContent; WebBrowser webBrowser; volatile int iCurrentStep; volatile bool blShouldWait; volatile int iDelay; Random rndRandom; System.Text.RegularExpressions.Regex reDelay; System.Text.RegularExpressions.Regex reClick; System.Text.RegularExpressions.Regex reIfGoto; System.Text.RegularExpressions.Regex reLabel; System.Text.RegularExpressions.Regex reExist; System.Text.RegularExpressions.Regex reRandomGoto; public GameController(int index) { iIndex = index; Initial(); } public GameController(int index, WebBrowser Browser, string[] ScriptContent) { iIndex = index; webBrowser = Browser; sScriptContent = ScriptContent; Initial(); } private void Initial() { reDelay = new System.Text.RegularExpressions.Regex(PublicData.RegString.sRegDelay, System.Text.RegularExpressions.RegexOptions.Compiled | System.Text.RegularExpressions.RegexOptions.Multiline | System.Text.RegularExpressions.RegexOptions.IgnoreCase); reClick = new System.Text.RegularExpressions.Regex(PublicData.RegString.sRegClick, System.Text.RegularExpressions.RegexOptions.Compiled | System.Text.RegularExpressions.RegexOptions.Multiline | System.Text.RegularExpressions.RegexOptions.IgnoreCase); reIfGoto = new System.Text.RegularExpressions.Regex(PublicData.RegString.sRegIfGoto, System.Text.RegularExpressions.RegexOptions.Compiled | System.Text.RegularExpressions.RegexOptions.Multiline | System.Text.RegularExpressions.RegexOptions.IgnoreCase); reLabel = new System.Text.RegularExpressions.Regex(PublicData.RegString.sRegLabel, System.Text.RegularExpressions.RegexOptions.Compiled | System.Text.RegularExpressions.RegexOptions.Multiline | System.Text.RegularExpressions.RegexOptions.IgnoreCase); reExist = new System.Text.RegularExpressions.Regex(PublicData.RegString.sRegExist, System.Text.RegularExpressions.RegexOptions.Compiled | System.Text.RegularExpressions.RegexOptions.Multiline | System.Text.RegularExpressions.RegexOptions.IgnoreCase); reRandomGoto = new System.Text.RegularExpressions.Regex(PublicData.RegString.sRegRandomGoto, System.Text.RegularExpressions.RegexOptions.Compiled | System.Text.RegularExpressions.RegexOptions.Multiline | System.Text.RegularExpressions.RegexOptions.IgnoreCase); rndRandom = new Random(); } public void Dispose() { if (thrdAutoAttack != null) if (thrdAutoAttack.ThreadState != System.Threading.ThreadState.Stopped) thrdAutoAttack.Abort(); if (webBrowser != null) if (!webBrowser.IsDisposed) webBrowser.Dispose(); } /// <summary> /// 是否进行挂机。挂机前应先设置脚本内容 /// </summary> public bool IsAutoAttack { get { return blIsAutoAttack; } set { if (blIsAutoAttack != value) { blIsAutoAttack = value; if (blIsAutoAttack) { iCurrentStep = 0; thrdAutoAttack = new System.Threading.Thread(new System.Threading.ThreadStart(AutoAttack)); thrdAutoAttack.Priority = System.Threading.ThreadPriority.BelowNormal; thrdAutoAttack.Start(); } else { if (thrdAutoAttack != null) if (thrdAutoAttack.ThreadState != System.Threading.ThreadState.Stopped) thrdAutoAttack.Abort(); } } } } private void AutoAttack() { iCurrentStep = 0; while (blIsAutoAttack) { string sCurrentStep = sScriptContent[iCurrentStep].Trim(); if (sCurrentStep.Length > 0) { blShouldWait = true; iDelay = 0; ExecuseStatement(sScriptContent[iCurrentStep]); while (blShouldWait) System.Threading.Thread.Sleep(10); if (iDelay > 0) System.Threading.Thread.Sleep(iDelay); } iCurrentStep++; if (iCurrentStep >= sScriptContent.Length) iCurrentStep = 0; } } private void ExecuseStatement(string Statement) { if (webBrowser.InvokeRequired) {
//下面这句会出错,提示“索引超出了数组界限。” webBrowser.Invoke(new StatementExecuseHandle(ExecuseStatement), new string[] { Statement }); } else { #region 执行脚本 System.Text.RegularExpressions.MatchCollection mcMatches; string sT = Statement; string sTT = string.Empty; mcMatches = reLabel.Matches(sT); if (mcMatches.Count == 0)//标签 { mcMatches = reDelay.Matches(sT); if (mcMatches.Count > 0)//延时 { iDelay = int.Parse(mcMatches[0].Groups["Time"].Value); } else { mcMatches = reIfGoto.Matches(sT); if (mcMatches.Count > 0)//跳转 { bool blShouldJump = false; string sIfType = mcMatches[0].Groups["IfType"].Value; string sCondition = mcMatches[0].Groups["Condition"].Value; string sLabel = mcMatches[0].Groups["Label"].Value; mcMatches = reExist.Matches(sCondition); if (mcMatches.Count > 0) { HtmlElement heT = SearchHtmlElement(mcMatches[0].Groups["SearchContent"].Value, GetSearchType(mcMatches[0].Groups["SearchType"].Value.ToLower())); blShouldJump = sIfType.ToLower() == PublicData.Behavior.ifexist ? (heT != null) : (heT == null); } else { //语法错误 MessageBox.Show(string.Format("在{0}行中\r\n{1}\r\n{2}", new object[] { iCurrentStep, sScriptContent[iCurrentStep], sCondition }), "语法错误"); } if (true)//可以跳转 { int iStepJump= GetLabelIndex(reLabel, sScriptContent, sLabel); if (iStepJump >= 0) { iCurrentStep = iStepJump; } else { //无效的标签被指定 MessageBox.Show(string.Format("在{0}行中\r\n{1}\r\n{2}", new object[] { iCurrentStep, sScriptContent[iCurrentStep], sLabel }), "无效的标签被指定"); } } } else { mcMatches = reClick.Matches(sT); if (mcMatches.Count > 0)//点击 { HtmlElement heT = SearchHtmlElement(mcMatches[0].Groups["SearchContent"].Value, GetSearchType(mcMatches[0].Groups["SearchType"].Value.ToLower())); if (heT != null) { heT.InvokeMember("Click"); } else { IsAutoAttack = false; MessageBox.Show(string.Format("{0}\r\n{1}", new object[] { sT, mcMatches[0].Groups["SearchContent"].Value }), "无效的元素特征"); } } else { mcMatches = reRandomGoto.Matches(sT);//随机跳转 if (mcMatches.Count > 0) { double dblT = rndRandom.NextDouble(); if (dblT > 1 - double.Parse(mcMatches[0].Groups["Ratio"].Value)) { string sLabel = mcMatches[0].Groups["Label"].Value; int iStepJump = GetLabelIndex(reLabel, sScriptContent, sLabel); if (iStepJump >= 0) { iCurrentStep = iStepJump; } else { //无效的标签被指定 MessageBox.Show(string.Format("在{0}行中\r\n{1}\r\n{2}", new object[] { iCurrentStep, sScriptContent[iCurrentStep], sLabel }), "无效的标签被指定"); } } } else { IsAutoAttack = false; MessageBox.Show(string.Format("在{0}行中\r\n{1}", new object[] { iCurrentStep, sScriptContent[iCurrentStep] }), "无效语句"); } } } } } #endregion blShouldWait = false; } } private int GetLabelIndex(System.Text.RegularExpressions.Regex reLabel, string[] sScriptContent, string sLabel) { int I = -1; while (I < sScriptContent.Length) { System.Text.RegularExpressions.Match match = reLabel.Match(sScriptContent[I]); if (match != null) if (match.Groups["Label"].Value == sLabel) break; } return I; } private ElementSearchTypeEnum GetSearchType(string SearchTypeString) { return SearchTypeString == PublicData.ElementSearchType.ID ? ElementSearchTypeEnum.ByID : (SearchTypeString == PublicData.ElementSearchType.InnerText ? ElementSearchTypeEnum.ByInnerText : (SearchTypeString == PublicData.ElementSearchType.OuterText ? ElementSearchTypeEnum.ByOuterText : (SearchTypeString == PublicData.ElementSearchType.OuterHtml ? ElementSearchTypeEnum.ByOuterHtml : ElementSearchTypeEnum.Unknow))); } public WebBrowser Browser { get { return webBrowser; } set { if (webBrowser != value) webBrowser = value; } } /// <summary> /// 脚本内容 /// </summary> public string[] ScriptContent { get { return sScriptContent; } set { IsAutoAttack = false; sScriptContent = value; } } public int index { get { return iIndex; } } /// <summary> /// 查找网页元素 /// </summary> /// <param name="ToSearch">条件字符串</param> /// <param name="SearchType">搜索类型</param> /// <returns>查找结果,无法找到时返回null</returns> public HtmlElement SearchHtmlElement(string ToSearch, ElementSearchTypeEnum SearchType) { HtmlDocument hdToSearch = webBrowser.Document; HtmlElement heT = null; switch (SearchType) { case ElementSearchTypeEnum.ByID://作为id查找 heT = hdToSearch.Body.All[ToSearch]; break; case ElementSearchTypeEnum.ByInnerText://查innertext foreach (HtmlElement heTT in hdToSearch.Body.All) { if (heTT.InnerText == ToSearch) { heT = heTT; break; } } break; case ElementSearchTypeEnum.ByOuterText://查outertext foreach (HtmlElement heTT in hdToSearch.Body.All) { if (heTT.OuterText == ToSearch) { heT = heTT; break; } } break; case ElementSearchTypeEnum.ByOuterHtml://查outerhtml ToSearch = System.Text.RegularExpressions.Regex.Unescape(ToSearch); foreach (HtmlElement heTT in hdToSearch.Body.All) { if (heTT.OuterHtml == ToSearch) { heT = heTT; break; } } break; } return heT; } }下面是脚本的内容:
start:
click innertext 铜钱;
delay 10000;
click id bt_exit;
delay 500;
random 0.7 goto start;
click id chatTab0;
delay 500;
random 1 goto start;
程序出错位置已经在上面标出了。主要出在Ramndom的二句脚本- 已移动 Sheng Jiang 蒋晟Moderator 2009年9月27日 16:54 Windows表单类库问题 (发件人:Visual C#)
全部回复
-
问题可能出在 hdToSearch.Body.All[ToSearch];这句上,你的ToSearch变量指定的值根本不在HTML文档中,所以导致那个错误。
你可以编写一个非常简单的HTML页面,然后测试一下你的程序。或者作为测试或调试,你可以遍历“All”里面的控件,看是否存在ToSearch指定的值。
理解的越多,需要记忆的就越少
试验过,错不在那句.
因为我的脚本里所指定的HtmlElement.id都是存在的,所以hdToSearch.Body.All[ToSearch]可以得到相应的HtmlElement.
另外,hdToSearch.Body.All[ToSearch]不应该出错.如果不存在相应id的HtmlElent,hdToSearch.Body.All[ToSearch]返回的是空值,而不是出错. -
Sorry,停的地方是在老地方:
webBrowser.Invoke(new StatementExecuseHandle(ExecuseStatement), new string[] { Statement });
BackgroundWorker.RunWorkerAsync,这句不会出错.
BackgroundWorker工作完成的事件也不会被激发,因为我的程序
private void AutoAttack() { iCurrentStep = 0; while (blIsAutoAttack)//在外部设定,如果不为false根本就不会退出这个线程的 { string sCurrentStep = sScriptContent[iCurrentStep].Trim(); if (sCurrentStep.Length > 0) { blShouldWait = true; iDelay = 0; //只要线程不终止,会一直调用ExecuseStatement ExecuseStatement(sScriptContent[iCurrentStep]); //等待脚本解释完成,blShouldWait在脚本解释完成后,在外部设置 while (blShouldWait) System.Threading.Thread.Sleep(10); //下面这句在脚本经过解释后,如果需要延时的话,线程休眠 if (iDelay > 0) System.Threading.Thread.Sleep(iDelay); } iCurrentStep++; if (iCurrentStep >= sScriptContent.Length) iCurrentStep = 0; } }
蒋先生.这种错误以前我也有碰过,现在忘了当时是怎么解决的.以前发生错误的时候是处理大文本,现在是WebBrowser... -