在C,Python,Perl,GO,Java,Javascript 语言中嵌入MSScriptControl.ScriptControl
·
前言
前面已经介绍在C++,C#,VB6,Delphi6语言中嵌入MSScriptControl.ScriptControl并执行脚本代码的实例,现在介绍在C,Python,Perl,GO,Java,Javascript 语言中嵌入ControlMSScriptControl.ScriptControl并执行脚本代码的实例。MSScriptControl.ScriptControl 是Windows环境中一个用于脚本执行的COM组件。下面这个表格汇总了它支持的主要脚本语言和基本方法:
| 支持语言 | 说明 |
|---|---|
| VBScript | 微软的Visual Basic脚本语言 |
| JScript | 微软的JavaScript实现 |
| 其他语言 | 理论上支持任何实现了ActiveX Scripting接口的引擎(如PERL、REXX),但非微软官方提供,需单独安装相应引擎 |
🔧 主要方法与属性
MSScriptControl.ScriptControl 提供了一些重要的方法和属性:
- Language:设置或获取脚本引擎的解释语言,例如 “VBScript” 或 “JScript”。
- AddCode:向脚本引擎中添加要执行的脚本代码。
- Eval:对表达式进行求值并返回结果。
- Run:运行一个指定的过程。
- ExecuteStatement:解释并执行脚本语句。
- AddObject:向脚本引擎中添加一个对象,以便在脚本中使用该对象提供的方法等。
- AllowUI:控制是否允许脚本显示用户界面元素(如消息框)。
- Timeout:设置或返回控件执行脚本的超时值。
- Error:发生错误时,此属性返回一个错误对象。
🗂️ 组件使用步骤
使用该组件的一般步骤如下:
- 在程序中加入或创建
ScriptControl。 - 定义一个
ScriptControl的实例。 - 调用
AddCode等方法向脚本引擎中加入要执行的脚本。 - 调用
Run或Eval等方法执行脚本。
💻 各语言调用示例
由于 MSScriptControl.ScriptControl 是一个COM组件,不同语言有各自的调用方式。这里提供C、Python、Perl、Go、Java和JavaScript的调用示例。
1. C语言 (使用Windows COM API)
C语言调用COM组件相对复杂,需要基本的COM知识。
#include <windows.h>
#include <oleauto.h>
int main() {
HRESULT hr;
IDispatch *pScriptControl = NULL;
VARIANT varResult, varLanguage, varCode, varProcedure;
BSTR bstrLanguage, bstrCode, bstrProcedure;
DISPID dispid;
DISPPARAMS dispparams = {NULL, NULL, 0, 0};
EXCEPINFO excepInfo;
// 初始化COM
CoInitialize(NULL);
// 创建MSScriptControl.ScriptControl对象
hr = CoCreateInstance(&CLSID_ScriptControl, NULL, CLSCTX_ALL, &IID_IDispatch, (void**)&pScriptControl);
if (SUCCEEDED(hr)) {
// 设置语言属性 (VBScript)
bstrLanguage = SysAllocString(L"VBScript");
varLanguage.vt = VT_BSTR;
varLanguage.bstrVal = bstrLanguage;
hr = InvokePut(pScriptControl, L"Language", &varLanguage); // 需自行实现InvokePut
// 准备要执行的VBScript代码
bstrCode = SysAllocString(L"Function Greet(name)\r\n Greet = \"Hello, \" & name & \"!\"\r\nEnd Function");
varCode.vt = VT_BSTR;
varCode.bstrVal = bstrCode;
// 调用AddCode方法添加代码
hr = InvokeMethod(pScriptControl, L"AddCode", &varCode); // 需自行实现InvokeMethod
// 准备运行的过程名和参数
bstrProcedure = SysAllocString(L"Greet");
varProcedure.vt = VT_BSTR;
varProcedure.bstrVal = bstrProcedure;
VARIANT varParam;
varParam.vt = VT_BSTR;
varParam.bstrVal = SysAllocString(L"World");
dispparams.rgvarg = &varParam;
dispparams.cArgs = 1;
// 调用Run方法执行函数
hr = pScriptControl->lpVtbl->Invoke(pScriptControl, GetIDForName(pScriptControl, L"Run"), &IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, &varResult, &excepInfo, NULL);
if (SUCCEEDED(hr)) {
// 输出结果
printf("Result: %ls\n", varResult.bstrVal);
VariantClear(&varResult);
}
// 清理资源
SysFreeString(bstrLanguage);
SysFreeString(bstrCode);
SysFreeString(bstrProcedure);
SysFreeString(varParam.bstrVal);
pScriptControl->lpVtbl->Release(pScriptControl);
}
CoUninitialize();
return 0;
}
说明:C中使用COM需要处理大量细节,如获取Dispatch ID、调用方法等。上述示例简化了InvokePut、InvokeMethod和GetIDForName等辅助函数的实现。实际编码中需查阅COM文档仔细处理。
2. Python
Python可通过pywin32库调用COM组件。
import win32com.client
def python_script_control_example():
try:
# 创建MSScriptControl.ScriptControl对象
sc = win32com.client.Dispatch("MSScriptControl.ScriptControl")
sc.Language = "VBScript"
# 执行VBScript
print("=== VBScript ===")
vbs_code = """
Function AddNumbers(x, y)
AddNumbers = x + y
End Function
Function Greet(name)
Greet = "Hello, " & name
End Function
"""
sc.AddCode(vbs_code)
result_add = sc.Run("AddNumbers", 5, 3)
result_greet = sc.Run("Greet", "Python")
print(f"5 + 3 = {result_add}")
print(f"Greeting: {result_greet}")
# 执行JScript
print("\n=== JScript ===")
sc.Language = "JScript"
js_code = """
function multiply(a, b) {
return a * b;
}
function getMessage(platform) {
return "Running in " + platform;
}
"""
sc.AddCode(js_code)
result_multiply = sc.Run("multiply", 6, 7)
result_message = sc.Run("getMessage", "Python")
print(f"6 * 7 = {result_multiply}")
print(f"Message: {result_message}")
# 使用Eval计算表达式
print("\n=== Eval Example ===")
sc.Language = "VBScript"
expression_result = sc.Eval("3 * 4 + 5")
print(f"Eval result: {expression_result}")
except Exception as e:
print(f"An error occurred: {e}")
if __name__ == "__main__":
python_script_control_example()
3. Perl
Perl可以通过Win32::OLE模块调用COM组件。
use strict;
use warnings;
use Win32::OLE;
sub perl_script_control_example {
eval {
# 创建MSScriptControl.ScriptControl对象
my $sc = Win32::OLE->new('MSScriptControl.ScriptControl');
$sc->{Language} = 'VBScript';
# 执行VBScript
print "=== VBScript ===\n";
my $vbs_code = '
Function ConcatenateStrings(str1, str2)
ConcatenateStrings = str1 & " " & str2
End Function
Sub DisplayMessage(msg)
MsgBox msg
End Sub
';
$sc->AddCode($vbs_code);
my $result_concat = $sc->Run('ConcatenateStrings', 'Hello', 'Perl');
print "Concatenated string: $result_concat\n";
# 执行JScript
print "\n=== JScript ===\n";
$sc->{Language} = 'JScript';
my $js_code = '
function calculateHypotenuse(a, b) {
return Math.sqrt(a*a + b*b);
}
function getVersion() {
return "JScript version 1.0";
}
';
$sc->AddCode($js_code);
my $result_hypo = $sc->Run('calculateHypotenuse', 3, 4);
my $result_version = $sc->Run('getVersion');
print "Hypotenuse: $result_hypo\n";
print "Version: $result_version\n";
# 使用Eval计算表达式
print "\n=== Eval Example ===\n";
$sc->{Language} = 'VBScript';
my $expression_result = $sc->Eval('Len("Hello World")');
print "Length of 'Hello World': $expression_result\n";
};
if ($@) {
print "An error occurred: $@\n";
}
}
perl_script_control_example();
4. Go
Go语言可以通过go-ole库调用COM组件。
package main
import (
"fmt"
"log"
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
)
func go_script_control_example() {
// 初始化COM
ole.CoInitialize(0)
defer ole.CoUninitialize()
// 创建MSScriptControl.ScriptControl对象
unknown, err := oleutil.CreateObject("MSScriptControl.ScriptControl")
if err != nil {
log.Fatal("CreateObject failed:", err)
}
defer unknown.Release()
sc, err := unknown.QueryInterface(ole.IID_IDispatch)
if err != nil {
log.Fatal("QueryInterface failed:", err)
}
defer sc.Release()
// 设置语言属性
_, err = oleutil.PutProperty(sc, "Language", "VBScript")
if err != nil {
log.Fatal("PutProperty Language failed:", err)
}
// 执行VBScript
fmt.Println("=== VBScript ===")
vbsCode := `
Function ReverseString(s)
ReverseString = StrReverse(s)
End Function
Function CalculateArea(radius)
CalculateArea = 3.14159 * radius * radius
End Function
`
_, err = oleutil.CallMethod(sc, "AddCode", vbsCode)
if err != nil {
log.Fatal("AddCode VBScript failed:", err)
}
resultReverse, err := oleutil.CallMethod(sc, "Run", "ReverseString", "Hello")
if err != nil {
log.Fatal("Run ReverseString failed:", err)
}
fmt.Printf("Reverse of 'Hello': %v\n", resultReverse.ToString())
resultArea, err := oleutil.CallMethod(sc, "Run", "CalculateArea", 5)
if err != nil {
log.Fatal("Run CalculateArea failed:", err)
}
fmt.Printf("Area of circle with radius 5: %v\n", resultArea.ToString())
// 执行JScript
fmt.Println("\n=== JScript ===")
_, err = oleutil.PutProperty(sc, "Language", "JScript")
if err != nil {
log.Fatal("PutProperty Language JScript failed:", err)
}
jsCode := `
function findMax(arr) {
return Math.max.apply(null, arr);
}
function repeatString(str, count) {
return Array(count + 1).join(str);
}
`
_, err = oleutil.CallMethod(sc, "AddCode", jsCode)
if err != nil {
log.Fatal("AddCode JScript failed:", err)
}
// 注意:传递数组参数可能需要特殊处理,这里简化了
resultMax, err := oleutil.CallMethod(sc, "Run", "findMax", []int32{10, 5, 25, 3, 15})
if err != nil {
log.Fatal("Run findMax failed:", err)
}
fmt.Printf("Max value: %v\n", resultMax.ToString())
resultRepeat, err := oleutil.CallMethod(sc, "Run", "repeatString", "Go!", 3)
if err != nil {
log.Fatal("Run repeatString failed:", err)
}
fmt.Printf("Repeated string: %v\n", resultRepeat.ToString())
}
func main() {
go_script_control_example()
}
5. Java
Java可以通过Jacob(Java COM Bridge)或类似的COM桥接库调用COM组件。
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
public class JavaScriptControlExample {
public static void main(String[] args) {
// 创建MSScriptControl.ScriptControl对象
ActiveXComponent sc = new ActiveXComponent("MSScriptControl.ScriptControl");
try {
// 设置语言属性
Dispatch.put(sc, "Language", "VBScript");
// 执行VBScript
System.out.println("=== VBScript ===");
String vbsCode =
"Function CountVowels(str)\n" +
" Dim count, i, char\n" +
" count = 0\n" +
" For i = 1 To Len(str)\n" +
" char = LCase(Mid(str, i, 1))\n" +
" If InStr(\"aeiou\", char) > 0 Then\n" +
" count = count + 1\n" +
" End If\n" +
" Next\n" +
" CountVowels = count\n" +
"End Function\n" +
"\n" +
"Function GetTypeName(value)\n" +
" GetTypeName = TypeName(value)\n" +
"End Function";
Dispatch.call(sc, "AddCode", vbsCode);
Variant resultVowels = Dispatch.call(sc, "Run", "CountVowels", "Hello World");
Variant resultType = Dispatch.call(sc, "Run", "GetTypeName", 42);
System.out.println("Vowels in 'Hello World': " + resultVowels);
System.out.println("Type of 42 in VBScript: " + resultType);
// 执行JScript
System.out.println("\n=== JScript ===");
Dispatch.put(sc, "Language", "JScript");
String jsCode =
"function formatCurrency(amount, symbol) {\n" +
" return symbol + amount.toFixed(2);\n" +
"}\n" +
"\n" +
"function createArray() {\n" +
" return ['Java', 'COM', 'Scripting'];\n" +
"}";
Dispatch.call(sc, "AddCode", jsCode);
Variant resultCurrency = Dispatch.call(sc, "Run", "formatCurrency", 19.99, "$");
Variant resultArray = Dispatch.call(sc, "Run", "createArray");
System.out.println("Formatted currency: " + resultCurrency);
System.out.println("Created array: " + resultArray);
// 使用Eval计算表达式
System.out.println("\n=== Eval Example ===");
Dispatch.put(sc, "Language", "VBScript");
Variant evalResult = Dispatch.call(sc, "Eval", "2^8 + 3*5");
System.out.println("Eval result: " + evalResult);
} finally {
sc.safeRelease();
}
}
}
6. JavaScript (Node.js)
Node.js可以通过node-win32-ole或类似模块调用COM组件。
const ole = require('win32-ole');
function javascriptScriptControlExample() {
try {
// 创建MSScriptControl.ScriptControl对象
const sc = new ole.ActiveXObject('MSScriptControl.ScriptControl');
sc.Language = 'VBScript';
// 执行VBScript
console.log('=== VBScript ===');
const vbsCode = `
Function IsPalindrome(str)
Dim cleanStr, reversedStr
cleanStr = LCase(Replace(str, " ", ""))
reversedStr = StrReverse(cleanStr)
IsPalindrome = (cleanStr = reversedStr)
End Function
Function GetSystemInfo
GetSystemInfo = "Running on Windows with VBScript"
End Function
`;
sc.AddCode(vbsCode);
const resultPalindrome = sc.Run('IsPalindrome', 'A man a plan a canal Panama');
const resultSystemInfo = sc.Run('GetSystemInfo');
console.log(`Is palindrome: ${resultPalindrome}`);
console.log(`System info: ${resultSystemInfo}`);
// 执行JScript
console.log('\n=== JScript ===');
sc.Language = 'JScript';
const jsCode = `
function calculateBMI(weight, height) {
return (weight / (height * height)).toFixed(2);
}
function getRandomColor() {
var colors = ['red', 'green', 'blue', 'yellow', 'purple'];
return colors[Math.floor(Math.random() * colors.length)];
}
`;
sc.AddCode(jsCode);
const resultBMI = sc.Run('calculateBMI', 70, 1.75);
const resultColor = sc.Run('getRandomColor');
console.log(`BMI: ${resultBMI}`);
console.log(`Random color: ${resultColor}`);
// 使用Eval计算表达式
console.log('\n=== Eval Example ===');
sc.Language = 'VBScript';
const evalResult = sc.Eval('Date()');
console.log(`Current date: ${evalResult}`);
} catch (error) {
console.error(`An error occurred: ${error.message}`);
}
}
javascriptScriptControlExample();
⚠️ 重要说明与局限
- 环境依赖:
MSScriptControl.ScriptControl是Windows平台的COM组件,主要适用于Windows环境。 - 语言支持:其核心支持VBScript和JScript。虽然通过实现ActiveX Scripting接口可支持其他语言(如PerlScript),但这通常需要额外安装相应的脚本引擎,并非微软官方标配。
- 现代替代:对于新的项目,可以考虑使用更现代的脚本引擎,例如:
- V8 JavaScript引擎 (用于JavaScript)
- Lua 等轻量级脚本语言
- 各语言内置的表达式求值库
- 安全考虑:在生产环境中执行动态脚本时,务必注意代码安全,防止注入攻击。
更多推荐



所有评论(0)