Powershell Try/Catch not executing when invoked from C# - c#

List item
$LOGFILE="c:\log2\crush1.txt"
function log
{
write-host $($args[0])
echo $($args[0]) >> $LOGFILE
}
log "Main Before TRY"
try {
log "Inside TRY"
}
catch {
log "Inside CATCH"
}
log "Main After TRY"
return "Powershell script completed successfully"
Here is my C# code:
namespace HostSamples {
using System;
using System.Management.Automation; // Windows PowerShell namespace.
using System.Collections.ObjectModel;
using System.Management.Automation.Runspaces;
using System.IO;
using System.Text;
/// <summary>
/// </summary>
internal class HostPS1
{
private static void Main(string[] args)
{
PowerShell ps = PowerShell.Create();
ps.AddScript(LoadScript(#"c:\\temp\\crush1.ps1"));
Console.WriteLine("Starting");
foreach (PSObject result in ps.Invoke())
{
Console.WriteLine(result);
}
Console.WriteLine("Finished");
Console.ReadLine();
}
static string LoadScript(string filename)
{
try
{
using (StreamReader sr = new StreamReader(filename))
{
// use a string builder to get all our lines from the file
StringBuilder fileContents = new StringBuilder();
// string to hold the current line
string curLine;
while ((curLine = sr.ReadLine()) != null)
{
fileContents.Append(curLine + "\n");
}
return fileContents.ToString();
}
}
catch (Exception e)
{
string errorText = "The file could not be read:";
errorText += e.Message + "\n";
return errorText;
}
}
} // End HostPs1. }

I found the answer. For some reason having a write-host call inside the log function caused the try to trigger an exception. The catch also called the log function, so it did not write anything to the output file. The output file traces made it look like the try-catch had been skipped entirely.
I cannot explain why the try-catch would complain about a write-host call, but the rest of the script does not. Possibly a scope issue.
Once I commented out the write-host statement in the log function, everything ran normally.

Related

C# Unhandled Exception: Cannot Read from a Closed Textreader

So I'm trying to have my program read from a text file and display what is on that text file inside the command prompt, like so...
But then the program can read only one line of the file, and then throws this error exception
I've tried going over the lines of my three .cs files they complain about. I tried debugging and editing my code, but the more I do it, the worse it gets, so I'm very lost and confused and I honestly don't know what to fix at this point.
These are the lines of codes they complain about, and right below them are the actual code files.
Line 42 of FileReader.cs --->
return streamReader.ReadLine();
FileReader.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace homework2
{
#region File Reader Class
// ___________________//
// FILE READER //
//____________________//
class FileReader : Reader
{
private StreamReader streamReader;
#region File Reader File Accessing Method
// Accessing the file
public FileReader(string fileName)
{
streamReader = System.IO.File.OpenText(fileName);
if (streamReader == null)
throw new Exception("OpenRead() failed for file " + fileName);
}
#endregion
#region Read Method
// Read Method
public override string Read()
{
// get and return a single line of text
return streamReader.ReadLine();
}
#endregion
#region Close Method
// Close Method
public override void Close()
{
streamReader.Close();
}
#endregion
}
#endregion
}
Line 48 of MorgReader.cs --->
while ((Box = Wrapped.Read()) == null)
MorgReader.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using homework2;
namespace homework2
{
#region Morg Reader Class
//___________________//
// MORG READER //
//___________________//
class MorgReader : ReaderDecorator
{
MorgFactory Fact;
public MorgReader(MorgFactory fact, Reader wrapped) : base(wrapped)
{
Fact = fact;
}
public override string Read()
{
return Wrapped.Read();
}
public override void Close()
{
Wrapped.Close();
}
public Morg ReadMorg()
{
#region splitting the text string
// A way to organize the block of text
string Box = " ";
while ((Box = Wrapped.Read()) == null)
return null;
string[] Part = Box.Split(',');
#endregion
#region Displaying each line of text from Morg Reader File to Morg factory
// Translate the info from Morg file to Morg factory to the program
Morg FactMorg = Fact.CreateMorg();
FactMorg.setName(Part[0]);
#region Converting location string to its variable
// A way to convert the string location to the current variable for location
Location FactLoc;
FactLoc = new Location();
FactLoc.X = Convert.ToInt32(Part[1]);
FactLoc.Y = Convert.ToInt32(Part[2]);
#endregion
/* FactMorg.Move(FactLoc.X, FactLoc.Y); */
FactMorg.setLocation(FactLoc);
FactMorg.setMovement(Part[3]);
FactMorg.setFeeding(Part[4]);
#endregion
return FactMorg;
}
}
#endregion
}
Line 33 of Program.cs --->
while ((NewMorg = MyReader.ReadMorg()) != null)
Program.cs:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace homework2
{
#region Main Program
class Program
{
static void Main(string[] args)
// ____________________ //
// MAIN PROGRAM //
//______________________//
{
MorgReader MyReader = (new MorgReader(new MyMorgFactory(),new FileReader("morgs.txt")));
Morg NewMorg = new Morg("");
while ((NewMorg = MyReader.ReadMorg()) != null)
{
string NewMorgName = NewMorg.getName();
Location NewMorgXY = NewMorg.getLocation();
string NewMorgMovement = NewMorg.getMovement();
string NewMorgFeeding = NewMorg.getFeeding();
Console.WriteLine(NewMorgName + " " + NewMorgXY.X + " " + NewMorgXY.Y + " " + NewMorgMovement + " " + NewMorgFeeding);
MyReader.Close();
}
//MorgTypeA Morg1 = new MorgTypeA("Axel, the Axe-shaped Morg");
//MorgTypeB Morg2 = new MorgTypeB("Bael, the Dark Morg");
//MorgTypeC Morg3 = new MorgTypeC("Corona, the Light Morg");
//Simulator morgGame = new Simulator(Morg1, Morg2, Morg3);
//morgGame.run();
}
}
#endregion
}
This is my first time doing C# and I'm very new to this. I appreciate your grand help.
You are closing your reader on first iteration of your while loop.
public static void Main(string[] args)
{
//some stuff
while ((NewMorg = MyReader.ReadMorg()) != null)
{
string NewMorgName = NewMorg.getName();
Location NewMorgXY = NewMorg.getLocation();
string NewMorgMovement = NewMorg.getMovement();
string NewMorgFeeding = NewMorg.getFeeding();
Console.WriteLine(NewMorgName + " " + NewMorgXY.X + " " + NewMorgXY.Y + " " + NewMorgMovement + " " + NewMorgFeeding);
//MyReader.Close(); -> this line put it out from the while loop
}
//put it here
MyReader.Close();
//other stuff
}

Can't figure out why GetFiles(...) isn't working for me

I'm making a simple program where I'm trying to read through text files and count the number of occurrences of a specific phrase. These text files are in fact log files for my server, but anyhow the folder structure including my program is like
FailedReqLogFiles
....
LogFiles
folder1
textFile1
textFile2
folder2
textFile3
folder3
textFile4
textFile5
textFile6
wmsvg
....
MyProgram.exe
and I'm running
C:\inetpub\logs\MyProgram.exe "LogFiles" "somephrase"
from the Windows command line. The entire source code for my program is
using System;
using System.IO;
using System.Text.RegularExpressions;
class Test
{
static void Main(string[] args)
{
// args[1] = expression to search for, e.g. "cloudrealized-email-top-banner"
try
{
int count = 0;
string [] folders = System.IO.Directory.GetFiles(args[0]); // LogFiles subfolders, e.g. {"W3SVC1", "W3SVC3", "W3SVC5" , ... }
Console.Write("length of folder: {0}\n", folders.Length);
foreach (string thisfolder in folders)
{
string[] logs = System.IO.Directory.GetFiles(thisfolder);
foreach (string thislog in logs)
{
using (StreamReader sr = new StreamReader(args[0]))
{
String line = sr.ReadToEnd();
for (Match m = Regex.Match(line, args[1]); m.Success; m = m.NextMatch()) ++count;
}
}
}
Console.WriteLine("{0} currences of {1} found in log files", count, args[1]);
}
catch (Exception e)
{
Console.WriteLine("Error occured");
Console.WriteLine(e.Message);
}
}
}
and I can't figure out why it's not finding the files, as it keeps printing "length of folder: 0"
Is there any glaring problem with my program?
You're calling string [] folders = System.IO.Directory.GetFiles(args[0]);
Have you instead tried Directory.GetDirectories?
https://msdn.microsoft.com/en-us/library/c1sez4sc(v=vs.110).aspx

How to write log file in c#?

How would I write a log file in c#?
Currently i have a timer with this statement which ticks every 20 secs:
File.WriteAllText(filePath+"log.txt", log);
For everything that i want logged i do this:
log += "stringToBeLogged";
As you can assume the string log just grows and grows as the program runs. (I don't even know if there is a maximum chars per string?)
I assume that there must be better ways of doing this. i just thought that it would be heavy to write the whole file again and again for every time something is added to the log.
From the performance point of view your solution is not optimal. Every time you add another log entry with +=, the whole string is copied to another place in memory. I would recommend using StringBuilder instead:
StringBuilder sb = new StringBuilder();
...
sb.Append("log something");
...
// flush every 20 seconds as you do it
File.AppendAllText(filePath+"log.txt", sb.ToString());
sb.Clear();
By the way your timer event is probably executed on another thread. So you may want to use a mutex when accessing your sb object.
Another thing to consider is what happens to the log entries that were added within the last 20 seconds of the execution. You probably want to flush your string to the file right before the app exits.
create a class create a object globally and call this
using System.IO;
using System.Reflection;
public class LogWriter
{
private string m_exePath = string.Empty;
public LogWriter(string logMessage)
{
LogWrite(logMessage);
}
public void LogWrite(string logMessage)
{
m_exePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
try
{
using (StreamWriter w = File.AppendText(m_exePath + "\\" + "log.txt"))
{
Log(logMessage, w);
}
}
catch (Exception ex)
{
}
}
public void Log(string logMessage, TextWriter txtWriter)
{
try
{
txtWriter.Write("\r\nLog Entry : ");
txtWriter.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(),
DateTime.Now.ToLongDateString());
txtWriter.WriteLine(" :");
txtWriter.WriteLine(" :{0}", logMessage);
txtWriter.WriteLine("-------------------------------");
}
catch (Exception ex)
{
}
}
}
Use File.AppendAllText instead:
File.AppendAllText(filePath + "log.txt", log);
public static void WriteLog(string strLog)
{
StreamWriter log;
FileStream fileStream = null;
DirectoryInfo logDirInfo = null;
FileInfo logFileInfo;
string logFilePath = "C:\\Logs\\";
logFilePath = logFilePath + "Log-" + System.DateTime.Today.ToString("MM-dd-yyyy") + "." + "txt";
logFileInfo = new FileInfo(logFilePath);
logDirInfo = new DirectoryInfo(logFileInfo.DirectoryName);
if (!logDirInfo.Exists) logDirInfo.Create();
if (!logFileInfo.Exists)
{
fileStream = logFileInfo.Create();
}
else
{
fileStream = new FileStream(logFilePath, FileMode.Append);
}
log = new StreamWriter(fileStream);
log.WriteLine(strLog);
log.Close();
}
Refer Link:
blogspot.in
as posted by #randymohan, with using statements instead
public static void WriteLog(string strLog)
{
string logFilePath = #"C:\Logs\Log-" + System.DateTime.Today.ToString("MM-dd-yyyy") + "." + "txt";
FileInfo logFileInfo = new FileInfo(logFilePath);
DirectoryInfo logDirInfo = new DirectoryInfo(logFileInfo.DirectoryName);
if (!logDirInfo.Exists) logDirInfo.Create();
using (FileStream fileStream = new FileStream(logFilePath, FileMode.Append))
{
using (StreamWriter log = new StreamWriter(fileStream))
{
log.WriteLine(strLog);
}
}
}
Very convenient tool for logging is http://logging.apache.org/log4net/
You can also make something of themselves less (more) powerful. You can use http://msdn.microsoft.com/ru-ru/library/system.io.filestream (v = vs.110). Aspx
Add log to file with Static Class
public static class LogWriter
{
private static string m_exePath = string.Empty;
public static void LogWrite(string logMessage)
{
m_exePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
if (!File.Exists(m_exePath + "\\" + "log.txt"))
File.Create(m_exePath + "\\" + "log.txt");
try
{
using (StreamWriter w = File.AppendText(m_exePath + "\\" + "log.txt"))
AppendLog(logMessage, w);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private static void AppendLog(string logMessage, TextWriter txtWriter)
{
try
{
txtWriter.Write("\r\nLog Entry : ");
txtWriter.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(),DateTime.Now.ToLongDateString());
txtWriter.WriteLine(" :");
txtWriter.WriteLine(" :{0}", logMessage);
txtWriter.WriteLine("-------------------------------");
}
catch (Exception ex)
{
}
}
}
if(!File.Exists(filename)) //No File? Create
{
fs = File.Create(filename);
fs.Close();
}
if(File.ReadAllBytes().Length >= 100*1024*1024) // (100mB) File to big? Create new
{
string filenamebase = "myLogFile"; //Insert the base form of the log file, the same as the 1st filename without .log at the end
if(filename.contains("-")) //Check if older log contained -x
{
int lognumber = Int32.Parse(filename.substring(filename.lastIndexOf("-")+1, filename.Length-4); //Get old number, Can cause exception if the last digits aren't numbers
lognumber++; //Increment lognumber by 1
filename = filenamebase + "-" + lognumber + ".log"; //Override filename
}
else
{
filename = filenamebase + "-1.log"; //Override filename
}
fs = File.Create(filename);
fs.Close();
}
Refer link:
http://www.codeproject.com/Questions/163337/How-to-write-in-log-Files-in-C
This is add new string in the file
using (var file = new StreamWriter(filePath + "log.txt", true))
{
file.WriteLine(log);
file.Close();
}
There are 2 easy ways
StreamWriter - http://www.dotnetperls.com/streamwriter
Log4Net like Log4j(Java) - http://www.codeproject.com/Articles/140911/log4net-Tutorial
If your application is multithreaded then in some environments file.appendalltext could give error like file already in use and if you skip that then you could lose important logs .
For that you can use
Lock object technique with file.append.. in that case it will wait for existing process to close and the write your log
This can also save you from adding other libraries in your source
Above code will throw: Process can't access the file because it is being used by another process error because of File.Create(m_exePath + "\" + "log.txt"); if you will comment out this it will work as expected
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace SolutionLogWriter
{
public static class LogWriterClass
{
private static string m_exePath = string.Empty;
public static void LogWrite(string logMessage)
{
m_exePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string fullpath = m_exePath + "\\" + "log.txt";
if (File.Exists(fullpath))
{
File.Delete(fullpath);
}
// File.Create(fullpath);
try
{
FileStream fs = new FileStream(fullpath, FileMode.OpenOrCreate);
using (StreamWriter w = new StreamWriter(fs))
AppendLog(logMessage, w);
}
catch (Exception ex)
{
AppendLog(ex.ToString());
}
}
private static void AppendLog(string logMessage, TextWriter txtWriter=null)
{
try
{
txtWriter.Write("\r\nLog Entry : ");
txtWriter.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(), DateTime.Now.ToLongDateString());
txtWriter.WriteLine(" :");
txtWriter.WriteLine(" :{0}", logMessage);
txtWriter.WriteLine("-------------------------------");
}
catch (Exception ex)
{
txtWriter.Write(ex.Message);
}
}
}
}

Using Office.Interop, certain Powerpoint filenames won't convert

I have a program that converts .ppt or pptx files to png's using C# and the Microsoft.Office.Interop stuff.
It works most of the time, but under certain circumstances, it seems to fail on specific filenames for some nondescript reason.
HRESULT E_FAIL at ... Presentations.Open
It'll fail on CT_Stress_Test - Copy (16).pptx and CT_Stress_Test - Copy (11).pptx It works for (2) thru (19), but fails on only these two. My question is why?
If I were to make copies of these copies, or rename them to something else, it'll convert just fine, so I think it might have something to do with the filename.
I have the same conversion program running on my server and my local machine. My local machine (Win 7) converts the problem files just file. It's only on the server (Win 2008) that I have problems with these two filenames.
EDIT: I've found another number that doesn't work: (38)
EDIT: I formatted the strings with Path functions, and that didn't help.
EDIT: I was able to fix it by trimming all the spaces from the file names. I still want to know why this happens, though.
Here's the program:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.IO;
using Microsoft.Office.Core;
using PowerPoint = Microsoft.Office.Interop.PowerPoint;
using System.Diagnostics;
using System.Timers;
using System.Security.Permissions;
using System.Collections.Concurrent;
namespace converter
{
class Program
{
public static int threadLimit=0;
public static string inDir;
public static string outDir;
public static string procDir;
public static Thread[] converterThreads;
public static BlockingCollection<string> todo;
static void Main(string[] args)
{
todo = new BlockingCollection<string>();
inDir = args[0];
outDir = args[1]+"\\";
procDir = args[2]+"\\";
Int32.TryParse(args[3],out threadLimit);
converterThreads = new Thread[threadLimit];
FileSystemWatcher watcher = new FileSystemWatcher(inDir); //Watcher "thread"
watcher.Filter = "*.ppt*";
watcher.NotifyFilter = watcher.NotifyFilter | NotifyFilters.CreationTime;
watcher.IncludeSubdirectories = false;
watcher.Created += new FileSystemEventHandler(fileChanged);
watcher.EnableRaisingEvents = true;
//Create consumer threads
for(var i=0;i<threadLimit;i++)
{
Conversion con = new Conversion();
converterThreads[i] = new Thread(new ThreadStart(con.watchCollection));
converterThreads[i].Start();
}
//stay open
Console.ReadLine();
}
//Producer
private static void fileChanged(object sender, FileSystemEventArgs e)
{
if(!(e.FullPath.Contains("~$"))){ //Ignore temp files
Console.WriteLine("found =" + e.FullPath);
todo.Add(e.FullPath);
}
}
}
class Logger{
static void toLog(String msg)
{
//TODO: log file
}
}
//Consumer
class Conversion
{
String input;
String output;
String outDir;
String process;
String nameWith;
String nameWithout;
string dir;
static List<CorruptFile> cFiles = new List<CorruptFile>();
int retryLimit = 20;
public Conversion()
{
this.outDir = Program.outDir;
this.process = Program.procDir;
}
//Continually watches collection for files to take.
public void watchCollection()
{
while (true)
{
System.Threading.Thread.Sleep(1000);
try
{
dir = Program.todo.Take();
if (dir != null)
{
this.nameWithout = Path.GetFileNameWithoutExtension(dir);
this.nameWith = Path.GetFileName(dir);
this.output = Path.GetDirectoryName(dir) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(dir);
Console.WriteLine("output = " + this.output);
this.input = Path.GetFullPath(dir);
Console.WriteLine("thread took " + this.nameWith);
convertPpt();
}
}
catch (InvalidOperationException) { }
}
}
public void convertPpt()
{
try
{
var app = new PowerPoint.Application();
var pres = app.Presentations;
var file = pres.Open(input, MsoTriState.msoFalse, MsoTriState.msoFalse, MsoTriState.msoFalse);
file.SaveAs(output, Microsoft.Office.Interop.PowerPoint.PpSaveAsFileType.ppSaveAsPNG, MsoTriState.msoTrue);
file.Close();
app.Quit();
Console.WriteLine("file converted " + input);
moveFile();
}
catch (Exception e)
{
Console.WriteLine("convertPpt failed " + e);
try
{
foreach (Process proc in Process.GetProcessesByName("POWERPNT"))
{
proc.Kill();
Console.WriteLine("process killed");
}
}
catch (Exception e3)
{
}
try
{
if (!(cFiles.Any(x => x.fileName == dir)))
{
cFiles.Add(new CorruptFile(dir));
Console.WriteLine("file added to watch list");
Program.todo.Add(dir);
}
else
{
var found = cFiles.Find(x => x.fileName == dir);
Console.WriteLine("in watch list = " + found.fileName);
if (found.numRetry >= retryLimit)
{
Console.WriteLine(nameWith+ " to be ignored");
try
{
cFiles.Remove(found);
Console.WriteLine("File ignored");
System.Threading.Thread.Sleep(300);
Console.WriteLine("Moving: " + input);
if (File.Exists("C:\\corrupt\\" + nameWith))
{
File.Replace(input, "C:\\corrupt\\" + nameWith, null);
Console.WriteLine("file moved to C:\\corrupt\\");
}
else
{
File.Move(input, "C:\\corrupt\\" + nameWith);
Console.WriteLine("file moved to C:\\corrupt\\");
}
}
catch(Exception e5)
{
Console.WriteLine("could not move file " + e5);
}
}
else
{
Console.WriteLine("retrying file on watch list");
found.numRetry++;
Program.todo.Add(dir);
}
}
}
catch { }
}
moveDir();
}
public void moveFile()
{
Console.WriteLine("moving" + input);
try
{
System.Threading.Thread.Sleep(500);
Console.WriteLine(string.Format("moving {0} to {1}", input, process + nameWith));
if (File.Exists(process + nameWith))
{
File.Replace(input, process + nameWith, null);
}
else
{
File.Move(input, process + nameWith);
}
}
catch (Exception e)
{
Console.WriteLine(string.Format("Unable to move the file {0} ", input) + e);
try
{
foreach (Process proc in Process.GetProcessesByName("POWERPNT"))
{
proc.Kill();
}
}
catch (Exception e3)
{
}
}
}
public void moveDir()
{
if(!Directory.Exists(output)){
return;
}
Console.WriteLine("moving dir " + output);
try
{
Console.WriteLine(string.Format("moving dir {0} to {1} ", output, outDir + nameWithout));
if (Directory.Exists(outDir + nameWithout))
{
Directory.Delete(outDir + nameWithout, true);
}
if (Directory.Exists(output))
{
Directory.Move(output, outDir + nameWithout);
}
}
catch (Exception e)
{
Console.WriteLine(string.Format("Unable to move the directory {0} ", output) + e);
try
{
foreach (Process proc in Process.GetProcessesByName("POWERPNT"))
{
proc.Kill();
}
}
catch (Exception e3)
{
}
}
}
}
class CorruptFile{
public string fileName;
public int numRetry;
public CorruptFile(string fn){
fileName = fn;
}
}
}
First up is a warning from Microsoft in this KB article here. Money quote is:
Microsoft does not currently recommend, and does not support,
Automation of Microsoft Office applications from any unattended,
non-interactive client application or component (including ASP,
ASP.NET, DCOM, and NT Services), because Office may exhibit unstable
behaviour and/or deadlock when Office is run in this environment.
Next question is why not use OpenXML for this? Here's a simple sample to get you started which counts the number of slides in a deck.
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Packaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
namespace OpenXmlDemo
{
class PptOpenXmlDemo
{
public int PptGetSlideCount(string fileName)
{
// Return the number of slides in a PowerPoint document.
const string documentRelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument";
const string presentationmlNamespace = "http://schemas.openxmlformats.org/presentationml/2006/main";
int returnValue = 0;
using (Package pptPackage = Package.Open(fileName, FileMode.Open, FileAccess.Read))
{
// Get the main document part (presentation.xml).
foreach (System.IO.Packaging.PackageRelationship relationship in pptPackage.GetRelationshipsByType(documentRelationshipType))
{
// There should be only a single relationship that refers to the document.
Uri documentUri = PackUriHelper.ResolvePartUri(new Uri("/", UriKind.Relative), relationship.TargetUri);
PackagePart documentPart = pptPackage.GetPart(documentUri);
// Get the slide part from the package.
if (documentPart != null)
{
XmlDocument doc = new XmlDocument();
doc.Load(documentPart.GetStream());
// Manage namespaces to perform XPath queries.
XmlNamespaceManager nsManager = new XmlNamespaceManager(doc.NameTable);
nsManager.AddNamespace("p", presentationmlNamespace);
// Retrieve the list of slide references from the document.
XmlNodeList nodes = doc.SelectNodes("//p:sldId", nsManager);
if (nodes != null)
{
returnValue = nodes.Count;
}
}
// There is only one officeDocument part. Get out of the loop now.
break;
}
}
return returnValue;
}
}
}

File cannot be used because another process is using it - can't find open stream

I'm using a StreamWriter to write to a file. I'm using a "using" so it should close automatically however when I try to save(which writes to the file) it gives me the "cannot access file because another process is using it" error. I can't seem to figure out where or why it is giving me this error. This is my code
[WebMethod]
public static bool saveToCSV(string[] valueArray)
{
bool saveOK = false;
try
{
string filepath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
using (StreamWriter sw = new StreamWriter(filepath + "\\spreadsheet.csv", false))
{
foreach (var i in valueArray)
{
if (i.ToString() == "\n")
{
sw.Write(sw.NewLine);
}
else
{
{
if (i.ToString() == "")
{
sw.Write(" ");
sw.Write(",");
}
else
{
sw.Write(i.ToString());
sw.Write(",");
}
}
}
}
sw.Flush();
}//close using
saveOK = true;
}
catch (Exception ex)
{
saveOK = false;
}
return saveOK;
}
That code looks OK.
Where else are you handling the file? Are all other file IO operations inclosed in a using block? What other applications might be touching the file?
If you open the file elsewhere and haven't disposed of the stream or if another application has the file open you will get this exception.
What's probably going on here is that your saveToCSV method is being called twice at the same time. Essentially two clients calling into the web service at the same time. This can lead to a situation where the first call has the file open for writing and hence the second call is denied access.
In order to protect against this you should use a lock to regulate access to the file
private static object _key = new object();
[WebMethod]
public static bool saveToCSV(string[] valueArray)
{
...
lock (_key) {
using (StreamWriter sw = new StreamWriter(filePath + "\\spreadsheet.csv")) {
...
}
}
}
Now if more than one client call occurs simultaneously they will only try to access the file one at a time

Categories

Resources