gifts2017

Код С# в bat-файле

Опубликовал Василий Демидов (Душелов) в раздел Программирование - Практика программирования

Маленькая забавность о том, как использовать все возможности dotNet в обычных bat-скриптах. Или сделать скриптовый язык из С#.

Статья очень зацепила, и вот - моя первая реализация скриптового применения возможностей .NET

См. также

Подписаться Добавить вознаграждение
Комментарии
1. Трактор Трактор (Трактор) 23.11.10 10:51
Изврат какой-то. Не проще два файла пользовать?
2. Влад Кацманевич (cool.clo) 23.11.10 11:32
не более чем прикол ,на деле даже не представляю смысл это использовать - в конце концов powershell был придуман. (даже в xp - скачать и поставить powershell не проблема)
3. Василий Демидов (Душелов) 23.11.10 16:29
(1) Какие 2 файла?
(2) Не все на повершеле можно сделать
4. Трактор Трактор (Трактор) 23.11.10 16:32
(3) батник и файл с исходниками на любом языке. Батником компили, исполняй что хочешь делай. Весь прикол держится только на том что всё затолкано в один файл.
5. Василий Демидов (Душелов) 23.11.10 17:03
(4) Именно так, и то, что он сразу сам и исполняется. И все библиотеки, которые нужны там же и подключаются.
6. Александр Медведев (anig99) 03.12.10 18:05
7. Ийон Тихий (cool.vlad4) 06.01.11 15:39
(0) Познавательно. На англоязычном ресурсе я где-то даже более изящное решение видел. Возник вопрос. Возможно ли использовать смешанный способ в 1С? Что я имею ввиду - к примеру я написал ВК, где у меня она ссылается на сборку, а в свою очередь сборка динамически компилируется ну предположим как здесь описано в 1С.
8. Ийон Тихий (cool.vlad4) 06.01.11 15:42
9. Василий Демидов (Душелов) 07.01.11 00:15
(7) Вполне возможно это сделать. Единственное, что не понятно, для каких целей это надо )
10. Василий Демидов (Душелов) 07.01.11 00:15
(8) Что-то сильно громоздкая компиляция ) Зато с кучей проверок.
11. Ийон Тихий (cool.vlad4) 07.01.11 08:29
(9) динамическая компиляция отжирает кучу времени, Зачем компилировать то, что можно скомпилировать заранее, и потом все думаю как linq в 1С прикрутить...(linq to xls или xml например)
PS (10) :D ну как же без них... на самом деле bat редко использую, есть powershell и команда add-type.
Душелов; +1 Ответить 1
12. Василий Демидов (Душелов) 09.01.11 22:43
(11) Ну давай возьмем какой-нибудь пример и попробуем сделать такой скрипт )
ЗЫ: Иногда скриптов стандартных не хватает, как в примере с геолокацией в Windows 7, тогда и такие батники помогают.
13. Ийон Тихий (cool.vlad4) 10.01.11 20:53
(12) Да, нужно что-нибудь интересное придумать...сегодня правда бездельничал - голова чего-то болит...для powershell лучше использовать продукты от sapien - какие-то бесплатные, какие-то платные(самый известный primal scripts), с помощью primal forms можно формы лепить - код будет примерно такой (для 1С)
outtext = "";
ActiveXPosh.OutputMode = OUTPUT_BUFFER;
ActiveXPosh.Execute("[reflection.assembly]::loadwithpartialname(""System.Windows.Forms"") | Out-Null
|[reflection.assembly]::loadwithpartialname(""System.Drawing"") | Out-Null
|$form1 = New-Object System.Windows.Forms.Form
|$comboBox1 = New-Object System.Windows.Forms.ComboBox
|$label1 = New-Object System.Windows.Forms.Label
|$button1 = New-Object System.Windows.Forms.Button
|$handler_button1_Click=
|{
| $label1.Text = ""fgbsdfhg""
|}
|$form1.Text = ""'Primal Form'""
|$form1.Name = ""'form1'""
|$form1.DataBindings.DefaultDataSourceUpdateMode = 0
|$System_Drawing_Size = New-Object System.Drawing.Size
|$System_Drawing_Size.Width = 292
|$System_Drawing_Size.Height = 273
|$form1.ClientSize = $System_Drawing_Size
|$comboBox1.FormattingEnabled = $True
|$System_Drawing_Size = New-Object System.Drawing.Size
|$System_Drawing_Size.Width = 121
|$System_Drawing_Size.Height = 21
|$comboBox1.Size = $System_Drawing_Size
|$comboBox1.DataBindings.DefaultDataSourceUpdateMode = 0
|$comboBox1.Name = ""'comboBox1'""
|$System_Drawing_Point = New-Object System.Drawing.Point
|$System_Drawing_Point.X = 78
|$System_Drawing_Point.Y = 189
|$comboBox1.Location = $System_Drawing_Point
|$comboBox1.TabIndex = 2
|$form1.Controls.Add($comboBox1)
|$label1.TabIndex = 1
|$System_Drawing_Size = New-Object System.Drawing.Size
|$System_Drawing_Size.Width = 100
|$System_Drawing_Size.Height = 23
|$label1.Size = $System_Drawing_Size
|$label1.Text = ""'label1'""
|$System_Drawing_Point = New-Object System.Drawing.Point
|$System_Drawing_Point.X = 78
|$System_Drawing_Point.Y = 134
|$label1.Location = $System_Drawing_Point
|$label1.DataBindings.DefaultDataSourceUpdateMode = 0
|$label1.Name = ""'label1'""
|$form1.Controls.Add($label1)
|$button1.TabIndex = 0
|$button1.Name = ""'button1'""
|$System_Drawing_Size = New-Object System.Drawing.Size
|$System_Drawing_Size.Width = 75
|$System_Drawing_Size.Height = 23
|$button1.Size = $System_Drawing_Size
|$button1.UseVisualStyleBackColor = $True
|$button1.Text = ""'button1'""
|$System_Drawing_Point = New-Object System.Drawing.Point
|$System_Drawing_Point.X = 78
|$System_Drawing_Point.Y = 50
|$button1.Location = $System_Drawing_Point
|$button1.DataBindings.DefaultDataSourceUpdateMode = 0
|$button1.add_Click($handler_button1_Click)
|$form1.Controls.Add($button1)
|$form1.ShowDialog()| Out-Null");
For Each str In ActiveXPosh.Output do
outtext = outtext + str;
outtext = outtext + Символы.ПС;
EndDo;

Сообщить(outtext);
ActiveXPosh.ClearOutput();
В данном случае ActiveXPosh - Это бесплатная COM-компонента от них же, которую можно использовать как уверяет разработчик из многих COM “совместимых” языков – из VBScript, JScript, KiXtart. Отчего же не использовать ее в 1С.
Данный компонент поддерживает выполнение следующих команд(из хелпа):
ClearOutput() - This method clears the internal output buffer.
Execute(strcommand) - Executes a PowerShell command or script.
Eval(strExpression) - Evaluates a PowerShell expression.
Init(execProfile) - Initial call to instantiate a PowerShell engine.
IsPowerShellInstalled - Returns True/False.
Output - A collection of strings filled with output from PowerShell
commands.
OutputString - The content of the output buffer as a single string.
OutputMode - Sets or gets the current output mode.
OutputWidth - Sets or gets the desired output width.
(В 1С я просто присвоил
OUTPUT_CONSOLE = 0;
OUTPUT_WINDOW = 1;
OUTPUT_BUFFER = 2; Для лучшей читабельности)
К примеру самое простое - листинг сервисов в ОС
outtext = "";
ActiveXPosh.OutputMode = OUTPUT_BUFFER;
ActiveXPosh.Execute("Get-WmiObject -class Win32_Service | Format-Table -property Name, State");

For Each str In ActiveXPosh.Output do
outtext = outtext + str;
outtext = outtext + Символы.ПС;
EndDo;

Сообщить(outtext);
ActiveXPosh.ClearOutput();

С использованием C#
outtext = "";
ActiveXPosh.OutputMode = OUTPUT_BUFFER;
ActiveXPosh.Execute("$source = @""
|public class BasicTest
|{
| public static int Add(int a, int b)
| {
| return (a + b);
| }
|
| public int Multiply(int a, int b)
| {
| return (a * b);
| }
|}
|""@
|
|Add-Type -TypeDefinition $source
|[BasicTest]::Add(4, 3)
|$basicTestObject = New-Object BasicTest
|$basicTestObject.Multiply(5, 2)");
For Each str In ActiveXPosh.Output do
outtext = outtext + str;
outtext = outtext + Символы.ПС;
EndDo;

Сообщить(outtext);
ActiveXPosh.ClearOutput();
C#, PowerShell и поворот строки
outtext = "";
ActiveXPosh.OutputMode = OUTPUT_BUFFER;
ActiveXPosh.Execute("$source = @""
|public class BasicTes
|{
| public static string Add(string s)
| {
| char[] arr = s.ToCharArray();
| System.Array.Reverse(arr);
| return new string(arr);
| }
|
| public int Multiply(int a, int b)
| {
| return (a * b);
| }

|}
|""@

|Add-Type -TypeDefinition $source
|[BasicTes]::Add(""765767567456769469697965794679467hhhhhhhhhhhhhhhhhhhhhhhhhh"")
|$basicTestObject = New-Object BasicTes
|$basicTestObject.Multiply(5, 2)");
For Each str In ActiveXPosh.Output do
outtext = outtext + str;
outtext = outtext + Символы.ПС;
EndDo;

Сообщить(outtext);
ActiveXPosh.ClearOutput();

Понравилось у PowerShell - возможность напрямую использовать дотнетовские сборки.
ЗЫ Это все прелюдия - а вот, что интересного такого сделать? Искал на http://gallery.technet.microsoft.com/ - но наверное плохо искал.
ЗЫ Давно появилась идея, но вот с реализацией туго, это сделать одно из двух - либо 1) сделать конфигурацию и программку на C#, для того, чтобы писать "скрипты" 1С в обычных текстовых файлах. В конфе бы просто содержались готовые "библиотечки". А программка бы идентифицировала эти "скрипты" (для того чтобы в назначенные задания - шедулер поставить) и отправляла через COM в 1С на выполнение в назначенное время. Можно подумать и об удаленной реализации - когда 1С на локальном компе нет. 2) Пришла идея - после http://infostart.ru/projects/3181/ - мне кажется смысла в компиляторе нет - поскольку огромная пропасть между языком 1С и "обычным" языком для трансляции из одного в другой. (Возможно, больше имеет смысл превращать код 1С в код C#, который выполняет такие же действия в 1С через COM). Идея создания скриптового языка 1С подобного. С библиотечками. Либо, чтобы он понимал чужие библиотечки. Может кому-то бы и пригодилось, но даже не знаю как это реализовать - сделать свой скриптовый язык это мощно, конечно.
14. Василий Демидов (Душелов) 10.01.11 23:47
(13)
1) Ну тут проблем вообще никаких не вижу. За исключением того, что в базах 1С надо дописывать некоторые функции в модуле внешнего соединения, которые будут принимать эти скрипты.
2) >больше имеет смысл превращать код 1С в код C#
Именно этим и занимался - можно генерить ВК с уже прописанным на 1С кодом (в целях той же защиты, например).
15. Ийон Тихий (cool.vlad4) 11.01.11 00:02
(14) С первым действительно все достаточно прозрачно - через модуль внешнего соединения -> процедура -> выполнить(код). Проблематично сделать скриптовый язык по языку (синтаксически) похожий на 1С. С 1С подобными запросами, имеющие возможность работы с различными объектами. Хотя может проще сделать "переводчик" в какой-нибудь скриптовый язык по типу работы вашего компилятора http://infostart.ru/projects/3181/ - вопрос насколько все это нужно?
16. Ийон Тихий (cool.vlad4) 11.01.11 14:52
+ Powershell скрипт обращения к методу GetHostEntry() - System.Net.DNS (помнится мне надо было разрешать адреса)

param ([string] $HostAddress = "127.0.0.1")
$HostIp = [System.Net.IPAddress]::Parse("127.0.0.1")
if (! ([system.Net.IPAddress]::TryParse($hostaddress, [ref] $HostIP))) {"Not valid IP address"; return}
$hostentrydetails = [System.Net.Dns]::GetHostEntry($HostIP)
"Host Name : {0}" -f $hostentrydetails.HostName
foreach ($alias in $hostentrydetails.alises) {
"Alias : {0}" -f $alias
}
foreach ($addr in $hostentrydetails.addresslist) {
"Address : {0}" -f $Addr.ipaddresstostring
}

С помощью ActiveX от Sapien можно все это сделать 1С, также как в вышеприведенном комментарии. (...проблема в том, что не везде powershell...можно сделать portable, но только для личного пользования - кстати нельзя ли сделать framework portable? надо попробовать...)
17. Ийон Тихий (cool.vlad4) 11.01.11 14:58
off: ни у кого не нашел карту google или yandex с кэшированием для работы оффлайн - никто не делал?
18. Василий Демидов (Душелов) 12.01.11 10:32
(15) Вот это уже ближе к истине, что большей частью никому не надо )
(16) Для него надо писать конструктор ) Как WMI Code Creator )
(17) Я делал
19. Ийон Тихий (cool.vlad4) 12.01.11 17:54
Про code creator с самого начала и подумал, но сейчас заботы ...малоинтересные, надо как-нибудь попробовать в целях образовательных хотя бы...
(18) это хорошо (про карту) - просто наткнулся на пост про кэширование и не обнаружил нигде на ИС упоминание про это, вот и подумал, что никто не делал :D
ЗЫ вообще надо как-то мне собранее быть, а то из стороны в сторону кидает - увидел, что кто-то выложил обработку про поиск картинок, тут же стал смотреть google api на предмет использования в 1С...
20. Ийон Тихий (cool.vlad4) 13.01.11 10:49
(18) Еще один глупый вопрос Василий - из прочтения статьи http://www.west-wind.com/presentations/DynamicCode/DynamicCode.htm я так понял - конечный результат это генерация c# скриптов для динамического выполнения в asp.net - вопрос следующий - возможно ли сделать в 1С такую штуку для генерации C# скрипта для динамического выполнения и получения результата
lcResult = (string) loScript.ExecuteCode(lcCode, "rick strahl",(int) x,(decimal) 10 );
if (loScript.bError)
MessageBox.Show(loScript.cErrorMsg + "\r\n\r\n" + loScript.cSourceCode);
else
MessageBox.Show(lcResult);

Как-то так они получают результат. Или есть методы попроще. Просто мне понравилась идея выполнения c# в 1С без ВК, но вот как результат получать? Вот и думаю как такую ВК написать, которая бы исполняла c# скрипты и возвращала результат.
21. Ийон Тихий (cool.vlad4) 13.01.11 11:14
+ 20 либо через полеhtmlдокумента, как-то через библиотечки javascript вызывать/выполнять c# код. а из полеhtml получать результат js
ЗЫ :D смешались в кучу кони люди
22. Василий Демидов (Душелов) 14.01.11 00:12
23. Василий Демидов (Душелов) 14.01.11 00:13
(21) Да это все несложно реализовать. Но компонента все равно понадобится. Скрипты все таки универсальнее будут.
24. Ийон Тихий (cool.vlad4) 14.01.11 18:12
(22) Elisy мне не нужен, сам сделаю :D . Пока задач серьезных нет, потому и маюсь. Скрипты да, что-то в этом есть - Exchange 2010 почти весь на повершелле говорят.
25. mak sim (yellow444) 10.01.12 13:23
вот раздолье вирусаписцам то