0

I have a powershell script that is supposed to be started by php like this:

$hashingCommand = "start powershell -file C:\Apache24\htdocs\\runHashCalc.ps1 \\\\$sAddr \\\\$dAddr $name $algorithm";
pclose(popen($hashingCommand, 'r'));

which leads to something like this:

C:\>WMIC path win32_process get Caption,ProcessId,Commandline | findstr "testingCopyJob"
powershell.exe            powershell  -file C:\Apache24\htdocs\runHashCalc.ps1 \\ACTUALPATH\netstorage\User \\ACTUALPATH\netstorage\copyfolder testingCopyJob sha256  5036

However the script does not do what it is supposed to do.

If I start the script with the exact same parameters from the commandline it works perfectly fine though.

C:\>powershell  -file C:\Apache24\htdocs\runHashCalc.ps1 \\ACTUALPATH\netstorage\User \\ACTUALPATH\netstorage\copyfolder testingCopyJob sha256
 \\config.sample.inc.php
sha256
mariadb --user=username --password=******* -e 'INSERT INTO testingCopyJob (file_name,hash) VALUES (' \\config.sample.inc.php',' 8AA4CE89D12978E805C6A128745A1A885A1E6523220C6647886DC74DC13F421A')' *****_xsw
[...]

The powershell script itself looks like this:

[...]
gci -af -rec $sourceFolder | Foreach-Object {
    $cmd = Get-FileHash $_.FullName -Algorithm $algorithm | Format-List
    $asString = $cmd | ft | out-string
    $answerArray = $asString.Split([System.Environment]::NewLine,[System.StringSplitOptions]::RemoveEmptyEntries)
    $hash = $answerArray[1].Split(":")[1]
    $path = $answerArray[2] -split ':',2
    $aPath = $path[1]
    $aPath=$aPath.Replace($sourceFolder,'')
    $aPath=$aPath.Replace('\','\\')
    write-host $aPath | Out-File -FilePath C:\Apache24\htdocs\hashlog.log -Append
    write-host $algorithm | Out-File -FilePath C:\Apache24\htdocs\hashlog.log -Append
    write-host "mariadb --user=user --password=******* -e 'INSERT INTO $name (file_name,hash) VALUES ('$aPath','$hash')' *****_xsw" | Out-File -FilePath C:\Apache24\htdocs\hashlog.log -Append
    $answer = mariadb --user=user --password=******* -e "INSERT INTO $name (file_name,hash,source) VALUES ('$aPath','$hash',0)" *****_xsw
    write-host $answer | Out-File -FilePath C:\Apache24\htdocs\hashlog.log -Append
}
[...]

(Not even the logging works like this Out-File -FilePath C:\Apache24\htdocs\hashlog.log -Append but that's also the case when running from cmd).

Any ideas on why this happens are welcome.

EDIT: Log works with write-output instead of write-host

Monocito
  • 117
  • 1
  • 12
  • 1
    As an aside: [`Write-Host` is typically the wrong tool to use](http://www.jsnover.com/blog/2013/12/07/write-host-considered-harmful/), unless the intent is to write _to the display only_, bypassing the success output stream and with it the ability to send output to other commands, capture it in a variable, or redirect it to a file. To output a value, use it _by itself_; e.g, `$value`, instead of `Write-Host $value` (or use `Write-Output $value`); see [this answer](https://stackoverflow.com/a/60534138/45375). To explicitly print only to the display _but with rich formatting_, use `Out-Host`. – mklement0 Oct 25 '22 at 01:22
  • 1
    Why are you using `start`? _All_ ``\`` chars. in your script file path should be escaped as ``\\``. – mklement0 Oct 25 '22 at 01:25
  • One workaround would be to just have the PHP write to say a c:\temp\temp.txt file and then have your PowerShell running in a loop say every 5min and read that file data, if any. – MTMDev Oct 25 '22 at 20:24
  • @mklement0 start is used for php not to wait for the result of the powershell script, otherwise it would wait. – Monocito Oct 26 '22 at 06:50
  • I am not sure why you need to run this part from command line and then pass it to script as input: `WMIC path win32_process get Caption,ProcessId,Commandline | findstr "testingCopyJob"`. You can instead make this thing part of PowerShell script and this whole thing will be simplified. It would be better if you just explain what you are trying to achieve, I can provide you a complete simplified solution. – SavindraSingh Oct 27 '22 at 03:56
  • @SavindraSingh the ´WMIC´ part is just to check that the script is running and does not actually do anything, the script is just supposed to add information gathered from files (hashes in this case) into a mariadb database – Monocito Oct 27 '22 at 08:43
  • @Monocito, I see - while that should work in principle, isn't there a way to make PHP itself _not_ wait for the launched process to terminate? It may just be posting artifact, but note that your `C:\Apache24\htdocs\\runHashCalc.ps1` is still broken due to missing backslashes. It would also help if you described _in what way_ the script doesn't do what you expect it to do when launched from PHP. – mklement0 Oct 27 '22 at 16:09
  • Try removing FT from this line: ‘$asString = $cmd | ft | out-string’. Instead use: ‘$asString = $cmd | out-string’ – SavindraSingh Oct 28 '22 at 14:58
  • 1
    Have you tried using proc_open instead, drop the "start". That will return your control back to PHP (you can keep hold of the returned process to check if it's still running, but PHP will continue to execute while you wait) without loading a middle cmd. If you're loading stuff from the environment (e.g. passwords) remember that you're running in an environment under apache or fast-cgi, and not as your user. Check details are available for those users(s). – Robbie Oct 31 '22 at 03:20

0 Answers0