php exec or pro_open C# exe OutOfMemoryException,CLI OK - c#

Environment:Win10 64bit, WAMP3.0.6 64bit(PHP v7.0.10,apache v2.4.23),ppt2png.exe(Written by C#,Call dcom PowerPoint Application)
1.php code :exec(ppt2png.exe,in ppt,out pngs).
<?php
//echo exec('whoami');
$cmd="D:\wamp64\www\convert\application\convert\util/../bin/ppt2png/ppt2img.exe D:\wamp64\www\convert\application\convert\util/../convert_tmp/ppt/ba228be6f2cfa6a6bc2a66878afacb662018-01-15-15-04-57-7206.pptx -t png -o D:\wamp64\www\convert\application\convert\util/../convert_tmp/png/ba228be6f2cfa6a6bc2a66878afacb662018-01-15-15-04-57-7206";
exec($cmd, $output, $status);
//var_dump($status);
var_dump($output);
// pro_open($cmd);
function pro_open($cmd)
{
$cmdErrorTxt = "error-output.txt";
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("file", $cmdErrorTxt, "a"),
);
$process = proc_open($cmd, $descriptorspec, $pipes);
if (is_resource($process)) {
fwrite($pipes[0], '<?php print_r($_ENV); ?>');
fclose($pipes[0]);
echo stream_get_contents($pipes[1]);
fclose($pipes[1]);
$return_value = proc_close($process);
return $return_value;
}
return 0;
}
2.c# ppt2png.exe code
static void Main(string[] args)
{
if (args.Length == 0)
{
Console.WriteLine(#"Usage: ppt2img <ppt|pptx> [options]
Option:
-t|--type <png|jpg>
-o|--output <dir>");
return;
}
try
{
for (int i = 0; i < args.Length; ++i)
{
if (args[i] == "--type" || args[i] == "-t")
{
++i;
imgType = args[i];
}
else if (args[i] == "--output" || args[i] == "-o")
{
++i;
outDir = args[i];
}
else if (inPpt.Length == 0)
inPpt = args[i];
else
throw new Exception("Unknow option '" + args[i] + "'");
}
}
catch (Exception e)
{
Console.WriteLine("Invalid args");
Console.WriteLine("{0}", e.Message);
return;
}
outDir = Path.GetFullPath(outDir);
inPpt = Path.GetFullPath(inPpt);
baseName = Path.GetFileNameWithoutExtension(inPpt);
Type officeType = Type.GetTypeFromProgID("Powerpoint.Application");
if (officeType == null)
{
// Powerpoint is not installed.
// Show message or alert that Powerpoint is not installed.
}
else
{
// Powerpoint is installed.
// Continue your work.
}
Microsoft.Office.Interop.PowerPoint.Application PowerPoint_App = new Microsoft.Office.Interop.PowerPoint.Application();
Microsoft.Office.Interop.PowerPoint.Presentations multi_presentations = PowerPoint_App.Presentations;
Microsoft.Office.Interop.PowerPoint.Presentation presentation = multi_presentations.Open(inPpt,
MsoTriState.msoTrue /* ReadOnly=true */,
MsoTriState.msoTrue /* Untitled=true */,
MsoTriState.msoFalse /* WithWindow=false */);
int count = presentation.Slides.Count;
for (int i = 0; i < count; i++)
{
Console.WriteLine("Saving slide {0} of {1}...", i + 1, count);
string fmtI= i.ToString("000");
String outName = String.Format(#"{0}\slide_{2}.{3}", outDir, baseName, fmtI, imgType);
try
{
presentation.Slides[i + 1].Export(outName, imgType, width, height);
}
catch (Exception e)
{
Console.WriteLine("Failed to export slide {0}", i + 1);
Console.WriteLine("{0}", e.Message);
break;
}
}
PowerPoint_App.Quit();
Console.WriteLine("Done");
}
This is correct when executed in cmd.
executed in cmd alone
executed in cmd by php cli
But wrong when executed by browser(when web server is Apache Or IIS) throwing OutOfMemoryException.
error-output.txt contains 'unhandled exception: OutOfMemoryException.'.
C# log indicates that C# program stops at
Microsoft.Office.Interop.PowerPoint.Application PowerPoint_App = new Microsoft.Office.Interop.PowerPoint.Application();
But when web server is Nginx,there is no such exception,it works out.
Who can give me some tips? thanks a lot!

That's not a PHP problem. It's an issue with the ppt2png.exe program. It's likely a PPT file that's too big or something but you should contact the original author of that program for support.

Old, but in case someone else has this issue - I had exactly the same issue with a C# program that used Interop to convert PPT slides to PNG on Windows Server 2008 R2. Called from command line worked perfectly, called from PHP via exec() gave Out of Memory error. Turned out I'd installed 64-bit Office 2016 but PHP was 32-bit. Reinstalling 32-bit Office solved the issue. Maybe that helps someone.

Related

Sharing violation on path

I am trying to write some string to a file, and here is the code:
private static void WriteSelfDefinedFile(string msg)
{
ArrayList logTypes = SelfDefinedLogRule(msg);
// New some StreamWriter here
StreamWriter[] sws = new StreamWriter[selfDefinedLogFileName.Length];
for(int i = 0;i<selfDefinedLogFileName.Length;i++)
{
sws[i] = new StreamWriter(selfDefinedLogDir + selfDefinedLogFileName[i], true);
Debug.Log("111");
}
// It is writting here, not important for this question,I think.
foreach(SelfDefinedLogType temp in logTypes)
{
int index = (int)temp;
foreach (SelfDefinedLogType n in Enum.GetValues(typeof(SelfDefinedLogType)))
{
if(temp == n && sws[index]!=null)
{
sws[index].WriteLine(System.DateTime.Now.ToString() + ":\t"+ msg);
break;
}
else if(sws[index] == null)
{
LogError("File " + selfDefinedLogFileName[index] + " open fail");
}
}
}
// Close the StreamWrite[] here
for(int i=0;i<selfDefinedLogFileName.Length;i++)
{
sws[i].Close();
Debug.Log("222");
}
}
When the client is sending msg to server or server replying some msg to client, this funtion will be called to write some message to some files.
And unity throws the IOException:Sharing violation on path D:\SelfDefinedLogs\SentAndReceiveMsg.txt, sometimes. I mean, it doesn't happened everytime I write.
I have closed all the opened streamWriter at the end of the funtion, but the problem still come up.I am really confused.I will be grateful if anybody gives some solutions to this problem.

Unable to change port or host/server, c#

I am currently making a client and server. The server will store people and their location using a dictionary. The client can then lookup a location or update/add a person and their location. For example, I could type 'Lucy', 'School', and the server will add that to the dictionary. If I then type 'Lucy' it should reply with 'School' and if I type in 'Lucy' 'Home' it should up date that to the dictionary.
However, in the arguments, the user may put /h followed by a host name and /p followed by a port number. I'm currently trying to implement this feature in the client, however it doesn't seem to be working at all.
The following is my code. I made a list for the arguments so that if it does have /h or /p followed by the appropriate information, I can reduce the number of arguments so it doesn't effect the other parts of the program.
static void Main(string[] args)
{
String server = "whois.networksolutions.com";
int port = 43;
List<string> list = new List<string>(args);
for (int i = 0; i < args.Length; i++)
{
if (args[i].Trim() == "/h")
{
string serverString = args[i + 1].Trim();
server = args[i + 1];
list.RemoveAt(i);
//remove h from the list
list.RemoveAt(i);
//remove server name from the lst
args = list.ToArray();
//update args array
i = i - 1;
Console.WriteLine("Server changed to " + serverString);
}
else if (args[i].Trim() == "/p")
{
string portString = args[i + 1];
port = Convert.ToInt32(args[i + 1].Trim());
list.RemoveAt(i);
//remove p from the list
list.RemoveAt(i);
//remover port number from list
args = list.ToArray();
//update args array
i = i - 1;
Console.WriteLine("Port changed to " + portString);
}
}
try
{
TcpClient client = new TcpClient();
client.Connect(server, port);
client.ReceiveTimeout = 1000;
client.SendTimeout = 1000;
StreamWriter sw = new StreamWriter(client.GetStream());
StreamReader sr = new StreamReader(client.GetStream());
sw.AutoFlush = true;
sw.WriteLine(args[0]);
if (args.Length == 1)
{
if (args[0] == "514872")
{
Console.WriteLine("514872 is being tested\r\n");
}
else
{
Console.WriteLine("ERROR: no entries found\r\n");
}
}
else if (args.Length == 2)
{
Console.WriteLine(args[0] + " location changed to be is being tested\r\n");
}
}
catch
{
Console.WriteLine("Connection failure.");
}
}
}
Any help would be massively appreciated!
Thank you
Lucy

C# AccessViolationException

I am installing a ttf file into my C:/Windows/Fonts folder from my C# WPF application.While installing I am getting System.AccessViolation Exception. My code is below:
int result = -1;
int error = 0;
var windowsDirectory = Environment.GetEnvironmentVariable("SystemRoot") + "\\Fonts\\";
var directoryInfo = new DirectoryInfo("../../Assets/Fonts");
foreach (var file in directoryInfo.GetFiles())
{
result = AddFontResource((new FileInfo(windowsDirectory + file.Name)).ToString());
error = Marshal.GetLastWin32Error();
if (error != 0)
{
System.Diagnostics.Debug.WriteLine(new Win32Exception(error).Message);
}
else
{
System.Diagnostics.Debug.WriteLine((result == 0) ? "Font is already installed." :
"Font installed successfully.");
}
}
How do Iresolve my issue
In case the exception is really based on missing administrator rights, you might want to read this articel about how to set up your app config for administrator rights.

Open and print PDF files

I'd like to open and print all PDF files located in a given folder. The files are named according to the following pattern:
NameOfThePrinter_Timestamp.pdf
Now I want to print those files using the corresponding printer:
static void Main(string[] args)
{
string pdf = #"C:\PathToFolder";
if (Directory.GetFiles(pdf).Length > 0)
{
string[] files = Directory.GetFiles(pdf);
var adobe = Registry.LocalMachine.OpenSubKey("Software").OpenSubKey("Microsoft").OpenSubKey("Windows").OpenSubKey("CurrentVersion").OpenSubKey("App Paths").OpenSubKey("AcroRd32.exe");
var path = adobe.GetValue("");
string acrobat = path.ToString();
for (int i = 0; i < files.Length; i++)
{
Process process = new Process();
process.StartInfo.FileName = acrobat;
process.StartInfo.Verb = "printto";
process.StartInfo.Arguments = "/p /s /h \"" + files[i] + "\"";
process.StartInfo.CreateNoWindow = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.UseShellExecute = false;
process.Start();
DateTime start = DateTime.Now;
IntPtr handle = IntPtr.Zero;
while (handle == IntPtr.Zero && DateTime.Now - start <= TimeSpan.FromSeconds(2))
{
try
{
System.Threading.Thread.Sleep(50);
handle = process.MainWindowHandle;
} catch (Exception) { }
}
foreach (String verb in process.StartInfo.Verbs)
{
// Display the possible verbs.
Console.WriteLine(" {0}. {1}", i.ToString(), verb);
i++;
}
System.Threading.Thread.Sleep(10000);
Console.Out.WriteLine("File: " + files[i] + " is printing!");
process.Kill();
}
foreach (string str in files)
{
File.Delete(str);
}
Console.Out.WriteLine("Files are deleted!");
}
}
My question is: How can I pass the printer name as parameter?
Here I've tried something, but it either throws and error or prints to the default printer:
process.StartInfo.Arguments = "/p /s /h \"" + files[i] + "\"";
You can use Ghostscript to send the PDF document to the printer.
Here you can find a sample how to send the PDF document to printer: How to print PDF on default network printer using GhostScript (gswin32c.exe) shell command
And here you can find Ghostscript wrapper for .NET if you want to control Ghostscript directly without calling .exe file: http://ghostscriptnet.codeplex.com
function printDisclosureDocument() {
var doc = document.getElementById('pdfDocument');
if (doc == 'undefined' || doc == null) {
var pdfbox = document.createElement('embed');
pdfbox.type = 'application/pdf';
pdfbox.src = 'ShowPDF.aspx?refid=' + $('#MainContent_hdnRefId').val();
pdfbox.width = '1';
pdfbox.height = '1';
pdfbox.id = 'pdfDocument';
document.body.appendChild(pdfbox);
}
if (doc != null && doc != 'undefined') {
//Wait until PDF is ready to print
if (typeof doc.print === 'undefined') {
setTimeout(function () { printDisclosureDocument(); }, 500);
} else {
doc.print();
}
}
else {
setTimeout(function () { printDisclosureDocument(); }, 500);
}
}

What could be causing an IndexOutOfRange exception with this code?

Recently, I've been getting an IndexOutOfRange exception in a particular method. The new code in this function reads a "csv" file (a .txt file renamed with the extension "CSV") and parses it; so it must be code specific to that or else the data itself that is raising this exception.
But it's apparently not on the Insert into the database, because I added a MessageBox.Show() in the catch block where the insert takes place, and I never see it.
public bool PopulatePlatypusItemsListAndInsertIntoPlatypusItemsTable(frmCentral fc)
{
const int Platypus_ID_OFFSET = 0;
const int Platypus_ITEM_ID_OFFSET = 1;
const int ITEM_ID_OFFSET = 2;
const int PACKSIZE_OFFSET = 3;
bool ret = false;
try
{
string dSQL;
bool First = true;
if (File.Exists(csvFilePathName))
{
int fzz = 0;
dSQL = "DELETE FROM PlatypusItems";
try
{
dbconn.DBCommand(dSQL, true);
}
catch
{
frmCentral.listboxMessage.TopIndex = frmCentral.listboxMessage.Items.Add(Convert.ToString(++frmCentral.lstMessageCount) +
". Error processing PlatypusItem data from server");
}
SqlCeConnection conn = dbconn.GetConnection();
if (conn != null && conn.State == ConnectionState.Closed)
{
conn.Open();
}
SqlCeCommand cmd = conn.CreateCommand();
cmd.CommandText = "INSERT INTO PlatypusItems ( PlatypusID, PlatypusItemID, ItemID, PackSize) VALUES (?, ?, ?, ?)";
if (!ret)
{
ret = true;
}
PlatypusItem DuckbillItm = new PlatypusItem();
string thisLine;
string[] arrLine;
using (StreamReader sr = new StreamReader(csvFilePathName))
{
while (sr.Peek() >= 0)
{
thisLine = sr.ReadLine();
arrLine = thisLine.Split(',');
DuckbillItm.PlatypusID = arrLine[Platypus_ID_OFFSET];
DuckbillItm.PlatypusItemID = arrLine[Platypus_ITEM_ID_OFFSET];
DuckbillItm.ItemID = arrLine[ITEM_ID_OFFSET];
DuckbillItm.PackSize = Convert.ToInt32(arrLine[PACKSIZE_OFFSET]);
PlatypusItemList.List.Add(DuckbillItm);
dSQL = "INSERT INTO PlatypusItems (PlatypusID, PlatypusItemID, ItemID, PackSize) VALUES (" + DuckbillItm.PlatypusID + ",'" +
DuckbillItm.PlatypusItemID + "','" + DuckbillItm.ItemID + "'," + DuckbillItm.PackSize + ")";
if (!First)
{
cmd.Parameters[0].Value = DuckbillItm.PlatypusID;
cmd.Parameters[1].Value = DuckbillItm.PlatypusItemID;
cmd.Parameters[2].Value = DuckbillItm.ItemID;
cmd.Parameters[3].Value = DuckbillItm.PackSize.ToString();
}
if (First)
{
cmd.Parameters.Add("#PlatypusID", DuckbillItm.PlatypusID);
cmd.Parameters.Add("#PlatypusItemID", DuckbillItm.PlatypusItemID);
cmd.Parameters.Add("#ItemID", DuckbillItm.ItemID);
cmd.Parameters.Add("#PackSize", DuckbillItm.PackSize);
cmd.Prepare();
First = false;
}
if (frmCentral.CancelFetchInvDataInProgress)
{
return false;
}
try
{
// testing with these reversed: - either way, get the IndexOutOfRange exception...
//dbconn.DBCommand(cmd, dSQL, true);
dbconn.DBCommand(cmd, cmd.CommandText, true); //<-- If this works as well or better, dSQL is only there for the progress updating code below
// the first line is the legacy code; the second seems more sensible to me; both seem to work
}
catch (Exception x)
{
MessageBox.Show(string.Format("dbcommand exc message = {0}; PlatypusID = {1}; PlatypusItemID = {2}; ItemID = {3}; PackSize = {4}",
x.Message, DuckbillItm.PlatypusID, DuckbillItm.PlatypusItemID, DuckbillItm.ItemID, DuckbillItm.PackSize));//TODO: Remove
frmCentral.listboxMessage.TopIndex =
frmCentral.listboxMessage.Items.Add(Convert.ToString(++frmCentral.lstMessageCount) +
". Error processing Platypus Item data from server");
}
fzz += dSQL.Length; //<-- tried commenting this weird code out, but still get IndexOutOfRangeException
if (fzz > fc.ProgressChangedIndex)
{
fc.ProgressChangedIndex = fzz + fc.ProgressChangedIncrement;
if (((frmCentral.ProgressBar.progressBar1.Maximum/4) + (fzz*3) < frmCentral.ProgressBar.progressBar1.Maximum) &&
((frmCentral.ProgressBar.progressBar1.Maximum/4) + (fzz*3) > frmCentral.ProgressBar.progressBar1.Value))
{
frmCentral.ProgressBar.progressBar1.Value = (frmCentral.ProgressBar.progressBar1.Maximum/4) + (fzz*3);
frmCentral.ProgressBar.progressBar1.Refresh();
}
}
}
}
}
}
catch (Exception ex)
{
duckbilledPlatypiRUs.ExceptionHandler(ex, "PlatypusItemFile.PopulatePlatypusItemsListAndInsertIntoPlatypusItemsTable");
}
return ret;
}
I know this code is kind of a wacko mix of different styles; the good code is mine, and the weird code is legacy (g,d&r)
I can do this, of course, to sweep the dust under the rug:
catch (Exception ex)
{
if (ex.Message.IndexOf("IndexOutOfRange") < 0)
{
duckbilledPlatypiRUs.ExceptionHandler(ex, "PlatypusItemFile.PopulatePlatypusItemsListAndInsertIntoPlatypusItemsTable");
}
}
...but I don't know if that IndexOutOfRangeException is actually something serious that is wreaking mayhem in the innards of this app.
UPDATE
I added this code:
if (arrLine[PLATYPUS_ID_OFFSET].Length > 10) //TODO: Remove?
{
MessageBox.Show(string.Format("PLATYPUS_ID_OFFSET length should be 10; was {0}", arrLine[PLATYPUS_ID_OFFSET].Length));
arrLine[PLATYPUS_ID_OFFSET] = arrLine[PLATYPUS_ID_OFFSET].Substring(0, 10);
}
if (arrLine[PLATYPUS_ITEM_ID_OFFSET].Length > 19)
{
MessageBox.Show(string.Format("PLATYPUS_ITEM_ID_OFFSET length should be 19; was {0}", arrLine[PLATYPUS_ID_OFFSET].Length));
arrLine[PLATYPUS_ITEM_ID_OFFSET] = arrLine[PLATYPUS_ITEM_ID_OFFSET].Substring(0, 19);
}
if (arrLine[ITEM_ID_OFFSET].Length > 19)
{
MessageBox.Show(string.Format("ITEM_ID_OFFSET length should be 19; was {0}", arrLine[PLATYPUS_ID_OFFSET].Length));
arrLine[ITEM_ID_OFFSET] = arrLine[ITEM_ID_OFFSET].Substring(0, 19);
}
...and I never saw those MessageBox.Show()s, so I guess it's not the three string values that are causing the problem; perhaps the int (PackSize). PackSize would never be greater than what Int32 allows; is there a TryParse() equivalent in .NET 1.1?
UPDATE 2
I do see the "IndexOutOfRange" from the exception here, and yet never the MessageBox.Show()s:
try
{
thisLine = sr.ReadLine();
arrLine = thisLine.Split(',');
if (arrLine[PLATYPUS_ID_OFFSET].Length > 10) //TODO: Remove?
{
MessageBox.Show(string.Format("PLATYPUS_ID_OFFSET length should be 10; was {0}", arrLine[PLATYPUS_ID_OFFSET].Length));
arrLine[PLATYPUS_ID_OFFSET] = arrLine[PLATYPUS_ID_OFFSET].Substring(0, 10);
}
. . .
DuckbillItm.PLATYPUSID = arrLine[PLATYPUS_ID_OFFSET];
DuckbillItm.PLATYPUSItemID = arrLine[PLATYPUS_ITEM_ID_OFFSET];
DuckbillItm.ItemID = arrLine[ITEM_ID_OFFSET];
DuckbillItm.PackSize = Convert.ToInt32(arrLine[PACKSIZE_OFFSET]);
}
catch (Exception exc)
{
MessageBox.Show(exc.Message);
}
UPDATE 3
It was bad data, after all; some of the lines had four commas in them instead of the expected three. So, I just removed those lines (after adding code to check each element of the array for size, and trimming them prior to that) and it runs fine.
My initial guess: Probably one of the arrLine[...] lines (e.g. DuckbillItm.PlatypusID = arrLine[Platypus_ID_OFFSET]) would cause this if your input .csv file is bad. Do a debug build and put your breakpoint on the catch handler, and tell us what "ex.StackTrace" says.

Categories