AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск Все разделы прочитаны

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 13.09.2010, 17:24   #1  
Beast-L is offline
Beast-L
Участник
Аватар для Beast-L
 
104 / 21 (1) +++
Регистрация: 20.10.2006
Адрес: Киев
ShellExecute on x64 server
Как выполнить shellexecute на сервере x64? (win2003 ax5 x64)

Собственно сама задача состоит в том чтобы распаковать файл на сервере и импортировать данные в аксу.

Пробовал клиентом запущенным на удаленном рабочем столе (на сервере), распаковка идет нормально. Если через серверный статический метод ругается на "Функция "ShellExecuteExW" в библиотеке DLL "SHELL32" привела к возникновению исключения.".

В результате танцев с бубном, статический метод принял вид:
X++:
public static server void unpack()
{
    CodeAccessPermission permission = new InteropPermission(InteropKind::DllInterop);
    ;

    permission.assert();

    WinAPI::shellExecuteServer("c:\\Program Files\\Microsoft Dynamics AX\\50\\Server\\DSU_WORK\\Bin\\7z.exe e -o\"d:\\install\\7-zip\" \"\\\\192.168.245.59\\in\\zip\\9#33905.126\"");
}
shellExecuteServer это shellExecute с server вместо client

Есть ли у кого какие нибудь свежие идеи по этому поводу?

Последний раз редактировалось Beast-L; 13.09.2010 в 17:26.
Старый 14.09.2010, 13:12   #2  
Beast-L is offline
Beast-L
Участник
Аватар для Beast-L
 
104 / 21 (1) +++
Регистрация: 20.10.2006
Адрес: Киев
Решилось написанием Class Library на c#, оттуда вызов shellexecute.

Пока лучше решения не нашел.
Старый 14.09.2010, 13:25   #3  
titov is offline
titov
Участник
 
73 / 87 (3) ++++
Регистрация: 23.12.2005
Адрес: Казань
WScript.Shell - попробуйте. Взято отсюда
Как разархивировать zip архив?
Старый 14.09.2010, 13:38   #4  
Beast-L is offline
Beast-L
Участник
Аватар для Beast-L
 
104 / 21 (1) +++
Регистрация: 20.10.2006
Адрес: Киев
А чем вызвать скрипт? ShellExecute штатный не работает.
Старый 14.09.2010, 14:05   #5  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5798 (201) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Цитата:
Сообщение от Beast-L Посмотреть сообщение
ShellExecute штатный не работает.
Во-первых, он не штатный - это ваша доделка. Во-вторых, эта тема проскакивала в блогах:
Цитата:
Background of this issue is that on 64bit the DLLFunction kernel class itself is not implemented in Dynamics AX 2009.
Так что забудьте про Win32 API при работе в AX 2009 на сервере.
Цитата:
Сообщение от Beast-L Посмотреть сообщение
Решилось написанием Class Library на c#, оттуда вызов shellexecute. Пока лучше решения не нашел.
А лучшего решения и не будет - не даром разработчики выделили отдельный класс WinAPIServer и все методы в нем переписали на .NET (кроме getLastError(), который с давних пор реализован в ядре).

Последний раз редактировалось gl00mie; 14.09.2010 в 14:07.
Старый 14.09.2010, 14:09   #6  
titov is offline
titov
Участник
 
73 / 87 (3) ++++
Регистрация: 23.12.2005
Адрес: Казань
Цитата:
Сообщение от Beast-L Посмотреть сообщение
А чем вызвать скрипт? ShellExecute штатный не работает.
X++:
static void ReturnCode_Job(Args _args)
{
COM    wsh             = new COM('WScript.Shell');
int        returnCode1 = -1;
int        returnCode2 = -1;
int        errorCode1 = -1;
int        errorCode2 = -1;
;
 
    returnCode1 = wsh.Run('winrar.exe e -y C:\\1.zip C:\\1\\', 1, true);
    errorCode1 = WinAPI::getLastError();
 
    returnCode2 = wsh.Run('winrar.exe e -y C:\\2.zip C:\\2\\', 1, true);
    errorCode2 = WinAPI::getLastError();
 
    info(strFmt('1.zip: ReturnCode = %1, ErrorCode = %2', returnCode1, errorCode1));
    info(strFmt('2.zip: ReturnCode = %1, ErrorCode = %2', returnCode2, errorCode2));
 
    wsh.finalize();
 
return;
}
код из ссылки, которую я привел
За это сообщение автора поблагодарили: Logger (1).
Старый 14.09.2010, 14:13   #7  
Beast-L is offline
Beast-L
Участник
Аватар для Beast-L
 
104 / 21 (1) +++
Регистрация: 20.10.2006
Адрес: Киев
Цитата:
Сообщение от gl00mie Посмотреть сообщение
Во-первых, он не штатный - это ваша доделка. Во-вторых, эта тема.
WinAPI::ShellExecute это не моя доделка, а стандартный функционал. Мой ShellExecute через .net работает вполне нормально.
Старый 14.09.2010, 14:18   #8  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5798 (201) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
WinAPI::shellExecuteServer(), используемый в примере кода из исходного сообщения, - это ваша доделка В AX 2009 серверные методы, как уже упоминалось, вынесены в отдельный класс WinAPIServer.
За это сообщение автора поблагодарили: titov (1).
Старый 14.09.2010, 14:20   #9  
Beast-L is offline
Beast-L
Участник
Аватар для Beast-L
 
104 / 21 (1) +++
Регистрация: 20.10.2006
Адрес: Киев
Цитата:
Сообщение от titov Посмотреть сообщение
X++:
static void ReturnCode_Job(Args _args)
{
COM    wsh             = new COM('WScript.Shell');
int        returnCode1 = -1;
int        returnCode2 = -1;
int        errorCode1 = -1;
int        errorCode2 = -1;
;
 
    returnCode1 = wsh.Run('winrar.exe e -y C:\\1.zip C:\\1\\', 1, true);
    errorCode1 = WinAPI::getLastError();
 
    returnCode2 = wsh.Run('winrar.exe e -y C:\\2.zip C:\\2\\', 1, true);
    errorCode2 = WinAPI::getLastError();
 
    info(strFmt('1.zip: ReturnCode = %1, ErrorCode = %2', returnCode1, errorCode1));
    info(strFmt('2.zip: ReturnCode = %1, ErrorCode = %2', returnCode2, errorCode2));
 
    wsh.finalize();
 
return;
}
код из ссылки, которую я привел
Метод "Run" в COM-объекте класса "WScript.Shell" возвратил код ошибки 0x80070002 (<неизвестно>), который означает: <неизвестно>.
Старый 14.09.2010, 14:21   #10  
Beast-L is offline
Beast-L
Участник
Аватар для Beast-L
 
104 / 21 (1) +++
Регистрация: 20.10.2006
Адрес: Киев
Цитата:
Сообщение от gl00mie Посмотреть сообщение
WinAPI::shellExecuteServer(), используемый в примере кода из исходного сообщения, - это ваша доделка В AX 2009 серверные методы, как уже упоминалось, вынесены в отдельный класс WinAPIServer.
В WinAPIServer нет shellexecute. А доделка shellexecuteserver, это по сути тот же shellexecute только на сервере.

Последний раз редактировалось Beast-L; 14.09.2010 в 14:25.
Старый 14.09.2010, 20:52   #11  
titov is offline
titov
Участник
 
73 / 87 (3) ++++
Регистрация: 23.12.2005
Адрес: Казань
Цитата:
Сообщение от gl00mie Посмотреть сообщение
В AX 2009 серверные методы, как уже упоминалось, вынесены в отдельный класс WinAPIServer.
две ссылки
http://blogs.msdn.com/b/czdaxsup/arc...m-a-batch.aspx
http://msdn.microsoft.com/en-us/libr...s.process.aspx

ниже почти готовый код для нового метода класса WinAPIServer

X++:
static server void ShellExecuteRunServer()
{
    System.Diagnostics.Process              process;
    System.Diagnostics.ProcessStartInfo     processStartInfo;
    int                                     exitCode;
    ;
    new InteropPermission(InteropKind::ClrInterop).assert();
    process = new System.Diagnostics.Process();
    processStartInfo = new System.Diagnostics.ProcessStartInfo();
    processStartInfo.set_FileName("winrar.exe");
    processStartInfo.set_Arguments("e -y E:\\1\\1.zip E:\\1\\2\\");
    process.set_StartInfo(processStartInfo);
    process.Start();
    process.WaitForExit();
 
    exitCode        = process.get_ExitCode();
    info(strFmt("%1",exitCode ));
    info("Finished");
}
работает!
За это сообщение автора поблагодарили: gl00mie (2).
Старый 15.09.2010, 10:19   #12  
Beast-L is offline
Beast-L
Участник
Аватар для Beast-L
 
104 / 21 (1) +++
Регистрация: 20.10.2006
Адрес: Киев
Почемуто виснет на process.WaitForExit();
Старый 15.09.2010, 11:22   #13  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5798 (201) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Не виснет, а ждет завершения процесса. Правда, если запускать процесс, который сам по себе не завершится, пока пользователь его не прибьет (какой-нить Excel или cmd), тогда, конечно, получится, что Аксапта "виснет". Есть перегруженный вариант метода WaitForExit(), которому можно указать максимальное время, в течение которого следует ожидать завершения запущенного процесса, - можно при желании использовать его, чтоб гарантированно не "висло".
Старый 15.09.2010, 11:33   #14  
Beast-L is offline
Beast-L
Участник
Аватар для Beast-L
 
104 / 21 (1) +++
Регистрация: 20.10.2006
Адрес: Киев
В том то и дело что именно виснет. Скорее все распаковка происходит быстро (архив маленький) и поэтому ждать уже нечего, и событие завершения происходит до вызова ожидания, поэтому и виснет.

Последний раз редактировалось Beast-L; 15.09.2010 в 11:36.
Старый 15.09.2010, 12:03   #15  
titov is offline
titov
Участник
 
73 / 87 (3) ++++
Регистрация: 23.12.2005
Адрес: Казань
Цитата:
Сообщение от Beast-L Посмотреть сообщение
В том то и дело что именно виснет. Скорее все распаковка происходит быстро (архив маленький) и поэтому ждать уже нечего, и событие завершения происходит до вызова ожидания, поэтому и виснет.
Windows Server 2008 R2 Ax2009 rollup 4 x64 - intel xeon 4x работает
сделал - архив файла 0(нуль) и 300 Мб. а также команда dir в пустом каталоге, а также несуществующая команда
не удалось повторить ошибку

а вот так что у вас вернет и будет ли результат? по вашей версии процесс уже выполнен и все нормально
X++:
process.Start();
//    process.WaitForExit();
 
    exitCode        = process.get_ExitCode();
    info(strFmt([COLOR=red]"%1"[/COLOR],exitCode ));
Старый 15.09.2010, 12:18   #16  
Beast-L is offline
Beast-L
Участник
Аватар для Beast-L
 
104 / 21 (1) +++
Регистрация: 20.10.2006
Адрес: Киев
Файл распакован, в результате - 0.
Старый 15.09.2010, 13:18   #17  
titov is offline
titov
Участник
 
73 / 87 (3) ++++
Регистрация: 23.12.2005
Адрес: Казань
Цитата:
Сообщение от Beast-L Посмотреть сообщение
Файл распакован, в результате - 0.
http://msdn.microsoft.com/en-us/library/ty0d8k56.aspx
Цитата:
Сообщение от цитата из ссылки
If you pass 0 (zero) to the method, it returns true only if the process has already exited.
Если вы передаете 0 (ноль) к методу, то возвращает истину, только если процесс уже завершился
предлагаю такой вариант
X++:
    while(!process.WaitForExit(0)) //проверяем, что процесс еще не закончен в Х++
    {
        sleep(100);
    }
За это сообщение автора поблагодарили: Beast-L (1).
Старый 16.09.2010, 19:44   #18  
someOne is offline
someOne
Участник
Аватар для someOne
 
173 / 429 (15) +++++++
Регистрация: 11.12.2008
Адрес: Москва
Для запуска на стороне сервера различных консольных exe написал такую функцию (для DAX2009) в классе WinAPIServer.

Позволяет также управлять временем ожидания выполнения приложения.
Возвращает результат (успешное / не успешное завершение)

X++:
static server boolean shellExecuteWait(str _commandLine, str _arguments = "", int _waitTime = -1)
{
    System.Diagnostics.Process          process;
    System.Diagnostics.ProcessStartInfo startInfo;
    InteropPermission                   permission = new InteropPermission(InteropKind::ClrInterop);
    System.Exception                    exception;
    Boolean                             exited;
    ;
    permission.assert();

    startInfo   = new System.Diagnostics.ProcessStartInfo(_commandLine);
    process     = new System.Diagnostics.Process();

    if (_arguments)
    {
        startInfo.set_Arguments(_arguments);
    }

    try
    {
        startInfo.set_UseShellExecute(false); // для отключения диалога безопасности доступа к сетевым файлам

        process.set_StartInfo(startInfo);
        process.Start();
        process.WaitForExit(_waitTime);

        exited = process.get_HasExited();

        if (exited == false)
        {
            process.Kill();

            return false;
        }

        return true;
    }
    catch (Exception::CLRError)
    {
        exception = CLRInterop::getLastException();

        while (exception)
        {
            error(exception.get_Message());

            exception = exception.get_InnerException();
        }

        return false;
    }
}
За это сообщение автора поблагодарили: gl00mie (2), player (1).
Старый 17.09.2010, 16:03   #19  
Beast-L is offline
Beast-L
Участник
Аватар для Beast-L
 
104 / 21 (1) +++
Регистрация: 20.10.2006
Адрес: Киев
Цитата:
Сообщение от titov Посмотреть сообщение
http://msdn.microsoft.com/en-us/library/ty0d8k56.aspx


Если вы передаете 0 (ноль) к методу, то возвращает истину, только если процесс уже завершился
предлагаю такой вариант
X++:
    while(!process.WaitForExit(0)) //проверяем, что процесс еще не закончен в Х++
    {
        sleep(100);
    }
Вроде бы работает. Но почему то остаются висячие процессы 7z на сервере.


В общем для своей задачи я нашел решение которое меня полностью устроило, это библиотека .NET IonicZip.
Старый 21.03.2011, 12:48   #20  
someOne is offline
someOne
Участник
Аватар для someOne
 
173 / 429 (15) +++++++
Регистрация: 11.12.2008
Адрес: Москва
Вот несколько измененная функция запуска приложения.

Возвращает текст, выданный запускаемым приложением, получаемый с консоли. Может быть полезно при запуске консольных утилит, возвращающих результат исполнения (или ошибки) выводом на экран. (например zip, rar и так далее).
Кроме того может управлять временем ожидания выполнения приложения. При превышении времени приложение будет принудительно завершено.

Может работать при запуске и на клиенте, и на сервере (написана для ax2009, для ax4 тоже должна работать).

Может быть пригодится кому - нибудь...

Например, при запуске:
X++:
static void test(Args _args)
{
    ;
    info(winapiserver::shellExecuteWaitInfo("cmd", "dir"));
}
Выдает:
Цитата:
Microsoft Windows [Version 5.2.3790]
(C) Copyright 1985-2003 Microsoft Corp.

C:\WINDOWS\system32>
Текст самой функции:
X++:
static server str shellExecuteWaitInfo(str _commandLine, str _arguments = "", int _waitTime = -1)
{
    System.String                       outputInfo;
    System.IO.StreamReader              streamReader;
    System.Diagnostics.Process          process;
    System.Diagnostics.ProcessStartInfo startInfo;
    InteropPermission                   permission = new InteropPermission(InteropKind::ClrInterop);
    System.Exception                    exception;
    Boolean                             exited;

    System.Text.Encoding                encoding;
    System.Text.Encoding                encoding866;
    System.Text.Encoding                encodingUTF;

    System.Byte[]                       tmp;
    str                                 ret;
    ;
    permission.assert();

    encodingUTF = System.Text.Encoding::get_Unicode();
    encoding866 = System.Text.Encoding::GetEncoding(866);


    startInfo   = new System.Diagnostics.ProcessStartInfo(_commandLine);
    process     = new System.Diagnostics.Process();

    if (_arguments)
    {
        startInfo.set_Arguments(_arguments);
    }

    try
    {
        startInfo.set_UseShellExecute(false); // для отключения диалога безопасности доступа к сетевым файлам
        startInfo.set_RedirectStandardOutput(true);

        process.set_StartInfo(startInfo);
        process.Start();

        streamReader = process.get_StandardOutput();

        encoding = streamReader.get_CurrentEncoding();

        outputInfo = streamReader.ReadToEnd();

        process.WaitForExit(_waitTime);

        exited = process.get_HasExited();

        if (exited == false)
        {
            process.Kill();

            return "";
        }

        tmp = encoding.GetBytes(outputInfo);

        tmp = System.Text.Encoding::Convert(encoding866, encodingUTF, tmp);

        ret = encodingUTF.GetString(tmp);

        if (ret)
            return ret;

        return "ok";
    }
    catch (Exception::CLRError)
    {
        exception = CLRInterop::getLastException();

        while (exception)
        {
            error(exception.get_Message());

            exception = exception.get_InnerException();
        }

        return "";
    }
}
За это сообщение автора поблагодарили: konfet (1).
Теги
64-bit, aos, ax2009, dllfunction, winapi, zip

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Connection к другому SQL Server Poleax DAX: Программирование 5 19.10.2010 10:49
emeadaxsupport: Unable to validate the AX 2009 Workflow Webservice URL on a Windows Server 2008 R2 x64 Blog bot DAX Blogs 0 05.01.2010 19:16
chrisfie: Project Server 2007 TechNet Webcasts recordings and decks Blog bot DAX Blogs 0 21.07.2009 10:05
dynamicsusers: SQL Server: x64 vs x86 Blog bot DAX Blogs 0 28.06.2007 17:00
aEremenko: Диагностика проблем при установке Microsoft Dynamics Ax 4.0 на Microsoft SQL Server 2005 Blog bot DAX Blogs 0 28.10.2006 16:01
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 02:35.