Printing Too Slow 追蹤

0
Avatar
Legacy Poster

Hi I'm using Bartender to print from a Mfg Execution system, what i do is create an XML file with all the information required to print the Label, i pass the XML file to the Bartender Server and My service pick up the file, move it to a temporary location and create one different Engine for Each file, when i start the engine it consumes a lot of time, same happen when i open the Bartender Format, i already tried to use a Task to create a Queue but it is actually slower that the first method, We're printing around 20 - 30 labels per minute and every time i Start the Engine the processor goes to 100%.

We have around 180 printers and we're expecting to have more eventually and i'd like to know what is the best way to print massively on Bartender, i don't use the Commander because it's harder to manage the information for the Substrings... here is my code i hope you can help.
public void ProcessPrintData(string XMLFile)
{
System.ComponentModel.BackgroundWorker ProcessRecord = new System.ComponentModel.BackgroundWorker();
ProcessRecord.DoWork += delegate
{
Engine btEngine = new Engine(true);

try
{
//btEngine.Start();

if (btEngine.IsAlive == false)
{
btEngine.Start();
}

//Verify if file is still there
if (!File.Exists(XMLFile))
{
btEngine.Stop(SaveOptions.DoNotSaveChanges);
GC.SuppressFinalize(btEngine);
btEngine = null;
return;
}

DataSet dsFileInfo = new DataSet();
dsFileInfo.ReadXml(XMLFile);

if (HasRowsInIt(dsFileInfo) == false)
{
DeleteFile(XMLFile);
btEngine.Stop(SaveOptions.DoNotSaveChanges);
GC.SuppressFinalize(btEngine);
btEngine = null;
return;
}

if (System.IO.Path.GetExtension(dsFileInfo.Tables["Information"].Rows[0]["LabelName"].ToString()).ToUpper() != ".BTW")
{
DeleteFile(XMLFile);
btEngine.Stop(SaveOptions.DoNotSaveChanges);
GC.SuppressFinalize(btEngine);
btEngine = null;
return;
}

if (System.IO.File.Exists(dsFileInfo.Tables["Information"].Rows[0]["LabelName"].ToString()) == false)
{
DeleteFile(XMLFile);
btEngine.Stop(SaveOptions.DoNotSaveChanges);
GC.SuppressFinalize(btEngine);
btEngine = null;
return;
}

LabelFormatDocument btFormat = btEngine.Documents.Open(dsFileInfo.Tables["Information"].Rows[0]["LabelName"].ToString());
btFormat.PrintSetup.IdenticalCopiesOfLabel = int.Parse(dsFileInfo.Tables["Information"].Rows[0]["Quantity"].ToString());
btFormat.PrintSetup.PrinterName = dsFileInfo.Tables["Information"].Rows[0]["Printer"].ToString();

DataSet dsDefinition = new DataSet();
StringReader stringReader = new StringReader(btFormat.SubStrings.XML);
dsDefinition.ReadXml(stringReader);

if (HasRowsInIt(dsDefinition))
{
for (int i = 0; i < dsDefinition.Tables[0].Rows.Count; i++)
{
string strValue = "";
for (int j = 0; j < dsFileInfo.Tables["Values"].Rows.Count; j++)
{
if (dsFileInfo.Tables["Values"].Rows[j]["FieldName"].ToString() == dsDefinition.Tables[0].Rows[i]["Name"].ToString())
{
strValue = dsFileInfo.Tables["Values"].Rows[j]["PrintValue"].ToString();
j = dsFileInfo.Tables["Values"].Rows.Count;
}
}

btFormat.SubStrings[dsDefinition.Tables[0].Rows[i]["Name"].ToString()].Value = strValue;
}
}
else
{

}

if (dsDefinition != null)
{
dsDefinition.Dispose();
dsDefinition = null;
}


int waitForCompletionTimeout = 5; // 5 seconds
Messages messages;
Result result = btFormat.Print(System.IO.Path.GetFileName(XMLFile), waitForCompletionTimeout, out messages);
string messageString = "";

if (result != Result.Success)
{
messageString = "";
foreach (Seagull.BarTender.Print.Message message in messages)
{
messageString += "\n\n" + message.Text;
}
}

if (messageString != "")
{

}

// Stop the BarTender print engine

dsFileInfo.Dispose();
dsFileInfo = null;

DeleteFile(XMLFile);

GC.SuppressFinalize(btFormat);
btFormat = null;

btEngine.ActiveDocument.Close(SaveOptions.DoNotSaveChanges);

btEngine.Stop(SaveOptions.DoNotSaveChanges);
GC.SuppressFinalize(btEngine);
btEngine = null;
return;
}
catch (Exception ex)
{

if (File.Exists(XMLFile))
{
DeleteFile(XMLFile);
}

GC.SuppressFinalize(btEngine);
btEngine = null;

}



};

ProcessRecord.RunWorkerAsync();

}

static void DeleteFile(string File)
{
try
{
System.IO.File.Delete(File);
}
catch (Exception ex)
{
//
}
}
static bool HasRowsInIt(DataSet dsObject)
{
if (dsObject == null)
{
return false;
}
else if (dsObject.Tables.Count <= 0)
{
return false;
}
else if (dsObject.Tables[0].Rows.Count >= 1)
{
return true;
}
else
{
return false;
}

}

3 意見

0
Avatar
Shotaro Ito
評論操作 永久連結

Hi Gabriel,
Starting bartender print engine takes long time and costs lot of IO and CPU, so it's not suitble for server-side printing when you start / stop print engine for every print job.
Which edition of BarTender do you use?

If you use BarTender Enterprise Automation (or Enterprise print server for 9.01 - 9.2), you have another option - BarTender XML Script and Commander.
Commander's XML can take substring data by <NamedSubstring> tag. Below's a simple BarTender XML Script to print a label.
[xml]<?xml version="1.0" encoding="utf-8"?>
<XMLScript Version="2.0">
<Command Name="Job1">
<Print>
<Format>c:\labels\Label1.btw</Format>
<PrintSetup>
<Printer>HP LaserJet</Printer>
</PrintSetup>
<NamedSubString Name="Product">
<Value>Chai Tea</Value>
</NamedSubString>
<NamedSubString Name="Price">
<Value>$18.00</Value>
</NamedSubString>
</Print>
</Command>
</XMLScript>
[/xml]
You may be able to transform your current XML data to BarTender XML Script using XSL Transform command in Commander task.
Alternatively, there's .net Print Server SDK too - that's Task-Queue approach would also match with your situation.

If you use BarTender Automation Edition (or Enterprise for 9.01 - 9.2), I truly recommend to upgrade to Enterprise Automation edition, and use Commander or use .net Print Server SDK's task based approach.
0
Avatar
Legacy Poster
評論操作 永久連結

Hi, Thanks for your reply, how do i use the transform method? do you have a brief sample?

Regards!
0
Avatar
Shotaro Ito
評論操作 永久連結

XSL Transform can be used from Commander Task option's Command tab > Command Type.
After transform, you can use BTXML Script command to send transformed xml to BarTender.
BarTender returns BTXML Response by default, so Save BTXML Response to file so you can find any error happens.

A primitive XSL to transform

source trigger file
[xml]<?xml version="1.0" encoding="utf-8"?>
<printCommands>
<label>
<labeltype>c:\Commander\formats\XSL.btw</labeltype>
<printerName>TEC B-458</printerName>
<copies>2</copies>
<data Name="SUBSTRING1">Apple</data>
<data Name="SUBSTRING2">3950</data>
</label>
</printCommands>[/xml]

XSL
[xml]<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="utf-8"/>

<xsl:template match="/">
<XMLScript Version="2.0">
<Command Name="Job1">
<xsl:for-each select="printCommands/label">
<Print>
<Format><xsl:value-of select="labeltype"/></Format>
<PrintSetup>
<xsl:apply-templates select="printerName"/>
<xsl:apply-templates select="copies"/>
</PrintSetup>
<xsl:for-each select="data">
<NamedSubString>
<xsl:attribute name="Name"><xsl:value-of select="@Name" /></xsl:attribute>
<Value><xsl:value-of select="."/></Value>
</NamedSubString>
</xsl:for-each>
</Print>
</xsl:for-each>
</Command>
</XMLScript>
</xsl:template>

<xsl:template match="printerName">
<Printer><xsl:value-of select="."/></Printer>
</xsl:template>

<xsl:template match="copies">
<IdenticalCopiesOfLabel><xsl:value-of select="."/></IdenticalCopiesOfLabel>
</xsl:template>

</xsl:stylesheet>[/xml]

Transformed result
[xml]
<?xml version="1.0"?>
<XMLScript Version="2.0">
<Command Name="Job1">
<Print>
<Format>c:\Commander\formats\XSL.btw</Format>
<PrintSetup>
<Printer>TEC B-458</Printer>
<IdenticalCopiesOfLabel>2</IdenticalCopiesOfLabel>
</PrintSetup>
<NamedSubString Name="SUBSTRING1">
<Value>Apple</Value>
</NamedSubString>
<NamedSubString Name="SUBSTRING2">
<Value>3950</Value>
</NamedSubString>
</Print>
</Command>
</XMLScript>
[/xml]

BTXML Response
[xml]<?xml version="1.0" encoding="utf-16"?>
<Response Version="2.0" AppName="BarTender" AppVersion="10.0" AppVersionId="1000" AppVersionMajor="10" AppVersionMinor="0" AppVersionBuild="2821" AppInstancePid="4752" AppInstanceGuid="{A82120EB-915E-44FC-AB7B-E277E07BB6EC}">
<User>MYPC\user</User>
<Server>MYPC</Server>
<Command Name="Job1">
<Print ID="12" GUID="{2E4FE7D7-000A-4424-8C0D-5D32C927E73E}" JobLastStatus="Queued" JobCompleted="true" JobName="XSL.btw">
<JobStatus Completed="true">
<TimeJobStart>2012-05-24T13:37:23.405</TimeJobStart>
<TimeJobQueued>2012-05-24T13:37:23.577</TimeJobQueued>
<TimeJobSent>2012-05-24T13:37:23.577</TimeJobSent>
<LastStatus>Queued</LastStatus>
<Description>Print job now waiting to be sent to printer.</Description>
</JobStatus>
<Message Id="1750" Guid="{6A577D13-19E0-4125-B6E2-2EE7114E6072}" Severity="Information" Category="Printing" Response="OK">
<Text>BarTender successfully sent the print job to the spooler.

Job Name: XSL.btw
Document: XSL.btw
Printer: TEC B-458</Text>
</Message>
</Print>
</Command>
</Response>
[/xml]

How the task looks like:
[attachment=229:XSL.png]

For how to write BarTender XML Script and how to read XML Response, please read BarTender's online help > Automating BarTender > Automation with BarTender XML Script.

For how to write XSL, please look at some web sites like...
www.w3schools.com/xsl/

登入寫評論。