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

Во время работы над идеей сервиса по сбросу пароля в системах SAP R/3 возник вопрос — а как запустить SAP GUI с нужными параметрами из браузера? Поскольку в этой идее подразумевалось использование веб-сервиса, сначала отрабатывающего по запросу SOAP из SAP GUI и отправляющего письмо со ссылкой на веб-страницу со скриптом сброса пароля на начальный, а потом уже отображение пользователю сообщения об успешном сбросе пароля и отображение этого самого начального пароля, то хотелось, чтобы на этой странице была еще и ссылка на запуск SAP GUI. Причем, чтобы эта ссылка открывала нужную систему, да еще, желательно, сразу с заполненными полями логина и пароля: пользователю оставалось бы только дважды заполнить продуктивный пароль.

Запуск SAP Logon — для нашей цели был не интересен, а при запуске sapgui.exe невозможно было указать мандант и имя пользователя, зато можно было запустить систему не определенную в SAP Logon. С другой стороны, запуск SAP GUI с произвольными параметрами сервера был не особенно актуален: уж если мы решаем задачу сброса пароля пользователя, то скорее всего у него в SAP Logon уже есть нужная строка, с нужными ему настройками и не надо лезть со своими. Зато заданным требованиям удовлетворяла технология SAP GUI Shortcut и собственно программа sapshcut.exe, которая давала возможность запускать SAP GUI с использованием определенного «ярлыка».

Решение задачи в лоб: запуск sapshcut.exe непосредственно из браузера с помощью объекта ActiveX:

function openSAPGui(sid, client, user, password) {
var shell = new ActiveXObject("WScript.Shell");
shell.run('sapshcut.exe -system="'+sid+'" -client='+client+' -user="'+user+'" -pw="'+password+'" -language=RU');
}

Решение плохое: во-первых, работает только в Internet Explorer, во-вторых, требует соответствующих настроек безопасности в браузере, которые в организации могут быть запрещены на доменном уровне, и даже если разрешены, то браузер выдает пользователю окно с пугающим предупреждением:



Решение №2 откопал в интернете: создание собственного веб-протокола. Позволяет запустить нужное нам приложение с помощью ссылки с указанием протокола, который мы сами регистрируем в Windows в реестре в разделе HKEY_CLASSES_ROOT. Поскольку у SAP GUI Shortcut в этом разделе есть свой подраздел, то можно туда добавить строковой параметр URL Protocol с пустым значением:



Данный протокол запускает sapgui.exe с параметром /SHORTCUT, что нам как бы и надо:



Ну или если мы хотим сделать вообще произвольный протокол (например, sapshcut), то зарегистрировать его можно с помощью следующего reg-файла:

Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\sapshcut]
@="sapshcut Handler"
"URL Protocol"=""
[HKEY_CLASSES_ROOT\sapshcut\DefaultIcon]
@="sapshcut.exe"
[HKEY_CLASSES_ROOT\sapshcut\shell]
[HKEY_CLASSES_ROOT\sapshcut\shell\open]
[HKEY_CLASSES_ROOT\sapshcut\shell\open\command]
@="sapshcut.exe \"%1\""

Теперь, если мы на веб-странице сделаем ссылку с указанием протокола Sapgui.Shortcut.File подобным образом:

<a href='Sapgui.Shortcut.File: -system=SID -client=200'>SID200</a>

у нас должно отобразиться окно вида:



И вроде всё замечательно, но при нажатии на кнопку «Разрешить» видим:



Опа, браузер пробел превратил в %20. Ну и другие символы тоже будут закодированы в свой числовой код с символом процента. И самое неприятное, что тут ничего нельзя сделать на уровне браузера (тут всё сделано по стандарту) — браузер не любит подобные символы, а командный интерпретатор Windows не работает с такими закодированными значениями. И еще один минус — в качестве параметра передается вся строка, включая название протокола и даже двоеточие (sapgui.shortcut.file:). Причем, хотя тот же sapshcut.exe умеет отбрасывает всё что не является для него параметром (начинается с символа «-«, потом название, «=» и значение), т.е. строка вида «sapgui.shortcut.file: -system=SID» еще прокатит, то без пробела «sapgui.shortcut.file:-system=SID» уже не работает.

Получается, что, в принципе, есть два варианта использования URI-протокола:

  1. Использование без параметров: Создаем целую кучу протоколов под все наши системы вида SIDMANDT, типа AAA200, BBB200 и т.п. Если нужно просто запустить нужную систему, то вариант вполне рабочий, но в нашем случае не подходит, поскольку уж хотя бы логин пользователя хочется тоже передать, а это таким образом не сделать.
  2. Использование программы-обертки для вызова sapshcut.exe или sapgui.exe. Суть данной программы проста — она должна брать ту строку, что ей передаст браузер через веб-протокол и её превращать в то представление, что принимает Windows, т.е. обратно превращает все коды символов в символы (может быть даже разбирает строку по параметрам) и уже вызывает SAP GUI гарантировано верной командой. В нашем случае тоже не совсем подходит (поэтому даже не стал её писать), потому что нам уже мало добавить протокол на всех пользовательских ПК (в рамках домена это еще куда ни шло, хотя тоже лучше избегать такой практики), но тут потребуется ещё дополнительно программу разместить на ПК, да еще и постоянно следить, чтобы она никуда не делась при переустановках ПО на ПК.

Т.е. данный вариант тоже отбрасываем как негодный нам.

Тут я уже начал думать, что с идеей запускать SAP GUI с нужными параметрами из браузера придется распрощаться, но тут мне в голову пришла мысль о том, что в SAP Logon можно сделать ярлык и его можно скопировать на рабочий стол. Я пользовался таким способом когда-то, но до этого файл ярлыка специально не смотрел. И оказалось, что данный ярлык представляет из себя обычный текстовый файл с расширением .sap. И если его запустить в Windows — запустится SAP GUI с параметрами, которые и указаны в этом файле. «Бинго!»

Формат данного файла примерно следующий (еще может быть запускаемая транзакция при старте, но я её опустил):

[System]
Name=SID
Client=200
[User]
Name=
Language=RU
Password=
[Function]
Title=
[Configuration]
GuiSize=Maximized
[Options]
Reuse=0

Вроде бы всё, что необходимо: и идентификатор системы, и мандант, и имя пользователя и даже пароль. И даже дополнительные параметры: Title — заголовок окна, GuiSize — размер запущенного окна (во весь экран или нет) и Reuse — открывать ли обязательно новое окно или использовать уже открытое с этой же системой. Но сразу вылез нюанс — пароль в SAP Logon оказалось задать нельзя, строка была заблокирована. Оказалось, что это сделано из соображений безопасности: все ярлыки созданные в SAP Logon он хранит в файле sapshortcut.ini (рядом с saplogon.ini в профиле пользователя Windows) и там они хотя и зашифрованы, но не слишком сильно и при большом желании их можно раскодировать. Но можно и разрешить это с помощью изменения значения одного параметра в реестре (по умолчанию значение 0):

Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\SAP\SAPShortcut\Security]
"EnablePassword"="1"

Это разблокирует для ввода поле «Пароль» на форме создания ярлыка в SAP Logon:



И при внесении в это поле пароля, он будет размещен в соответствующей строке
sapshortcut.ini, но вот при перетаскивании ярлыка на рабочий стол он там не появляется — зато можно его туда добавить вручную. Пароль зашифрован, для 111111 он будет следующего вида: PW_49B02219D1F6, для 222222 — PW_4AB3211AD2F5. Но нас больше интересует то, что этот пароль шифруется одним способом, не зависящим от конкретного ПК и, если мы будем сбрасывать пароль на начальный, то можно в этом поле использовать одно заранее известное значение. Ну а если мы захотим использовать произвольно созданный пароль — то придется понять алгоритм этого шифра. Но, судя по приведенным примерам, сделать это будет несложно. Кстати, в SAP GUI 7.40 это поле вообще пропало с формы, но файл с заполненным паролем он корректно воспринимает.

То есть получается, что в браузере достаточно щелкнуть по ссылке на файл с расширением .sap и с нужным форматом — и он предложит его открыть как файл типа SAP GUI Shortcut (естественно на ПК с установленным SAP GUI) и откроет нам окно SAP GUI с указанными параметрами (если пара SID и мандант есть в списке SAP Logon на этом ПК).

Но, понятно, что просто файлы никто заранее создавать и складировать на сайт не будет — их надо генерировать исходя из нужных параметров. Например, можно создать скрипт на PHP для генерации ярлыков (sapshcut.php):

<?php
$queries = array();
parse_str($_SERVER['QUERY_STRING'], $queries);
$Title = $queries['Title'];
$Size = $queries['Size'];
$SID = $queries['SID'];
$Client = $queries['Client'];
if($Client == '') { $Client=200; };
$Lang = $queries['Language'];
if($Lang=='') { $Lang = 'RU'; };
$User = $queries['Username'];
if($User<>'') { $Password = $queries['Password']; };
$filename = $SID.$Client.'.sap';
header('Content-disposition: attachment; filename='.$filename);
header('Content-type: application/sap');
echo "[System]\r\n";
echo "Name=".$SID."\r\n";
echo "Client=".$Client."\r\n";
echo "[User]\r\n";
echo "Name=".$Username."\r\n";
echo "Language=".$Lang."\r\n";
if($Password<>'') echo "Password=".$Password."\r\n";
echo "[Function]\r\n";
if($Title<>'') {echo "Title=".$Title."\r\n";} else {echo "Title=Вход в систему\r\n";};
echo "[Configuration]\r\n";
if($Size=='max') { echo "GuiSize=Maximized\r\n"; };
echo "[Options]\r\n";
echo "Reuse=0\r\n";
?>

Если не задавать имя пользователя и пароль, то получим следующее окно с запросов логина и пароля:



Если передать только логин — то поле логин будет заполнено, а поле пароль пустое. Если же мы передаем пользователю и логин и пароль, но у пользователя на ПК в реестре ключ EnablePassword в разделе [HKEY_CURRENT_USER\Software\SAP\SAPShortcut\Security] установлен в 0, то получим то же самое. И только если этот ключ установлен в 1 и мы передаем и имя и начальный пароль, то система сразу запросит дважды ввести новый постоянный пароль. Что и требовалось получить.

В итоге, имеем следующий набор рассмотренных вариантов как иллюстрация всего вышесказанного:

<html>
<head>
<script>
function openSAPGui(sid, client, user, password) {
var shell = new ActiveXObject("WScript.Shell");
shell.run('sapshcut.exe -system="'+sid+'" -client='+client+' -user="'+user+'" -pw="'+password+'" -language=RU');
}
</script>
</head>
<body>
<a href='' onclick="javascript:openSAPGui('SID', '200', 'test', '');"/>Example 1: Execute sapshcut.exe (ActiveX)<br>
<a href='Sapgui.Shortcut.File: -system=SID -client=200'>Example 2: Open sapshcut.exe (URI)</a><br>
<a href='sapshcut.php?SID=SID&Client=200&User=test'>Example 3: Open file .sap (SAP GUI Shortcut)</a><br>
</body>
</html>

Мне подошел последний вариант. Но также можно вместо генерации ярлыков SAP использовать, например, генерацию CMD-файлов, которые также при открытии из браузера откроют вам окно SAP GUI. Ниже приведен пример (sapguicmd.php) прямого запуска SAP GUI с указанием полной строки подключения, без необходимости иметь настроенный SAP Logon:

<?php
$queries = array();
parse_str($_SERVER['QUERY_STRING'], $queries);
$Title = $queries['Title'];
$ROUTER = $queries['ROUTER'];
$ROUTERPORT = $queries['ROUTERPORT'];
$HOST = $queries['HOST'];
$PORT = $queries['PORT'];
$MESS = $queries['MESS'];
$LG = $queries['LG'];
$filename = 'SAPGUI_';
if($MESS<>'') $filename = $filename.$MESS;
if($HOST<>'') $filename = $filename.$HOST;
if($PORT<>'') $filename = $filename.'_'.$PORT;
$filename = $filename.'.cmd';
header('Content-disposition: attachment; filename='.$filename);
header('Content-type: application/cmd');
echo "@echo off\r\n";
echo "chcp 1251\r\n";
echo "echo Вход в ".$Title."\r\n";
echo "set SAP_CODEPAGE=1504\r\n";
echo 'if exist "%ProgramFiles(x86)%\SAP\FrontEnd\SapGui\sapgui.exe" set gui=%ProgramFiles(x86)%\SAP\FrontEnd\SapGui\sapgui.exe'."\r\n";
echo 'if exist "%ProgramFiles%\SAP\FrontEnd\SapGui\sapgui.exe" set gui=%ProgramFiles%\SAP\FrontEnd\SapGui\sapgui.exe'."\r\n";
echo "set logon=";
if($ROUTER<>'') echo "/H/".$ROUTER;
if($ROUTERPORT<>'') echo "/S/".$ROUTERPORT;
if($MESS<>'') echo "/M/".$MESS;
if($HOST<>'') echo "/H/".$HOST;
if($PORT<>'') echo "/S/".$PORT;
if($LG<>'') echo "/G/".$LG;
echo "\r\n";
echo '"%gui%" %logon%'."\r\n";
?>

Комментарии (16)


  1. ivanbolhovitinov
    06.04.2019 19:03

    И я ходил похожими путями. Мой способ: entropii.net/?p=783


  1. Taraflex
    07.04.2019 01:39
    +1

    Все можно было сделать на порядок проще.
    Пример:

    Windows Registry Editor Version 5.00
    
    [HKEY_CURRENT_USER\SOFTWARE\Classes\runapp]
    "URL Protocol"=""
    @="URL:Universal run app"
    
    [HKEY_CURRENT_USER\SOFTWARE\Classes\runapp\shell]
    
    [HKEY_CURRENT_USER\SOFTWARE\Classes\runapp\shell\open]
    
    [HKEY_CURRENT_USER\SOFTWARE\Classes\runapp\shell\open\command]
    @="mshta javascript:new(ActiveXObject)('WScript.Shell').Run(decodeURI('%1'.substr(7))),window.close()"
    

    В браузере открываем страницу
    runapp:notepad.exe hello.txt
    Таким образом можно извенуться и запускать любые комманды.


    1. Taraflex
      07.04.2019 01:41

      Естественно при реальном использовании, нужно декодировать и передавать только аргументы для запуска конкретного приложения. Я описал лишь концепт.


    1. Duke Автор
      07.04.2019 08:43

      А это разве не только в IE работать будет?


      1. Taraflex
        07.04.2019 18:24

        В любом браузере на Windows 2000 и выше.
        Протестил в хром.


        1. Duke Автор
          07.04.2019 19:41

          Тогда прикольно, надо тоже протестировать, проверить как он работает с разными параметрами безопасности установленными в IE. Не зря статейку написал — коллективный разум даёт интересные ответы на интересные вопросы.


    1. Duke Автор
      08.04.2019 22:13

      Спасибо за решение, действительно работает и даже на параметры безопасности в IE не обращает внимания. Я немного модифицировал предлагаемую строку, чтобы запускался sapshcut.exe:
      Windows Registry Editor Version 5.00

      [HKEY_CURRENT_USER\SOFTWARE\Classes\sapshcut]
      @="URL:sapshcut Handler"
      "URL Protocol"=""

      [HKEY_CURRENT_USER\SOFTWARE\Classes\sapshcut\shell]

      [HKEY_CURRENT_USER\SOFTWARE\Classes\sapshcut\shell\open]

      [HKEY_CURRENT_USER\SOFTWARE\Classes\sapshcut\shell\open\command]
      @="mshta javascript:new(ActiveXObject)('WScript.Shell').Run(decodeURI('%1'.replace(':','.exe'))),window.close()"

      Остается ровно один вопрос — стоит ли использовать? Данный вариант требует прописывания на всех компах организации веб-протокола, что не так-то уж элементарно на сотнях тысяч рабочих мест (не сколько технически, сколько организационно). Поэтому для меня вариант с генерацией .sap файла пока выглядит более привлекательно. Хотя этот вариант со скриптом-обёрткой прямо в реестре красив своим лёгким безумием.


      1. Taraflex
        09.04.2019 01:42

        В зависимости от браузера и его настроек, пользователю может не быть предложено запустить .sap файл.
        + может появляться некрасивая пустая вкладка перед началом загрузки файла (можно чуть компенсировать добавив атрибут download к ссылкам).
        Вариант с реестром имхо более надежный и работает в один клик.


        1. Duke Автор
          09.04.2019 06:29

          Я проверял в разных браузерах. Специально указал header('Content-type: application/sap');
          Браузер просто предлагает открыть файл с зарегистрированным в реестре расширением, пустой вкладки не появляется.


      1. Taraflex
        09.04.2019 01:46

        del


      1. Taraflex
        09.04.2019 01:50

        В вашем варианте кстати дыра. Можно запустить
        sapshcut: && format c:


        1. Duke Автор
          09.04.2019 06:26

          Да, надо будет тогда еще все спецсимволы порезать.


          1. Taraflex
            09.04.2019 06:41

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

            Решение задачи в лоб: запуск sapshcut.exe непосредственно из браузера с помощью объекта ActiveX:

            Это не будет работать по той же причине. Неудачный пароль все сломает.


  1. Akhmad
    08.04.2019 11:14

    а под линукс?


    1. Duke Автор
      08.04.2019 18:27

      А под Linux надо писать отдельную статью. В нашей организации мы не используем клиент под Linux, поэтому пока ничего сказать не могу.


  1. crrr
    08.04.2019 18:33

    В свое время для этих целей писал java апплет, а он уже делал все что нужно было.