^_^填坑备忘^_^C#自动化编程实现STK+Exata对卫星互联网星座进行网络仿真

  1. C#实际选择 STK11版本 or STK12版本的问题备注。

C# 自动化客户端调用 STK 时,实际选择 STK11 版本 or STK12 版本 的调试运行备注】

以下代码"更新并重新打包备份为"〔testSTKQualNetInterface备份08.1_★避坑★【种子卫星:天线直接安装在卫星上,中间不能有Sensor传感器】.zip〕

源码文件: g:\teststkqualnetinterface\starlinksimulationclient.cs

private void button_OpenSTK_Click(object sender, EventArgs e)

{

#region 打开STK引擎:首先尝试打开现有STK软件,没有现成打开的STK;则新建打开一个STK软件实例

try

{//尝试获取现在已经在运行的 STK实例

m_uiApp = System.Runtime.InteropServices.Marshal.GetActiveObject("STK11.Application") as AgUiApplication;

#region C#自动化客户端调用STK时,实际选择 STK11版本 or STK12版本 的调试运行备注 @2024-5-7 09:16:28

// 貌似上面的 GetActiveObject("STK11.Application") 指定调用 STK11版本,

// 其实不是,真正决定C#调用哪个版本的的STK,即【实际选择 STK11版本 or STK12版本】,

// 是由【[testSTKQualNetInterface]】C#工程里引用的[AGI.STKObjects.Interop]系列【.Net互操作程序集】的STK版本决定的!

// 比如,目前这个工程引用的[AGI.STKObjects.Interop.dll]是 12.0.0.0,那么运行时调用的就是 STK12版本

// 所以,貌似 GetActiveObject("STK11.Application") 中的 "STK11.Application" 对 STK11版本 or STK12版本 都适用。

#endregion C#自动化客户端调用STK时,实际选择 STK11版本 or STK12版本 的调试运行备注

  1. 将〔testSTKQualNetInterface备份08.1_★避坑★【种子卫星:天线直接安装在卫星上,中间不能有Sensor传感器】.zip〕中的《 Program.cs StarlinkSimulationClient.cs StarlinkSimulationClient.Designer.cs XLsatNPF.cs 》源码文件重新替换到〔F:\WS_STK_use_Interop\test_Client 〕解决方案中的'testSTKQualNetInterface'工程中,调试运行:
    1. 编译通过、运行正常,未报错;
    2. '一键自动化测试',最后一步是调用[button_SaveToVDF_Click]加密保存场景为*.vdf,密码为 roottoor ;
    3. 调试运行时,C#调用STK11.6正常;保存的[D:\Temp\Starlink5x4_20SAT-SimScenario.vdf],既能用 STK11.6 也能用 STK12.2 打开(密码roottoor);

STK11.6 逆向编译生成的 Exata 插件,测试运行正常 卫星节点位置可以正常调用 STK 进行更新】★ STK+Exata 联合仿真★

    1. 【STK11.6逆向编译生成的Exata插件,测试运行正常】用STK11.6重新打开加密保存的[D:\Temp\Starlink5x4_20SAT-SimScenario.vdf],调出'软件逆向(反编译后重新编译)JSLS生成的'【QualNet Interface】场景管理器,对卫星Antenna天线建立网络连接并且建立星间链路,再在【QualNet Interface】场景管理器里单击'go',能够正常调用Exata进行网络仿真!
    2. STK11.6调用Exata插件进行网络仿真,生成的仿真*.config配置文件及目录,可以正常用Exata7.3打开(Exata6.2设置了调试断点会报错),卫星节点位置可以正常调用 STK 进行更新
  1. 因为【QualNet Interface Scenario Explorer】场景管理器,本质上在操作时,是调用'作为组件服务 的[AGI.StkQualnetUiControls ]++服务器'++,所以跟踪调试的时候:

★客户端服务器 CS 模式 调试运行 QualNet Interface Scenario Explorer 】场景管理器 STK.Net 组件插件

    1. 首先还是运行【[F:\WS_STK_use_Interop\test_Client]】解决方案里的"C#客户端",单击'一键自动化测试',等待C#客户端操作STK服务器,创建仿真场景完毕;
    2. 然后打开【[F:\WS_STK_use_Interop\test_Server]】解决方案,:
    3. 第三,在打开的【[F:\WS_STK_use_Interop\test_Server ]】解决方案中,附加到进程,++附加到++ ++[AgUiApplication.exe]STK++ ++软件进程++
    4. 在【[F:\WS_STK_use_Interop\test_Server ]】解决方案的《NetworkInterfaceForm.cs》(位于[F:\WS_STK_use_Interop\test_Server\AGI.StkQualnetUiControls\]工程),找到构造函数,下断点以便跟踪调试;

public NetworkInterfaceForm (NetworkInterface networkInterface, Entity parentEntity, AgStkObjectRoot stkRoot)

    1. 在【[test_Client ]】客户端解决方案运行的C#程序打开的STK11.6软件中,手动操作调出【QualNet Interface Scenario Explorer】场景管理器,选定某颗卫星(比如XL11),右键'Add',目的是为该卫星添加网络接口Interface; è 马上可以发现【[test_Server ]】里的NetworkInterfaceForm (NetworkInterface networkInterface, Entity parentEntity, AgStkObjectRoot stkRoot)断点被拦截命中,这时的调用堆栈是:

> AGI.StkQualnetUiControls.dll!AGI.StkQualnetUiControls.NetworkInterfaceForm .NetworkInterfaceForm(AGI.StkQualnetObjectModel.NetworkInterface networkInterface, AGI.StkQualnetObjectModel.Entity parentEntity, AGI.STKObjects.AgStkObjectRoot stkRoot) 行 24 C#

AGI.StkQualnetUiControls.dll!AGI.StkQualnetUiControls.StkQualnetScenarioExplorer.OnEntityAddNetworkInterfaceMenuItemClick(object sender, System.EventArgs e) 行 253 C#

AGI.StkQualnetUiControls.dll!AGI.StkQualnetUiControls.StkQualnetScenarioExplorer.networkInterfacesContextMenuAdd_Click(object sender, System.EventArgs e) 行 266 C#

  1. 经跟踪调试,锁定【QualNet Interface Scenario Explorer】场景管理器'针对Antenna天线添加Interface网络接口'的关键代码:

★调试找到关键代码★【场景管理器'针对 Antenna 天线添加 Interface 网络接口'】

    1. F:\WS_STK_use_Interop\test_Server\AGI.StkQualnetUiControls\StkQualnetScenarioExplorer.cs 】的[OnEntityAddNetworkInterfaceMenuItemClick ],其中,两句最关键的是【 new NetworkInterfaceForm(null, entityTreeNode.Entity, this.StkRoot); 】和【 NetworkInterface networkInterface = networkInterfaceForm.GetNetworkInterface(); 】;
    2. F:\WS_STK_use_Interop\test_Server\AGI.StkQualnetUiControls\NetworkInterfaceForm.cs 】的[public NetworkInterface GetNetworkInterface()];
    3. 最终结果:对[AGI.StkQualnetObjectModel.NetworkInterface]类型的【[networkInterface] 类成员变量】进行赋值。

① 【《StkQualnetScenarioExplorer.cs》】的[ OnEntityAddNetworkInterfaceMenuItemClick ]:

源码如下:

private void OnEntityAddNetworkInterfaceMenuItemClick(object sender, EventArgs e)

{

EntityTreeNode entityTreeNode = this.EntityContextMenu.Tag as EntityTreeNode;

if (entityTreeNode != null && entityTreeNode.Entity != null)

{

NetworkInterfaceForm networkInterfaceForm = new NetworkInterfaceForm(null, entityTreeNode.Entity, this.StkRoot);

if (networkInterfaceForm.ShowDialog() == DialogResult.OK)

{

NetworkInterface networkInterface = networkInterfaceForm.GetNetworkInterface();

entityTreeNode.Entity.NetworkInterfaces.Add(networkInterface);

entityTreeNode.InterfacesNode.Nodes.Add(new NetworkInterfaceTreeNode(networkInterface));

}

}

}

② 【《NetworkInterfaceForm.cs》】的[ public NetworkInterface GetNetworkInterface() ]

源码如下:

public NetworkInterface GetNetworkInterface()

{

if (this.m_networkInterface == null)

{

this.m_networkInterface = new NetworkInterface(this.InterfaceName);

}

else

{

this.m_networkInterface.Name = this.InterfaceName;

}

IAgStkObject agStkObject = null;

if (this.transmitterInstanceNameCombo.SelectedIndex < 0)

{

IAgStkObject agStkObject2 = this.m_stkRoot.GetObjectFromPath(this.m_parentEntity.StkObjectPath.PathString);

if (this.useTransmitterSensor.Checked)

{

if (this.transmitterSensorCombo.SelectedIndex < 0)

{

try

{

agStkObject = (agStkObject2 = agStkObject2.Children.New(AgESTKObjectType.eSensor, this.transmitterSensorCombo.Text));

goto IL_B5;

}

catch

{

agStkObject2 = null;

goto IL_B5;

}

}

agStkObject2 = (this.transmitterSensorCombo.SelectedItem as ComboBoxItem).Item as IAgStkObject;

}

IL_B5:

try

{

if (agStkObject2 != null)

{

IAgStkObject agStkObject3 = agStkObject2.Children.New(AgESTKObjectType.eAntenna, this.transmitterInstanceNameCombo.Text);

this.m_networkInterface.TransmitAntennaStkPath = agStkObject3.Path;

}

goto IL_11E;

}

catch

{

goto IL_11E;

}

}

IAgStkObject agStkObject4 = (this.transmitterInstanceNameCombo.SelectedItem as ComboBoxItem).Item as IAgStkObject;

this.m_networkInterface.TransmitAntennaStkPath = agStkObject4.Path;

IL_11E:

if (this.useTransmitAntennaForReceiveCheckBox.Checked)

{

this.m_networkInterface.ReceiveAntennaStkPath = this.m_networkInterface.TransmitAntennaStkPath.PathString;

}

else

{

if (this.receiverInstanceNameCombo.SelectedIndex < 0)

{

IAgStkObject agStkObject5 = this.m_stkRoot.GetObjectFromPath(this.m_parentEntity.StkObjectPath.PathString);

if (this.useReceiverSensor.Checked)

{

if (this.receiverSensorCombo.SelectedIndex < 0)

{

try

{

if (agStkObject != null && this.receiverSensorCombo.Text.Equals(this.transmitterSensorCombo.Text))

{

agStkObject5 = agStkObject;

}

else

{

agStkObject5 = agStkObject5.Children.New(AgESTKObjectType.eSensor, this.receiverSensorCombo.Text);

}

goto IL_200;

}

catch

{

agStkObject5 = null;

goto IL_200;

}

}

agStkObject5 = (this.receiverSensorCombo.SelectedItem as ComboBoxItem).Item as IAgStkObject;

}

IL_200:

try

{

if (agStkObject5 != null)

{

IAgStkObject agStkObject6 = agStkObject5.Children.New(AgESTKObjectType.eAntenna, this.receiverInstanceNameCombo.Text);

this.m_networkInterface.ReceiveAntennaStkPath = agStkObject6.Path;

}

goto IL_26F;

}

catch

{

goto IL_26F;

}

}

IAgStkObject agStkObject7 = (this.receiverInstanceNameCombo.SelectedItem as ComboBoxItem).Item as IAgStkObject;

this.m_networkInterface.ReceiveAntennaStkPath = agStkObject7.Path;

}

IL_26F:

return this.m_networkInterface;

}

③[AGI.StkQualnetObjectModel.NetworkInterface]类型的【[networkInterface]类成员变量】调试时,内部变量赋值情况

  • networkInterface {interface0} AGI.StkQualnetObjectModel.NetworkInterface

AGI.StkQualnetObjectModel.ISTKQualNetMappingWriterInterface.RainOutagePercent 0.1 double

ChannelIndex -1 int

+ IPv4Address {169.0.0.0} AGI.StkQualnetObjectModel.IPv4Address

+ IPv4SubnetMask {255.255.255.0} AGI.StkQualnetObjectModel.IPv4SubnetMask

IPv6Address null AGI.StkQualnetObjectModel.IPv6Address

IPv6SubnetMask null AGI.StkQualnetObjectModel.IPv6SubnetMask

  • Id {444ff6ea-ac23-472a-be0b-0e28797a73c8} System.Guid

InterfaceId -1 int

IsNodeExpanded false bool

IsSatelliteInterface false bool

Link null AGI.StkQualnetObjectModel.IConnection

Name "interface0" string

NameWithParent "interface0" string

NetworkProtocol eIPv4 AGI.StkQualnetObjectModel.NetworkProtocolType

Parent null AGI.StkQualnetObjectModel.NetworkInterfaceList

PropertyChanged null System.ComponentModel.PropertyChangedEventHandler

QualNetInterfaceId "-1" string

  • RainOutagePercent {AGI.StkQualnetObjectModel.VariableDouble} AGI.StkQualnetObjectModel.VariableDouble

+ ReceiveAntennaStkPath {/Satellite/XL11/Antenna/antennaU1} AGI.StkQualnetObjectModel.StkObjectPath

STKReceiveAntennaPath "/Application/STK/Scenario/StarlinkSimScenario/Satellite/XL11/Antenna/antennaU1" string

STKTransmitAntennaPath "/Application/STK/Scenario/StarlinkSimScenario/Satellite/XL11/Antenna/antennaU1" string

  • Subcategory {AGI.StkQualnetObjectModel.NetworkInterfaceSubcategory} AGI.StkQualnetObjectModel.NetworkInterfaceSubcategory

+ TransmitAntennaStkPath {/Satellite/XL11/Antenna/antennaU1} AGI.StkQualnetObjectModel.StkObjectPath

  • m_id {AGI.StkQualnetObjectModel.VariableGuid} AGI.StkQualnetObjectModel.VariableGuid

  • m_idVariable {AGI.StkQualnetObjectModel.VariableInterfaceId} AGI.StkQualnetObjectModel.VariableInterfaceId

m_link null AGI.StkQualnetObjectModel.IConnection

m_name "interface0" string

m_parent null AGI.StkQualnetObjectModel.NetworkInterfaceList

  • m_receiveAntennaPath {AGI.StkQualnetObjectModel.VariableStkObjectPath} AGI.StkQualnetObjectModel.VariableStkObjectPath

  • m_transmitAntennaPath {AGI.StkQualnetObjectModel.VariableStkObjectPath} AGI.StkQualnetObjectModel.VariableStkObjectPath

  • Static members

AGI.StkQualnetUiControls.dll!AGI.StkQualnetUiControls.StkQualnetScenarioExplorer.OnEntityAddNetworkInterfaceMenuItemClick(object sender, System.EventArgs e) 行 253 C#

  1. 修改【反编译后重新编译报错的[AGI.StkQualnetObjectModel]】,并添加到[test_Client]解决方案,调整工程项目依赖顺序,编译成功:

[AGI.StkQualnetObjectModel] 逆向后编译成功★ →修改【反编译后重新编译报错的 [AGI.StkQualnetObjectModel] 】,并添加到 [test_Client] 解决方案,调整工程项目依赖顺序,编译成功

★【反编译导出为 VS2019****项目 】使用dnSpy v6.1.8 选择导出为VS2019 项目

★【VS2022 打开反编译导出的项目】打开反编译的[AGI.StkQualnetObjectModel]VS2019****项目 ,修改编译报错的地方,其实大概就是几类报错问题(之前还是心理惧怕,以为很多错误^_^);

★【++VS2022++ ++修改++ [AGI.StkQualnetObjectModel]反编译后**++报错地方++**,编译成功】编译成功的代码打包备份在〔[F:\WS_STK_use_Interop\AGI.StkQualnetObjectModel STK11.6 Exata 插件, dnSpy 逆向后重新编译成功 ^_^ .zip ]〕 → 后来发现其实也可以用VS2015打开!!!;

★【将修改报错完毕的[AGI.StkQualnetObjectModel]添加到[test_Client]解决方案,调整工程项目依赖顺序,编译成功】编译成功的代码打包备份在〔[F:\WS_STK_use_Interop\test_Client 【成功编译 ^_^ 添加 [AGI.StkQualnetObjectModel] 逆向工程之后】 .zip ]〕。

★★★★★【VS2022修改[AGI.StkQualnetObjectModel]反编译后报错地方,编译成功】

①(string)element.Attribute("min"); 未赋值报错问题;

源码文件: F:\WS_STK_use_Interop\AGI.StkQualnetObjectModel\AGI.StkQualnetObjectModel\QualnetXmlHelper.cs

else if (text3.Equals("TEXT")) // JSLS备注: IPv6 地址格式

{

// JSLS备注: 下面的 dnSpy 反编译源码 重新编译 报错

//(string)element.Attribute("min");

//(string)element.Attribute("max");

string strJSLS_min = (string)element.Attribute("min");

string strJSLS_max = (string)element.Attribute("max");

if (text.ToUpper().Contains("V6-ADDRESS")) // JSLS备注: IPv6 地址格式

{

if (text5.Length == 0)

{

text5 = "2000::"; // JSLS备注: IPv6 地址格式

}

result = new VariableIPv6Address(text2, text, text7, flag2, text6, text9, text8, optional, text5);

}

else

{

result = new VariableString(text2, text, text7, flag2, text6, text9, text8, optional, text5);

}

}

② using(){ while() } 改为 foreach() 迭代问题;

源码文件:F:\WS_STK_use_Interop\AGI.StkQualnetObjectModel\AGI.StkQualnetObjectModel\Scenario.cs

// Token: 0x060003D1 RID: 977 RVA: 0x00010A18 File Offset: 0x0000EC18

public static void ImportFromStkScenario(AgScenario stkScenario, Scenario newScenario)

{

newScenario.StkRoot = (stkScenario.Root as AgStkObjectRoot);

foreach (object obj in stkScenario.Children)

{

IAgStkObject agStkObject = (IAgStkObject)obj;

Entity entity;

if (agStkObject.ClassType == AgESTKObjectType.eMissileSystem)

{

// JSLS备注: 下面的 dnSpy 反编译原始代码,报错!

// 【错误 CS1674 "IEnumerator": using 语句中使用的类型必须可隐式转换为"System.IDisposable" AGI.StkQualnetObjectModel D:\Intel\11111\AGI.StkQualnetObjectModel\Scenario.cs】

//using (IEnumerator enumerator2 = agStkObject.Children.GetEnumerator())

// JSLS分析:查看阅读 STK 编程帮助文档, STK编程中, foreach() 迭代方式用得多一些!

// using (IEnumerator enumerator2 = agStkObject.Children.GetEnumerator())

// 加上 while (enumerator2.MoveNext())

// 实际上应该就是【 foreach(IAgStkObject obj2 in iagObjectItems) 】迭代方式?

IAgStkObjectCollection iagObjectItems = agStkObject.Children;

foreach(IAgStkObject obj2 in iagObjectItems)

{

//while (enumerator2.MoveNext())

//{

//object obj2 = enumerator2.Current;

IAgStkObject stkObject = (IAgStkObject)obj2;

entity = Scenario.CreateEntityFromStkObject(newScenario, stkObject);

if (entity != null && entity != null)

{

newScenario.Hierarchy.Entities.Add(entity);

}

//}

//continue;

}

}

entity = Scenario.CreateEntityFromStkObject(newScenario, agStkObject);

if (entity != null && entity != null)

{

newScenario.Hierarchy.Entities.Add(entity);

}

}

}

③ yield return 问题;

源码文件: F:\WS_STK_use_Interop\AGI.StkQualnetObjectModel\AGI.StkQualnetObjectModel\Node.cs

// Token: 0x060002EC RID: 748 RVA: 0x00009D26 File Offset: 0x00007F26

public IEnumerator<Element> GetDepthFirstEnumerator()

{

yield return this.mData;

foreach (Node<Element> node in this.mChildren)

{

IEnumerator<Element> kidenumerator = node.GetDepthFirstEnumerator();

while (kidenumerator.MoveNext())

{

// 下面 dnSpy 反编译的代码 重新编译报错

//!0! = kidenumerator.Current;

//yield return !;

// JSLS备注:不知道这个逻辑对不对?

this.mData = kidenumerator.Current;

yield return this.mData;

}

kidenumerator = null;

}

IEnumerator<Node<Element>> enumerator = null;

yield break;

yield break;

}

④ < PrivateImplementationDetails >.ComputeStringHash(type) 密封类问题;

源码文件: F:\WS_STK_use_Interop\AGI.StkQualnetObjectModel\AGI.StkQualnetObjectModel\QualNetAppConfigWriter.cs

// JSLS备注: 【 < PrivateImplementationDetails > 】应该是个密封类, 修改名字为【 [JSLS_XiaoYuHao__PrivateImplementationDetails__JSLS_DaYuHao] 】

internal sealed class JSLS_XiaoYuHao__PrivateImplementationDetails__JSLS_DaYuHao

{

// Token: 0x06000759 RID: 1881 RVA: 0x0001D0CC File Offset: 0x0001B2CC

internal static uint ComputeStringHash(string s)

{

uint num = 0U;

if (s != null)

{

num = 2166136261U;

for (int i = 0; i < s.Length; i++)

{

num = ((uint)s[i] ^ num) * 16777619U;

}

}

return num;

}

}

// Token: 0x0600030A RID: 778 RVA: 0x0000A01C File Offset: 0x0000821C

public bool Write()

{

if (this.m_scenario.Connections.Applications.Count > 0 && !File.Exists(this.FilePath))

{

try

{

this.m_writer = File.CreateText(this.FilePath);

this.m_writer.AutoFlush = true;

foreach (NetworkApplication networkApplication in this.m_scenario.Connections.Applications)

{

this.WriteFormattedString("{0} {1} {2} ", new object[]

{

networkApplication.Type,

networkApplication.Source.NodeId,

networkApplication.Destination.NodeId

});

string type = networkApplication.Type;

// JSLS备注: 【 < PrivateImplementationDetails > 】应该是个密封类, 修改名字为【 [JSLS_XiaoYuHao__PrivateImplementationDetails__JSLS_DaYuHao] 】

//uint num = < PrivateImplementationDetails >.ComputeStringHash(type);

uint num = JSLS_XiaoYuHao__PrivateImplementationDetails__JSLS_DaYuHao.ComputeStringHash(type);

if (num <= 2037514399U)

{

if (num <= 893884390U)

{

if (num != 563683786U)

{

if (num != 570659453U)

{

if (num == 893884390U)

{

if (type == "CBR")

{

this.WriteCBR(networkApplication);

}

}

}

else if (type == "TELNET")

⑤ ★★ Func<T, TResult>() 委托类型函数声明问题;

源码文件: F:\WS_STK_use_Interop\AGI.StkQualnetObjectModel\AGI.StkQualnetObjectModel\QualnetConfigFileMapping \ConfigFileInfo.cs

#region JSLS备注: 【 Func<NodeInfo, bool> 委托名称 】,表示输入为[NodeInfo]类型、输出为[bool]类型,名字叫[委托名称]的委托!

/*

以下示例所演示的那样将 lambda 表达式分配给 Func<T, TResult>委托。

using System;

public class LambdaExpression

{

public static void Main()

{

Func<string, string> convert = s => s.ToUpper();

string name = "Dakota";

Console.WriteLine(convert(name));

}

}

*/

#endregion JSLS备注: 【 Func<NodeInfo, bool> 委托名称 】,表示输入为[NodeInfo]类型、输出为[bool]类型,名字叫[委托名称]的委托!

//Func<NodeInfo, bool> <>9__1;

// JSLS备注: 声明一个 目前为空的【委托】

// 参考:VS2010帮助《Func<TResult> 委托》

#region 参考 VS2010帮助《Func<TResult> 委托》 中 的最后一个例子

/*

using System;

static class Func1

{

public static void Main()

{

// Note that each lambda expression has no parameters.

LazyValue<int> lazyOne = new LazyValue<int>(() => ExpensiveOne());

LazyValue<long> lazyTwo = new LazyValue<long>(() => ExpensiveTwo("apple"));

Console.WriteLine("LazyValue objects have been created.");

// Get the values of the LazyValue objects.

Console.WriteLine(lazyOne.Value);

Console.WriteLine(lazyTwo.Value);

}

static int ExpensiveOne()

{

Console.WriteLine("\nExpensiveOne() is executing.");

return 1;

}

static long ExpensiveTwo(string input)

{

Console.WriteLine("\nExpensiveTwo() is executing.");

return (long)input.Length;

}

}

class LazyValue<T> where T : struct

{

private Nullable<T> val;

private Func<T> getValue;

// Constructor.

public LazyValue(Func<T> func)

{

val = null;

getValue = func;

}

public T Value

{

get

{

if (val == null)

// Execute the delegate.

val = getValue();

return (T)val;

}

}

}

*/

#endregion 参考 VS2010帮助《Func<TResult> 委托》 中 的最后一个例子

Func<NodeInfo, bool> JSLSdebug__DaYuXiaoYu9__1 = new Func<NodeInfo, bool>( (nodeInfo) => (false) );

// 【空委托】的写法: 右箭头的 左边 [nodeInfo] 表示输入类型为[NodeInfo]的形参,右箭头的 右边[false] 表示 委托函数实现时返回 bool 类型的 值 false 。

//Func<NodeInfo, bool> <>9__3;

Func<NodeInfo, bool> JSLSdebug__DaYuXiaoYu9__3 = new Func<NodeInfo, bool>( (nodeInfo) => (false) );

// 【空委托】的写法: 右箭头的 左边 [nodeInfo] 表示输入类型为[NodeInfo]的形参,右箭头的 右边[false] 表示 委托函数实现时返回 bool 类型的 值 false 。

foreach (string text2 in match.Value.Substring(num2 + 1, num3 - num2 - 1).Split(new char[]

{

','

}))

{

List<string> list3 = new List<string>();

if (text2.ToUpper().Contains("THRU"))

{

string text3 = text2.ToUpper();

int num4 = text3.IndexOf('T');

int num5 = text3.IndexOf('U');

string s = text3.Substring(0, num4 - 1).Trim();

string s2 = text3.Substring(num5 + 1).Trim();

int num6;

int.TryParse(s, out num6);

int num7;

int.TryParse(s2, out num7);

for (int j = num6; j <= num7; j++)

{

list3.Add(j.ToString());

}

}

else

{

list3.Add(text2);

}

foreach (string text4 in list3)

{

bool flag = false;

string trimmedCurId = text4.Trim();

long num8 = long.Parse(trimmedCurId);

string pattern4 = string.Format(ConfigFileInfo.s_satelliteNodeSearchPattern, trimmedCurId);

if (Regex.Match(configText, pattern4).Success)

{

IEnumerable<NodeInfo> nodeInfo = this.m_nodeInfo;

Func<NodeInfo, bool> predicate;

// 假如 predicate 委托函数 为空的话

if ((predicate = /*<>9__1*/ JSLSdebug__DaYuXiaoYu9__1) == null)

{

predicate = (/*<>9__1*/ JSLSdebug__DaYuXiaoYu9__1 = ((NodeInfo n) => n.Subnet.Equals(subnet) && n.IsSatellite));

// JSLS备注: 【 Func<NodeInfo, bool> 委托名称 】,表示输入为[NodeInfo]类型、输出为[bool]类型,名字叫[委托名称]的委托!

/*

以下示例所演示的那样将 lambda 表达式分配给 Func<T, TResult>委托。

using System;

public class LambdaExpression

{

public static void Main()

{

Func<string, string> convert = s => s.ToUpper();

string name = "Dakota";

Console.WriteLine(convert(name));

}

}

*/

}

if (new List<NodeInfo>(nodeInfo.Where(predicate)).Count == 0)

{

flag = true;

}

}

★★★★★【将修改报错完毕的[AGI.StkQualnetObjectModel]添加到[test_Client] 解决方案,调整工程项目依赖顺序,编译成功】

重点需要注意:

①被依赖项目编译后 *.dll 输出目录设置问题:具体在【某个工程项目】右键 → 属性 → 生成 → 输出 → 将【输出路径】设置为 STK11.6 的 Exata .Net DLL组件插件目录位置,即【[ C:\Program Files\AGI\STK 11\STK-QualNet Interface\ ]】

②项目依赖设置问题:特别注意,不仅要右键'解决方案'选择[项目依赖项]、[项目生成顺序]进行设置;而且,还要记得,对'每个具体的工程项目' ,再右键选择[生成依赖项]→[项目依赖项]、[项目生成顺序]进行设置。

相关推荐
ling1s3 小时前
C#基础(15)选择排序
开发语言·数据结构·算法·c#
CN.LG8 小时前
浅谈C#之SynchronizationContext
开发语言·c#
wiseyao121919 小时前
C#中判断socket是否已断开的方法
c#
friklogff19 小时前
【C#生态园】从容面对.NET性能挑战:全面解析多种性能监控工具
开发语言·c#·.net
E-iceblue20 小时前
C# 裁剪PDF页面
c#·pdf api·pdf页面·裁剪pdf
雷工笔记20 小时前
C#知识|软件接口的认识
c#
美人泪下020 小时前
c#将int转为中文数字
前端·c#
DLR-SOFT1 天前
C#如何把写好的类编译成dll文件
开发语言·c#
Crazy Struggle1 天前
2024 年 C# 高效开发:精选实用类库
c#·.net·精选类库
折纸星空Unity课堂1 天前
Unity3d开发的C#编码规范
unity·c#·游戏开发