1

Тема: VBScript: используем классы .NET

Классы .NET могут быть спрограммированы таким образом, что они будут доступны как COM-объекты, надо только их зарегистрировать специальной утилитой. Многие стандартные классы .NET Framework поддерживают такую возможность. Например, командная строка регистрации:

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727>regasm System.dll

После этого на VBScript будет работать, например, такой код:

Set web = CreateObject("System.Net.WebClient")
web.DownloadFile "http://script-coding.com/", "c:\temp\script-coding.htm"

Этот скрипт сохранит страничку "http://script-coding.com/" в файл "c:\temp\script-coding.htm".

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

2

Re: VBScript: используем классы .NET

Решение от Gepard (г. Ставрополь), cборка .NET. Сайт http://forum.d01-soft.ru/.
Подключение объектов из произвольных сборок .NET.
Зарегистрируйте подобной командой:

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727>RegAsm  c:\temp\ObjectFerm.dll

Затем поместите сборку в кэш сборок подобной командой:

C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin>gacutil /i c:\temp\ObjectFerm.dll

Пример использования:

Set OF = CreateObject("ObjectFerm")
Set web = OF.GetObject("C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.dll", "System.Net.WebClient")
web.DownloadFile "http://script-coding.com/", "c:\temp\myfile.htm"

В архиве готовая библиотека, исходник, командный файл регистрации, утилита gacutil, примеры.

Post's attachments

ObjectFerm.rar 64.14 kb, 904 downloads since 2008-02-13 

You don't have the permssions to download the attachments of this post.
Предложения в русском языке начинаются с большой буквы и заканчиваются точкой.
В названии ветки всегда должен быть указан язык программирования или среда исполнения скрипта, если это возможно.

3

Re: VBScript: используем классы .NET

Ещё пример к решению в предыдущем посте. Скрипт опять сохранит страничку "http://script-coding.com/" в файл "c:\temp\script-coding.htm", но уже в случае, если вы находитесь за прокси, требующем авторизации. Этот пример демострирует методы SetParameterCount, SetParameterValue и GetObjectP, которые позволяют работать с объектами, конструкторы которых требуют параметров.

Set OF = CreateObject("ObjectFerm")
Set web = OF.GetObject("C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.dll", "System.Net.WebClient")
OF.SetParameterCount 2
OF.SetParameterValue 0, "proxy.mydomain.ru" ' IP прокси 
OF.SetParameterValue 1, 8080 ' порт прокси 
Set prx = OF.GetObjectP("C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.dll", "System.Net.WebProxy")
OF.SetParameterCount 2
OF.SetParameterValue 0, "v.pupkin" ' login
OF.SetParameterValue 1, "pass" ' pass
Set crc = OF.GetObjectP("C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.dll", "System.Net.NetworkCredential")
web.Proxy = prx
web.Proxy.Credentials = crc
web.DownloadFile "http://script-coding.com/", "c:\temp\myfile.htm"

Есть проблема: объекты, возвращаемые функцией GetObjectP, не совсем корректно работают. Обращение через точку к свойствам объектов, возвращённых GetObjectP, приводит к ошибке "требуется объект" (с объектами, возвращёнными GetObject, этого не происходит). При этом функция TypeName() для первых всегда возвращает "Object", а для вторых - возвращает имя класса. Например, строка

prx.Credentials = crc

работать не будет, но работают, как ни странно, такие строки:

web.Proxy = prx
web.Proxy.Credentials = crc
Предложения в русском языке начинаются с большой буквы и заканчиваются точкой.
В названии ветки всегда должен быть указан язык программирования или среда исполнения скрипта, если это возможно.

4

Re: VBScript: используем классы .NET

По мотивам статьи Использование консольного компилятора .NET Framework для создания приложений. Следующий reg-файл добавляет в контекстное меню .vb-файлов четыре различных команды компиляции и запуска. Это позволит писать небольшие программы на VB.NET почти с теми же удобствами, что и обычные скрипты WSH.

Windows Registry Editor Version 5.00 

[HKEY_CLASSES_ROOT\.VB] 
@="vbfile" 

[HKEY_CLASSES_ROOT\vbfile] 

[HKEY_CLASSES_ROOT\vbfile\shell] 

[HKEY_CLASSES_ROOT\vbfile\shell\open] 
@="Открыть в SciTE" 

[HKEY_CLASSES_ROOT\vbfile\shell\open\command] 
@="\"C:\\Program Files\\SciTE\\SciTE.exe\" \"%1\"" 

[HKEY_CLASSES_ROOT\vbfile\shell\open1] 
@="Скомпилировать .NET (консоль)" 

[HKEY_CLASSES_ROOT\vbfile\shell\open1\command] 
@="cmd /k \"\"C:\\WINDOWS\\Microsoft.NET\\Framework\\v2.0.50727\\vbc.exe\" \"%1\" /out:\"%1.exe\"\"" 

[HKEY_CLASSES_ROOT\vbfile\shell\open2] 
@="Скомпилировать и запустить .NET (консоль)" 

[HKEY_CLASSES_ROOT\vbfile\shell\open2\command] 
@="cmd /k \"\"C:\\WINDOWS\\Microsoft.NET\\Framework\\v2.0.50727\\vbc.exe\" \"%1\" /out:\"%1.exe\" && \"%1.exe\"\"" 

[HKEY_CLASSES_ROOT\vbfile\shell\open3] 
@="Скомпилировать .NET (win)" 

[HKEY_CLASSES_ROOT\vbfile\shell\open3\command] 
@="cmd /k \"\"C:\\WINDOWS\\Microsoft.NET\\Framework\\v2.0.50727\\vbc.exe\" \"%1\" /out:\"%1.exe\" /target:winexe\"" 

[HKEY_CLASSES_ROOT\vbfile\shell\open4] 
@="Скомпилировать и запустить .NET (win)" 

[HKEY_CLASSES_ROOT\vbfile\shell\open4\command] 
@="cmd /k \"\"C:\\WINDOWS\\Microsoft.NET\\Framework\\v2.0.50727\\vbc.exe\" \"%1\" /out:\"%1.exe\" /target:winexe && \"%1.exe\"\""

Пример использования. Создайте текстовый файл с расширением .vb с таким кодом:

Imports System.Windows.Forms 
Public Class WinForm 
   Inherits System.Windows.Forms.Form 
   Private b As New Button() 
   Public Sub New() 
       MyBase.New() 
       MyBase.Topmost = True 
       MyBase.Text = "Кнопка с текущим временем" 
       b.Dock = DockStyle.Fill 
       b.Text = Now() 
       AddHandler b.Click, AddressOf b_Click 
       MyBase.Controls.Add(b) 
       MyBase.Show() 
   End Sub 
   Public Sub b_Click(ByVal sender As Object, ByVal e As EventArgs) 
       b.Text = Now() 
   End Sub 
   Public Shared Sub Main() 
       System.Windows.Forms.Application.Run(New WinForm()) 
   End Sub 
End Class

Откройте контекстное меню Проводника на этом vb-файле, и вы сможете почти мгновенно скомпилировать и запустить его четырьмя способами.

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

5

Re: VBScript: используем классы .NET

Ещё одно решение от Gepard. Исполнение .NET кода на лету.
Сборка .NET, регистрируется как COM-объект, точно так же, как и предыдущая.
Пример исполнения кода C# на VBScript:

Set gl = CreateObject("Gepard.Loader")
gl.SetAdditionalAssemblysCount 2 
gl.SetAdditionalAssembly "System.dll"
gl.SetAdditionalAssembly "System.Windows.Forms.dll"
strForBuild = vbCrLF
strForBuild = strForBuild & "using System.Windows.Forms;" & vbCrLF
strForBuild = strForBuild & "namespace ClassLibrary1" & vbCrLF
strForBuild = strForBuild & "{" & vbCrLF
strForBuild = strForBuild & "public class Class1" & vbCrLF
strForBuild = strForBuild & "{" & vbCrLF
strForBuild = strForBuild & "public void ShowMessage(string Message)" & vbCrLF
strForBuild = strForBuild & "{" & vbCrLF
strForBuild = strForBuild & "MessageBox.Show(Message);" & vbCrLF
strForBuild = strForBuild & "}" & vbCrLF
strForBuild = strForBuild & "}" & vbCrLF
strForBuild = strForBuild & "}" & vbCrLF
If gl.Build(strForBuild) Then
    Set newObj = gl.GetObject("ClassLibrary1.Class1")
    newObj.ShowMessage "Тестовое сообщение"
Else
    WScript.Echo "Ошибка компиляции!"
End If

Замечания:
1. Метод Build для одного и того же модуля надо делать один раз (GetObject - сколько угодно), т.к. если компилировать одну и ту же сборку для каждого нового объекта, можно очень быстро забить память.
2. Возможность компиляции кода на VB.NET (метод BuildVB).

Set gl = CreateObject("Gepard.Loader")
gl.SetAdditionalAssemblysCount 1 
gl.SetAdditionalAssembly "System.Windows.Forms.dll"
strForBuild = vbCrLF
strForBuild = strForBuild & "Imports System.Windows.Forms" & vbCrLF
strForBuild = strForBuild & "Public class Class1" & vbCrLF
strForBuild = strForBuild & "Public Sub ShowMessage(Message As String)" & vbCrLF
strForBuild = strForBuild & "MessageBox.Show(Message)" & vbCrLF
strForBuild = strForBuild & "End Sub" & vbCrLF
strForBuild = strForBuild & "End Class" & vbCrLF
If gl.BuildVB(strForBuild) Then
    Set newObj = gl.GetObject("Class1")
    newObj.ShowMessage "Привет, BuildVB!"
Else
    WScript.Echo "Ошибка компиляции!"
End If

В архивах - исходник и готовая библиотека (loader.dll).

Post's attachments

loader.rar 51.96 kb, 596 downloads since 2008-02-15 

LoaderEx.rar 204.3 kb, 624 downloads since 2008-02-15 

You don't have the permssions to download the attachments of this post.
Предложения в русском языке начинаются с большой буквы и заканчиваются точкой.
В названии ветки всегда должен быть указан язык программирования или среда исполнения скрипта, если это возможно.

6

Re: VBScript: используем классы .NET

Решения, приведённые в данной ветке, являются скорее идеями, чем законченными решениями. Что, однако, не делает их менее интересными.

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

7

Re: VBScript: используем классы .NET

Пишем минимальный COM-сервер на VB.NET. По мотивам и в продолжение статьи Использование консольного компилятора .NET Framework для создания приложений.
Создаём текстовый файл с расширением .vb следующего содержания:

Imports System
Imports System.Reflection

<Assembly:AssemblyKeyFile("./Key.sn")>
<Assembly:AssemblyVersion("1.0.0.0")>

Namespace TestComponentLib

Public Interface ITestComponent
    Function Mult (x As Integer, y As Integer) As Integer
    ReadOnly Property About() As String
End Interface

Public class TestComponent
    Implements ITestComponent

    Public Function Mult (x As Integer, y As Integer) As Integer Implements ITestComponent.Mult
        Mult = x * y
    End Function

    Public ReadOnly Property About() As String Implements ITestComponent.About
        Get
            Return "Этот COM-сервер написан на VB.NET."
        End Get
    End Property
End Class

End Namespace

Как видно из кода, наш COM-сервер TestComponentLib.TestComponent будет поддерживать свойство только для чтения About, которое возвращает строку, а также метод Mult, который перемножает два полученных аргумента и возвращает результат.
Файл Key.sn, который должен находиться рядом с нашим исходником, содержит пару криптографических ключей, которые будут идентифицировать нашу сборку в GAC (Global Assembly Cache - Глобальный кэш сборок). Этот файл можно сгенерировать примерно такой командой:

sn.exe -k Key.sn

Откомпилировать наш COM-сервер можно примерно такой командой:

"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\vbc.exe" "c:\temp\test.vb" /out:"c:\temp\test.dll" /target:library

После этого зарегистрировать наш COM-сервер можно примерно такой командой:

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727>regasm c:\temp\test.dll

И наконец, поместить наш COM-сервер в GAC (Global Assembly Cache) можно примерно такой командой:

gacutil /i c:\temp\test.dll

После всего этого будет работать такой код на VBScript:

Set objTest = CreateObject("TestComponentLib.TestComponent")
WScript.Echo objTest.About
WScript.Echo objTest.Mult(3, 4)

Как видно, написать COM-сервер на VB.NET не просто, а очень просто . И вполне возможно обойтись для этого только стандартной установкой .NET Framework, парочкой бесплатных консольных утилит, не требующих установки (sn.exe и gacutil.exe находятся во вложении этого поста) и любым текстовым редактором.

Post's attachments

utils.zip 87.01 kb, 642 downloads since 2008-02-17 

You don't have the permssions to download the attachments of this post.
Предложения в русском языке начинаются с большой буквы и заканчиваются точкой.
В названии ветки всегда должен быть указан язык программирования или среда исполнения скрипта, если это возможно.

8

Re: VBScript: используем классы .NET

Очень простой диалог множественного выбора, использующий классы .NET, выполнен на VBScript.

'---------------------------------------------------------------
' Очень простой диалог множественного выбора, использующий классы
' .NET, выполнен на VBScript. 
'---------------------------------------------------------------
' NET Framework v2.0.50727
' OC WinME/XP
'---------------------------------------------------------------
 Set Form1    =CreateObject("System.Windows.Forms.Form")

 Set Radio1    =CreateObject("System.Windows.Forms.RadioButton")
 Set Radio2    =CreateObject("System.Windows.Forms.RadioButton")
 Set Radio3    =CreateObject("System.Windows.Forms.RadioButton")

 Set Button1    =CreateObject("System.Windows.Forms.Button")
 Set Button2    =CreateObject("System.Windows.Forms.Button")
'---------------------------------------------------------------
 Form1.Text         = "Диалог выбора"
 Form1.MaximizeBox     = False
 Form1.MinimizeBox     = False
 Form1.Width        = 340
 Form1.Height        = 150
 Form1.AutoSize     = True

 Button1.Parent = Form1
 Button2.Parent = Form1
 Radio1.Parent = Form1
 Radio2.Parent = Form1
 Radio3.Parent = Form1
'---------------------------------------------------------------
 With Button1
    .Text    = "Отмена"
    .Left    = 10
    .Top    = 120
    .Width    = 150
    .Height    = 20
    .DialogResult = vbCancel
 End With
'---------------------------------------------------------------
 With Button2
    .Text = "Принять"
    .Left    = 170
    .Top    = 120
    .Width    = 150
    .Height    = 20
    .DialogResult = vbOk
 End With
'---------------------------------------------------------------
 With Radio1
    .Left    = 10
    .Top    = 10
    .Width    = 310
    .Height    = 20
    .Text    = "Вариант 1"
    .Checked = True
 End With
'---------------------------------------------------------------
 With Radio2
    .Left    = 10
    .Top    = 50
    .Width    = 310
    .Height    = 20
    .Text    = "Вариант 2"
 End With    
'---------------------------------------------------------------
 With Radio3
    .Left    = 10
    .Top    = 90
    .Width    = 310
    .Height    = 20
    .Text    = "Вариант 3"
 End With    
'---------------------------------------------------------------
 Form1.CancelButton=Button1
 Form1.CancelButton=Button2
 Form1.ShowDialog

 If Form1.DialogResult = vbOk Then 
    If Radio1.Checked Then  FinalizeDialog(Radio1.Text)
    If Radio2.Checked Then  FinalizeDialog(Radio2.Text)
    If Radio3.Checked Then  FinalizeDialog(Radio3.Text)
 End If

 WScript.Quit()
'---------------------------------------------------------------
 Sub FinalizeDialog(Choice)
    MsgBox Choice, vbSystemModal Or vbInformation, "Результат выбора"
 End Sub
'---------------------------------------------------------------

9

Re: VBScript: используем классы .NET

Ещё один вариант такого же скрипта, но с меньшей «ручной» завязкой на координаты и размеры:

Option Explicit

Dim objNetForm
Dim objTextBox
Dim objButtonOK, objButtonCancel

ReDim arrRadioButtons(0)

Dim i
Dim arrVariants
Dim strTitle
Dim strDescription

arrVariants    = Array("Вариант 1", "Вариант 2", "Вариант 3", "Вариант 4", "Вариант 5")
strTitle       = "Выберете один из вариантов"
strDescription = "Наша Таня громко плачет, уронила в речку мячик. Тише, Танечка, не плачь, не утонет в речке мяч." & vbCrLf & vbCrLf & _
    "Идет бычок, качается, вздыхает на ходу, вот-вот доска кончается, сейчас я упаду." & vbCrLf & vbCrLf & _
    "Зайку бросила хозяйка, под дождём остался зайка. Со скамейки слезть не мог, весь до ниточки промок." & vbCrLf & vbCrLf & _
    "Уронили мишку на пол, оторвали мишке лапу. Всё равно его не брошу, потому что он хороший." & vbCrLf & vbCrLf & _
    "Посвящается всем, вспомнившим голодное детство, деревянные игрушки и автора этих стихов :)."

'-----------------------------------------------------------------------------
Set objNetForm = WScript.CreateObject("System.Windows.Forms.Form")
'-----------------------------------------------------------------------------
Set objTextBox = WScript.CreateObject("System.Windows.Forms.TextBox")

With objTextBox
    .Text    = strDescription
    
    .Left    = 10
    .Top     = 10
    
    .WordWrap   = True
    .MultiLine  = True
    .ScrollBars = 3
    
    .Width = 300
    .Size  = .GetPreferredSize(.Size)
    
    .ReadOnly = True
    
    .Parent = objNetForm
End With
'-----------------------------------------------------------------------------
ReDim Preserve arrRadioButtons(UBound(arrVariants))

For i = LBound(arrVariants) To UBound(arrVariants)
    Set arrRadioButtons(i) = WScript.CreateObject("System.Windows.Forms.RadioButton")
    
    With arrRadioButtons(i)
        .Text         = arrVariants(i)
        
        .Left         = objTextBox.Left
        
        If i = LBound(arrVariants) Then
            .Top      = objTextBox.Top + objTextBox.Height
            .Checked  = True
        Else
            .Top      = arrRadioButtons(i - 1).Top + arrRadioButtons(i - 1).Height
        End If
        
        .Parent       = objNetForm
    End With
Next
'-----------------------------------------------------------------------------
Set objButtonOK = WScript.CreateObject("System.Windows.Forms.Button")

With objButtonOK
    .Text         = "OK"
    
    .Left         =  10
    .Top          = _
        arrRadioButtons(UBound(arrRadioButtons)).Top + _
        arrRadioButtons(UBound(arrRadioButtons)).Height + 10
    
    .Parent = objNetForm
    .DialogResult = 1
End With


Set objButtonCancel = WScript.CreateObject("System.Windows.Forms.Button")

With objButtonCancel
    .Text         = "Отмена"
    
    .Left         = objButtonOK.Left + objButtonOK.Width + 10
    .Top          = objButtonOK.Top
    
    .Parent       = objNetForm
    .DialogResult = 2
End With
'---------------------------------------------------------------
With objNetForm
    .Text = strTitle
    
    .MaximizeBox = False
    .MinimizeBox = False
    
    .AcceptButton = objButtonOK
    .CancelButton = objButtonCancel
    
    .FormBorderStyle = 1
    
    ' Тут бы надо задавать никак не «.Size», а «.ClientSize», но как с этим танцевать — непонятно…
    .Width    = objButtonCancel.Left + objButtonCancel.Width  + 10
    .Height   = objButtonCancel.Top  + objButtonCancel.Height + 10
    ' …ну, да ладно, хотя бы относительно поправим через…
    .AutoSize = True
    
    .TopMost       = True
    .StartPosition = 1
    
    objTextBox.TabIndex = UBound(arrRadioButtons) + 3
End With
'---------------------------------------------------------------

'---------------------------------------------------------------
objNetForm.ShowDialog()

If objNetForm.DialogResult = 1 Then
    For i = LBound(arrRadioButtons) To UBound(arrRadioButtons)
        If arrRadioButtons(i).Checked Then
            WScript.Echo "Выбрано: #" & CStr(i + 1) & ", Text:", arrRadioButtons(i).Text
            
            Exit For
        End If
    Next
Else
    WScript.Echo "Выбора не было сделано."
End If


objNetForm.Dispose()

Set objNetForm = Nothing

WScript.Quit 0

Массив «arrVariants» — варианты выбора, «strTitle» — заголовок окна,  «strDescription» — поясняющий текст.

С низким поклоном в сторону коллеги Poltergeyst'а.

10

Re: VBScript: используем классы .NET

The Gray Cardinal пишет:

Затем поместите сборку в кэш сборок подобной командой:

C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin>gacutil /i c:\temp\ObjectFerm.dll

Чтобы поместить сборку в кэш (GAC), совсем необьязательно пользоваться утилитой gacutil. Достаточно просто перетащить нужную сборку методом Drag & Drop в папку кэша C:\WINDOWS\assembly открытую в Проводнике.

Обязательно, чтобы сборка была подписана, например при компилляции, с помощью ключа сгенерированого утилитой sn, иначе кэш не примет неподписанную сборку.