RichTextBox lifetime in static method context - c#

Please take a look at the method depicted below
public static string RemoveRTF(string input)
{
string output = input;
RichTextBox RichTextBox1 = new RichTextBox();
try {
RichTextBox1.Rtf = input;
output = RichTextBox1.Text;
} catch (ArgumentException argExp) {
/*
* The supplied input value is not in RTF format.
* Ignore.
*/
}
return output;
}
My question is, will the above code when called several times generate a large amount of USER Objects, Handles Or GDI Objects.
The reason for asking is that I have some code which worked perfectly one day and then the next day without any code changes made stopped working with the reported error :
Error creating Window Handle..
Only thing is that I cant seem to see the cause for the problem except that the callstack shows me that the error originates in the above code.
TaskManager do not reveal a large amount of USER objects or such being created, so I really do not know what is going on.

You should dispose your RichTextBox to free up any unmanaged resources.
RichTextBox1.Dispose();

or you can make one global RichTextBox and use it.
RichTextBox RichTextBox1 = new RichTextBox();
public static string RemoveRTF(string input)
{
string output = input;
try {
RichTextBox1.Rtf = input;
output = RichTextBox1.Text;
RichTextBox1.rtf = null;
} catch (ArgumentException argExp) {
/*
* The supplied input value is not in RTF format.
* Ignore.
*/
}
return output;
}
or use using()

The RichTextBox object only works on the UI thread. Calling this code from the background thread will throw an Exception with a message like "Error creating Window Handle.."

I also received the same error that u r facing "Error creating window handle". This issue occurs because even if we create object of RichTextBox and and set that object to null at the end of the method, it does not get disposed and so initially it works fine and then later on it start giving "error creating window handle". So instead use "Using". It will dispose object of richTextBox outside "using" context. This will solve that error.
private String RemoveRtf(String RtfScript)
{
string PlainText = null;
try
{
if (!String.IsNullOrEmpty(RtfScript))
{
using (RichTextBox richTxtBox = new RichTextBox())
{
richTxtBox.Rtf = RtfScript;
PlainText = richTxtBox.Text;
}
}
}
catch (Exception ex)
{
// log error here
}
finally
{
RtfScript = null;
}
return PlainText;
}

Related

unable to read text file using stream reader and place txt into custom class

so i am trying to read text from a txt file and then add the text in to a custom class list,
the code is
public static List<BookInfo> LoadCSVFile(string fileName, out string qError)
{
qError = "";
fileName = "books.txt";
List<BookInfo> Book_Info = new List<BookInfo>();
StreamReader read = null;
try
{
read = new StreamReader(fileName);
while (!read.EndOfStream)
{
string line = read.ReadLine();
string[] values = line.Split(',');
if (values.Length == 3)
{
string Title = values[0].Trim();
string Author = values[1].Trim();
string ISBN = values[2].Trim();
try
{
Book_Info.Add(new BookInfo(Title, Author, ISBN));
}
catch (Exception ex)
{
qError = ex.Message;
return null;
}
}
else
{
qError = $"line {line} was unable to be read";
return null;
}
}
}
catch
{
qError = $"failed to open file: {fileName}";
return null;
}
finally
{
if (read != null)
{
read.Close();
}
}
if (qError == "")
{
return Book_Info;
}
return null;
}
once i have read the text it will be displayed in a form which i believe to be coded correctly
i have placed an error message in to show when the file has been read and each time i try something new the same error appears.
have i gone wrong somewhere when reading the txt file?
Edit:
Text file was created using visual studio and is in the same solution, text file is in bin/debug
I totally agree with thegeneral's answer, but to answer your initial question I suspect your books.txt file was not located in your Bin/Debug folder. I did test your code ;-P
Some notes
if you are going to use something that Implements IDisposable, it's always good practice to use the using statement
If this is only a small file, why bother with StreamReader when you can just use File.ReadAllLines
Linq is your friend, projection is a wonderful thing.
If you really want to parse a CSV file, I'd seriously consider a dedicated CSV parser library (like CsvHelper). It will save you many headaches
This is not really the bastion of perfect coding, however I tried to work with what you had and the spirit of what you were trying to do.
Some code:
public static List<BookInfo> LoadCSVFile(string fileName, out string qError)
{
try
{
// read all lines in to another type
// just makes it easier for errors which you seem to want
var lines = File.ReadAllLines(fileName)
.Select(x => new { Values = x.Split(','), Text = x })
.ToList();
// get a list of errors,
var errors = lines.Where(x => x.Values.Length != 3)
.Select((s, i) => $"Bad book! Line {i} : {s.Text}");
// return some errors
qError = string.Join(Environment.NewLine, errors);
// project lines to your books
return lines.Where(x => x.Values.Length == 3)
.Select(x => new BookInfo(x.Values[0], x.Values[0], x.Values[0]))
.ToList();
}
catch (Exception e)
{
qError = e.Message;
}
return null;
}
Disclaimer
I wouldn't usually catch errors like this, it's rather nasty
The whole anonymous type and returning errors is a bit smelly, if the file is corrupt, I'd just throw a big nasty exception and be done with it. Make the user do the right thing
This is going to fail the second you have a title with a comma in it
This is completely untested!

gsapi_init_with_args is made: -100

I'm trying to build a PostScript to PDF Converter using Ghostscript.Net.
The Args that GetArgs return, are the ones I usually use to call gswin32c.exe and they work fine.
But every time i call Process, i get an error Saying "An error occured when call to 'gsapi_init_with_args' is made: -100". Googling that error didn't bring anything up so I thought I might ask here.
Are there differnet arguments to consider when calling the .dll directly with Ghostscript.net? Or did I made a mistake somewhere else?
Here's my class:
public class PdfConverter
{
#region Private Fields
private List<GhostscriptVersionInfo> _Versions = GhostscriptVersionInfo.GetInstalledVersions(GhostscriptLicense.GPL | GhostscriptLicense.AFPL | GhostscriptLicense.Artifex);
#endregion
#region Private Properties
private GhostscriptVersionInfo Version { get; set; }
#endregion
#region Construction
public PdfConverter()
{
Version = GhostscriptVersionInfo.GetLastInstalledVersion();
}
#endregion
#region Public Members
public bool ConvertToPdf(DirectoryInfo dir)
{
var d = dir;
if(!d.Exists)
return false;
var postScriptFiles = d.GetFiles("*.ps");
var pdfFiles = postScriptFiles.Select(psf => new FileInfo(Path.ChangeExtension(psf.FullName, ".pdf")));
foreach(var file in postScriptFiles) {
//ThreadPool.QueueUserWorkItem(new WaitCallback((o) => {
Process(file, new FileInfo(Path.ChangeExtension(file.FullName, ".pdf")));
//}));
}
pdfFiles.ForEach(pdf => pdf?.Refresh());
return pdfFiles.All(pdf => pdf.Exists);
}
#endregion
#region Private Helpers
private void Process(FileInfo inputFile, FileInfo outputFile)
{
Console.WriteLine($"Converting {inputFile} to {outputFile}");
var proc = new GhostscriptProcessor(Version, true);
proc.Process(GetArgs(inputFile, outputFile).ToArray(), new ConsoleStdIO(true, true, true));
}
private IEnumerable<string> GetArgs(FileInfo inputFile, FileInfo outputFile)
{
return new [] {
$"-q ",
$"-sDEVICE=pdfwrite",
$"-dSAFER",
$"-dNOPAUSE",
$"-dBATCH",
$"-sPAPERSIZE=a4",
$"-dEmbedAllFonts=true",
$"-dAutoRotatePages=/None",
$"-sOutputFile=\"{outputFile.FullName}\"",
$"-dCompatibilityLevel#1.4",
$"-c .setpdfwrite",
$"-f \"{inputFile.FullName}\""
};
}
#endregion
}
Edit:
I forgot to mention: To implement it i had to make my own GhostsdcriptStdIO class. I admit that I'm not entirely sure if I did this right. Although it does get instanciated without exceptions, and override StdOut(...) get's called, and the output is written to the console as expected. override void StdError(...) get's called as well. And also written to the console as expeted.
The Output of the error btw is:
"**** Could not open the file "c:\temp\test.pdf""
"**** Unable to open the initial device, quitting."
Here's my ConsoleStdIO class:
public class ConsoleStdIO : Ghostscript.NET.GhostscriptStdIO
{
#region Construction
public ConsoleStdIO(bool handleStdIn, bool handleStdOut, bool handleStdError) : base(handleStdIn, handleStdOut, handleStdError) { }
#endregion
#region Overrides
public override void StdError(string error)
{
var foo = Encoding.Default.GetBytes(error);
var lenght = foo.Length;
using (var err = Console.OpenStandardError()) {
if(err.CanWrite)
err.Write(foo, 0, lenght);
}
}
public override void StdIn(out string input, int count)
{
byte[] bytes = new byte[0];
using(var stdInput = Console.OpenStandardInput()) {
stdInput.Read(bytes, 0, count);
}
input = Encoding.Default.GetString(bytes);
}
public override void StdOut(string output)
{
var foo = Encoding.Default.GetBytes(output);
var lenght = foo.Length;
using (var err = Console.OpenStandardError()) {
if(err.CanWrite)
err.Write(foo, 0, lenght);
}
}
#endregion
}
Again: doing the same operation with the exact same files and arguments using gswin32c.exe works fine.
Happy Hacking
Error -100 is gs_error_Fatal, which means 'something catastrophic went wrong'. Its an indication that the program failed to start up properly and we can't tell why. The back channel may contain more information.
And indeed, the back channel tells you what's wrong:
**** Could not open the file "c:\temp\test.pdf
**** Unable to open the initial device, quitting.
Ghostscript is unable to open the output file, which means it can't open the pdfwrite device (because that requires an output file) so it aborts the operation.
There could be a number of reasons why Ghostscript can't open the output file. The first thing I'd do is trim down the number of arguments;
You don't want -q (quiet) when you are trying to debug a problem, you want all the information you can get.
I'd remove -dSAFER at least to start with, because that prevents Ghostscript accessing directories outside the current working directory and certain 'special' ones. It may well prevent you accessing the temp directory.
You don't need to set EmbedAllFonts when its the same value as the default.
You could drop the CompatibilityLevel (and note that you've used a # there instead of an =) switch, and the AutoRotatePages while getting this to work.
The "-c .setpdfwrite -f" string has been pointless for years but people still keep using it. All that does these days is slow down the start of processing, ditch it.
Finally you can try changing the backslash ('\') characters to forward slash ('/') in case your string handling is messing that up, or use double backslashes (I'd use the forward slash myself).
You should also check that c:\test\temp.pdf doesn't exist, or if it does exist is not read-only or already open in a different application.
So I solved the problem...
After taking KenS' advice I could run the application without Ghostscript (not Ghostscript.NET) giving me any errors. But it did not produce an actual PDF File.
So KenS's answer did not quite solve the problem, but since 'less is more' and since he took the time to talk to me on IRC to verify that my args in itself were correct, I'll give the answer points nonetheless.
What actually solved my was the following:
Here my original GetArgs(...)
private IEnumerable<string> GetArgs(FileInfo inputFile, FileInfo outputFile)
{
return new [] {
$"-sDEVICE=pdfwrite",
$"-dNOPAUSE",
$"-dBATCH",
$"-sPAPERSIZE=a4",
#"-sFONTPATH=" + System.Environment.GetFolderPath(System.Environment.SpecialFolder.Fonts),
$"-sOutputFile={outputFile.FullName}",
$"{inputFile.FullName}",
};
}
Someone in #csharp pointed out to me, that in c, the first argument is always the name of the command. So he suggested to just put "gs" as the first argument (as a dummy) and try... And that's what actually solved my problem.
So this is how the working GetArgs(...) looks:
private IEnumerable<string> GetArgs(FileInfo inputFile, FileInfo outputFile)
{
return new [] {
$"gs",
$"-sDEVICE=pdfwrite",
$"-dNOPAUSE",
$"-dBATCH",
$"-sPAPERSIZE=a4",
#"-sFONTPATH=" + System.Environment.GetFolderPath(System.Environment.SpecialFolder.Fonts),
$"-sOutputFile={outputFile.FullName}",
$"{inputFile.FullName}",
};
}

MPEG-7 descriptors

I am trying to compare images by MPEG7 descriptors and I found a implementation by http://chatzichristofis.info/?page_id=19 but when I call Apply() function so the exception is thrown.
EHD_Descriptor ehd = new EHD_Descriptor(11);
var img = new Bitmap("LargerImage.jpg");
.
.
.
descriptor = ehd.Apply(img);
descriptor = ehd.Quant(descriptor);
Exception
System.AccessViolationException was unhandled
HResult=-2147467261
Message=...
Does anyone has any experiance with these descriptors or any reference to other descriptors which works without exceptions (from unmanaged code, I think)?
If someone has a same problem and just need to proccess other images, so one solution is:
[HandleProcessCorruptedStateExceptions]
[SecurityCritical]
private double[] DoSecurityCritical(SimpleRnd.CEDD cedd, Bitmap img) {
try {
// List<double[]> temp = locate.extract(img,600);
double [] temp = cedd.Apply(img);
return temp;
} catch (Exception) {
return null;
}
}
Just use stronger catch with security attributes.

strange behavior of XamlReader.Load()?

I've got a very strange issue while parsing an external XAML file. The pre-history is that I want to load an external XAML file with content to process. But I want to load as many different files as I want. That happens by unloading the old and loading the new one.
My issue is:
When I load a xaml the first time, everything is good, all as it should be.
But when I load the same xaml the second time, every entry of the object im Loading is there twice. If I run this again, every object is there three times and so on...
To debug the project yourself, download it here. The function starts at line 137 in the file "Control Panel.xaml.cs". I realy don't know what this is. Is it my fault or simply a bug? If yes, is there a workaround?
/// <summary>
/// Load a xaml file and parse it
/// </summary>
public void LoadPresentation()
{
this.Title = "Control Panel - " + System.IO.Path.GetFileName(global.file);
System.IO.FileStream XAML_file = new System.IO.FileStream(global.file, System.IO.FileMode.Open);
try
{
System.IO.StreamReader reader = new System.IO.StreamReader(XAML_file);
string dump = reader.ReadToEnd(); //This is only for debugging purposes because of the strange issue...
XAML_file.Seek(0, System.IO.SeekOrigin.Begin);
presentation = (ResourceDictionary)XamlReader.Load(XAML_file);
//Keys the resourceDictionary must have to be valid
if (presentation["INDEX"] == null || presentation["MAIN_GRID"] == null || presentation["CONTAINER"] == null || presentation["LAYOUTLIST"] == null)
{
throw new Exception();
}
//When this list is loaded, every item in it is there twice or three times or four... Why????
TopicList Index = null;
Index = (TopicList)presentation["INDEX"];
for (int i = 0; i < topics.Count; )
{
topics.RemoveAt(i);
}
foreach (TopicListItem item in Index.Topics)
{
topics.Insert(item.TopicIndex, (Topic)presentation[item.ResourceKey]);
}
lv_topics.SelectedIndex = 0;
selectedIndex = 0;
}
catch
{
System.Windows.Forms.MessageBox.Show("Failed to load XAML file \"" + global.file + "\"", "Parsing Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
presentation = null;
}
finally
{
XAML_file.Close();
}
}
Edit:
I have tried to serialize the object that was read from the XamlReader and in the output was nowhere any childelement... But if I pull the object out of the dictionary, the children are all there (duplicated and triplicated, but there).
I have already tried to clear the list over
topics.Clear();
and
topics=new ObservableCollection<TopicListItem>();
lv_topics.ItemsSource=topics;
Try Index.Topics.Clear() after loading the Topics into your topics object. That appears to get rid of the duplication.
//When this list is loaded, every item in it is there twice or three times or four... Why????
TopicList Index = null;
Index = (TopicList)presentation["INDEX"];
topics.Clear();
foreach (TopicListItem item in Index.Topics)
{
topics.Insert(item.TopicIndex, (Topic)presentation[item.ResourceKey]);
}
Index.Topics.Clear(); //Adding this will prevent the duplication
lv_topics.SelectedIndex = 0;
selectedIndex = 0;
In the code post topics is not declared in LoadPresentation() so naturally it will have any prior values.
I know you said you tried topics=new ObservableCollection(); but please try again. And put that IN LoadPresentation()
public void LoadPresentation()
{
ObservableCollection<TopicListItem> topics = new ObservableCollection<TopicListItem>()
I would pass filename
public void LoadPresentation(string fileName)
I get you may need to use topics outside LoadPresentation but this is debugging. If you need topics outside the return it.
public ObservableCollection<TopicListItem> LoadPresentation(string fileName)
If that does not fix it I would put a try catch block on the XAML_file.Close(); to see if something weird is not going on.

Try-catch creating new array in C# - where to initialize it?

If I'm reading a string from a config file, I'd use a similar approach to the below, in case the string isn't present in the file being read and an exception results. However, if I want to do the same for a string[] array, I can't just 'new it up' outside the try block because the size is not known.
I can't new it up in the try block itself. How should it be approached?
string[] logContent; // can't new it up here as don't know the size
try
{
logContent = File.ReadAllLines(aLogFile);
}
catch
{
throw new Exception("LoggerStandard: Specified Logfile exists but could not be read.");
}
You could initialize it to a default value:
string[] logContent = null;
try
{
logContent = File.ReadAllLines(aLogFile);
}
catch
{
// Be careful with the error message here => there might be other reasons
// that the ReadAllLines threw an exception
throw new Exception("LoggerStandard: Specified Logfile exists but could not be read.");
}
You can initialize it with null and then check against it.
By default it is null. You can leave it as is, if this is appropriate for your program, or initialize to any array according to your needs. Anyway, successful initialization inside of try block overrides this.
string[] logContent=null;
try
{
logContent = File.ReadAllLines(aLogFile);
}
catch
{
throw new Exception("LoggerStandard: Specified Logfile exists but could not be read.");
}

Categories

Resources