1

Тема: VBS: хитрости/особенности

Сегодня стояла задача сделать маленький быстрый скрипт для GPO, чтобы он был максимально маленького размера. Сокращал всё как только можно и дошло до экспериментов, вот что выяснилось...

ipa="192.168.42.77"
splitter=split(ipa,".")
subnet=splitter(2)

тоже самое можно получить так

ipa="192.168.42.77"
subnet=split(ipa,".")(2)

Мне это показалось интересным

Времени не хватает... :-(

2

Re: VBS: хитрости/особенности

Вот еще так можно

subnet=split("192.168.42.77",".")(2)

3

Re: VBS: хитрости/особенности

Поздравляю ! У каждого Колумба своя Америка )

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

4

Re: VBS: хитрости/особенности

Блин...  ребята, мы вообще мозги ?!?!

Времени не хватает... :-(

5

Re: VBS: хитрости/особенности

Функция, выполняет некоторые действия и возвращает ссылку на саму себя. Результат: несколько вызовов функции подряд превращаются в магию. Практической ценности мало, но красиво.

Function Say (Value)
	WScript.Echo Value
	Set Say = GetRef("Say")
End Function

Say("Hello, World!")("I am Magus")("My name is Merlin")
( 2 * b ) || ! ( 2 * b )

6

Re: VBS: хитрости/особенности

Rumata пишет:

Функция, выполняет некоторые действия и возвращает ссылку на саму себя.

Рекурсия.

Xameleon пишет:

Поздравляю ! У каждого Колумба своя Америка )

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

7

Re: VBS: хитрости/особенности

Возврат ссылки на себя не есть тоже самое что и вызов функции из нее же самой
Предыдущий код можно преобразовать в серию вызовов функции

Say("Hello, World!")
Say("I am Magus")
Say("My name is Merlin")

Подобный прием встречается в javascript. Так что Америку я не открыл, а всего лишь спонтанно портировал прием из одного языка в другой.

( 2 * b ) || ! ( 2 * b )

8

Re: VBS: хитрости/особенности

Rumata пишет:

Возврат ссылки на себя не есть тоже самое что и вызов функции из нее же самой

Возможно, я не совсем прав, но по сути, по-моему, то же самое.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

9

Re: VBS: хитрости/особенности

Перенёс тему в профильный раздел.

10 (изменено: Евген, 2011-09-30 20:40:39)

Re: VBS: хитрости/особенности

Rumata пишет:
Say("Hello, World!")("I am Magus")("My name is Merlin")

Мда...  согласен, такого синтаксиса в использовании тоже не видовал...:/
ну фишка-то здесь вот в этом
   

Set Say = GetRef("Say")

Где-то у нас dab000 собирал мегаобфускатор...  дык вот если б он примастерил эти тонкости в свой обфускатор - было б вообще чудно...

Но для начала пускай все выложаться для набора коллекции подобных "ляп" в синтаксисе...

Времени не хватает... :-(

11

Re: VBS: хитрости/особенности

интересный пост, интересные фичи, интересная коллекция получается

Евген пишет:

Где-то у нас dab000 собирал мегаобфускатор...  дык вот если б он примастерил эти тонкости в свой обфускатор - было б вообще чудно...

польстили за мега , "примастерить" эти фичи в обфускаторе можно - регулярные выражения - сила , правда пока не вижу каким образом

Евген пишет:

ну фишка-то здесь вот в этом
   

Set Say = GetRef("Say")

GetRef, наверное, немного из другой оперы - HTA - таким образом, похоже, рекурсию можно организовать, не пробовал

12

Re: VBS: хитрости/особенности

Да что же вы все на рекурсию заглядываетесь. Это цепочка вызовов функций. Все не мог найти правильное определение, вот - Continuation passing style.

( 2 * b ) || ! ( 2 * b )

13

Re: VBS: хитрости/особенности

Я тоже в упор рекурсии не вижу.

14

Re: VBS: хитрости/особенности

Rumata пишет:

Функция, выполняет некоторые действия и возвращает ссылку на саму себя. Результат: несколько вызовов функции подряд превращаются в магию. Практической ценности мало, но красиво.

Function Say (Value)
    WScript.Echo Value
    Set Say = GetRef("Say")
End Function
 
Say("Hello, World!")("I am Magus")("My name is Merlin")

Супер!
Это определённо что-то новенькое! И никак не рекурсия.
Getref в данном примере говорит только о том что идёт возварат ссылки, о чем уже и сказал Rumata.
Всё же не понятно - как оно происходит
Недокументированная особенность языка? Да нет...
'________________________________________________________
Спустя некоторое время:
А, до меня дошла суть! Никаких чудес. Ну ведь это же элементарно:

Интерпретируем строку в уме (слева направо):

Say("Hello, World!")("I am Magus")("My name is Merlin")

функция выполняет некое действие и на то самое место, где стоит вызов функции с параметром возвращается ссылка на туже самую функцию.
Получается уже:

Say("I am Magus")("My name is Merlin")

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

Say("My name is Merlin")

Поэтому то и получается что строка - синтаксически верная.

15

Re: VBS: хитрости/особенности

Рекурсии, и правда, никакой, да и практической ценности, действительно, мало

16

Re: VBS: хитрости/особенности

Я уже говорил, что этот прием используется в javascript. Не часто, но используется. Там эта особенность бывает востребована. Например, в jQuery работают по этому принципу - возврат объекта, что позволяет создавать цепочки вызовов методов объекта. Или создание и одновременно многократный вызов безымянной функции, чтобы не плодить сущности. В VBS это не возможно, поэтому и нет в нем ценности. Или я ошибаюсь и не знаю, что в VBS есть возможность возвращать ссылку на текущий объект?

( 2 * b ) || ! ( 2 * b )

17

Re: VBS: хитрости/особенности

Rumata, думаю, не ошибаетесь, ибо вроде как нет там такого понятия, как «текущий объект».

Вкратце изложенное проще описать, уйдя от кажущейся рекурсии, так: вызов процедуры/функции можно производить при помощи GetRef("<Имя процедуры/функции>"):

Option Explicit

Call GetRef("Proc") (GetRef("FuncAdd")(2), GetRef("FuncAdd")(3))

WScript.Quit 0

Sub Proc(Value1, Value2)
    WScript.Echo "Proc:", Value1, Value2
End Sub

Function FuncAdd(Value)
    WScript.Echo "Func:", Value
    
    FuncAdd = Value + 1
End Function
FuncAdd: 2
FuncAdd: 3
Proc: 3 4

18 (изменено: dab00, 2011-10-02 12:09:22)

Re: VBS: хитрости/особенности

В VBS я применяю GetRef для привязки процедур к событиям объектов HTML, не было пока необходимости в ином применении (пытаюсь оправдать показанное выше невежество )

19

Re: VBS: хитрости/особенности

2 alexii:

alexii пишет:

Rumata, думаю, не ошибаетесь, ибо вроде как нет там такого понятия, как «текущий объект».

Ммм... А использование "Me" в процедурах разве не считается за некий аналог ?

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

20

Re: VBS: хитрости/особенности

То в VB/VBA.

21

Re: VBS: хитрости/особенности

Я проверил - в VBS тоже есть. А вот то что это не документировано - это плохо. Имею в виду scripts56.chm (версию и время скачивания файла не помню, но одна из последних). Ключевое слово Me упоминается в нескольких статьях этой документации, но нет отдельной статьи, описывающей это ключевое слово.

( 2 * b ) || ! ( 2 * b )

22

Re: VBS: хитрости/особенности

Ага. Нашёл. Если я правильно понял, то в VBScript «Me» представляет собой объект типа «VBScriptTypeInfo»:

WScript.Echo TypeName(Me)

ссылающийся на сам скрипт?

А в JScipt «this» — это ссылка не на скрипт, а на функцию, так?

23

Re: VBS: хитрости/особенности

2 alexii: На сколько я знаю - в VBScript "Me" в глобальном виде это действительно ссылка на объект скрипта и в процедурах так же. Но в случае подключеных событий это ссылка на объект породивший событие.

К примеру:


Option Explicit

MsgBox "Глобальная ссылка на Me:" & TypeName(Me)

Test

Sub Test()
	MsgBox "Ссылка на Me внутри обычной процедуры:" & TypeName(Me)
End Sub

Dim sc

set sc = WScript.CreateObject("MSScriptControl.ScriptControl.1","sc_")
sc.Language = "vbscript"
sc.AddCode "Dim a as long"

Sub sc_error()
	MsgBox "Ссылка на Me внутри события:" & TypeName(me)
End Sub
Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

24 (изменено: Rumata, 2011-10-03 11:13:24)

Re: VBS: хитрости/особенности

alexii пишет:

ссылающийся на сам скрипт?


Sub Proc()
	WScript.Echo "Self.Proc()"
End Sub

Set Self = Me
Self.Proc

Me.Proc
alexii пишет:

А в JScipt «this» — это ссылка не на скрипт, а на функцию, так?

Точнее будет так. this это ссылка на объект, который является текущим контекстом вызова. В контексте всего скрипта this указывает на глобальный объект.

( 2 * b ) || ! ( 2 * b )

25

Re: VBS: хитрости/особенности

Спасибо, ясно. И вроде бы, внутри определения класса «Me» ссылается на класс, так?

26

Re: VBS: хитрости/особенности

Вроде бы да

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

27

Re: VBS: хитрости/особенности

Я бы сказал, что Me ссылается на экземпляр объекта.

( 2 * b ) || ! ( 2 * b )

28 (изменено: Rumata, 2011-10-09 10:34:08)

Re: VBS: хитрости/особенности

Вроде бы тематически подходит.

Я недавно решил перевести небольшой фрагмент кода работы с javascript на vbscript. С сожалением обнаружил, что в Vbscript весьма неудобные функции для работы с датой. Например:

1. получить количество дней в текущем месяце


var days = new Date(2011, 9 + 1, 0).getDate();

на vbscript объемнее, но еще терпимо


N = Now
F = DateAdd("m", 1, N)
days = DateDiff("d", N, F)

2. получить день недели для последнего дня месяца


var lday = new Date(2011, 9 + 1, 0).getDay();

на vbscript "неуклюжий"


N = Now
F = DateAdd("m", 1, N)
F = DateAdd("d", -DatePart("d", F), F)

lday = DatePart("w", F)

Подскажите, пожалуйста. Это такое положение вещей или я просто плохо искал?

( 2 * b ) || ! ( 2 * b )

29

Re: VBS: хитрости/особенности

Rumata пишет:

... обнаружил, что в Vbscript весьма неудобные функции для работы с датой...

А мне нравятся средства VBS:

'1. получить количество дней в текущем месяце
DateSerial(Year(Date), Month(Date) + 1 , 1) - DateSerial(Year(Date), Month(Date), 1)

'2. получить день недели для последнего дня текущего месяца
Weekday(DateSerial(Year(Date), Month(Date) + 1, 0), 2) 'первый день недели - понедельник

30

Re: VBS: хитрости/особенности

Бррр...

WScript.Echo Now
WScript.Echo Weekday(Now, vbUseSystemDayOfWeek)
WScript.Echo Weekday(Now, vbSunday)
WScript.Echo Weekday(Now, vbMonday)

Результат...

C:\>cscript z.vbs
Microsoft (R) Windows Script Host Version 5.7
Copyright (C) Microsoft Corporation. All rights reserved.

10.10.2011 14:48:16
1
2
1

Ой как не информативно. Что есть 1 и 2? 1 - понедельник или воскресенье?

Здесь Weekday Function четко сказано, что

The Weekday function can return any of these values:
vbSunday 1 Sunday
vbMonday 2 Monday
...

( 2 * b ) || ! ( 2 * b )

31

Re: VBS: хитрости/особенности

А-а-а... У них на МСДНе неверная информация. Понял как надо интерпретировать возвращаемую информацию. Weekday возвращает порядковый номер дня недели для данной даты, если бы отсчет начинался с определенного дня в неделе. То есть, если отсчет начинается с воскресенья (1), то понедельник - второй день, если с понедельника (2), то понедельник - день первый, и т.д.

( 2 * b ) || ! ( 2 * b )

32

Re: VBS: хитрости/особенности

Как цитировал когда-то коллега Xameleon — «если звёзды зажигают…» Благодаря данной теме, я сумел решить старую больную проблему, а именно: определить внутри обработки событий объекта «WshRemote» конкретный экземпляр объекта, вызвавший данное событие, и получить к нему доступ. Сие стало доступным, благодаря данной теме и коллегам Xameleon и Rumata (наподобие VBS/WMI: Многопоточный WshController с ограничением длины очереди, но проще).

Remote.vbs, имитация случайного времени исполнения удалённого скрипта:

Option Explicit

Dim lngTime

Randomize Timer

lngTime = Rnd() * 10 * 1000

WScript.Sleep lngTime

WScript.Quit 0

Local.vbs, пока без организации очереди, без реальной удалённой работы — только демонстрация концепции:

Option Explicit

Dim objDictionary

Dim objWshController
Dim objWshRemote

Dim i
Dim intKey


Set objDictionary    = WScript.CreateObject("Scripting.Dictionary")
Set objWshController = WScript.CreateObject("WSHController")

For i = 1 To 20
	Set objWshRemote = objWshController.CreateScript("""C:\Мои проекты\WshController\Remote.vbs""")
	WScript.ConnectObject objWshRemote, "Remote_"
	
	objDictionary.Add i, objWshRemote
Next


For Each intKey In objDictionary.Keys
	objDictionary.Item(intKey).Execute
Next

Do
	WScript.Sleep 100
Loop Until objDictionary.Count = 0

Set objWshController = Nothing
Set objDictionary    = Nothing

WScript.Quit 0
'=============================================================================

'=============================================================================
Sub Remote_Error
	Dim objWshError
	
	Set objWshError = Me.Error
	WScript.Echo "Error " & objWshError.Number & " - Line: " & objWshError.Line & ", Char: " & objWshError.Character & vbCrLf & "Description: " & objWshError.Description
End Sub
'=============================================================================

'=============================================================================
Sub Remote_Start
	Dim intKey
	
	For Each intKey In objDictionary.Keys
		If Me Is objDictionary.Item(intKey) Then
			WScript.Echo "Start", intKey
		End If
	Next
End Sub
'=============================================================================

'=============================================================================
Sub Remote_End
	Dim intKey
	
	For Each intKey In objDictionary.Keys
		If Me Is objDictionary.Item(intKey) Then
			WScript.Echo "End", intKey
			
			WScript.DisconnectObject objDictionary.Item(intKey)
			Set objDictionary.Item(intKey) = Nothing
			
			objDictionary.Remove intKey
		End If
	Next
End Sub
'=============================================================================

33

Re: VBS: хитрости/особенности

Блин, дошло !!!
Не сразу, но дошло....  фишка в me
Вообще прикольно !!!
alexii - МОЗГ !!!
Признаю - это лучше моего того варианта !!!
Это настоящая многопоточность WSHController !!!

Времени не хватает... :-(

34

Re: VBS: хитрости/особенности

Поправил в своём предыдущем посте все позабытые на радостях «theError» на «objWshError».

35

Re: VBS: хитрости/особенности

OFF: Никогда бы не подумал, что это для кого то станет открытием. ) Наверное потому что слишком к этому привык. Повторюсь - ":D Поздравляю ! У каждого Колумба своя Америка )". Рад что у Вас получилось задуманное.

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

36

Re: VBS: хитрости/особенности

Ссспасибо! Я действительно всегда предполагал, что Me — прерогатива больших VB-языков.

Xameleon пишет:

У каждого Колумба своя Америка

И это запомню .

37

Re: VBS: хитрости/особенности

2 alexii будет ли окончательный вариант реализации многопоточности в Вашем исполнении ?
(с предварительной асинхронной проверкой хостов пингами, ограничением длины очереди потоков , логированием успешности отработки и т.д. и т.п.)

Времени не хватает... :-(

38

Re: VBS: хитрости/особенности

Евген, в ближайшие пару месяцев я вряд ли найду время. И, как показывает опыт, где два месяца — там и четыре .

39

Re: VBS: хитрости/особенности

Всем доброго времени суток! Экспериментируя с execute(), я обнаружил возможность создавать функции, "вложенные" в функции - динамически объявлять процедуры и функции в области видимости переменных определенной процедуры или функции (метода, принадлежащего экземпляру класса). Правда, объявленная таким образом "локальная" функция не видит локальных переменных (переменных экземпляра класса), а обращается напрямую к глобальным переменным скрипта.

dim x
x = "global"
' вызов процедуры, объявляющей внутри себя процедуру
globalsub()
' после завершения процедуры объявленная в ней процедура более недоступна для вызова
' localsub() ' ошибка - несоответствие типа, в глобальном контексте процедура не появляется

sub globalsub()
    dim x
    x = "local" ' локально объявленная процедура не видит локально объявленную переменную
    execute _
        "sub localsub()" & vbcrlf & _
            "msgbox ""localsub message""" & vbcrlf & _
            "msgbox ""x = "" & x" & vbcrlf & _
        "end sub"
    localsub()
end sub

Подобным образом могут быть динамически объявлены классы в области видимости переменных определенной процедуры, функции, метода экземпляра класса, и в области видимости экземпляра класса.

' получение экземпляра класса, объявленного внутри функции
set objsourceless = newobj()
msgbox typename(objsourceless)
' после завершения функции объявленный в ней класс более недоступен для создания новых экземпляров
' set objtest = new clslocal ' ошибка - класс не определен, в глобальном контексте класс не появляется
' объявление класса внутри экземпляра класса, объявленного внутри функции
objsourceless.executestatement _
    "class clsadditional" & vbcrlf & _
        "public default sub run()" & vbcrlf & _
            "msgbox ""additional class message""" & vbcrlf & _
        "end sub" & vbcrlf & _
    "end class"
' получение экземпляра класса, объявленного внутри экземпляра класса, объявленного внутри функции
set objadditional = objsourceless.getinstance("clsadditional")
msgbox typename(objadditional)
objadditional()

function newobj()
    ' создание класса в области видимости функции
    execute _
        "class clslocal" & vbcrlf & _
            "public sub executestatement(statement)" & vbcrlf & _
                "executeglobal statement" & vbcrlf & _
            "end sub" & vbcrlf & _
            "public function getinstance(clsname)" & vbcrlf & _
                "set getinstance = eval(""new "" & clsname)" & vbcrlf & _
            "end function" & vbcrlf & _
        "end class"
    ' создание экземпляра класса
    set newobj = new clslocal
end function

А теперь о главном. Практической пользы в данной возможности я углядеть так и не сумел.

Щт Уккщк Куыгьу Туче
’ҐЄгй п Є®¤®ў п бва Ёж : 1251

40

Re: VBS: хитрости/особенности

omegastripes, для меня неожиданно и крайне интересно. ) Возьму на заметку. Мне такой "фокус" был нужен, когда хотел ссылку на onreadystatechange зацепить процедуру внутри класса. Сейчас попробую.

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

41

Re: VBS: хитрости/особенности

Продолжая тему VBScript: создание пользовательского объекта, можно использовать еще один вариант. Создание пользовательского объекта как экземпляра локально объявленного класса позволит не засорять глобальное пространство скрипта:

strmytypename = "customobject" ' тип объекта
arrmykeys = array("property1", "property2") ' массив с названиями свойств объека
arrmyvalues = array("value1", createobject("scripting.dictionary")) ' массив со значениями свойств
' создание объекта
set objmy = getmyobj(strmytypename, arrmykeys, arrmyvalues)
' проверка
msgbox typename(objmy)
msgbox objmy.property1
msgbox typename(objmy.property2)

function getmyobj(strtypename, arrkeys, arrvalues)
    dim i
    execute "class " & strtypename & ": public " & join(arrkeys, ", ") & ": end class: set getmyobj = new " & strtypename
    for i = 0 to ubound(arrkeys)
        if isobject(arrvalues(i)) then
            execute "set getmyobj." & arrkeys(i) & " = arrvalues(i)"
        else
            execute "getmyobj." & arrkeys(i) & " = arrvalues(i)"
        end if
    next
end function
Щт Уккщк Куыгьу Туче
’ҐЄгй п Є®¤®ў п бва Ёж : 1251

42

Re: VBS: хитрости/особенности

И еще один момент, касающийся execute, в дополнение к посту #39.
В то время, как вызов execute внутри процедуры или функции (или внутри метода экземпляра класса) создаёт процедуры, функции и классы локально, простое присвоение значения еще не объявленной переменной приводит к созданию переменной с этим значением в глобальном пространстве скрипта. Такое поведение я ожидал от executeglobal, но никак не от execute.. При чем данное присвоение даже не вызовет ошибку "переменная не определена" при наличии option explicit в первой строке скрипта - ошибка появится лишь в том случае, если инструкцию option explicit поставить вначале строки, выполняемой execute.

Щт Уккщк Куыгьу Туче
’ҐЄгй п Є®¤®ў п бва Ёж : 1251

43

Re: VBS: хитрости/особенности

Давно (уже года 2-3, наверно) хотел спросить по поводу этой фичи, предложенной Rumata.
Есть возможность применять при нескольких параметрах?

44

Re: VBS: хитрости/особенности

Flasher,

Наверное можно так:


Call Test("Text1", vbInformation, "Title1")("Text2", vbExclamation, "Title2")

Function Test(Prompt, Buttons, Title)
	MsgBox Prompt, Buttons, Title
	Set Test = GetRef("Test")
End Function
Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

45

Re: VBS: хитрости/особенности

Xameleon
Оно! Спасибо! Плюс это решает проблему обрыва и необходимости повтора последнего вызова в цепочке.
И, полагаю, имеет смысл в ряде случаев применять CPS вместо цикла в цикле. Нашёл по теме на русском.

P.S.: Это ж надо было столько прождать, чтобы узнать, что всё уткнётся в Call. Столько бы места и времени сэкономил...

46

Re: VBS: хитрости/особенности

Flasher, Вам попалась задача, где цепочки вызовов в VBS пригодились?

( 2 * b ) || ! ( 2 * b )

47

Re: VBS: хитрости/особенности

Rumata, да, хватало таких задач.

48

Re: VBS: хитрости/особенности

Замечательно! В свое время для меня это было просто игра, проверка воможностей активно используемых в других языках.

( 2 * b ) || ! ( 2 * b )

49

Re: VBS: хитрости/особенности

Покажу на простом примере:

' Есть некая дата в неподходящем формате (файла, например)
FDate = "5/5/5 5:5:5"

Dy = Day(FDate)  : Mh = Month(FDate)  : Yr = Year(FDate)
Hr = Hour(FDate) : Mn = Minute(FDate) : Sc = Second(FDate)

' Запишем в переменную дату 1-го преобразования
NDate = ReDate(FDate)

' Вызовем функцию 2-го преобразования
Call AddNull(Dy)(Mh)(Hr)(Mn)(Sc)

' Покажем разницу
MsgBox  "До преобразований:" & vbTab & FDate &_
vbCr & "1-е преобразование:" & vbTab & NDate &_
vbCr & "2-е преобразование:" & vbTab & ReDate(FDate)

Function AddNull(DateT)
  DateT = Right("0" & DateT, 2)
  Set AddNull = GetRef("AddNull")
End Function

Function ReDate(FDate)
  ReDate = Dy & "." & Mh & "." & Yr & " " & Hr & ":" & Mn & ":" & Sc
End Function

50

Re: VBS: хитрости/особенности

Flasher

Оно! Спасибо! Плюс это решает проблему обрыва и необходимости повтора последнего вызова в цепочке.

Wow. Да не за что. Рад, что пригодилось. Посмотрел Ваш пример, но пока что не понял почему нельзя его было реализовать по аналогии с этой темой - VBS: Abby Finereader Bank 6.0. Выгрузка даты в dbf в формате ggggmmdd ?

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

51

Re: VBS: хитрости/особенности

Xameleon
Ну, так очевидно, что в подобном случае Right("0" & DateT, 2) пришлось бы писать 5 раз вместо одного.

52

Re: VBS: хитрости/особенности

Flasher, понял. Тогда наверное имеет смысл.

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

53

Re: VBS: хитрости/особенности

В рамках последнего обсуждения множественного вызова функции с двумя переменными ранее вертелась мысль избавления от сущностей, когда значением (или его частью) переменной может выступать имя самой переменной. Делается это простым присвоением через Execute:

Execute Var & "=""Var"""

Что это даёт? Ну, во-первых, в ряде случаев избавление от необходимости задействовать коллекцию или опять же вызывать процедуру/функцию для динамического присвоения (пример c GetRef см. ниже в одном и кодов).
Т.е. вместо того, чтобы придумывать переменные с присвоением им значений можно в цикле имплантировать значения в имена и там же обработать:

Вот простой пример экономии. Привычное представление

' Запись в 139 символов:
C  = " класс"
C1 = "1" & C
C2 = "2" & C
C3 = "3" & C
C4 = "4" & C
C5 = "5" & C
C6 = "6" & C
C7 = "7" & C
C8 = "8" & C
C9 = "9" & C

переводим в

' Запись в 59 символов (полный аналог предыдущего):
For i = 1 To 9: Execute "C" & i & " = i & "" класс""" :Next

' Теперь у нас на руках все переменные C1-9 c данными. Т.е. их можно
' сравнивать, обрабатывать, вставлять в текст, перетасовывать и т.п.
' Пример:
MsgBox "Маша пошла в " & C5 & "." & vbCr & _
"Миша из " & C9 & "а решил сложную задачу по алгебре."

Или, предположим, мы располагаем списком значений, входящих в группу некого свойства объекта.
Примеры:

+ Возвращаем пути спецпапок по их именам:
Set FSO = CreateObject("Scripting.FileSystemObject")
With CreateObject("WScript.Shell")
  For i = 0 To .SpecialFolders.Count - 1
  	Path = .SpecialFolders(i)
  	Execute Replace(FSO.GetFileName(Path), " ", "") & " = Path" 
  Next
End With
WScript.Echo "делаем дела с папкой " & Fonts
WScript.Echo "делаем дела с папкой " & SendTo
+ Выделяем из списка частоту процессора и оперативную память:
Set Shell = CreateObject("Shell.Application")
GetVar("DirectoryServiceAvailable")("DoubleClickTime")("ProcessorLevel")_
  ("ProcessorSpeed")("ProcessorArchitecture")("PhysicalMemoryInstalled")

MsgBox "Частота процессора: " & vbTab & ProcessorSpeed & " MHz" & vbCr &_
     "Физическая память: " & vbTab & PhysicalMemoryInstalled & " байт(а)"

Function GetVar(Var)
  Execute Var & "= Shell.GetSystemInformation(Var)"
  Set GetVar = GetRef("GetVar")
End Function
+ Отобразим некоторые теги композиции:
Set Track = CreateObject("WMPlayer.OCX")._
NewMedia("C:\Windows\winsxs\X80C99~1.163\SLEEPA~1.MP3")

For i = 0 To Track.AttributeCount - 1
	Attr = Track.GetAttributeName(i)
	Execute "i" & Replace(Attr, "WM/", "") & "= Track.GetItemInfo(Attr)"
Next

MsgBox  "Номер: "  & vbTab & iTrackNumber & vbCr & _
		"Имя: "    & vbTab & iTitle       & vbCr & _
		"Альбом: " & vbTab & iAlbumTitle  & vbCr & _
		"Автор: "  & vbTab & iAuthor      & vbCr & _
		"Жанр: "   & vbTab & iGenre       & vbCr & _
		"Год: "    & vbTab & iYear, 4160, " MP3-теги"
+ Выведем свойства фотографии:
File = "C:\Windows\winsxs\X828C9~1.163\RU-wp5.jpg"

Set Img = WScript.CreateObject("WIA.ImageFile")
Img.LoadFile File

With Img.Properties
  For i = 1 To .Count
    FN = .Item(i).Name : If Not .Item(i).IsVector _
    And Not IsNumeric(FN) Then Execute FN & " = .Item(i).Value"
  Next
End With

Sr = InStrRev(File, "\") : FN = Mid(File, Sr + 1) : T = vbTab
Set Folder = CreateObject("Shell.Application").NameSpace(Left(File, Sr))
For Each P In Split("Name Directory DocTitle Owner Attributes " &_
                    "Copyright Dimensions Type Create Write Access")
  Execute "i" & P & " = Folder.ParseName(FN).ExtendedProperty(P)"
Next

MsgBox "Имя файла:"      & T & iName       & vbCr & _
       "Тип файла:"      & T & iType       & vbCr & _
       "Название:"       & T & iDocTitle   & vbCr & _
       "Разрешение:"     & T & XResolution & " x " & YResolution & " dpi" & vbCr & _
       "Размер кадра:"   & T & iDimensions & " пкс" & vbCr & _
       "Ширина кадра:"   & T & ExifPixXDim & " пкс" & vbCr & _
       "Высота кадра:"   & T & ExifPixYDim & " пкс" & vbCr & _
       "Дата съёмки:"    & T & DateTime    & vbCr & _
       "Дата создания:"  & T & iAccess     & vbCr & _
       "Дата изменения:" & T & iCreate     & vbCr & _
       "Автор съёмки:"   & T & Artist      & vbCr & _
       "Владелец:"       & T & iOwner      & vbCr & _
       "Автор. права:"   & T & Copyright

Приверженцу мелкомягкого эстетизма подобный подход в оптимизации может показаться радикальным и режущим глаз, но, полагаю, не я первый, кто горел желанием проделывать на VBS вещь, которая нативно вплетена в JS.
Буду рад, если кто оценит.

54 (изменено: Xameleon, 2017-01-29 21:37:56)

Re: VBS: хитрости/особенности

Решил добавить сюда. Это не заготовка полезного инструмента, а только "сэмпл" ещё одного использования вложенных вызовов.


Option Explicit

'Sample 1
MsgBox New [$].add("[").add("      no spaces      ").trim.add("]")

'Sample 2
MsgBox New [$].add("      test [1] [2] [3]").replace("/\d/g","!").replace("/test/gi","->").trim

'Sample 3
MsgBox New [$].add("     IT WAS UPCASE TEXT WITH SPACES ") _
			  .trim() _
			  .toLowerCase() _
			  .add("    and lower case text") _
			  .toUpperCase()

Class [$]
	Dim [b$],[s$]

	Function toUpperCase()
		[b$] = UCase([b$])
		Set toUpperCase = Me
	End Function

	Function toLowerCase()
		[b$] = LCase([b$])
		Set toLowerCase = Me
	End Function

	Function trim()
		[b$] = re("/^\s+|\s+$/g").replace([b$],"")
		Set [trim] = Me
	End Function
	
	Public Default Function text()
		text = [s$] & [b$]
	End Function
	
	Function add(text)
		[s$] = [s$] & [b$]
		[b$] = text
		Set add = Me
	End Function
	
	Function replace(pat, rep)
		[b$] = re(pat).replace([b$],rep)
		Set replace = Me
	End Function
	
	Function match(pat)
		Set match = re(pat).execute([b$])
	End Function
	
	Private Function re(pat)
		Set re = New RegExp
		re.Pattern = "^\/(.+)\/([igm]*)$"
		Dim matches: Set matches = re.Execute(pat)
		If matches.Count < 1 Then re.Pattern = pat: Exit Function
		Set matches = matches(0).subMatches
		re.Pattern = matches(0)
		re.Global = InStr(1,matches(1),"g",1)
		re.IgnoreCase = InStr(1,matches(1),"i",1)
		re.MultiLine = InStr(1,matches(1),"m",1)
	End Function
	
End Class
Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !