Convert Postscript to Text file using ghostscript - c#

my client wants me to do one task. which is whenever I print ctrl+P from the browser it will go automatically that contents to the database which is sql.
Now, Let me explain what I have tried to achieve this. Usually printerPlusPlus which is third party tool. Which adds virtual printer and prints the files PS to the temp directory than I can read the contents of that postscript file and save it to the database.
My real question is there anything from which I can convert this post script files to text or read them and save the texts to the database?
Or is there any better way to achieve this task?
Ghostscript is the alternate and ow-some feature to convert the postscripts to the text or pdf. But, I am completely clueless about the documentation and how to execute their commands.
_viewer.Interpreter.RunFile("C:\\PrinterPlusPlus\\Temp\\ankit_SONY-VAIO_sony_20151227_185020_3.ps");
GhostscriptPngDevice dev = new GhostscriptPngDevice(GhostscriptPngDeviceType.Png16m);
dev.GraphicsAlphaBits = GhostscriptImageDeviceAlphaBits.V_4;
dev.TextAlphaBits = GhostscriptImageDeviceAlphaBits.V_4;
dev.ResolutionXY = new GhostscriptImageDeviceResolution(96, 96);
dev.InputFiles.Add(#"C:\\PrinterPlusPlus\\Temp\\ankit_SONY-VAIO_sony_20151227_185020_3.ps");
dev.OutputPath = #"C:\\PrinterPlusPlus\\Temp\\ankit_SONY-VAIO_sony_20151227_185020_3.txt";
dev.Process();
_preview.Activate();
I tried this but this seems to be not working and adding ASCII text to the txt file.

I found ghostscript little confusing. But, I found the solution from here
string inputFile = #"E:\gss_test\test_postscript.ps";
GhostscriptPipedOutput gsPipedOutput = new GhostscriptPipedOutput();
// pipe handle format: %handle%hexvalue
string outputPipeHandle = "%handle%" + int.Parse(gsPipedOutput.ClientHandle).ToString("X2");
using (GhostscriptProcessor processor = new GhostscriptProcessor())
{
List<string> switches = new List<string>();
switches.Add("-empty");
switches.Add("-dQUIET");
switches.Add("-dSAFER");
switches.Add("-dBATCH");
switches.Add("-dNOPAUSE");
switches.Add("-dNOPROMPT");
switches.Add("-sDEVICE=pdfwrite");
switches.Add("-o" + outputPipeHandle);
switches.Add("-q");
switches.Add("-f");
switches.Add(inputFile);
try
{
processor.StartProcessing(switches.ToArray(), null);
byte[] rawDocumentData = gsPipedOutput.Data;
//if (writeToDatabase)
//{
// Database.ExecSP("add_document", rawDocumentData);
//}
//else if (writeToDisk)
//{
// File.WriteAllBytes(#"E:\gss_test\output\test_piped_output.pdf", rawDocumentData);
//}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
gsPipedOutput.Dispose();
gsPipedOutput = null;
}
}
This reads the postscript files easily :)

Related

c# Novacode.Picture to System.Drawing.Image

I'm reading in a .docx file using the Novacode API, and am unable to create or display any images within the file to a WinForm app due to not being able to convert from a Novacode Picture (pic) or Image to a system image. I've noticed that there's very little info inside the pic itself, with no way to get any pixel data that I can see. So I have been unable to utilize any of the usual conversion ideas.
I've also looked up how Word saves images inside the files as well as Novacode source for any hints and I've come up with nothing.
My question then is is there a way to convert a Novacode Picture to a system one, or should I use something different to gather the image data like OpenXML? If so, would Novacode and OpenXML conflict in any way?
There's also this answer that might be another place to start.
Any help is much appreciated.
Okay. This is what I ended up doing. Thanks to gattsbr for the advice. This only works if you can grab all the images in order, and have descending names for all the images.
using System.IO.Compression; // Had to add an assembly for this
using Novacode;
// Have to specify to remove ambiguous error from Novacode
Dictionary<string, System.Drawing.Image> images = new Dictionary<string, System.Drawing.Image>();
void LoadTree()
{
// In case of previous exception
if(File.Exists("Images.zip")) { File.Delete("Images.zip"); }
// Allow the file to be open while parsing
using(FileStream stream = File.Open("Images.docx", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using(DocX doc = DocX.Load(stream))
{
// Work rest of document
// Still parse here to get the names of the images
// Might have to drag and drop images into the file, rather than insert through Word
foreach(Picture pic in doc.Pictures)
{
string name = pic.Description;
if(null == name) { continue; }
name = name.Substring(name.LastIndexOf("\\") + 1);
name = name.Substring(0, name.Length - 4);
images[name] = null;
}
// Save while still open
doc.SaveAs("Images.zip");
}
}
// Use temp zip directory to extract images
using(ZipArchive zip = ZipFile.OpenRead("Images.zip"))
{
// Gather all image names, in order
// They're retrieved from the bottom up, so reverse
string[] keys = images.Keys.OrderByDescending(o => o).Reverse().ToArray();
for(int i = 1; ; i++)
{
// Also had to add an assembly for ZipArchiveEntry
ZipArchiveEntry entry = zip.GetEntry(String.Format("word/media/image{0}.png", i));
if(null == entry) { break; }
Stream stream = entry.Open();
images[keys[i - 1]] = new Bitmap(stream);
}
}
// Remove temp directory
File.Delete("Images.zip");
}

C# How Can I Play A Video From A Memory Stream Using DirectShow(quartz.dll)?

I have a C# Visual Studio WinForms .NET app that plays video using the QuartzTypeLib (quartz.dll). With the code I've written, I can play any video file from the hard drive.
Here's the code at the top that executes when the app starts:
public const int WS_CHILD = 0x40000000;
public const int WS_CLIPCHILDREN = 0x2000000;
public QuartzTypeLib.IMediaControl mc;
public QuartzTypeLib.IVideoWindow videoWindow = null;
IMediaPosition mp = null;
And here's the code that opens the video file:
private void openMediaToolStripMenuItem_Click(object sender, EventArgs e)
{
// Open a media file.
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "Video Files|*.mpg;*.avi;*;*.wmv;*.mov";
ofd.FilterIndex = 1;
if (DialogResult.OK == ofd.ShowDialog())
{
// Stop the playback for the current movie if a video is currently playing.
if (mc != null)
mc.Stop();
if (pbVideoDisplay.Image != null)
pbVideoDisplay.Image = null;
// Load the movie file.
FilgraphManager graphManager = new FilgraphManager();
graphManager.RenderFile(ofd.FileName);
mp = graphManager as IMediaPosition;
mc = (IMediaControl)graphManager;
tsbtnPlay.Enabled = tsbtnPause.Enabled = tsbtnStop.Enabled = true;
// Attach the view to the picture box (pbVideoDisplay) on frmMain.
try
{
videoWindow = (IVideoWindow)graphManager;
videoWindow.Owner = (int)pbVideoDisplay.Handle;
videoWindow.WindowStyle = WS_CHILD | WS_CLIPCHILDREN;
videoWindow.SetWindowPosition(
pbVideoDisplay.ClientRectangle.Left,
pbVideoDisplay.ClientRectangle.Top,
pbVideoDisplay.ClientRectangle.Width,
pbVideoDisplay.ClientRectangle.Height);
}
catch //(Exception Ex)
{
// I'll write code for this when I have a need to.
}
// Now we convert the video to a byte array.
FileStream fs = new FileStream(ofd.FileName, FileMode.Open, FileAccess.Read);
try
{
// Here we convert the video to Base 64.
VideoInBytes = new byte[fs.Length];
VideoInBytes = System.Text.Encoding.UTF8.GetBytes(ofd.FileName);
VideoInBase64 = Convert.ToBase64String(VideoInBytes);
}
catch //(Exception Ex)
{
//throw new Exception("Error in base64Encode" + Ex.Message);
}
}
}
Notice that I have code that converts the video to a Base64 string. This string will obviously have to be loaded into a memory stream. I'd like to add code that will allow me to play a video from a memory stream. Is that even possible with DirectShow and if so, what code would I need to add and where would I put it?
The DirectShow way is to create a special so-called filter (source filter) that outputs video data and then add it to the graph chain.
Usually a filter is written in C++. Of course almost any code that can be written in C++ can be rewritten in C#. It could take a lot of work, for instance look at this article:
http://www.codeproject.com/Articles/421167/Pure-NET-DirectShow-Filters-in-Csharp
Another way is file emulation. In this case you would need 3rd party solution like BoxedApp.
The idea is to intercept some file functions like SetFilePointer and ReadFile, to provide data as it is written from a real file (but in fact it is read from memory).

Add PDF file as attachment to TestTrack using SOAP

I have recently started using C# over the past year so I'm somewhat new to this, but can usually hack through things with some effort, but this one is eluding me. We use TestTrack for development bug/issue tracking at our company. I've created a custom windows forms app to be the front-end to TestTrack for one of our departments. It connects using SOAP. I'm not using WPF/WCF and don't want to go that route. I'm having difficulty finding any examples of how to correctly encode a file for attachment that is a PDF. The code below does actually create an attachment in TestTrack to an already-existing issue, but when you try to open it in TestTrack, it pops up an error message that says "Insufficient Data For An Image". The example below does work if you're wanting to add a text file to TestTrack using SOAP. I'm wanting to know what I need to change below so that I can get a PDF file into TestTrack and then be able to open it in the TestTrack application without the error mentioned above. Thanks in advance for any input/help.
public void getAttachments(long lSession, CDefect def)
{
ttsoapcgi cgiengine = new ttsoapcgi();
// Lock the defect for edit.
CDefect lockedDefect = cgiengine.editDefect(lSession, def.recordid, "", false);
string attachment = "c:\\TEST\\TEST_PDF.PDF";
CFileAttachment file = new CFileAttachment();
file.mstrFileName = Path.GetFileName(attachment);
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
StreamReader reader = new StreamReader(attachment);
file.mstrFileName = Path.GetFileName(attachment);
file.mpFileData = enc.GetBytes(reader.ReadToEnd());
reader.Close();
CReportedByRecord reprec = lockedDefect.reportedbylist[0];
CFileAttachment[] afile = reprec.attachmentlist;
if (afile == null)
{
lockedDefect.reportedbylist[0].attachmentlist = new CFileAttachment[1];
lockedDefect.reportedbylist[0].attachmentlist[0] = file;
}
// Save our changes.
cgiengine.saveDefect(lSession, lockedDefect);
}
}
Here is the modified method that allowed me to attach a PDF to SOAP and get it into TestTrack as an attachment to an issue:
public void getAttachments(long lSession, CDefect def)
{
ttsoapcgi cgiengine = new ttsoapcgi();
// Lock the defect for edit.
CDefect lockedDefect = cgiengine.editDefect(lSession, def.recordid, "", false);
string attachment = "c:\\TEST\\TEST_PDF.PDF";
CFileAttachment file = new CFileAttachment();
file.mpFileData = File.ReadAllBytes(attachment);
file.mstrFileName = Path.GetFileName(attachment);
CReportedByRecord reprec = lockedDefect.reportedbylist[0];
CFileAttachment[] afile = reprec.attachmentlist;
if (afile == null)
{
lockedDefect.reportedbylist[0].attachmentlist = new CFileAttachment[1];
lockedDefect.reportedbylist[0].attachmentlist[0] = file;
}
// Save our changes.
cgiengine.saveDefect(lSession, lockedDefect);
}

Can't read file properly from windows notepad

I write some codes for simple text editor in C# and I use rich text box control, I found a problem that I can't solve. The problem is when I save a file in my text editor and then try to reopen it using windows notepad, it become in one line, this is the example
This is when I write and save from my app
After I save it and open in windows notepad it becomes like this
here are my code for saving a fie
try
{
saveFileDialog1.ShowDialog();
this.Text = file = toolStripTextBox1.Text = saveFileDialog1.FileName;
isi = richTextBox1.Text;
write = new System.IO.StreamWriter(file);
write.WriteLine(isi);
write.Close();
toolStripStatusLabel2.Text = "Saved";
}
catch (Exception)
{
toolStripStatusLabel2.Text = "Save cancelled by user";
}
do you have any idea how to fix it?
You are probably getting this because you are trying to save richTextBox1.Text (the whole text) in one line only using the following code
isi = richTextBox1.Text;
write = new System.IO.StreamWriter(file);
write.WriteLine(isi);
write.Close();
It's recommended to use write.WriteLine() on a specific line number in richTextBox1 then move to another line.
Example
for (int i = 0; i < richTextBox1.Lines.Length; i++)
{
write.WriteLine(richTextBox1.Lines[i]);
}
write.Close();
Another Solution
There's already a built-in function for RichTextBox to save a file with a specific encoding. You may use RichTextBox.SaveFile() for this purpose.
Example
RichTextBox.SaveFile(string path, RichTextBoxStreamType);
Where path represents saveFileDialog1.FileName in your code. For RichTextBoxStreamType, it's best to set it as RichTextBoxStreamType.PlainText as long as you do not use RTF such as Color/Font/Protection/Indent/etc...
Then, you may read the file again using the following method
RichTextBox.LoadFile(string path, RichTextBoxStreamType);
NOTICE: If the file is not in RTF and you try to read it in RTF (RichTextBox.LoadFile(string path, RichTextBoxStreamType.RichText);)
you may encounter formatting errors. In this case, you'll need to catch the exception and read the file in a Plain or Unicode encoding.
Example
RichTextBox _RichTextBox = new RichTextBox();
try
{
_RichTextBox.LoadFile(#"D:\Resources\text.txt", RichTextBoxStreamType.RichText);
}
catch (Exception EX)
{
if (EX.Message.ToLower().Contains("format is not valid"))
{
_RichTextBox.LoadFile(#"D:\Resources\text.txt", RichTextBoxStreamType.PlainText);
}
}
Thanks,
I hope you find this helpful :)
Saves the contents of the RichTextBox to a file by using richtextbox 's own save method: SaveFile(string, RichTextBoxStreamType);
you can refer this : http://msdn.microsoft.com/en-us/library/system.windows.forms.richtextbox.savefile%28VS.71%29.aspx
load the content of file by LoadFile(Stream, RichTextBoxStreamType);, refer this: http://msdn.microsoft.com/en-us/library/system.windows.forms.richtextbox.loadfile(v=vs.71).aspx

Search and replace contents of text file based on mappings in CSV file in C#

I am new to programming and am working on a C# project that will search and replace certain words in a text file with new values. I have some code that works, but the OLD and NEW values are hardcoded right now. I would like to use an external CSV file as a configuration file so the user can add or update the OLD to NEW mappings at a later time. This is my current code with the OLD and NEW values hardcoded:
try
{
StreamReader file = new StreamReader(inputfullfilepath);
TextWriter writer = new StreamWriter(outputfile);
while ((line = file.ReadLine()) != null)
{
line = line.Replace("OLD1", "NEW1");
line = line.Replace("OLD2", "NEW2");
// etc....
writer.WriteLine(line);
}
file.Close();
File.Move(inputfullfilepath, inputfullfilepath + ".old");
writer.Close();
File.Move(outputfile, outputfilepath + #"\" + inputfilename);
MessageBox.Show("File Scrub Complete", "Success");
}
catch
{
MessageBox.Show("Error: Be sure data paths are valid.", "Error",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
The code takes each line of the text file, tries to do a search/replace for all OLD to NEW mappings, then goes to the next line in the text file. The problem I am trying to wrap my head around is being able to make this list of OLD to NEW mappings dynamic based on a CSV (or XML if that would be easier?) configuration file so the user can add new search/replace keywords.
I tried to use the C# Application Settings in Visual Studio (which creates an XML configuration file) but I had a really hard time understanding how to make that work. What's the best way to do this so the values don't have to be hardcoded?
A csv file will work just fine.
I'll create a new Object which i'll call ReplaceObject
public ReplaceObject()
{
public string original;
public string updated;
//ideally you'd use getters and setters, but I'll keep it simple
}
Now we read from the csv
List<ReplaceObject> replaceList = new List<ReplaceObject>
while (reader.peek != -1)
{
string line = reader.readln();
var splitLine = line.split(',');
ReplaceObject rObject = new ReplaceObject();
rObject.original = splitLine[0];
rObject.updated = splitLine[1];
replaceList.add(rObject);
}
Now we go through the list.. and replace
string entireFile = //read all of it
foreach (ReplaceObject o in replaceList)
{
entireFile.Replace(o.original,o.updated);
}
//write it at the end
(Note that my code is missing some checks, but you should get the idea. Also you might want to use a StringBuilder)
My suggestion would be that you use the Settings.cs instead of CSV
It is very easy to use them and involves very less code
e.g. Properties.Settings.Default.Old1;
Here is a walkthrough http://msdn.microsoft.com/en-us/library/aa730869(v=vs.80).aspx
See this example showing how you can use it http://www.codeproject.com/Articles/17659/How-To-Use-the-Settings-Class-in-C

Categories