[C# MS V10.16.02.34] IPrintset.Publish crashes when plotting PNG with WorkerMicroStation

I have implemented the IPrintManager code example from the MSTNPlatformNET.chm for plotting using an existing PltCfgFile

The code for this is almost verbatim except that I load the PNG driver instead of the PDF driver, and that I've set publishingParams.UseSeparateJobs = true where in the example this is false (Png plot doesn't support batch jobs):

void IPrintManagerDocsExample()
{
    IPrintManager printManager = PrintManagerProxy.GetLocalPrintManager();

    IPrinter printer = printManager.CreatePrinter();
    printer.InitializeFromPltcfgFile(new FileSpec(@"c:\png.pltcfg"));

    IPrinterForm printerFormAnsiA = printer.FindFormByName("ANSI A");

    IPrintSet printSet = printManager.CreatePrintSet();
    printSet.InitializeFromPrinter(printer);
    printSet.UseWorkerMicroStation = false; //The magic sauce that makes MicroStation not crash

    IPrintDefinition[] printDefinitions = printSet.CreatePrintDefinitions(new FileSpec(Session.Instance.GetActiveDgnFile().GetFileName()), null);

    foreach (IPrintDefinition printDefinition in printDefinitions)
    {
        ICadPrintDefinition cadPrintDefinition = printDefinition as ICadPrintDefinition;
        cadPrintDefinition.PrinterForm = printerFormAnsiA;
        cadPrintDefinition.Maximize();
    }

    IFolder folder = printSet.CreateFolder(@"TempFolder");
    printSet.Items.Add(folder);

    folder.Items.AddRange(printDefinitions);

    PublishingParams publishingParams = new PublishingParams();

    publishingParams.UseSeparateJobs = true;
    publishingParams.OutputFspec = new FileSpec(@"C:\temp\TestMethod.png", true);
    printSet.Publish(publishingParams);

    printSet.Close();
    printer.Release();
}

And the png.pltcfg (created using the Edit printer driver configurartion):

<PrinterConfiguration xmlns="PrinterConfiguration.01.04">
    <DisplayLabel>SEED_PNG</DisplayLabel>
    <Visible>1</Visible>
    <BorderIncludeFileName>False</BorderIncludeFileName>
    <BorderOutlineIsOn>True</BorderOutlineIsOn>
    <LORIPJpegQuality>75</LORIPJpegQuality>
    <Programs />
    <HonorRasterTransparency>2</HonorRasterTransparency>
    <ResolutionUnits>6</ResolutionUnits>
    <BorderIncludeDateTime>False</BorderIncludeDateTime>
    <ScaleAdjustmentFactor>1,1,0</ScaleAdjustmentFactor>
    <EnableOutputWidth>2</EnableOutputWidth>
    <DefaultLineCap>1</DefaultLineCap>
    <RasterParametersMonoAsIs>False</RasterParametersMonoAsIs>
    <MoveMode>2</MoveMode>
    <StartPlotAction>0</StartPlotAction>
    <DriverOutputMode>0</DriverOutputMode>
    <DefaultPrintFileExtension>png</DefaultPrintFileExtension>
    <BorderIncludeModelName>False</BorderIncludeModelName>
    <BorderPen>1</BorderPen>
    <RasterParametersQuality>100</RasterParametersQuality>
    <Commands />
    <OleParametersRasterize>2</OleParametersRasterize>
    <RasterizeUsingBands>2</RasterizeUsingBands>
    <BorderTextHeightCM>0.254</BorderTextHeightCM>
    <FontMaps />
    <FenceOutlineIsOn>False</FenceOutlineIsOn>
    <CropRasterTransparency>2</CropRasterTransparency>
    <EndPlotAction>0</EndPlotAction>
    <SymbolAssigns />
    <EnableDriverClipping>2</EnableDriverClipping>
    <BorderTextOffsetCM>0,0,0</BorderTextOffsetCM>
    <Styles>
        <Style>
            <NoHardware>False</NoHardware>
            <RunLengths>0.35 1.05</RunLengths>
            <Units>4</Units>
        </Style>
        <Style>
            <NoHardware>False</NoHardware>
            <RunLengths>1.75 1.05</RunLengths>
            <Units>4</Units>
        </Style>
        <Style>
            <NoHardware>False</NoHardware>
            <RunLengths>4.2 1.4</RunLengths>
            <Units>4</Units>
        </Style>
        <Style>
            <NoHardware>False</NoHardware>
            <RunLengths>2.8 1.05 0.7 1.05</RunLengths>
            <Units>4</Units>
        </Style>
        <Style>
            <NoHardware>False</NoHardware>
            <RunLengths>1.4 1.4</RunLengths>
            <Units>4</Units>
        </Style>
        <Style>
            <NoHardware>False</NoHardware>
            <RunLengths>2.1 0.7 0.7 0.7 0.7 0.7</RunLengths>
            <Units>4</Units>
        </Style>
        <Style>
            <NoHardware>False</NoHardware>
            <RunLengths>2.8 0.7 1.4 0.7</RunLengths>
            <Units>4</Units>
        </Style>
    </Styles>
    <DefaultNumCopies>1</DefaultNumCopies>
    <LevelOfDetailMode>1</LevelOfDetailMode>
    <RasterParametersPrintRaster>True</RasterParametersPrintRaster>
    <ResolutionDotsPerUnit>100,100,0</ResolutionDotsPerUnit>
    <AutoOpenPlotFile>False</AutoOpenPlotFile>
    <DefaultColorMode>2</DefaultColorMode>
    <CustomProperties />
    <ColorMaps>
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap />
        <ColorMap>
            <UseDesignBackgroundColor>True</UseDesignBackgroundColor>
        </ColorMap>
    </ColorMaps>
    <SupportsPaths>2</SupportsPaths>
    <BorderWidthCM>0.025</BorderWidthCM>
    <StrokeRaster>2</StrokeRaster>
    <RasterParametersContrast>0</RasterParametersContrast>
    <DefaultPrintFileAutoOverwrite>False</DefaultPrintFileAutoOverwrite>
    <FenceOutlinePen>1</FenceOutlinePen>
    <PlotterModel>loriprgb</PlotterModel>
    <AutoCenter>False</AutoCenter>
    <Forms>
        <Form>
            <DisplayName>ISO A0</DisplayName>
            <Size>1189,841,0</Size>
            <Units>4</Units>
        </Form>
        <Form>
            <DisplayName>ISO A1</DisplayName>
            <Size>841,594,0</Size>
            <Units>4</Units>
        </Form>
        <Form>
            <DisplayName>ISO A2</DisplayName>
            <Size>594,420,0</Size>
            <Units>4</Units>
        </Form>
        <Form>
            <DisplayName>ISO A3</DisplayName>
            <Size>420,297,0</Size>
            <Units>4</Units>
        </Form>
        <Form>
            <DisplayName>ISO A4</DisplayName>
            <Size>297,210,0</Size>
            <Units>4</Units>
        </Form>
        <Form>
            <DisplayName>Arch E1</DisplayName>
            <Size>42,30,0</Size>
            <Units>6</Units>
        </Form>
        <Form>
            <DisplayName>Arch E</DisplayName>
            <Size>48,36,0</Size>
            <Units>6</Units>
        </Form>
        <Form>
            <DisplayName>Arch D</DisplayName>
            <Size>36,24,0</Size>
            <Units>6</Units>
        </Form>
        <Form>
            <DisplayName>Arch C</DisplayName>
            <Size>24,18,0</Size>
            <Units>6</Units>
        </Form>
        <Form>
            <DisplayName>Arch B</DisplayName>
            <Size>18,12,0</Size>
            <Units>6</Units>
        </Form>
        <Form>
            <DisplayName>Arch A</DisplayName>
            <Size>12,9,0</Size>
            <Units>6</Units>
        </Form>
        <Form>
            <DisplayName>ANSI E</DisplayName>
            <Size>44,34,0</Size>
            <Units>6</Units>
        </Form>
        <Form>
            <DisplayName>ANSI D</DisplayName>
            <Size>34,22,0</Size>
            <Units>6</Units>
        </Form>
        <Form>
            <DisplayName>ANSI C</DisplayName>
            <Size>22,17,0</Size>
            <Units>6</Units>
        </Form>
        <Form>
            <DisplayName>ANSI B</DisplayName>
            <Size>17,11,0</Size>
            <Units>6</Units>
        </Form>
        <Form>
            <DisplayName>ANSI A</DisplayName>
            <Size>11,8.5,0</Size>
            <Units>6</Units>
        </Form>
        <Form>
            <DisplayName>1280X1024</DisplayName>
            <Size>12.8,10.24,0</Size>
            <Units>6</Units>
        </Form>
        <Form>
            <DisplayName>1024X768</DisplayName>
            <Size>10.24,7.68,0</Size>
            <Units>6</Units>
        </Form>
        <Form>
            <DisplayName>800X600</DisplayName>
            <Size>8,6,0</Size>
            <Units>6</Units>
        </Form>
        <Form>
            <DisplayName>640X480</DisplayName>
            <Size>6.4,4.8,0</Size>
            <Units>6</Units>
        </Form>
        <Form>
            <DisplayName>MAX</DisplayName>
            <Size>16,16,0</Size>
            <Units>6</Units>
        </Form>
    </Forms>
    <LORIPFormat>2</LORIPFormat>
    <RasterParametersGrayscale>False</RasterParametersGrayscale>
    <WeightMaps>
        <WeightMap>
            <Width>0.169</Width>
            <Units>4</Units>
        </WeightMap>
        <WeightMap>
            <Width>0.375</Width>
            <Units>4</Units>
        </WeightMap>
        <WeightMap>
            <Width>0.5</Width>
            <Units>4</Units>
        </WeightMap>
        <WeightMap>
            <Width>0.625</Width>
            <Units>4</Units>
        </WeightMap>
        <WeightMap>
            <Width>0.75</Width>
            <Units>4</Units>
        </WeightMap>
        <WeightMap>
            <Width>0.875</Width>
            <Units>4</Units>
        </WeightMap>
        <WeightMap>
            <Width>1</Width>
            <Units>4</Units>
        </WeightMap>
        <WeightMap>
            <Width>1.125</Width>
            <Units>4</Units>
        </WeightMap>
        <WeightMap>
            <Width>1.25</Width>
            <Units>4</Units>
        </WeightMap>
        <WeightMap>
            <Width>1.375</Width>
            <Units>4</Units>
        </WeightMap>
        <WeightMap>
            <Width>1.5</Width>
            <Units>4</Units>
        </WeightMap>
        <WeightMap>
            <Width>1.625</Width>
            <Units>4</Units>
        </WeightMap>
        <WeightMap>
            <Width>1.75</Width>
            <Units>4</Units>
        </WeightMap>
        <WeightMap>
            <Width>1.875</Width>
            <Units>4</Units>
        </WeightMap>
        <WeightMap>
            <Width>2</Width>
            <Units>4</Units>
        </WeightMap>
        <WeightMap>
            <Width>2.125</Width>
            <Units>4</Units>
        </WeightMap>
        <WeightMap>
            <Width>2.25</Width>
            <Units>4</Units>
        </WeightMap>
        <WeightMap>
            <Width>2.375</Width>
            <Units>4</Units>
        </WeightMap>
        <WeightMap>
            <Width>2.5</Width>
            <Units>4</Units>
        </WeightMap>
        <WeightMap>
            <Width>2.625</Width>
            <Units>4</Units>
        </WeightMap>
        <WeightMap>
            <Width>2.75</Width>
            <Units>4</Units>
        </WeightMap>
        <WeightMap>
            <Width>2.875</Width>
            <Units>4</Units>
        </WeightMap>
        <WeightMap>
            <Width>3</Width>
            <Units>4</Units>
        </WeightMap>
        <WeightMap>
            <Width>3.125</Width>
            <Units>4</Units>
        </WeightMap>
        <WeightMap>
            <Width>3.25</Width>
            <Units>4</Units>
        </WeightMap>
        <WeightMap>
            <Width>3.375</Width>
            <Units>4</Units>
        </WeightMap>
        <WeightMap>
            <Width>3.5</Width>
            <Units>4</Units>
        </WeightMap>
        <WeightMap>
            <Width>3.625</Width>
            <Units>4</Units>
        </WeightMap>
        <WeightMap>
            <Width>3.75</Width>
            <Units>4</Units>
        </WeightMap>
        <WeightMap>
            <Width>3.875</Width>
            <Units>4</Units>
        </WeightMap>
        <WeightMap>
            <Width>4</Width>
            <Units>4</Units>
        </WeightMap>
        <WeightMap>
            <Width>4.125</Width>
            <Units>4</Units>
        </WeightMap>
    </WeightMaps>
    <DefaultPrintFileExtensionAutoIncrement>False</DefaultPrintFileExtensionAutoIncrement>
    <ReplaceTransMaskWithTransColor>2</ReplaceTransMaskWithTransColor>
    <DefaultLineJoin>4</DefaultLineJoin>
    <CurveTolerance>1</CurveTolerance>
    <RasterParametersBrightness>0</RasterParametersBrightness>
    <DefaultPrintFileName>$(MS_PLTFILES)$(basename(_DGNFILE))-$(MS_PLTMODELNAME)<autoInc?prefix=-?digits=3?base=0></DefaultPrintFileName>
    <RollOrientation>0</RollOrientation>
    <PlotTo3D>False</PlotTo3D>
    <MinimumLevelOfDetail>3</MinimumLevelOfDetail>
    <BorderIsOn>False</BorderIsOn>
    <AutoRotateDir>1</AutoRotateDir>
    <MaximumMiterAngleDeg>90</MaximumMiterAngleDeg>
    <VersionMajor>1</VersionMajor>
    <OptimizeRasterColorDepth>2</OptimizeRasterColorDepth>
    <MergeBackgroundRasters>1</MergeBackgroundRasters>
    <PrintPoints>True</PrintPoints>
    <VersionMinor>4</VersionMinor>
    <Driver>LORIP</Driver>
    <Comments>SEED</Comments>
    <DefaultPenTableFileName xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true" />
    <DefaultDesignScriptFileName xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true" />
    <PrintStyleName xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true" />
    <LORIPfullSheet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true" />
    <RequiredOrientation>0</RequiredOrientation>
</PrinterConfiguration>


When running this code printSet.Publish(publishingParams); gets executed and will start publishing, however after a couple of seconds the following exceptions gets thrown, crashing the running MicroStation instance:
System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'

This exception was originally thrown at this call stack:
    Bentley.MstnPlatformNET.Print.PrintFoundation.OutputToMessageCenter(Bentley.MstnPlatformNET.Print.IUserMessage)
    Bentley.MstnPlatformNET.Print.PrintSet.InvokeUserMessageEvent(Bentley.MstnPlatformNET.Print.IUserMessage)
    Bentley.MstnPlatformNET.Print.MicroStationEngine.InvokeUserMessageEvent(Bentley.MstnPlatformNET.Print.IUserMessage)
    System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(object, object[], out object[])
    System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(ref System.ServiceModel.Dispatcher.MessageRpc)
    System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(ref System.ServiceModel.Dispatcher.MessageRpc)
    System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(ref System.ServiceModel.Dispatcher.MessageRpc)
    System.ServiceModel.Dispatcher.MessageRpc.Process(bool)
    System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump(System.ServiceModel.Channels.RequestContext, bool, System.ServiceModel.OperationContext)
    System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(System.ServiceModel.Channels.RequestContext, System.ServiceModel.OperationContext)
    ...
    [Call Stack Truncated]

Looking at the running processes I can see that a MicroStation process is still running. If I don't interrupt this process and wait about a minute the plot will still be generated, despite the crash of the initial instance.

When I use the Pdf driver this behavior doesn't happen.

If I change the code creating the PrintSet to include the line printSet.UseWorkerMicroStation = false; after initialization of the PrintSet, MicroStation will not crash and create the plot using the current MicroStation instance.

Is this a bug within the printing classes, or some weird incompatibility between my Png PltCfg and the plotter?

Regards,
Remy

This is a continuation of a previous question asked here: [CE 10.16.02.34] C# equivalent of PrintDescriptionRef - MicroStation Programming Forum - MicroStation Programming - Bentley Communities

Parents
  • When publishing with UseSeparateJob=False, in the general sense multiple print output files will be created.  When invoking Publish(), the application only has control of the output folder.  The output file names within that folder are generated by the product using the PrintSet.OutputFileNameExpression value.

     

    The relevant documentation in PublishingParams:

     

    /*------------------------------------------------------------------------------------**/

    /// <summary>The output file specification, when publishing either a print set or a

    /// single print definition as a set to a file.</summary>

    /// <remarks>This property is required when printing a set to a single output file.

    /// It is ignored when publishing as separate jobs.</remarks>

    /*-------------------------------------------------------------------------------------*/

    public FileSpec OutputFspec

     

    /*------------------------------------------------------------------------------------**/

    /// <summary>The output folder specification, when publishing multiple definitions as

    /// separate files to a folder.</summary>

    /// <remarks>If printing definitions as separate files, this property specifies in

    /// which folder the files will be placed (unless the option of printing to the source

    /// folder is specified.  If this property is null, MS_PLTFILES is used.</remarks>

    /*-------------------------------------------------------------------------------------*/

    public FolderSpec OutputFolderSpec

     

    Just eyeballing your code, it appears you are instructing the product to create separate output files but not specifying a destination folder.  The documentation says that in that case, the MS_PLTFILES folder will be used.  Perhaps that fallback path is defective, or perhaps your value of that variable is causing problems when evaluated in the context of the background worker process.  As an experiment, try setting the PublishingParams.OutputFolderSpec property to a fully-qualified folder path.

     

    Also as an experiment, you can try other printer driver configurations such as tiff.pltcfg, cals.pltcfg, hpglrtl.pltcfg, etc. to see if your exception is the specific to the less-commonly-used LORIP printer driver.

          
    .

  • Andrew,

    Specifying an OutputFolderSpec using a fully qualified folder path yields the same results as when I'm using the default path (besides the output path changing).


    I've tried a bunch of different configs, the results varying per setup. If we use the setup as described in the documentation where we run on a worker instance and have UseSeperateJobs = false:

    void IPrintManagerDocsExample()
    {
        IPrintManager printManager = PrintManagerProxy.GetLocalPrintManager();
    
        IPrinter printer = printManager.CreatePrinter();
        printer.InitializeFromPltcfgFile(new FileSpec(@"C:\Program Files\Bentley\MicroStation CONNECT Edition\MicroStation\Default\pltcfg\pdf.pltcfg")); //Exchange for any of the plot configs
    
        IPrinterForm printerFormAnsiA = printer.FindFormByName("ANSI A");
    
        IPrintSet printSet = printManager.CreatePrintSet();
        printSet.InitializeFromPrinter(printer);
    
        IPrintDefinition[] printDefinitions = printSet.CreatePrintDefinitions(new FileSpec(Session.Instance.GetActiveDgnFile().GetFileName()), null);
    
        foreach (IPrintDefinition printDefinition in printDefinitions)
        {
            ICadPrintDefinition cadPrintDefinition = printDefinition as ICadPrintDefinition;
            cadPrintDefinition.PrinterForm = printerFormAnsiA;
            cadPrintDefinition.Maximize();
        }
    
        IFolder folder = printSet.CreateFolder(@"TempFolder");
        printSet.Items.Add(folder);
    
        folder.Items.AddRange(printDefinitions);
    
        PublishingParams publishingParams = new PublishingParams();
    
        publishingParams.UseSeparateJobs = false;
        publishingParams.OutputFspec = new FileSpec(@"C:\temp\TestPlot." + printer.DefaultExtension, true);
        printSet.Publish(publishingParams);
    
        printSet.Close();
        printer.Release();
    }


    The results are as followed:
    PltCfg     | SeperateJobs | Result
    -----------|--------------|--------
    png        | false        | N/A
    jpeg       | false        | N/A
    tiff       | false        | N/A
    cals       | false        | N/A
    hpgl2      | false        | N/A
    hpglrtl    | false        | N/A
    Markup_pdf | false        | Works
    pdfnongeo  | false        | Works
    pdf        | false        | Works

    (Note that N/A indicates that the plot won't run because UseSeperateJobs = false is not supported, throwing a nullReference exception when Publish gets called)

    If we now set UseSeperateJobs = true and use an OutputFolderSpec rather than OutputFSpec we get the following code:
    void IPrintManagerDocsExample()
    {
        IPrintManager printManager = PrintManagerProxy.GetLocalPrintManager();
    
        IPrinter printer = printManager.CreatePrinter();
        printer.InitializeFromPltcfgFile(new FileSpec(@"C:\Program Files\Bentley\MicroStation CONNECT Edition\MicroStation\Default\pltcfg\png.pltcfg"));//Exchange for any of the plot configs
    
        IPrinterForm printerFormAnsiA = printer.FindFormByName("ANSI A");
    
        IPrintSet printSet = printManager.CreatePrintSet();
        printSet.InitializeFromPrinter(printer);
    
        IPrintDefinition[] printDefinitions = printSet.CreatePrintDefinitions(new FileSpec(Session.Instance.GetActiveDgnFile().GetFileName()), null);
    
        foreach (IPrintDefinition printDefinition in printDefinitions)
        {
            ICadPrintDefinition cadPrintDefinition = printDefinition as ICadPrintDefinition;
            cadPrintDefinition.PrinterForm = printerFormAnsiA;
            cadPrintDefinition.Maximize();
        }
    
        IFolder folder = printSet.CreateFolder(@"TempFolder");
        printSet.Items.Add(folder);
    
        folder.Items.AddRange(printDefinitions);
    
        PublishingParams publishingParams = new PublishingParams();
    
        publishingParams.UseSeparateJobs = true;
        publishingParams.OutputFolderSpec = new FolderSpec(@"C:\Temp\");
        printSet.Publish(publishingParams);
    
        printSet.Close();
        printer.Release();
    }


    We get a situation where none of the plots will run, including the previously working PDF plots. Failing with the System.AccessViolationException as explained above:
    PltCfg     | SeperateJobs | Result
    -----------|--------------|--------
    png        | false        | Crashes
    jpeg       | false        | Crashes
    tiff       | false        | Crashes
    cals       | false        | Crashes
    hpgl2      | false        | Crashes
    hpglrtl    | false        | Crashes
    Markup_pdf | false        | Crashes
    pdfnongeo  | false        | Crashes
    pdf        | false        | Crashes


    Now when we add the line printSet.UseWorkerMicroStation = false to the above code (so using UseSeperateJobs = true) to force the plotter to work on the current MicroStation instance all the plot configs will work:
    PltCfg     | SeperateJobs | Result
    -----------|--------------|--------
    png        | false        | Works
    jpeg       | false        | Works
    tiff       | false        | Works
    cals       | false        | Works
    hpgl2      | false        | Works
    hpglrtl    | false        | Works
    Markup_pdf | false        | Works
    pdfnongeo  | false        | Works
    pdf        | false        | Works



    So in short it looks like:
    publishingParams.UseSeparateJobs = false works for non LORIP printers using non-seperated jobs in both a worker and main instance of MicroStation
    publishingParams.UseSeparateJobs = true and an OutputFolderSpec doesn't work at all when using a worker instance of MicroStation
    publishingParams.UseSeparateJobs = true and setting UseWorkerMicroStation = false works for all printer drivers.

    As Robert Hook suggested I'll also make a full memory dump and send it. 

     

  • I've tried a bunch of different configs, the results varying

    Good analysis.  If only everyone could be as thorough!

     
    Regards, Jon Summers
    LA Solutions

  • I was able to reproduce your findings, but unfortunately not able to determine a cause.  It appears to be a defect in MicroStation.

     

    Using MicroStation 10.16.2 and its SDK, I modified the PrintSet.cpp sample to read as below.  Basically I commented out the print style stuff, replaced with printer driver configuration with "png.pltcfg", and for good measure (not required but wanted to be sure) commented out the UseSeparateJobs=False path.

     

    The result should be a single PNG created in the MS_PLTFILES folder, and as you observed, that PNG is created but the worker MicroStation processes crashes shortly thereafter.

     

    I did find a crash dump file to analyze, which indicated a memory access violation trying to make a cross-process call to write a message to the interactive process's Message Center.  The crash doesn't appear to be due to any flaw in the sample code nor any part of the MicroStation printing system that I still recognize.

     

    Alas that's as much help as I can provide.  I'm no longer in a position where I can build a debug MicroStation or dive deeper to figure out what's different between what the sample program is doing versus Print Organizer.  Something involving control over the MicroStation user interface perhaps.

     

    All I can suggest is logging a service ticket, and/or

     

    (a) use the longstanding, well-tested native-code mdlPlotDesc API to create individual plot files from the active design file inside the interactive process,

    (b) use the longstanding, well-tested plotdlg.ma "print" keyins which is the most common way to automate the MicroStation printing system for non-set printing,

    (c) use Print Organizer keyins if printing as a set or heterogeneous WorkSets are required, or

    (d) use the .NET Print API with UseWorkerMicroStation=False although I'm somewhat leery of that because that path is not as well exercised and it would be easier to run into unsupported/untested conditions.

     

     

    /*--------------------------------------------------------------------------------------+
    |
    |     $Source: MstnExamples/Printing/PrintSet/PrintSet.cpp $
    |
    |  $Copyright: (c) 2015 Bentley Systems, Incorporated. All rights reserved. $
    |
    |   This example demonstates use of the .NET Print API to programatically compose and
    |   publish a print set (PSET) consisting of fixed print definition(s) for the active
    |   design file.
    |
    +--------------------------------------------------------------------------------------*/
    #include <Mstn\MdlApi\MdlApi.h>
    
    #pragma managed
    
    #using <System.dll>
    #using <Bentley.PrintAPI.dll>
    #using <Bentley.DgnPlatformNET.dll>
    
    using namespace System::IO;
    using namespace System::Collections::Generic;
    
    using namespace Bentley::MstnPlatformNET::Print;
    
    namespace BD = Bentley::DgnPlatform;
    
    /*---------------------------------------------------------------------------------**//**
    * @bsiclass
    +--------------------------------------------------------------------------------------*/
    struct ScopedSuccessMessage
        {
        bool IsSuccess;
        
        ScopedSuccessMessage() { IsSuccess = false; }
    
        ~ScopedSuccessMessage()
            {
            if (IsSuccess)
                {
                mdlOutput_messageCenter (BD::OutputMessagePriority::Info,
                                         L"PRINTSET succeeded.", NULL, BD::OutputMessageAlert::None);
                }
            else
                {
                mdlOutput_messageCenter (BD::OutputMessagePriority::Error,
                                         L"PRINTSET failed.", NULL, BD::OutputMessageAlert::None);
                }
            }
        };
    
    /*---------------------------------------------------------------------------------**//**
    * @bsiclass
    +--------------------------------------------------------------------------------------*/
    public ref class ScopedPrinter sealed
        {
    private:
        IPrinter^ m_printer;
    
        void init() { m_printer = nullptr; }
        void close() { if (m_printer) m_printer->Release(); m_printer = nullptr; }
    
    public:
        ScopedPrinter() { init(); }
        ~ScopedPrinter() { close(); }
        IPrinter^ get() { return m_printer; }
        void set (IPrinter^ value) { m_printer = value; }
        void clear() { init(); }
        };
    
    /*---------------------------------------------------------------------------------**//**
    * @bsiclass
    +--------------------------------------------------------------------------------------*/
    public ref class ScopedPrintSet sealed
        {
    private:
        IPrintSet^ m_printSet;
    
        void init() { m_printSet = nullptr; }
        void close() { if (m_printSet) m_printSet->Close(); m_printSet = nullptr; }
    
    public:
        ScopedPrintSet() { init(); }
        ~ScopedPrintSet() { close(); }
        IPrintSet^ get() { return m_printSet; }
        void set (IPrintSet^ value) { m_printSet = value; }
        void clear() { init(); }
        };
    
    /*---------------------------------------------------------------------------------**//**
    * @bsimethod                                                              Bentley Systems
    +--------------------------------------------------------------------------------------*/
    extern "C" DLLEXPORT void MdlMain (int argc, WCharCP argv[])
        {
        mdlOutput_messageCenter (BD::OutputMessagePriority::Info, L"PRINTSET starting...", NULL, BD::OutputMessageAlert::None);
    
        ScopedSuccessMessage scopedSuccessMessage;
    
        //
        // This example assumes that the WorkSet contains a print style called either "PDF" or "PDF (full size)".
        //
        /* System::String^ usePrintStyleName1 = "PDF";
        System::String^ usePrintStyleName2 = "PDF (full size)"; */
    
        //
        // Print definitions for any valid source file may be added to the print set,
        // not just the active design file.  We use the active design file here for convenience.
        //
        BeFileName activeDgnFileName (tcb->dgnfilenm);
    
        //
        // The PrintAPI works with FileSpec objects, which encapsulate a universal file specification (UFS),
        // a host file specification (HFS) and a DMS moniker string.  The UFS may be a ProjectWise URL or a
        // partially-specified local file on disk.  The HFS is a string suitable to be given to fopen,
        // and is usually fully qualified.  A valid FileSpec must contain at least the UFS; the HFS and moniker
        // strings may be searched for and filled in later.
        //
        FileSpec^ activeDgnFspec = gcnew FileSpec (gcnew System::String (activeDgnFileName.c_str()));
    
        //
        // These stack variables ensure that the managed objects they contain are released before they are disposed.
        // It's important that the native resources owned by the managed objects be disposed on the same thread in
        // which they were created, e.g. they cannot be released by the garbage collection thread.
        //
        ScopedPrinter scopedPrinter;
        ScopedPrintSet scopedPrintSet;
    
        //
        // Everything involving the .NET Print API starts with the IPrintManager interface.
        //
        IPrintManager^ printManager = PrintManagerProxy::GetLocalPrintManager();
        if (nullptr == printManager)
            return;
    
        //
        // Look up the print style to use.
        //
        /* IPrintStyleManager^ printStyleManager = printManager->CreatePrintStyleManager();
        if (nullptr == printStyleManager)
            return;
    
        IPrintStyle^ printStyle = printStyleManager->GetPrintStyleByName (usePrintStyleName1);
        if (nullptr == printStyle)
            printStyle = printStyleManager->GetPrintStyleByName (usePrintStyleName2);
    
        if (nullptr == printStyle)
            return; */
    
        //
        // Create the printer that we will use to initialize the print set.
        // Since we create this object, we are responsible for releasing it.
        //
        /* IPrinter^ initialPrinter = printManager->CreateAndInitializeDefaultPrinter (nullptr, nullptr, nullptr); */
    
        IPrinter^ initialPrinter = printManager->CreatePrinter();
    
        initialPrinter->InitializeFromPltcfgFile (gcnew FileSpec ("png.pltcfg"));
    
        scopedPrinter.set (initialPrinter);
        if (nullptr == initialPrinter)
            return;
    
        //
        // Create and initialize the print set.
        // Since we create this object, we are responsible for releasing it.
        //
        IPrintSet^ printSet = printManager->CreatePrintSet();
        scopedPrintSet.set (printSet);
        if (nullptr == printSet)
            return;
    
        if (! printSet->InitializeFromPrinter (initialPrinter))
            return;
    
        //
        // Set print set properties.
        //
        printSet->Name = "Example Print Set";
        
        printSet->OutputFileNameExpression =
            gcnew OutputFileNameExpression (StandardOutputFileNameExpression::Sequence_Set);
    
        printSet->PrintDefNameExpression =
            gcnew PrintDefNameExpression (StandardPrintDefNameExpression::SourceFile);
    
        //
        // Apply the print style to the print set.
        // This may change global properties such the printer.
        //
        /* printSet->ApplyPrintStyle (printStyle); */
    
        //
        // Create one or more print definitions for the specified design file and add them to the print set.
        // The contents of the effective print style determine how many print definitions are created.
        // Note that at this point, a background process is started to open the specified design file.
        // The design file loaded inside the current process is not disturbed.
        //
        array<IPrintDefinition^>^ printDefinitionsToAdd = printSet->CreatePrintDefinitions (activeDgnFspec, nullptr /* printStyle */);
        if (nullptr == printDefinitionsToAdd)
            return;
    
        printSet->Items->AddRange (printDefinitionsToAdd);
    
        //
        // Modify properties of all the print definitions contained within the print set.
        // In this case, we maximize the print size and make sure that rasterized mode is not selected.
        //
        for each (IPrintDefinition^ printDefinition in printSet->GetPrintDefinitionList (nullptr, true))
            {
            // We know this is a CAD print definition because we created it from the active design file,
            // not a PDF or raster source file, but we check the print definition type just to be safe and
            // avoid having to perform a dynamic_cast.
            if (PrintDefinitionType::Cad == printDefinition->PrintDefinitionType)
                {
                ICadPrintDefinition^ cadPrintDefinition = reinterpret_cast<ICadPrintDefinition^> (printDefinition);
    
                cadPrintDefinition->Maximize();
                cadPrintDefinition->IsRasterized = false;
                }
            }
    
        //
        // Publish the print set.
        //
        IPrinter^ printer = printSet->Printer;
    
        PublishingParams^ publishingParams = gcnew PublishingParams();
    
        if ((printer->Destination == Destination::File) || (printer->Destination == Destination::Metafile))
            {
            WString msPltfiles;
            mdlSystem_getCfgVar (&msPltfiles, L"MS_PLTFILES");
            
            System::String^ outputDir =
                (! msPltfiles.empty()) ? gcnew System::String (msPltfiles.c_str()) : System::Environment::CurrentDirectory;
    
            // Create a multi-page output file if the printer supports it, otherwise print as separate jobs.
            if (0) /* printer->SupportsPrintAsSet */
                {
                System::String^ outputHfs = Path::Combine (outputDir, printSet->Name + "." + printer->DefaultExtension);
                publishingParams->OutputFspec = gcnew FileSpec (outputHfs, true);
                }
            else
                {
                publishingParams->UseSeparateJobs = true;
                publishingParams->OutputFolderSpec = gcnew FolderSpec (outputDir, true);
                }
            }
    
        mdlOutput_messageCenter (BD::OutputMessagePriority::Info, L"PRINTSET printing...", NULL, BD::OutputMessageAlert::None);
    
        if (! printSet->Publish (publishingParams))
            return;
    
        scopedSuccessMessage.IsSuccess = true;
        }
    

          
    .

    Answer Verified By: Remy Moerland 

  • Andrew,

    Excellent!
    Thanks for your help in finding the cause and suggestions. 

    I'll use one of your suggested methods to work with, and file a service ticket in the meantime (if anything to make your developer team aware of the issue.

    Regards,
    Remy

  • Someone from Bentley support replied to the service request I have put in about this issue.

    Their suggestion was to add a MessageHandler.
    I am presuming that this redirects the logs away from the faulty code that throws the memory violation, see below the code as it is in the MSTNPlatformNET.chm example code, but with the added MessageHandler that prevents the crash from occuring:

    private static void OnUserMessageHandler(IUserMessage message)
    {
        //Can use anything for message handling, or completely ignore it
        //PrintLogger.Info(message.Text);
        System.Diagnostics.Debug.WriteLine(message.Text);
    }
    
    
    public static void LoripPlot(string unparsed)
    {
    
        IPrintManager printManager = PrintManagerProxy.GetLocalPrintManager();
    
        IPrinter printer = printManager.CreatePrinter();
        printer.InitializeFromPltcfgFile(new FileSpec(@"C:\Program Files\Bentley\MicroStation CONNECT Edition\MicroStation\Default\pltcfg\png.pltcfg"));
    
        IPrinterForm printerFormAnsiA = printer.FindFormByName("ANSI A");
    
        IPrintSet printSet = printManager.CreatePrintSet();
        printSet.InitializeFromPrinter(printer);
    
        printSet.OnUserMessage += OnUserMessageHandler;
    
        IPrintDefinition[] printDefinitions = printSet.CreatePrintDefinitions(new FileSpec(Session.Instance.GetActiveDgnFile().GetFileName()), null);
    
        foreach (IPrintDefinition printDefinition in printDefinitions)
        {
            ICadPrintDefinition cadPrintDefinition = printDefinition as ICadPrintDefinition;
            cadPrintDefinition.PrinterForm = printerFormAnsiA;
            cadPrintDefinition.Maximize();
        }
    
        IFolder folder = printSet.CreateFolder(@"TempFolder");
        printSet.Items.Add(folder);
    
        folder.Items.AddRange(printDefinitions);
    
        PublishingParams publishingParams = new PublishingParams();
        publishingParams.UseSeparateJobs = true;
        publishingParams.OutputFolderSpec = new FolderSpec(@"C:\Temp\");
        printSet.OutputFileNameExpression = new OutputFileNameExpression(StandardOutputFileNameExpression.PrintDefinitionName);
    
        printSet.Publish(publishingParams);
    
        printSet.Close();
        printer.Release();
    }
    


    Setting publishingParams.UseSeparateJobs = false is no longer required either using this workaround. 

    Answer Verified By: Remy Moerland 

Reply
  • Someone from Bentley support replied to the service request I have put in about this issue.

    Their suggestion was to add a MessageHandler.
    I am presuming that this redirects the logs away from the faulty code that throws the memory violation, see below the code as it is in the MSTNPlatformNET.chm example code, but with the added MessageHandler that prevents the crash from occuring:

    private static void OnUserMessageHandler(IUserMessage message)
    {
        //Can use anything for message handling, or completely ignore it
        //PrintLogger.Info(message.Text);
        System.Diagnostics.Debug.WriteLine(message.Text);
    }
    
    
    public static void LoripPlot(string unparsed)
    {
    
        IPrintManager printManager = PrintManagerProxy.GetLocalPrintManager();
    
        IPrinter printer = printManager.CreatePrinter();
        printer.InitializeFromPltcfgFile(new FileSpec(@"C:\Program Files\Bentley\MicroStation CONNECT Edition\MicroStation\Default\pltcfg\png.pltcfg"));
    
        IPrinterForm printerFormAnsiA = printer.FindFormByName("ANSI A");
    
        IPrintSet printSet = printManager.CreatePrintSet();
        printSet.InitializeFromPrinter(printer);
    
        printSet.OnUserMessage += OnUserMessageHandler;
    
        IPrintDefinition[] printDefinitions = printSet.CreatePrintDefinitions(new FileSpec(Session.Instance.GetActiveDgnFile().GetFileName()), null);
    
        foreach (IPrintDefinition printDefinition in printDefinitions)
        {
            ICadPrintDefinition cadPrintDefinition = printDefinition as ICadPrintDefinition;
            cadPrintDefinition.PrinterForm = printerFormAnsiA;
            cadPrintDefinition.Maximize();
        }
    
        IFolder folder = printSet.CreateFolder(@"TempFolder");
        printSet.Items.Add(folder);
    
        folder.Items.AddRange(printDefinitions);
    
        PublishingParams publishingParams = new PublishingParams();
        publishingParams.UseSeparateJobs = true;
        publishingParams.OutputFolderSpec = new FolderSpec(@"C:\Temp\");
        printSet.OutputFileNameExpression = new OutputFileNameExpression(StandardOutputFileNameExpression.PrintDefinitionName);
    
        printSet.Publish(publishingParams);
    
        printSet.Close();
        printer.Release();
    }
    


    Setting publishingParams.UseSeparateJobs = false is no longer required either using this workaround. 

    Answer Verified By: Remy Moerland 

Children
No Data