win.ShellExecute не дает такой возможности, только ShellExecuteEx из WinAPI.
os.Execute использовать не могу, т.к. в панелях открыт NetBox и он попытается выполнить это в данной панели, там вообще баш.
Возможно ли как-то использовать ShellExecuteEx в lua скрипте, или как-то по другому исполнить cmd /c command и дождаться его выполнения именно на хосте ФАРа, а не на хосте того, что открыто в панели?
Бог ты мой, нашел на задворках форума и переделал, может кому нужно будет:
Code: Select all
function MsgBox( msg )
far.Message( msg )
end
local ffi = require "ffi"
local C = ffi.C
ffi.cdef [[
typedef struct { // _SECURITY_ATTRIBUTES
unsigned long nLength;
void* lpSecurityDescriptor;
int32_t bInheritHandle;
} SECURITY_ATTRIBUTES;
typedef struct { // _STARTUPINFOW
unsigned long cb;
wchar_t* lpReserved;
wchar_t* lpDesktop;
wchar_t* lpTitle;
unsigned long dwX;
unsigned long dwY;
unsigned long dwXSize;
unsigned long dwYSize;
unsigned long dwXCountChars;
unsigned long dwYCountChars;
unsigned long dwFillAttribute;
unsigned long dwFlags;
unsigned short wShowWindow;
unsigned short cbReserved2;
unsigned char* lpReserved2;
void* hStdInput;
void* hStdOutput;
void* hStdError;
} STARTUPINFOW;
typedef struct { // _PROCESS_INFORMATION
void* hProcess;
void* hThread;
unsigned long dwProcessId;
unsigned long dwThreadId;
} PROCESS_INFORMATION;
int32_t CreatePipe(void** hReadPipe,void** hWritePipe,SECURITY_ATTRIBUTES* lpPipeAttributes,unsigned long nSize);
int32_t CreateProcessW(const wchar_t* lpApplicationName,wchar_t* lpCommandLine,SECURITY_ATTRIBUTES* lpProcessAttributes,SECURITY_ATTRIBUTES* lpThreadAttributes,int32_t bInheritHandles,unsigned long dwCreationFlags,void* lpEnvironment,const wchar_t* lpCurrentDirectory,STARTUPINFOW* lpStartupInfo,PROCESS_INFORMATION* lpProcessInformation); // https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx
int32_t ReadFile(void* hFile,void* lpBuffer,unsigned long nNumberOfBytesToRead,unsigned long* lpNumberOfBytesRead,void* lpOverlapped);
int32_t CloseHandle(void* hObject);
void* GetStdHandle(unsigned long nStdHandle);
int32_t GetLastError(void);
bool GetExitCodeProcess(HANDLE hProcess, int32_t* lpExitCode); // https://msdn.microsoft.com/en-us/library/windows/desktop/ms683189(v=vs.85).aspx
int32_t WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds); // https://msdn.microsoft.com/en-us/library/windows/desktop/ms687032(v=vs.85).aspx
int32_t IsTextUnicode(const void* lpv,int iSize,int* lpiResult);
]]
local advapi32 = ffi.load("advapi32")
local IS_TEXT_UNICODE_ASCII16 = 0x0001
local IS_TEXT_UNICODE_STATISTICS = 0x0002
local STILL_ACTIVE = 0x0103 -- = 259 = STATUS_PENDING in WinNT.h
local CREATE_NO_WINDOW = 0x8000000
local STD_INPUT_HANDLE = -10
local STARTF_USESTDHANDLES = 0x00000100
local INFINITE = 0xFFFFFFFF
local function exec( command )
local exitcode = ffi.new( "DWORD[1]" )
local ret, err, output = nil
local pipe_security = ffi.new( "SECURITY_ATTRIBUTES" )
pipe_security.nLength = ffi.sizeof( pipe_security )
pipe_security.bInheritHandle = true
local pipe_in,pipe_out = ffi.new( "void*[1]" ), ffi.new( "void*[1]" )
if C.CreatePipe( pipe_in, pipe_out, pipe_security, 0 ) then
local startup = ffi.new( "STARTUPINFOW" )
startup.cb = ffi.sizeof( startup )
startup.dwFlags = STARTF_USESTDHANDLES
startup.hStdInput = C.GetStdHandle( STD_INPUT_HANDLE )
startup.hStdOutput = pipe_out[0];
startup.hStdError = pipe_out[0];
local info = ffi.new( "PROCESS_INFORMATION" )
if C.CreateProcessW(
ffi.NULL,
command and ffi.cast( "void*", win.Utf8ToUtf16( command .. "\0" ) ) or ffi.NULL,
ffi.NULL,
ffi.NULL,
true,
CREATE_NO_WINDOW,
ffi.NULL,
folder and ffi.cast( "void*", win.Utf8ToUtf16( folder .. "\0" ) ) or ffi.NULL,
startup,
info ) ~= 0 then
C.CloseHandle( pipe_out[0] )
local size = 1024
local buffer = ffi.new( "char[?]", size )
local readed = ffi.new( "unsigned long[1]" )
local unicode = ffi.new( "int[1]" )
unicode[0] = bit64.bor( IS_TEXT_UNICODE_ASCII16, IS_TEXT_UNICODE_STATISTICS )
output = ""
while true do
C.ReadFile( pipe_in[0], buffer, size, readed, ffi.NULL )
if readed[0] == 0 then
break
else
output = output .. ( advapi32.IsTextUnicode( buffer, readed[0], unicode ) == 0 and win.OemToUtf8 or win.Utf16ToUtf8 )( ffi.string( buffer, readed[0] ) )
end
end
--C.WaitForSingleObject(info.hProcess,INFINITE)
if C.GetExitCodeProcess( info.hProcess, exitcode ) then
ret = exitcode[0]
err = nil
else
ret = false
err = C.GetLastError()
end
C.CloseHandle( info.hThread )
C.CloseHandle( info.hProcess )
else
ret = nil
err = C.GetLastError()
end
C.CloseHandle( pipe_in[0] )
end
return ret, err, output
end
ret, err, output = exec( "cmd /c \"dir *.*\"" )