When I was working on the latest release of the BlogThisUsingPostXINGPlugin,
I kept running into file access issues.
The whole thing was an excersize in refactoring - well, really, the whole
thing WAS a refactor, since the basic functionality already existed, but I was
making additions in how things were going to work.
First, I changed the XsltStream to return a FileStream or a
ManifestResourceStream, based on the existence of a user-specific file:
1 Stream XsltStream
2 {
3 get
4 {
5 string filePath = Path.Combine(ConfigurationPath, this.BlogType.ToString() + ".xslt");
6 if(File.Exists(filePath)){
7 //read from a file stream.
8 FileStream fs = new FileStream(filePath, FileMode.Open);
9 return (Stream)fs;
10 }else{
11 string resourceName = "PostXING.Rss.BlogExtensions.Resources." + this.BlogType.ToString() + ".xslt";
12 return Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName);
13 }
14 }
15 }
Again, this part was shamelessly lifted modified from
haacked who generously gave out the source
code for his BlogThisUsingWbloggarPlugin. (the configurationPath property was
changed a bit to enable more than one file to go into that particular path).
Then I added a button next to each option in the config dialog that says
simply "Customize...". Pressing this button opens a modal form that loads up the
text from the user-defined file if it exists, else from the resource
stream.:
1 string transformPath;
2
3 public CustomizeForm()
4 {
5 //
6 // Required for Windows Form Designer support
7 //
8 InitializeComponent();
9
10 }
11
12 public CustomizeForm(string TransformToCustomize) : this(){
13 transformPath = Path.Combine(BlogThisUsingPostXINGPlugin.ConfigurationPath, string.Format("{0}.xslt", TransformToCustomize));
14
15 this.LoadTransform(TransformToCustomize);
16 }
17
18 private void LoadTransform(string TransformToCustomize){
19 string resourceName = string.Format("PostXING.Rss.BlogExtensions.Resources.{0}.xslt", TransformToCustomize);
20 //Stream resourceStream;
21 StreamReader sr;
22
23 if(File.Exists(transformPath)){
24 sr = new StreamReader(transformPath);
25 this.rtbTransform.Text = sr.ReadToEnd();
26 sr.Close();
27
28 }else{
29 sr = new StreamReader(ResourceStream(resourceName));
30 this.rtbTransform.Text = sr.ReadToEnd();
31 sr.Close();
32
33 }
34 }
35
36 Stream ResourceStream(string resourceName){
37 return Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName);
38 }
3 buttons were added to the form: Revert to Original, Apply, and Cancel. I
didn't really think that I needed DialogResults, since you have to invoke the
plugin via its menu every time you want to use it. Revert to Original just
deletes the user-defined file. Cancel simply closes the form and does nothing.
Apply does this:
1 private void btnApply_Click(object sender, System.EventArgs e) {
2 if(File.Exists(transformPath)){
3 File.Delete(transformPath);
4 }
5
6 StreamWriter sw = new StreamWriter(transformPath, false); //doesn't release file handle?
7 sw.Write(this.rtbTransform.Text);
8 sw.Flush();
9 sw.Close();
10
11 this.Close();
12 }
Notice my little note to myself? It turned out that I tried using the using
statement, using File.CreateText(transformPath) (which is why the pre-step
File.Delete is in there) and I kept getting "Cannot access file 'blah' because
it is in use by another process." When I opened up sysinternal's process
explorer and searched for the file, it said that the file handle was opened by
RssBandit. grr.
All I ended up having to do was to add one argument to File.Open from the
XsltStream property getter:
1 Stream XsltStream
2 {
3 get
4 {
5 string filePath = Path.Combine(ConfigurationPath, this.BlogType.ToString() + ".xslt");
6 if(File.Exists(filePath)){
7 //read from a file stream.
8 FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
9 return (Stream)fs;
10 }else{
11 string resourceName = "PostXING.Rss.BlogExtensions.Resources." + this.BlogType.ToString() + ".xslt";
12 return Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName);
13 }
14 }
15 }
And bam! the problem went away. It looks like the default for a new
FileStream (sans FileAccess attribute) is FileAccess.ReadWrite. Anyways, I hope
this helps someone else out there from banging their head too much.
[ Currently Playing : Inertiatic ESP - Mars Volta - De-Loused In
The Comatorium (4:23) ]