Pull to refresh

Выполнение javascript в программе на C#

Reading time 4 min
Views 56K


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

Под катом я расскажу о нерядовом взаимодействии с сайтом, каким образом я решил задачу на тот момент и смогли ли обе библиотеки справиться с той же задачей. Сразу скажу, что речь пойдёт о следующих библиотеках: jint и javascriptdotnet.

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

Начну с небольшой истории как начиналась разработка, я зашёл на сайт, перешёл в кабинет, после чего загрузил fiddler и начал смотреть и записывать какие параметры куда передаются, с помощью каких методов и по каким ссылкам. Довольно быстро я набросал себе алгоритм и принялся реализовывать, но столкнулся с проблемой, оказалось, что один из параметров, который я принял за случайное число не являлся таковым, чуть позже выяснилось, что вызов функции random() на самом видном месте служил лишь для отвлечения внимания, что же на самом деле там происходит помогло мне установить дополнение для Firefox под названием javascript deobfuscator, для тех, кто не знаком с данным или похожими дополнениями, то выглядит оно, таким образом, при открытии на странице google.com:



В моём случае было несколько проще, т.к. никаких фоновых скриптов не выполнялось, а чётко было видно, какие скрипты выполнялись при том или ином действии. Вот тогда я и узнал, что для получения моего «случайного» числа должно выполниться больше 200 строк кода или немногим больше 15 функций. Первым о чём я подумал, что сейчас быстренько переведу данный код на C# и на этом закончу, но проблема была в том, что знания javascript у меня поверхностные, а весь код пропущен через обфускатор и по коду видно, что там какие-то криптографические преобразования происходят, поэтому я решил, что проще будет данный код выполнить в исходном виде.

Для того, чтобы проверить, действительно ли выполняется мой код, я сразу выбрал самый простой способ — это с помощью компонента webBrowser, пример из Msdn:

webBrowser1.DocumentText =
  "<html><head><script>" +
  "function test(message) { alert(message); }" +
  "</script></head><body><button " +
  "onclick=\"window.external.Test('called from script code')\">" +
  "call client code from script code</button>" +
  "</body></html>";


* This source code was highlighted with Source Code Highlighter.

После чего достаточно вызвать следующий код:
webBrowser1.Document.InvokeScript("test", new String[] { "called from client code" });

Но данный пример подходит лишь для теста, т.к. компонент webBrowser я категорически не хотел использовать в своей программе, поэтому я принялся искать другие способы решения и нашёл следующий пример:

Шаги для создания .dll:

1. Создать файл в блокноте, только с этой строкой:
class EvalClass { function Evaluate(expression: String) { return eval(expression); } }

2. Сохранить файл как C:\MyEval.js
3. Открыть VS Command Prompt (Start, Programs, VS, VS Tools)
4. Написать Cd\ чтобы оказаться в корне C:\
5. Написать
jsc /t:library C:\MyEval.js

6. После чего появиться новый файл MyEval.dll.
7. Скопировать MyEval.dll в проект и добавить ссылку на него (также нужно сослаться на Microsoft.Jscript.dll).
8. После чего можно обращаться к библиотеке таким образом:
EvalClass jScriptEvaluator = new EvalClass();
object objResult = jScriptEvaluator.Evaluate(“1==1 && 2==2”);

objResult вернет True.


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

Библиотека jint


Лицензия: The MIT License (MIT)

Первым делом я решил попробовать примеры, все они заработали, но как я заметил, что на codeplex тоже есть проблемы с парсером, который «съел» в некоторых местах скобки, немного поправив примеры, все они заработали. Дальше я принялся пробовать его работу на своём наборе функций, но к сожалению так и не смог заставить библиотеку вернуть мне искомое значение, гуглил, читал обсуждения. пробовал что-то менять, но к сожалению не смог побороть String.fromCharCode():

Jint.JintException: Method isn't defined: fromCharCode

Библиотека подключается стандартно, добавить ссылки и написать:
using Jint;

После чего достаточно такого кода, чтобы вызвать функцию:
StreamReader sr = new StreamReader(@"C:\habr_javascript\MyEval.js");
string script = sr.ReadToEnd();

JintEngine engine = new JintEngine();
engine.Run(script);

object num = engine.Run("Evaluate(42210607);");
MessageBox.Show(num.ToString());


* This source code was highlighted with Source Code Highlighter.


Библиотека javascriptdotnet


Лицензия: New BSD License (BSD)

Запустив один пример, следом я сразу начал пробовать свой тестовый пример и бинго, всё заработало с первого раза.

Указываем ссылку на библиотеку, добавляем директиву using:
using Noesis.Javascript;

И пишем код, который практически идентичен предыдущему:
StreamReader sr = new StreamReader(@"C:\habr_javascript\MyEval.js");
string script = sr.ReadToEnd();

JavascriptContext context = new JavascriptContext();
context.Run(script);

object num = context.Run("Evaluate(42210607);");
MessageBox.Show(num.ToString());


* This source code was highlighted with Source Code Highlighter.


Вывод


Не хотелось бы говорить что-то плохое в адрес jint, т.к. скорее всего я просто не разобрался и она работает не хуже javascriptdotnet. Хоть моя программа уже работает больше 6 месяцев, но мне сразу хотелось упростить возможные правки, т.к. в случае, если разработчики сайта поменяют буквально один символ, то мне придётся пересобрать библиотеку, а в случае jint и javascriptdotnet достаточно лишь отредактировать файл ресурсов. Также сложно себе представить, как можно добавлять функции во время выполнения программы. Более активно развивается библиотека jint и последний релиз был совсем недавно 14 февраля 2011 года, когда javascriptdotnet обновилась 16 сентября 2010 года. Библиотеки могут быть использованы не только для указанного в статье способа, но также и для тестирования Вашего сайта, на том же stackoverflow видел, что разработчики использовали jint для тестирования серверного javascript, собственно там же больше упоминают о jint. В общем, надеюсь, что данная статья была Вам полезна и в случае необходимости взаимодействия C# с javascript она будет Вам полезна.
Tags:
Hubs:
+22
Comments 8
Comments Comments 8

Articles