Skip to content
Advertisement

Why is a remote batch file not executed by PsExec started from a batch file ran from within a PHP script with function exec?

I am currently facing the issue that I want to implement a PHP script that starts a batch file on a remote server.

After hours of ideas the nearest I came to the solution was a batch file on a local server which could be started by the PHP script. However, the batch file somehow does not start the remote batch file when started via PHP script.

If the batch file c:directoryappssubclassesactionstest.bat is started locally with a double click, the remote batch file c:directorysubtest.bat is executed without a problem by PsExec.

The permissions are granted as needed.

I am using the following code in PHP to start the first batch file:

$cmd = '"c:\directoryapps\sub\classes\actions\test.bat"';
exec('cmd /c '.$cmd.' &');

The code of that batch file is as followed:

"C:/Windows/System32/SysinternalsSuite/PsExec.exe" \server -i -u **** -p **** c:\directory\sub\test.bat 

How do I implement a working version of this?

I have also tried to run the first batch file code from within PHP script with even less success.

Advertisement

Answer

The main problem is the decision to install the Sysinternals Suite into a subdirectory of %SystemRoot%System32. That was no good decision and cause the issue here.

The directory %SystemRoot%System32 is for 64-bit applications executed in 64-bit environment on 64-bit Windows.

The usage of %SystemRoot%System32, which is usually expanded to C:WindowsSystem32, in 32-bit environment results in a redirection by Windows File System Redirector to %SystemRoot%SysWOW64 respectively expanded C:WindowsSysWOW64.

%SystemRoot%SysWOW64 contains the 32-bit system executables, but not the directory SysinternalsSuite with file PsExec.exe.

python.exe is a 32-bit executable. For that reason is started with just cmd in the Python script %SystemRoot%SysWOW64cmd.exe which is the 32-bit version of Windows command processor. 32-bit cmd fails to find C:WindowsSysWOW64SysinternalsSuitePsExec.exe and so psexec.exe is not executed at all.

Well, starting cmd.exe to run a batch file which contains only one command line to run psexec.exe with wrong path for 32-bit environment is not needed at all.

It would be enough to use in Python script:

$args = '\\server -i -u "****" -p "****" "C:\directory\sub\test.bat"';
exec('C:\Windows\Sysnative\SysinternalsSuite\PsExec.exe '.$args.);

32-bit python.exe runs with this code the 32-bit executable PsExec.exe in subdirectory SysinternalsSuite of 64-bit Windows system directory with the appropriate arguments.

The special redirecting Sysnative exists only for 32-bit applications executed in 32-bit environment. Please note that Sysnative is neither a directory nor a symbolic link or hard link. The file system does not contain an entry Sysnative in directory C:Windows. For that reason it is not possible to use in a batch file if exist %SystemRoot%Sysnative or if exist %SystemRoot%Sysnative as both conditions evaluate always to false. But if exist %SystemRoot%Sysnativecmd.exe can be used in a batch file to find out if the batch file is processed by 32-bit Windows command processor on a 64-bit Windows because of the condition evaluates to true in this use case.

I recommend reading also the Microsoft documentation pages WOW64 Implementation Details and Registry Keys Affected by WOW64 to get knowledge on how 32-bit Windows emulation works on 64-bit Windows.


A minor issue is appending & at end of the Windows command line. An ampersand at end of a shell script line is interpreted only by Unix/Linux/Mac shell script interpreters as instruction to run the executable detached in background. So the shell script interpreter does not wait for termination of the started executable before continuation of the script or before the user can enter the next command to execute.

Windows command processor cmd.exe interprets an ampersand outside a double quoted argument string as AND operator usually used to specify multiple commands on one command line, see single line with multiple commands using Windows batch file. If there is after & nothing on a command line interpreted by cmd.exe, the Windows command processor ignores the AND operator.

Therefore do not append & on a Windows command line.


There are two more minor issues in the batch file on command line:

"C:/Windows/System32/SysinternalsSuite/PsExec.exe" \server -i -u **** -p **** c:\directory\sub\test.bat

The directory separator on Windows is and not / as explained by Microsoft on documentation page Naming Files, Paths, and Namespaces. The Windows kernel replaces by default all / by in a file/folder string before passing the string to the appropriate file system function. But the usage of Linux/Mac directory separator / can nevertheless result in unexpected behavior.

Example:

Run in a Windows command prompt window:

for %I in (C:/Windows/*.exe) do @echo %I

The found executables in Windows directory are output with C: and the file name without path. So assigned to loop variable I is a string which references an executable file in current directory of drive C:. But the current directory on drive C: on execution of this command line is most likely not C:Windows which would cause issues on really processing the file name assigned to loop variable I instead of just printing it to console window.

Run in same command prompt window now:

for %I in (C:Windows*.exe) do @echo %I

The same file names are output as before, but this time with full path.

Conclusion: Do not use / in file/folder strings on Windows and depend on automatic correction of Windows kernel. / is used on Windows mainly for beginning of an option.

The usage of \ in a batch file between two directory names and between a directory name and a file name is also always wrong and must be corrected by Windows kernel before passing the file/folder name string to the file system by removing one backslash. \ is valid only at beginning of a UNC path.

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement