Printing - Need to transfer selected printer settings - c#

I am working on a printing feature where GUI applications create & store XPS files to be printed in a temp directory and spawn a new C# program which picks these files & sends them to printer.
I need to show the printdialog in the GUI application as the xps file generation process needs some input like page range from user specified settings in print dialog page.
Then the GUI invokes the C# "MyPrinter" process which actually prints the xps files. I am able to transfer PrintTicket settings by serializing them to a file from GUI (through SaveTo API) and reading it from "MyPrinter" process. Sample code at MyPrinter process -
var server = new PrintServer(#"\\servername"); // need to get this from GUI processs
var printQueue = server.GetPrintQueue("printername"); // We can use printQueue name here
printQueue.UserPrintTicket = GetPrintTicket();
int index = 0;
foreach (var printFileName in new DirectoryInfo(printingPath).EnumerateFiles("*.xps"))
{
printQueue.AddJob(string.Format("CustomPrint-{0}", ++index), printFileName.FullName, printQueue.IsXpsDevice);
}
private PrintTicket GetPrintTicket()
{
var reader = new FileStream(#"C:\temp\printTicket.xml", FileMode.Open);
var ticket = new PrintTicket(reader);
reader.Close();
return ticket;
}
Wanted to know -
If there is way to serialize the printQueue settings to a file (need print server and printer name at bare minimum) ? Already tried using Xamlreader/XamlWriter but it seems PrintQueue class does not have a default constructor.
OR
Any other way I could reliably transfer selected printer settings from one application to another ?
Thanks in advance
Amit

I suggest that you have a read of the Serialization (C# and Visual Basic) page from MSDN. In .NET, you can make practically any class serializable simply, using the SerializableAttribute Class like this:
[Serializable] // <--- This is all you need
public class YourClass
{
...
}
You can find several code examples describing how to save a serialized class in the Basic Serialization page on MSDN... from this linked page:
MyObject obj = new MyObject();
obj.n1 = 1;
obj.n2 = 24;
obj.str = "Some String";
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("MyFile.bin", FileMode.Create, FileAccess.Write,
FileShare.None);
formatter.Serialize(stream, obj);
stream.Close();

I used following way to transfer print settings & print using another process -
Serialized PrintTicket class, it already has "ToXml()" method.
Transferred the printername
For actual printing in the "MyPrinter" process, did the following-
var server = new PrintServer(printDialog.PrintQueue.HostingPrintServer.Name);
var printQueue = server.GetPrintQueue(printDialog.PrintQueue.Name);
printQueue.UserPrintTicket = GetPrintTicket();
PrintUsingXpsDocWriter(printQueue);
}
private void PrintUsingXpsDocWriter(PrintQueue printQueue)
{
var docWriter = PrintQueue.CreateXpsDocumentWriter(printQueue);
int index = 0;
foreach (var printFileName in new DirectoryInfo(printingPath).EnumerateFiles("*.xps"))
{
}
printQueue.Dispose();
}
private PrintTicket GetPrintTicket()
{
// This file had serialized print ticket settings
var reader = new FileStream(#"C:\temp\printTicket.xml", FileMode.Open);
var ticket = new PrintTicket(reader);
reader.Close();
return ticket;
}
Thanks

Related

getting an error that 'the process cannot access the file because it is being used by another process' in my dot net program

I tried 'using' but it says that the method is not Idisposable. I checked for running processes in Task Manager, nothing there. My goal is to upload a file from local directory to the Rich Text editor in my website. Please help me resolve this issue. Thanks in Advance
public void OnPostUploadDocument()
{
var projectRootPath = Path.Combine(_hostingEnvironment.ContentRootPath, "UploadedDocuments");
var filePath = Path.Combine(projectRootPath, UploadedDocument.FileName);
UploadedDocument.CopyTo(new FileStream(filePath, FileMode.Create));
// Retain the path of uploaded document between sessions.
UploadedDocumentPath = filePath;
ShowDocumentContentInTextEditor();
}
private void ShowDocumentContentInTextEditor()
{
WordProcessingLoadOptions loadOptions = new WordProcessingLoadOptions();
Editor editor = new Editor(UploadedDocumentPath, delegate { return loadOptions; }); //passing path and load options (via delegate) to the constructor
EditableDocument document = editor.Edit(new WordProcessingEditOptions()); //opening document for editing with format-specific edit options
DocumentContent = document.GetBodyContent(); //document.GetContent();
Console.WriteLine("HTMLContent: " + DocumentContent);
//string embeddedHtmlContent = document.GetEmbeddedHtml();```
//Console.WriteLine("EmbeddedHTMLContent: " + embeddedHtmlContent);
}
FileStream is disposable, so you can use using on it:
using (var stream = new FileStream(filePath, FileMode.Create)
{
UploadedDocument.CopyTo(stream);
}

How to monitor a logfile that seems to be open all the time (much like notepad++ does)?

I'm trying to build a small program to monitor my pfirewall.log, but I can't seem to open it.
I found quite many (simple) answers, that all kinda say
// use FilesystemWatcher
// open FileStream
// read from last position to end
// output new lines
The problem here is: The file seems to always be opened by another process already. I guess that's the windows process writing to the file, since it's getting written to all the time, as Notepad++ shows me.
Which means, Notepad++ can for some reason do what I can not: Read the file despite it being opened already.
I initialize my monitor in the constructor:
public FirewallLogMonitor(string path)
{
if (!File.Exists(path))
throw new FileNotFoundException("Logfile not found");
this.file = path;
this.lastPosition = 0;
this.monitor = new FileSystemWatcher(Path.GetDirectoryName(path), Path.GetFileName(path));
this.monitor.NotifyFilter = NotifyFilters.Size;
}
And try to read the file on monitor.Changed event:
private void LogFileChanged(object sender, FileSystemEventArgs e)
{
using (FileStream stream = new FileStream(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.Read))
using (StreamReader reader = new StreamReader(stream))
{
stream.Seek(this.lastPosition, SeekOrigin.Begin);
var newLines = reader.ReadToEnd();
this.lastPosition = stream.Length;
var filteredLines = filterLines(newLines);
if (filteredLines.Count > 0)
NewLinesAvailable(this, filteredLines);
}
}
It always throws the IOException on new FileStream(...) to tell me the file is already in use.
Since Notepad++ does it, there has to be a way I can do it too, right?
**Edit: ** A button does this:
public void StartLogging()
{
this.IsRunning = true;
this.monitor.Changed += LogFileChanged;
this.monitor.EnableRaisingEvents = true;
}
**Edit2: ** This is not a duplicate of FileMode and FileAccess and IOException: The process cannot access the file 'filename' because it is being used by another process, since that one assumes I have control over the writing process. Will try the other suggestions, and report back with results.
If i understand your question you can use the notepad++ itself with a plugin to monitor you need to go to:
plugins -> Document Moniter -> Start to monitor
if you dont have this plugin you can download it here:
http://sourceforge.net/projects/npp-plugins/files/DocMonitor/

Does XML deserialize lock the file from reading?

I have an xml file which is used by multiple process for reading. Here is the code snippet used for deserializing the xml. I want to make sure the below code does not read lock the file.
public Address TestReadLock(string myXmlFile)
{
using (StreamReader sr = new StreamReader(myXmlFile))
{
XmlReaderSettings xrs = new XmlReaderSettings();
xrs.ValidationType = ValidationType.None;
xrs.XmlResolver = null;
using (XmlReader reader = XmlReader.Create(sr, xrs))
{
return (Address)xmlSerializer.Deserialize(reader);
}
}
}
I tried testing this by creating a dll of above function and loaded the file through powershell and VS in a loop at same time it worked fine.
public void Main()
{
for (int i = 0; i < 1000; i++)
{
Address myaddress = TestReadLock(#C:\MyDetails.xml")
}
}
Based on my understanding the above code should read lock the file nad while testing it is not the case
Is there a possibility like testing I did is wrong or my understanding is not correct?
new StreamReader(string) uses FileAccess.Read and FileShare.Read - it will not prevent other readers. If you want different control: use FileStream directly to control the access / sharing.

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);
}

JSON.NET writing invalid JSON?

It appears that JSON.NET is writing invalid JSON, although I wouldn't be surprised if it was due to my misuse.
It appears that it is repeating the last few characters of JSON:
/* ... */ "Teaser":"\nfoo.\n","Title":"bar","ImageSrc":null,"Nid":44462,"Vid":17}]}4462,"Vid":17}]}
The repeating string is:
4462,"Vid":17}]}
I printed it out to the console, so I don't think this is a bug in Visual Studio's text visualizer.
The serialization code:
static IDictionary<int, ObservableCollection<Story>> _sectionStories;
private static void writeToFile()
{
IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication();
using (IsolatedStorageFileStream stream = storage.OpenFile(STORIES_FILE, FileMode.OpenOrCreate))
{
using (StreamWriter writer = new StreamWriter(stream))
{
writer.Write(JsonConvert.SerializeObject(_sectionStories));
}
}
#if DEBUG
StreamReader reader = new StreamReader(storage.OpenFile(STORIES_FILE, FileMode.Open));
string contents = reader.ReadToEnd();
JObject data = JObject.Parse(contents);
string result = "";
foreach (char c in contents.Skip(contents.Length - 20))
{
result += c;
}
Debug.WriteLine(result);
// crashes here with ArgumentException
// perhaps because JSON is invalid?
var foo = JsonConvert.DeserializeObject<Dictionary<int, List<Story>>>(contents);
#endif
}
Am I doing something wrong here? Or is this a bug? Are there any known workarounds?
Curiously, JObject.Parse() doesn't throw any errors.
I'm building a Silverlight app for Windows Phone 7.
When writing the file you specify
FileMode.OpenOrCreate
If the file exists and is 16 bytes longer than the data you intend to write to it (from an older version of your data that just happens to end with the exact same data) then that data will still be present when you're done writing your new data.
Solution:
FileMode.Create
From:
http://msdn.microsoft.com/en-us/library/system.io.filemode.aspx
FileMode.Create: Specifies that the operating system should create a new file. If the file already exists, it will be overwritten

Categories