You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C#.NET中实现类似VBScript的对象复用逻辑

PCOMM会话管理VBS转C#的问题与解决

问题描述

原本用VBScript开发了一套PCOMM会话管理方案:动态销毁并复用AutSess对象,排除生产会话("A"会话)及登录特定业务应用(窗口标题含"HOSTORS"或"NDB")的会话,仅使用可用会话。

迁移至C#.NET后编写了逻辑相似的代码,遇到两个问题:

  • 尝试在循环内重新声明AutSess ObjEmulator = new AutSess();时触发CS0136错误(命名冲突)
  • C#中ObjEmulator = null无法像VBScript的Set ObjEmulator = Nothing那样彻底销毁COM对象

原VBScript代码

Set Connect_Manager = CreateObject("pcomm.autECLConnMgr")
Set autECLConnList = CreateObject("PCOMM.autECLConnList")
Set ObjEmulator = CreateObject("pcomm.auteclsession")

autECLConnList.Refresh
Num = autECLConnList.Count
PrevNum = Num

If Num = 0 Then
   MsgBox "You must have at least two PCOMM sessions open to use this tool." & vbnewline & vbnewline &  "Program is now terminating.", vbOKOnly + vbExclamation + vbSystemModal, "No Session Error"
   SetEverythingToNothing
   WScript.Echo "EXIT"
   WScript.Quit
End If

strSession = autECLConnList(Num).Name
Connect_Manager.autECLConnList.Refresh

ObjEmulator.SetConnectionByName (strSession)
Window_Title = ObjEmulator.autECLWinMetrics.WindowTitle

If InStr(Window_Title, "HOSTORS") <> 0 Or strSession = "A" Or InStr(Window_Title, "NDB") <> 0 Then
   Set ObjEmulator = Nothing
   Loop_Count = 1
   Do
      ResEmulator = "No"
      PrevNum = PrevNum - 1
      If PrevNum = 0 Then
         MsgBox "You need to have more than one session open." & vbnewline & "Program is now terminating.", vbOKOnly + vbExclamation + vbSystemModal, "One Session Error"
         SetEverythingToNothing
         WScript.Echo "EXIT"
         WScript.Quit
      Else
         strSession = autECLConnList(PrevNum).Name
         If strSession = "A" Then
            MsgBox "You cannot use your production (A) session." & vbnewline & "Please open another session." & vbnewline & "Program is now terminating.", vbOKOnly + vbExclamation + vbSystemModal, "Production Session Error"
            SetEverythingToNothing
            WScript.Echo "EXIT"
            WScript.Quit
            Exit Do
         Else
            Set ObjEmulator = CreateObject("pcomm.auteclsession")
            Connect_Manager.autECLConnList.Refresh
            ObjEmulator.SetConnectionByName (strSession)
            Window_Title = ObjEmulator.autECLWinMetrics.WindowTitle
            If InStr(Window_Title, "NDB") <> 0 Or InStr(Window_Title, "HOSTORS") <> 0 Then
               Set ObjEmulator = Nothing
            Else
               ResEmulator = "Yes"
            End If
         End If
      End If
      Loop_Count = Loop_Count + 1
      If Loop_Count = 10 Then
         MsgBox "Unable to connect to a session." & vbnewline & "Please make sure you have working sessions." & vbnewline & "Program is now terminating.", vbOKOnly + vbExclamation + vbSystemModal, "Production Session Error"
         SetEverythingToNothing
         WScript.Echo "EXIT"
         WScript.Quit
         Exit Do
      End If
   Loop Until ResEmulator = "Yes"
End If

改写后的C#代码(存在问题版本)

AutConnList autECLConnList = new AutConnList();
AutConnMgr Connect_Manager = new AutConnMgr();
AutSess ObjEmulator = new AutSess();
       
autECLConnList.Refresh();
int Num = autECLConnList.Count;
int PrevNum = Num;

if (Num == 0)
{
    MessageBox.Show("You must have at least two PCOMM sessions open to use this tool." + Environment.NewLine + Environment.NewLine + "Program is now terminating.", "No Session Error", MessageBoxButtons.OK, 
    MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1, 
    MessageBoxOptions.DefaultDesktopOnly);
    return;
}

string strSession = autECLConnList[Num].Name;
autECLConnList.Refresh();

ObjEmulator.SetConnectionByName(strSession);
string Window_Title = ObjEmulator.autECLWinMetrics.WindowTitle;


if (Window_Title.IndexOf("HOSTORS") == 0 || strSession == "A" || Window_Title.IndexOf("NDB") == 0)
{
    ObjEmulator = null;
    int Loop_Count = 1;
    string ResEmulator = "No";
    do
    {
        PrevNum -= 1;
        if (PrevNum == 0)
        {
            MessageBox.Show("You need to have more than one session open." + Environment.NewLine + "Program is now terminating.", "One Session Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);
            return;
        }
        else
        {
            strSession = autECLConnList[PrevNum].Name;
            if (strSession == "A")
            {
                MessageBox.Show("You cannot use your production (A) session." + Environment.NewLine + "Please open another session." + Environment.NewLine + "Program is now terminating.", "Production Session Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);
                return;
            }
            else
            {
                ObjEmulator = new AutSess();
                autECLConnList.Refresh();
                ObjEmulator.SetConnectionByName(strSession);
                Window_Title = ObjEmulator.autECLWinMetrics.WindowTitle;
                if (Window_Title.IndexOf("HOSTORS") == 0 || Window_Title.IndexOf("NDB") == 0)
                {
                    ObjEmulator = null;
                }
                else
                {
                    ResEmulator = "Yes";
                }
            }
        } 
        Loop_Count++;
        if (Loop_Count == 10)
        {
            MessageBox.Show("Unable to connect to a session." + Environment.NewLine + "Please make sure you have working sessions." + Environment.NewLine + "Program is now terminating.", "Production Session Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);
            return;
        }
    } while (ResEmulator == "Yes");
}

解决方案

1. 解决CS0136命名冲突错误

CS0136是因为在同一作用域内重复声明同名变量。C#不允许在同一作用域内多次声明相同名称的变量,只需要去掉重复的声明语句,直接对已声明的变量重新赋值即可:

  • 把循环内的AutSess ObjEmulator = new AutSess();改为ObjEmulator = new AutSess();(变量ObjEmulator已经在方法顶部声明过)

2. 实现COM对象的彻底销毁

PCOMM的AutSess是COM互操作对象,仅设置ObjEmulator = null只是断开C#对它的引用,COM侧的资源不会立即释放。要实现类似VBScriptSet ObjEmulator = Nothing的效果,需要:

  • 先检查对象是否实现IDisposable接口,若实现则调用Dispose()
  • 对于COM对象,调用Marshal.ReleaseComObject()强制释放COM引用,确保资源回收

示例代码:

// 销毁AutSess对象的方法
private void ReleaseEmulator(AutSess emulator)
{
    if (emulator != null)
    {
        // 如果实现了IDisposable,先调用Dispose
        if (emulator is IDisposable disposable)
        {
            disposable.Dispose();
        }
        // 强制释放COM引用
        System.Runtime.InteropServices.Marshal.ReleaseComObject(emulator);
    }
}

在需要销毁对象的地方调用该方法:

// 替换原有的ObjEmulator = null
ReleaseEmulator(ObjEmulator);
ObjEmulator = null;

修正后的核心循环逻辑

if (Window_Title.IndexOf("HOSTORS") != -1 || strSession == "A" || Window_Title.IndexOf("NDB") != -1)
{
    ReleaseEmulator(ObjEmulator);
    ObjEmulator = null;
    int Loop_Count = 1;
    string ResEmulator = "No";
    do
    {
        PrevNum -= 1;
        if (PrevNum == 0)
        {
            MessageBox.Show("You need to have more than one session open." + Environment.NewLine + "Program is now terminating.", "One Session Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);
            // 退出前释放所有资源
            ReleaseEmulator(ObjEmulator);
            return;
        }
        else
        {
            strSession = autECLConnList[PrevNum].Name;
            if (strSession == "A")
            {
                MessageBox.Show("You cannot use your production (A) session." + Environment.NewLine + "Please open another session." + Environment.NewLine + "Program is now terminating.", "Production Session Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);
                ReleaseEmulator(ObjEmulator);
                return;
            }
            else
            {
                // 先释放旧对象再创建新对象
                ReleaseEmulator(ObjEmulator);
                ObjEmulator = new AutSess();
                autECLConnList.Refresh();
                ObjEmulator.SetConnectionByName(strSession);
                Window_Title = ObjEmulator.autECLWinMetrics.WindowTitle;
                if (Window_Title.IndexOf("HOSTORS") != -1 || Window_Title.IndexOf("NDB") != -1)
                {
                    ReleaseEmulator(ObjEmulator);
                    ObjEmulator = null;
                }
                else
                {
                    ResEmulator = "Yes";
                }
            }
        } 
        Loop_Count++;
        if (Loop_Count == 10)
        {
            MessageBox.Show("Unable to connect to a session." + Environment.NewLine + "Please make sure you have working sessions." + Environment.NewLine + "Program is now terminating.", "Production Session Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);
            ReleaseEmulator(ObjEmulator);
            return;
        }
    } while (ResEmulator != "Yes"); // 修正循环条件,原代码逻辑错误:应该是ResEmulator != "Yes"时继续循环
}

注意:原C#代码中的循环条件while (ResEmulator == "Yes")是错误的,应该改为while (ResEmulator != "Yes"),否则会不符合原VBScript的逻辑。

内容的提问来源于stack exchange,提问作者Lou

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 07:45:53