Как запустить два или более пользовательских протокола URL из Javascript
У меня есть старая HTML-страница, которая создает файл сценария и выполняет его с помощью:
fsoObject = new ActiveXObject("Scripting.FileSystemObject")
wshObject = new ActiveXObject("WScript.Shell")
Я пытаюсь изменить его и сделать его пригодным для использования также из других браузеров. Если вы знаете ответ, прекратите чтение и, пожалуйста, ответьте. Если нет быстрого ответа, вот описание моих попыток. Я успешно справился с работой, но только когда сценарий был короче, чем 2000 символов. Мне нужна помощь для сценариев длиной более 2000 символов.
Веб-страница предназначена только для внутреннего использования, поэтому мне легко создать собственный протокол URL-адреса на каждом компьютере, который запускает файл VBScript с сетевого диска.
Я создал свой собственный протокол URL, который запускает файл VBScript, например:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\MyUrlProtocol]
"URL Protocol"=""
@="Url:MyUrlProtocol"
"UseOriginalUrlEncoding"=dword:00000001
[HKEY_CLASSES_ROOT\MyUrlProtocol\DefaultIcon]
@="C:\\Windows\\System32\\WScript.exe"
[HKEY_CLASSES_ROOT\MyUrlProtocol\shell]
[HKEY_CLASSES_ROOT\MyUrlProtocol\shell\open]
[HKEY_CLASSES_ROOT\MyUrlProtocol\shell\open\command]
@="C:\\Windows\\System32\\WScript.exe \"X:\\MyUrlProtocol.vbs\" \"%1\""
В MyUrlProtocol.vbs
У меня есть это:
MsgBox "The length of the link is " & Len(WScript.Arguments(0)) & " characters"
MsgBox "The content of the link is: " & WScript.Arguments(0)
Когда я нажимаю на <a href="MyUrlProtocol:test" id="test">click me</a>
Я вижу два сообщения, так что все работает хорошо (протестировано с Chrome и IE в Windows 7.)
Это работает также, когда я выполняю document.getElementById("test").click()
Я подумал, что это может быть решением: я передам текст сценария статическому сценарию VBS, который создаст динамический сценарий и запустит его, но в этой системе я не могу передать более ~2000 символов.
Поэтому я попытался разбить текст скрипта на куски размером менее 2000 символов и смоделировать несколько нажатий на ссылку, но работает только первый.
Итак, я попробовал с xmlhttp.open("GET","MyUrlProtocol:test",false);
Хром говорит Cross origin requests are only supported for HTTP
,
Можно ли передать более 2000 символов в сценарий VBScript через собственный протокол URL?
Если нет, возможно ли вызывать несколько пользовательских протоколов URL-адресов последовательно?
Если нет, есть ли другой способ создать файл сценария и запустить его из Javascript?
РЕДАКТИРОВАТЬ 1
Я нашел решение, но в Chrome работает только тогда, когда ему нравится, поэтому я вернулся к исходной точке.
Приведенный ниже код в IE выполняет сценарий 4 раза (правильно), но в Chrome выполняется только первое выполнение.
Если я изменю это на delay += 2000
Затем Chrome обычно запускает скрипт 2 раза, но иногда 1, а иногда 3 или даже 4 раза.
Если я изменю это на delay += 10000
Затем он обычно запускает скрипт 4 раза, но иногда пропускает один.
Функция всегда выполняется 4 раза, как в Chrome, так и в IE. Что странно в том, что sr.click()
иногда ничего не делает и выполнение функции продолжается.
<HTML>
<HEAD>
<script>
var delay;
function runScript(text) {
setTimeout(function(){runScript2(text)}, delay);
delay += 100;
}
function runScript2(text) {
var sr = document.getElementById('scriptRunner');
sr.href='intelliclad:'+text;
sr.click();
}
function test(){
delay = 0;
runScript("uno");
runScript("due");
runScript("tre");
runScript("quattro");
}
</script>
</HEAD>
<BODY>
<input type="button" value="Run test" onclick="test()">
<a href="nothing yet" id="scriptRunner">scriptRunner</a>
</BODY>
</HMTL>
РЕДАКТИРОВАТЬ 2
Я попытался с предложением Люка установить следующий тайм-аут из-за обратного вызова, но ничего не изменилось (IE работает всегда, Chrome, когда ему нравится).
Вот новый код:
var scripts;
var delay = 2000;
function runScript() {
var sr = document.getElementById('scriptRunner');
sr.href = 'intelliclad:' + scripts.shift();
sr.click();
if(scripts.length)
setTimeout(function() {runScript()}, delay);
}
function test(){
scripts = ["uno", "due", "tre", "quattro"];
runScript();
}
Немного предыстории: страница запрашивает форму панели, которая может быть всего несколькими параметрами [nfaces=1, shape1='square', width1=100]
или сотни параметров для панелей с несколькими гранями, множеством слотов, множеством крепежных элементов и т. д. После запроса всех параметров генерируется скрипт для нашего внутреннего 3D CAD (который может быть больше 20 КБ), и CAD запускается и запрашивается выполнение сценарий.
Я хотел бы сделать все на стороне клиента, потому что страница обслуживается веб-сервером Domino, который даже не может мечтать об управлении таким сложным сценарием.
3 ответа
Я не прочитал весь ваш пост... есть ответ:
Я тоже хочу, чтобы пользовательские протоколы URL могли обрабатывать длинные URL. Они просто нет. IE еще хуже, так как некоторые ОС принимают только 800 символов.
Итак, вот решение:
For long urls, only pass a single use token. The vbscript uses the token
and does a url get to your web server to get all of the data.
Это единственный способ, которым я смог успешно передать много данных. Если вы когда-нибудь найдете более четкое решение, не забудьте опубликовать его здесь.
Обновить:
Обратите внимание, что это лучший способ, который я нашел, чтобы справиться с ограничениями протокола URL. Я тоже хотел бы, чтобы это было не нужно. Это работает и работает хорошо.
Вы упомянули Домино, так что, возможно, вам нужно что-то в среде POS... Я создаю POS-систему на веб-основе, чтобы мы могли столкнуться со многими такими же проблемами.
Предположим, вы хотите, чтобы пользовательский URL-адрес печатал PDF-файл на принтере по умолчанию без всплывающего всплывающего окна. Мы должны делать это тысячи раз в день...
При создании веб-страницы добавьте кнопку печати, которая при нажатии вызывает пользовательский URL: myproto://printpdf? Id=12345&tocken=onetimetoken
это выполнит ваш VBScript на локальном рабочем столе
в вашем vbscript разбирайте аргументы и реагируйте. В этом случае ваша команда - printpdf, идентификатор - 123456, и у вас есть одноразовый ключ токена.
получить скрипт vb для https: https://mydomain.com/APIs/printpdf.whatever?id=12345&key=onetimetoken
проверьте учетные данные на основе IP-адреса и токена, если все выровнены, а затем верните содержимое PDF (вы можете преобразовать PDF в строку байтового массива)
теперь у vbscript есть pdf, соберите его и запишите его во временную папку, затем выполните команду печати pdf без вывода сообщений (я использую Sumatra PDF http://blog.kowalczyk.info/software/sumatrapdf/free-pdf-reader.html)
Миссия выполнена.
Так как я знаю, что вам делать в вашем пользовательском URL-адресе и в общем рабочем процессе, я могу только описать, как я решил проблему с URL-адресом сортировки.
Используя эту технику, возможности безграничны. Вы имеете полный контроль над локальным компьютером, на котором запущен веб-браузер, у вас есть одноразовый токен, который предоставляет доступ к веб-API и может возвращать любую информацию, которую вы программируете.
Вы можете написать собственный протокол URL, чтобы включить печь для пиццы, если хотите:)
Если вы не можете создать код на стороне сервера, который прослушивает запрос get vbscript, это не сработает.
Возможно, вы сможете передать данные из браузера в VBScript, используя буфер обмена.
Обновление 2:
Поскольку в этом случае данные находятся на клиенте (одна форма может определять сотни параметров), серверный API не знает, что ответить на запрос сценария vb. Таким образом, описанному выше рабочему процессу должны предшествовать эти два шага:
onkeypress
событие выполняет отправку для отправки текущих параметров на серверСервер отвечает обновленной формой, добавляя в тело
onload
вызов функции, которая использует другой метод submit для вызова пользовательского URL, как описано в пункте 1, указанном выше.
Обновление 3: stenci, то, что вы добавили (в обновлении 2), будет работать. Я бы сделал это так:
- пользователь нажимает кнопку, говоря, что я закончил редактирование формы
- AJAX опубликовать форму на сервере
- сервер сохраняет данные и прикрепляет уникальный ключ к хранилищу данных
- сервер возвращает ключ к функции обратного вызова ajax
- теперь клиент имеет единственный ключ использования и вызывает схему URL, передающую ключ
- vbscript отправляет https на сервер и передает ключ
- сервер возвращает данные в VBScript
Это немного затянуто. После кодирования это будет работать как шарм.
Единственная альтернатива, которую я вижу, - это скопировать данные формы в буфер обмена, используя что-то вроде: http://zeroclipboard.org/
а затем в VBScript посмотреть, можете ли вы прочитать буфер обмена, как: Используйте буфер обмена из VBScript
Как насчет создания iFrame для каждого экземпляра? Что-то вроде этого:
function runScript(text) {
var iframe = document.createElement('iframe');
iframe.src = 'intelliclad:'+text;
document.body.appendChild(iframe);
}
function test(){
runScript("uno");
runScript("due");
runScript("tre");
runScript("quattro");
}
Затем вы можете использовать стили CSS, чтобы сделать эти фреймы прозрачными / скрытыми.
Вам может не понравиться этот ответ, но я использовал этот метод в прошлом, и он работает.
Вместо того, чтобы полагаться на ActiveX, рассмотрите возможность использования Java-апплета и JNI.
По сути, вы должны убедиться, что собственные скрипты, которые вы хотите запустить, доступны на вашем клиентском компьютере вместе с оболочкой JNI.
Апплет должен быть как минимум самоподписанным, чтобы браузер мог загружать и получать доступ к собственной библиотеке. После загрузки библиотек JNI вы можете легко вызывать методы со страницы / апплета.
В результате использования Java вы можете использовать один и тот же апплет для Windows, а также для клиентов Linux, при условии, конечно, что на соответствующих клиентах имеются собственные библиотеки.
Эта серия статей рассказывает именно о вашей проблеме: http://www.javaworld.com/article/2076775/java-security/escape-the-sandbox--access-native-methods-from-an-applet.html
PS статья действительно старая, но концепция остается неизменной.