C# 运行 VBScript with MSScriptControl AddObject with string 失败

C# run VBScript with MSScriptControl AddObject with string failed

这是我的 C# 程序:

class Program
{
    static void Main(string[] args)
    {
        CallVbsFunction(1); //Work
        CallVbsFunction(1.2); //Work
        CallVbsFunction('a'); //Work
        CallVbsFunction("a"); //!!Exception see bellow
    }

    private static void CallVbsFunction(object p)
    {
        var sc = new MSScriptControl.ScriptControl();
        sc.Language = "VBScript";
        sc.AllowUI = true;

        try
        {         
            sc.AddCode(System.IO.File.ReadAllText("script.vbs"));
            sc.AddObject("myguid", p, false);
            var parameters = new object[] { "a" };
            sc.Run("test", ref parameters);
        }
        catch (Exception e)
        {
            Console.Out.WriteLine(e.ToString());
        }
    }
}

我的 VBScript 文件内容:

Function Test(a)
    MsgBox myguid
End Function

最后,当我将 AddObject() 与字符串对象一起使用时,这是我的异常:

System.Runtime.InteropServices.COMException (0x800A0005): Invalid procedure call or argument at MSScriptControl.IScriptControl.Run(String ProcedureName, Object[]& Parameters) at Srcipting.Program.CallVbsFunction(Object p) in Program.cs

您需要使用 ComVisible:

的包装器对象
[ComVisible(true)]
public class StringWrapper
{
    private string wrappedString;

    public StringWrapper(string value)
    {
        wrappedString = value;
    }

    public override string ToString()
    {
        return wrappedString;
    }
}

CallVbsFunction(new StringWrapper("a"));

问题是 .net String 对象对于 MSScriptControl 的第一眼看起来像是本机 vb 字符串,但第二眼看起来不像。


只有当你直接注册一个字符串或者注册一个returns一个字符串的函数时,你才需要使用这个包装器。注册具有字符串类型属性的对象时没有问题。您传递给 Run() 的参数也没有问题,因为这些参数将由 .net 运行时正确编组为本机 vb 字符串。


因此最好的选择可能是不向您的脚本提供单独的字符串,而是提供一个封装了您希望它使用的所有不同值的对象。

定义这个class

[ComVisible(true)]
public class HostOptions
{
    public string OptionA { get; set; }
    public string OptionB { get; set; }
}

然后构造对象并设置所有属性并注册到脚本控件

var hostOptions = new HostOptions();
hostOptions.OptionA = "AAA";
hostOptions.OptionB = "BBB";

sc.AddObject("HostOptions", hostOptions, false);

然后您可以像这样在脚本中使用它:

Function Test(a)
    MsgBox HostOptions.OptionA
    MsgBox HostOptions.OptionB
End Function