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
这是我的 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