2015-03-24 2 views

ответ

2
  1. В VBScript нет анонимных функций/подмножеств/методов.
  2. Вы можете использовать GetRef() (см. sample1, sample2), чтобы получить что-то вроде указателя функции, который может быть передан в функции/подсистемы, которые будут там вызваны (обратный вызов). Но в VBScript нет замыканий, поэтому в VBScript возможны ошибки в других языках.
  3. Для конкретные проблемы, которые могут быть решены с помощью функций более высокого порядка в функциональных языках, могут быть (почти) эквивалентные решения VBScript, включающие классы/объекты; но для обсуждения этого подхода вам необходимо подробно описать вашу/такую ​​проблему.
+0

Спасибо! Тем временем я выяснил путь вокруг него, хотя это было очень специфично, а потому не очень абстрактное решение. Ну что ж. – DJD

0

VBScript имеет возможность исполнять арбитражный кодекс.

Выполнение и Eval просто выполняют то, что они говорят строкой, содержащей код.

ExecuteGlobal добавляет код в вашу программу, как новую функцию, новые переменные.

Сценарий управления добавляет скриптовый язык vbscript/jscript в любую программу, включая vbscripts. Он может иметь доступ к данным хоста.

Если вы используете ExecuteGlobal/Execute/Eval, лучше сначала запустить скриптконтроль, чтобы проверить наличие синтаксических ошибок (поскольку вы не можете улавливать синтаксические ошибки, но вы можете уловить ошибку времени выполнения, которую элемент управления скриптом дает синтаксис ошибка).

Таким образом, вы можете создать свою программу во время выполнения.

Set Arg = WScript.Arguments 
set WshShell = createObject("Wscript.Shell") 
Set Inp = WScript.Stdin 
Set Outp = Wscript.Stdout 

Sub VBSCmd 
    RawScript = LCase(Arg(1)) 
    'Remove^from quoting command line and replace : with vbcrlf so get line number if error 
    Script = Replace(RawScript, "^", "") 
    Script = Replace(Script, "'", chr(34)) 
    Script = Replace(Script, ":", vbcrlf) 
    'Building the script with predefined statements and the user's code 
    Script = "Dim gU" & vbcrlf & "Dim gdU" & vbcrlf & "Set gdU = CreateObject(" & chr(34) & "Scripting.Dictionary" & chr(34) & ")" & vbcrlf & "Function UF(L, LC)" & vbcrlf & "Set greU = New RegExp" & vbcrlf & "On Error Resume Next" & vbcrlf & Script & vbcrlf & "End Function" & vbcrlf 

    'Testing the script for syntax errors 
    On Error Resume Next 
    set ScriptControl1 = wscript.createObject("MSScriptControl.ScriptControl",SC) 
     With ScriptControl1 
      .Language = "VBScript" 
      .UseSafeSubset = False 
      .AllowUI = True 
     .AddCode Script 
    End With 
    With ScriptControl1.Error 
     If .number <> 0 then 
      Outp.WriteBlankLines(1) 
      Outp.WriteLine "User function syntax error" 
      Outp.WriteLine "==========================" 
      Outp.WriteBlankLines(1) 
      Outp.Write NumberScript(Script) 
      Outp.WriteBlankLines(2) 
      Outp.WriteLine "Error " & .number & " " & .description 
      Outp.WriteLine "Line " & .line & " " & "Col " & .column 
      Exit Sub 
     End If 
    End With 

    ExecuteGlobal(Script) 

    'Remove the first line as the parameters are the first line 
    'Line=Inp.readline 
    Do Until Inp.AtEndOfStream 
     Line=Inp.readline 
     LineCount = Inp.Line 

     temp = UF(Line, LineCount) 
     If err.number <> 0 then 
      outp.writeline "" 
      outp.writeline "" 
      outp.writeline "User function runtime error" 
      outp.writeline "===========================" 
      Outp.WriteBlankLines(1) 
      Outp.Write NumberScript(Script) 
      Outp.WriteBlankLines(2) 
      Outp.WriteLine "Error " & err.number & " " & err.description 
      Outp.WriteLine "Source " & err.source 

      Outp.WriteLine "Line number and column not available for runtime errors" 
      wscript.quit 
     End If 
     outp.writeline temp 
    Loop 
End Sub 

Vbs

filter vbs "text of a vbs script" 
filter vb "text of a vbs script" 

Используйте двоеточия для того чтобы отделить заявления и линии. Используйте одиночные кавычки вместо двойных кавычек, если вам нужна одна цитата, использующая chr (39). Скопируйте скобки и амперсанд с символом ^. Если вам понадобится использование каретки chr (136).

Эта функция называется UF (для пользовательской функции). Он имеет два параметра: L, который содержит текущую строку и LC, который содержит linecount. Задайте результаты сценария UF. См. Пример.

Доступны три глобальных объекта. Необъявленная глобальная переменная gU для поддержания состояния. Используйте его как массив, если вам нужно больше одной переменной. Объект словаря gdU для сохранения и доступа к предыдущим строкам. И объект RegExp greU готов к использованию.

Пример

Этот VBS скрипт вставляет номер строки и устанавливает линию к функции UF, какой фильтр печатает.

filter vbs "uf=LC ^& ' ' ^& L"<"%systemroot%\win.ini" 

Вот как это выглядит в памяти

Dim gU 
Set gdU = CreateObject("Scripting.Dictionary") 
Set greU = New RegExp 

Function UF(L, LC) 

---from command line--- 
    uf=LC & " " & L 
---end from command line--- 

End Function 

Если будет отображать отладочные детали ошибки фильтра синтаксиса.

User function syntax error 
========================== 


1 Dim gU 
2 Dim gdU 
3 Set greU = CreateObject("Scripting.Dictionary") 
4 Function UF(L, LC) 
5 On Error Resume Next 
6 uf=LC dim & " " & L 
7 End Function 

Error 1025 Expected end of statement 
Line 6 Col 6 


User function runtime error 
=========================== 


1 Dim gU 
2 Dim gdU 
3 Set greU = CreateObject("Scripting.Dictionary") 
4 Function UF(L, LC) 
5 On Error Resume Next 
6 uf=LC/0 & " " & L 
7 End Function 

Error 11 Division by zero 
Source Microsoft VBScript runtime error 
Line number and column not available for runtime errors 
+0

Я думал об этом, но это не очень изящное решение. Поскольку цель заключалась в том, чтобы мой код был более надежным и чистым, eval и co. не очень полезны. Тем не менее, вы правы в том, что если цель моей попытки функции более высокого порядка состояла в том, чтобы просто передавать фрагменты кода для выполнения, это было бы безупречное решение. – DJD

0

Забавная вещь о функциональных объектах заключается в том, что они по определению являются утечкой памяти. Это означает, что, как только вы создаете объект функции, вам нужно сохранить область, в которой она была создана, неповрежденной, что отбросило меня.

Class VBCompiler  
    Public leaks 

    Public Sub Class_Initialize() 
     leaks = Array() 
    End Sub 

    Public Function Compile(code) 
     Dim compiler, result 

     Set compiler = CreateObject("MSScriptControl.ScriptControl") 
     Set portal = CreateObject("Scripting.Dictionary") 
     Dim name 

     compiler.Language = "VBScript" 
     compiler.AddObject "portal", portal, True 
     compiler.ExecuteStatement code 
     name = compiler.Procedures(1).Name 
     compiler.ExecuteStatement "portal.Add ""result"", GetRef(""" & name & """)" 

     ' save the script control because if we go out of scope... 
     ' our function object goes poof! 
     ' leaks.Push compiler 
     ReDim Preserve leaks(UBound(leaks) + 1) 
     Set leaks(UBound(leaks)) = compiler 

     Set Compile = portal("result") 
    End Function 
End Class 

Dim z 
Set z = New VBCompiler 
Set z2 = z.Compile("Function Foo(s):MsgBox s:Foo = 2:End Function") 
z2("Hi!") 
z2 "Hello Again!" 

дает два окна сообщений по желанию

Class VBCompiler  
    Public Function Compile(code) 
     Dim compiler, result 

     Set compiler = CreateObject("MSScriptControl.ScriptControl") 
     Set portal = CreateObject("Scripting.Dictionary") 
     Dim name 

     compiler.Language = "VBScript" 
     compiler.AddObject "portal", portal, True 
     compiler.ExecuteStatement code 
     name = compiler.Procedures(1).Name 
     compiler.ExecuteStatement "portal.Add ""result"", GetRef(""Foo"") "    
     Set Compile = portal("result") 
    End Function 
End Class 

Dim z 
Set z = New VBCompiler 
Set z2 = z.Compile("Function Foo():MsgBox ""Well Met!"":Foo = 2:End Function") 
z2("Hi!") 
z2 "Hello Again!" 

выше дает (29, 5) (null): Unspecified error. Эта ошибка по существу: your object has committed suicide.

Этот подход может быть улучшен (в частности, проблема расточительного сценария ScriptControl для компиляции без каких-либо планов их выпуска).

Смежные вопросы