13.09.2010, 17:24 | #1 |
Участник
|
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\""); } Есть ли у кого какие нибудь свежие идеи по этому поводу? Последний раз редактировалось Beast-L; 13.09.2010 в 17:26. |
|
14.09.2010, 13:12 | #2 |
Участник
|
Решилось написанием Class Library на c#, оттуда вызов shellexecute.
Пока лучше решения не нашел. |
|
14.09.2010, 13:25 | #3 |
Участник
|
WScript.Shell - попробуйте. Взято отсюда
Как разархивировать zip архив? |
|
14.09.2010, 13:38 | #4 |
Участник
|
А чем вызвать скрипт? ShellExecute штатный не работает.
|
|
14.09.2010, 14:05 | #5 |
Участник
|
Во-первых, он не штатный - это ваша доделка. Во-вторых, эта тема проскакивала в блогах:
Цитата:
Background of this issue is that on 64bit the DLLFunction kernel class itself is not implemented in Dynamics AX 2009.
Последний раз редактировалось gl00mie; 14.09.2010 в 14:07. |
|
14.09.2010, 14:09 | #6 |
Участник
|
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 |
Участник
|
|
|
14.09.2010, 14:18 | #8 |
Участник
|
WinAPI::shellExecuteServer(), используемый в примере кода из исходного сообщения, - это ваша доделка В AX 2009 серверные методы, как уже упоминалось, вынесены в отдельный класс WinAPIServer.
|
|
|
За это сообщение автора поблагодарили: titov (1). |
14.09.2010, 14:20 | #9 |
Участник
|
Цитата:
Сообщение от 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; } |
|
14.09.2010, 14:21 | #10 |
Участник
|
В WinAPIServer нет shellexecute. А доделка shellexecuteserver, это по сути тот же shellexecute только на сервере.
Последний раз редактировалось Beast-L; 14.09.2010 в 14:25. |
|
14.09.2010, 20:52 | #11 |
Участник
|
Цитата:
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 |
Участник
|
Почемуто виснет на process.WaitForExit();
|
|
15.09.2010, 11:22 | #13 |
Участник
|
Не виснет, а ждет завершения процесса. Правда, если запускать процесс, который сам по себе не завершится, пока пользователь его не прибьет (какой-нить Excel или cmd), тогда, конечно, получится, что Аксапта "виснет". Есть перегруженный вариант метода WaitForExit(), которому можно указать максимальное время, в течение которого следует ожидать завершения запущенного процесса, - можно при желании использовать его, чтоб гарантированно не "висло".
|
|
15.09.2010, 11:33 | #14 |
Участник
|
В том то и дело что именно виснет. Скорее все распаковка происходит быстро (архив маленький) и поэтому ждать уже нечего, и событие завершения происходит до вызова ожидания, поэтому и виснет.
Последний раз редактировалось Beast-L; 15.09.2010 в 11:36. |
|
15.09.2010, 12:03 | #15 |
Участник
|
Цитата:
сделал - архив файла 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 |
Участник
|
Файл распакован, в результате - 0.
|
|
15.09.2010, 13:18 | #17 |
Участник
|
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.
предлагаю такой вариант X++: while(!process.WaitForExit(0)) //проверяем, что процесс еще не закончен в Х++ { sleep(100); } |
|
|
За это сообщение автора поблагодарили: Beast-L (1). |
16.09.2010, 19:44 | #18 |
Участник
|
Для запуска на стороне сервера различных консольных 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 |
Участник
|
Цитата:
Сообщение от titov
http://msdn.microsoft.com/en-us/library/ty0d8k56.aspx
Если вы передаете 0 (ноль) к методу, то возвращает истину, только если процесс уже завершился предлагаю такой вариант X++: while(!process.WaitForExit(0)) //проверяем, что процесс еще не закончен в Х++ { sleep(100); } В общем для своей задачи я нашел решение которое меня полностью устроило, это библиотека .NET IonicZip. |
|
21.03.2011, 12:48 | #20 |
Участник
|
Вот несколько измененная функция запуска приложения.
Возвращает текст, выданный запускаемым приложением, получаемый с консоли. Может быть полезно при запуске консольных утилит, возвращающих результат исполнения (или ошибки) выводом на экран. (например 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 |
|
Опции темы | Поиск в этой теме |
Опции просмотра | |
|