Windows Service cannot create a text file - c#

Ok so this is my code for the OnStart method
File.CreateText("test.txt");
StreamWriter write = File.AppendText("test.txt");
write.WriteLine("Hello world, the service has started");
write.Flush();
write.Close();
I am successfully able to install the service. However when i start i get the message that the service started and then stopped. When i check the Event Viewer it gives me this
Service cannot be started. System.IO.IOException: The process cannot access the file 'C:\Windows\system32\test.txt' because it is being used by another process.
Ok what's going on here. I don't think its a permission problem as the ProcessInstaller is set to LocalSystem.

You do not need to use the first File.CreateText statement. This creates a stream writer on the file which is not closed.
Your File.AppendText tries to create a new StreamWriter on the same file and hence you get the File in use error.
Also, as MSDN says your file will be created if it does not exist.
If the file specified by path does not exist, it is created. If the file does exist, write operations to the StreamWriter append text to the file

You can use like this
string path = #"path\test.txt";
if (!File.Exists(path))
{
// Create a file to write to.
using (StreamWriter sw = File.CreateText(path))
{
sw.WriteLine("Hello world, the service has started");
}
}

I think one line code is more then enough.
File.AppendAllText(#"path\test.txt", "Hello world, the service has started");
Appends the specified string to the file, creating the file if it does not already exist.

you should try with the full path for the file, the windows service run in the C:\Windows\System32 folder
string fileName="E:\\Service\\file.txt"
File.Create(file);

Related

Can I ReadLock a file while I create/modify it using System.IO.File.WriteAllText() method?

I need to create a process that creates/modifies some text files in a folder. I am using below code to do that:
file = new System.IO.FileInfo(filePath);
file.Directory.Create();
System.IO.File.WriteAllText(file.FullName, "Some text...");
I have a Biztalk queue that looks into the text files in the folder every 2 minutes and picks up the files to process them. I want to lock the files when I am creating/modifying so that Biztalk wont try to process those files. How can I achieve this?
I read about Transactional NTFS in windows which will let me create Transaction context but windows documentation says this feature will deprecated and recommends not to use it.
If the file is on a local NTFS volume of CIFS share, the File Adapter will not attempt to read an open file. However,
A better pattern would be to do your file work in a temporary folder, then copy the completed files to the BizTalk folder only when they are done. That way, you don't have to worry about locking at all.
To acquire an exclusive lock you can use the file stream to do so
using (FileStream fs = new FileStream("Test.txt", FileMode.Append, FileAccess.Write, FileShare.None))
{
using (StreamWriter sw = new StreamWriter(fs))
{
sw.WriteLine("test");
}
}
This way you are locking the file exclusively for the current file stream. Any other application or even a new instance of file stream from another thread within the same application attempts to read or write to the file will be denied by the operating system.
In most cases, write file with different extension then rename the file works fine.

How can I get the file path for a file I only know the name of? C#

So I'm making a Tic Tac Toe application and have created a Text file linked to the program to hold the following information:
the name
the time took to win
the difficulty
I know the timer is redundant for a quick game like Tic Tac Toe but I'll use it in the future for other programs.
My question is how can I find the full path of the file while only knowing the name of the file?
I want to do this using the program so it can be transferred to any computer and still be able to access the file without the user having to input it.
The code I've tried is:
string file_name = Path.Combine(Environment.CurrentDirectory, "Tic Tac Toe\\HighScores.txt");
But this just looks in the Debug folder, where the file isn't located. The application is entirely a console application.
Try to dedicate the file in a fixed sub directory:
\TicTacToe.exe
\settings\settings.cfg
So the path is dependent of your executable file.
You'll fetch the directory by calling Directory.GetCurrentDirectory()
You can set a desired directory by setting Environment.CurrentDirectory
A common way to handle this case is the one described above.
Another would be to use user specifiy directories like the %appdata% path and create a dedicated directory there.
%appdata%\TicTacToe\settings.cfg
Everytime your application starts it should lookup the folder %appdata%\TicTacToe\
If it is present, your application has been executed with this user.
If not, just create a new one, so we know it's the first run.
You can get the %appdata% path by calling
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
Example of what i would have done
private void setUp(){
string filename = "settings.cfg";
string dir = "TicTacToe";
string appdata =Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
string fullpath = Path.Combine(Path.Combine(appdata,dir),filename);
//check if file exists, more accurate than just looking for the folder
if(File.Exists(fullpath )){
//read the file and process its content
}else{
Directory.CreateDirectory(Path.Combine(appdata,dir)); // will do nothing if directory exists, but then we have a bug: no file, but directory available
using (FileStream fs = File.Create(fullpath))
{
Byte[] info = new UTF8Encoding(true).GetBytes("This is some text in the file.");
// Add some information to the file.
fs.Write(info, 0, info.Length);
}
}
}
Hope it helped.
Perhaps have a configuration file for your application and store the directory name in there.
An old example from MS, but should still be applicable...
How to store and retrieve custom information from an application configuration file by using Visual C#

StreamReader path changes automatically

I have some strange problem (for me).
There is an application which is a windows form application "firstapp.exe".
There is another application which is windows form application too "launcher.exe".
And there is a console application with name "server.exe".
Both firstapp and launcher are in the same directory. In that directory there is also a "Config" folder with some other files in it.
The code which I use to read one file from config folder in firstapp:
StreamReader reader = new StreamReader("Config\\launcher.txt");
string readed_config = reader.ReadToEnd();
reader.Close();
If I run the firstapp application with launcher (using process.start) all goes fine.
When I run it with console application, which is not in the same directory as firstapp I get the "directory not found exception" from that part of code (posted above).
How can I solve the problem?
Why is console application adding its own path to another application which should run independently?
Sounds like you need to set the WorkingDirectory property of your Process before calling Process.Start.
string launcherPath = #"C:\SomePathToLauncher\Launcher.exe";
myProcess.StartInfo.FileName = launcherPath;
myProcess.StartInfo.WorkingDirectory = Path.GetDirectoryName(launcherPath);
myProcess.Start();
StreamReader reader = new StreamReader("Config\\launcher.txt");
Never use hard-coded relative file paths in your code. It critically depends on Environment.CurrentDirectory and that's way too unpredictable. External code can kill you as you found out. Internal code as well, use OpenFileDialog and your code will crash. You can always get a full path with Assembly.GetEntryAssembly().Location and the Path class:
var exedir = Path.GetDirectory(Assembly.GetEntryAssembly().Location);
var path = Path.Combine(exedir, #"Config\launcher.txt");
using (var reader = new StreamReader(path)) {
//...
}
Now it always works.
It's because your path is relative and the Current Working Directory is different when the console app kicks off your winform. Also, you should wrap the stream reader in a using statement. As it stands, unless you explicitly call Dispose() elsewhere in your code you're holding on to resources that should be freed.
To fix your problem either change the WorkingDirectory when you start the process using Process.StartInfo.WorkingDirectory or change the path in your code so it is not relative. Or another option would be to pass the path to the application or read it from a resource file so that it can be given the appropriate path when it executes.
the answer is in the question. you are saying that "When I run it with console application, which is not in the same directory". if it's not in the same directory how will it find a directory "Config" if it diesn't exist there. make sure that the directory exist there

XML Read throws "device not ready"

I'm trying to read a xml file but everytime the code arrives at the load()-function it throws the exeption "the device is not ready". This is the code:
const string filepath = #"E:\xml\somefile.xml";
XmlDocument fileDoc = new XmlDocument();
fileDoc.Load(filepath);
The drive "E:\" is a physical HDD where the webapplication is saved in a folder called "app". So the folder xml is completely independent of the web apllication and iis. I also tried to locate the xml in the application folder but the same error occured.
Has someone an idea what I am missing?
Check if the file "E:\xml\somefile.xml" is not locked in you process when you try to read the xml. Use the right usinging of call Dispose() on the objects which write the file.

Issue while reading a xml file in WCF service

WCF service has one method ( Let's say TestMethod) in which I try to create a File Stream like this :
System.IO.FileStream fs = new System.IO.FileStream(#"D:\Test.xml", System.IO.FileMode.Open);
My Client and Service is on the same solution.
When the Client makes a call to TestMethod ( Exposed in Web service ) it will give this error:
Access to the path 'D:\DXDirectoryAuth.xml' is denied.
Please Help!!
Okay, if you have put the file in the directory or a sub-directory of your WCF service you should be able to access the file without any permissions issues.
The question is how are you attempting to access the file?
You should probably get the current directory of the service then append the relative file location onto the current directory and then attempt to open the file something like this:
var appPath = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath;
bodyFile = Path.Combine(appPath, #"templates\email.txt");
var body = File.OpenText(bodyFile).ReadToEnd();
HTH
Ollie
Have you tried:
System.IO.FileStream fs = new System.IO.FileStream(#"D:\Test.xml", System.IO.FileMode.Open, System.IO.FileAccess.Read);
The default constructor of FileStream() asks for read and write access.
Security!
The reason being you are trying to access a file location outside of the directory where you have hosted your WCF service...
You are either going to have to grant the account the WCF runs under permissions to that directory or move the file into the directory\sub-directory where you are hosting the WCF service.
Ollie

Categories

Resources