I am developing a Windows Phone 8 application but am having a lot of issues with file access permission exceptions hindering the approval of my application when ever I try accessing files in the "local" folder (this only happens after the application has been signed by the WP store, not when deployed from Visual Studio). To solve this I have moved all file operations to IsolatedStorage and this seems to have fixed the problems.
I only have one problem left though. My application needs to make use of the file extension system to open external files and this seems to involve the file first being copied to the local folder where after I can then manually copy it into IsolatedStorage. I have no problem in implementing this but it seems that a file access permission exception also occurs once the system tries to copy the external file into the local folder.
The only way I think this can be solved is if I can direct the system to directly copy into IsolatedStorage but I cannot figure how to do this or if it is even possible. It seems as if though the SharedStorageAccessManager can only copy into a StorageFolder instance but I have no idea how to create one that is directed into IsolatedStorage, any ideas?
PS. Do you think that the Microsoft system might be signing my application with some incompetent certificate or something because there is not a hint of trouble when I deploy the application from Visual Studio, it only happens when Microsoft tests it or when I install it from the store using the Beta submission method.
Below is a screenshot of the catched exception being displayed in a messagebox upon trying to open a file from an email:
EDIT:
Just to make it even clearer, I do NOT need assistance in figuring out the normal practice of using a deep link uri to copy an external file into my application directory. I need help in either copying it directly into isolatedstorage or resolving the file access exception.
Listening for a file launch
When your app is launched to handle a particular file type, a deep link URI is used to take the user to your app. Within the URI, the FileTypeAssociation string designates that the source of the URI is a file association and the fileToken parameter contains the file token.
For example, the following code shows a deep link URI from a file association.
/FileTypeAssociation?fileToken=89819279-4fe0-4531-9f57-d633f0949a19
Upon launch, map the incoming deep link URI to an app page that can handle the file
// Get the file token from the URI
// (This is easiest done from a UriMapper that you implement based on UriMapperBase)
// ...
// Get the file name.
string incomingFileName = SharedStorageAccessManager.GetSharedFileName(fileID);
// You will then use the file name you got to copy it into your local folder with
// See: http://msdn.microsoft.com/en-us/library/windowsphone/develop/windows.phone.storage.sharedaccess.sharedstorageaccessmanager.copysharedfileasync(v=vs.105).aspx
SharedStorageAccessManager.CopySharedFileAsync(...)
I've inline the information on how to do this from MSDN http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj206987(v=vs.105).aspx
Read that documentation and it should be clear how to use the APIs as well as how to setup your URI mapper.
Good luck :)
Ok I figured it out. The "install" directory is actually restricted access but for some reason the Visual Studio signing process leaves the app with enough permissions to access this folder. The correct procedure of determining a relative directory is not to use "Directory.GetCurrentDirectory()" but rather to use "ApplicationData.Current.LocalFolder". Hope this helps!
At first I thought I'm facing a very simple task. But now I realized it doesn't work as I imagined, so now I hope you people can help me out, because I'm pretty much stuck at the moment.
My scenario is this (on a Windows 2008 R2 Server):
A file gets uploaded 3 times per day to a FTP directory. The filename is always the same, which means the existing file gets overwritten every time.
I have programed a simple C# service which is watching the FTP upload directory, I'm using the FileSystemWatcher class for this.
The upload of the file takes a few minutes, so once the File Watcher registers a change, I'm periodically trying to open the file, to see if the file is still being uploaded (or locked)
Once the file isn't locked anymore, I try to move the file over to my IIS Virtual Directory. I have to delete the old file first, and then move the new file over. This is where my problem starts. The file seems to be always locked by IIS (the w3wp.exe process).
After some research, I found out that I have to kill the process which is locking the file (w3wp.exe in this case). In order to do this, I have created a new application pool and converted the virtual directory into an application. Now my directory is running under a seperate w3wp.exe process, which I supposedly can safely kill and move the new file over there.
Now I just need to find the proper w3wp.exe process (there are 3 w3wp.exe processes running in total, each running under a seperate application pool) which has the lock on my target file. But this seems to be an almost impossible task in C#. I found many questions here on SO regarding "Finding process which locked a specific file", but none of the answers helped me.
Process Explorer for example is exactly telling me which process is locking my file.
The next thing I don't understand is, that I can delete the target file through Windows Explorer without any problem. Just my C# application gets the "File is being used by another process" error. I wonder what's the difference here...
Here are the most notable questions on SO regarding locked files and C#:
Win32: How to get the process/thread that owns a mutex?
^^
The example code here does actually work, but this outputs the open handle IDs for every active process. I just can't figure out how to search for a specific filename, or at least resolve the handle ID to a filename. This WinAPI stuff is way above my head.
Using C#, how does one figure out what process locked a file?
^^
The example code here is exactly what I need, but unfortunately I can't get it to work. It is always throwing an "AccessViolationException" which I can't figure out, since the sample code is making extensive use of WinAPI calls.
Simple task, impossible to do? I appreciate any help.
EDIT
Here are some relevant parts of my server code:
Helper function to detect if a file is locked:
private bool FileReadable(string file, int timeOutSeconds)
{
DateTime timeOut = DateTime.Now.AddSeconds(timeOutSeconds);
while (DateTime.Now < timeOut)
{
try
{
if (File.Exists(file))
{
using (FileStream fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.None))
{
return true;
}
}
return false;
}
catch (Exception)
{
Thread.Sleep(500);
}
}
m_log.LogLogic(0, "FileReadable", "Timeout after [{0}] seconds trying to open the file {1}", timeOutSeconds, file);
return false;
}
And this is the code in my FileSystemWatcher event, which is monitoring the FTP upload directory. filepath is the newly uploaded file, targetfilepath is the target file in my IIS directory.
// here I'm waiting for the newly uploaded file to be ready
if (FileReadable(filepath, FWConfig.TimeOut))
{
// move uploaded file to IIS virtual directory
string targetfilepath = Path.Combine(FWConfig.TargetPath, FWConfig.TargetFileName);
if(File.Exists(targetfilepath))
{
m_log.LogLogic(4, "ProcessFile", "Trying to delete old file first: [{0}]", targetfilepath);
// targetfilepath is the full path to my file in my IIS directory
// always fails because file is always locked my w3wp.exe :-(
if(FileReadable(targetfilepath, FWConfig.TimeOut))
File.Delete(targetfilepath);
}
File.Move(filepath, targetfilepath);
}
EDIT2:
Killing the w3wp.exe process while clients are downloading the file would be no problem for us. I'm just having a hard time finding the right w3wp.exe process which is locking the file.
Also, my client application, which is downloading the file on the clients, is checking the HTTP HEAD for the Last-Modified date. The client is checking the date every 10 minutes. So it is possible that the file is being locked by IIS because there are clients continously checking the HTTP HEAD for the file. Nonetheless, I don't understand why I can manually delete/rename/move the file through windows explorer without any problems. Why does this work, and why does my application get a "Locked by another process" exception?
One problem I've run into is that a file exists while it is still being written, which means it would be locked as well. If your FileReadable() function were called at this time, it would return false.
My solution was to, in the proc which writes the file, write the file to, say, OUTPUT1.TXT, and then after it is fully written and the FileStream closed, rename it to OUTPUT2.TXT. This way, the existence of OUTPUT2.TXT indicates that the file is written and (hopefully) unlocked. Simply check for OUTPUT2.TXT in your FileReadable() loop.
Everybody say...
"Do it a better way"
Nobody say how!!!
Here's how. Because you mentioned 'My Client Application,' there is a key opportunity here that you would not have if you didn't have control over the apps reading the file.
Just use new filenames each time.
You have control of the program reading and writing the files. Put an incrementing # in the filesnames, have the client pick the biggest # (Actually the latest date, then your numbers can wrap around). Have the writer program clean up old files if it can; if not, they won't hurt anything. IIS will eventually let go of them. If not, just open up explorer every week and do it yourself!
Other keys that make this work are the low frequency of updates (files won't build up too bad), and the fact that the FTP+webserver are on the same drive (Otherwise the MOVE is not atomic and clients could get a half-copied file. Solution if FTP drive is different would be to copy to a temp drive on the webserver then move).
but what if you can't change the client or it has to read just one name?
Front-end it with a script. Have the client hit an ASPX that sets the right HTTP headers and has the 'pick the right file' logic, and spits out the file contents. This is a very popular trick pages use to write images stored on a database out to the browser, while the img tag appears to read from a file. (google along that lines for sample code).
sounds like a hack, it's not. Modern lockless memory cache systems do a similar thing. It is impossible for a lock or corruption to occur; until the 'write' is complete, readers see the old version.
plus, it's simple, everybody from a script kiddie to a punchcard vetern will know exactly what you're up to. Go low-tech!
You're troubleshooting a symptom of the problem not a fix for the root cause. If you want to go down that path here is the code to kill processes http://www.codeproject.com/Articles/20284/My-TaskManager - but the better idea would be to do it properly and work out whats wrong. I suggest in the Catch Exception of FileReadable:
catch (Exception ex) {
if (ex is IOException && IsFileLocked(ex)) {
//Confirm the code see's it as a FileLocked issue, not some other exception
//its not safe to unlock files used by other processes, because the other process is likely reading/writing it.
}
}
private static bool IsFileLocked(Exception exception)
{
int errorCode = Marshal.GetHRForException(exception) & ((1 << 16) - 1);
return errorCode == 32 || errorCode == 33;
}
Turn off any Anti-Virus software and re-test
Increase the polling timeout duration to see if its just a timing thing
Check the FTP logfile and see the status for the disconnected client and compare the status code with the ones here.
I don't see in your sample code where you are closing your file stream. Keeping the file stream open will keep a lock on the file. It would be a good idea to close the stream. You probably don't want to be killing your w3wp.exe process, as others here have mentioned.
restarting IIS can unlock the file taken by w3wp.exe.
cmd (run as administrator) -> iisreset /stop -> update/delete file in
windows explorer -> iisreset /start
I am developing c# application, which is running as a windows service.
What ever transactions we are doing in the application i am writing it into log file.
A log directory is added in app.config file as below.
<add key ="LogDir" value="log" />
<add key ="LogLevel" value="2" />
And in the c# code the above one is accessing as below.
int logLevel = Convert.ToInt32(ConfigurationManager.AppSettings["logLevel"]);
if (logLevel > 0)
{
logger = new Logger();
logger.TraceLevel = logLevel - 1;
logger.logDir = ConfigurationManager.AppSettings["logDir"];
logger.logFileBaseName = "touchserver";
}
And then when any process is happening i am writing the data to the log as below.
TouchServer.Log(Logger.MessageType.Trace, 1, "Item successfully deleted");
And when i run my application in debug mode (i mean as console application) the log file will be created in the application's debug folder and the data will write into the log file.
But my problem is that when i install my application as service the log file is not getting created in the debug folder, and i am unable to see the actions performed , in case if anything went wrong.
Please help me to find a solution in this.
And i am installing service using Installutil command.
Thanks in advance
sangita
While you could get into why this is not working and fix the solution, overall there is no need to implement a logging component.
There are excellent free libraries available that do this very well. log4net is very popular. It is easy to use, feature rich and efficient. Take a look at it.
But my problem is that when i install my application as service the log file is not getting created in the debug folder, and i am unable to see the actions performed , in case if anything went wrong.
Check out what are the result of the IO operations by using Process Monitor. I suspect you'll find the identity being used to run the service process does not have write permissions where it is trying to write the log file.
But the better option is to use an existing logging library as Hemal suggests.
I have a service that controls an RS-232 device and logs actions to a file. I am to write another service which will read the log file line by line and run some queries on a database then delete all the logs.
My concern is about read and write conflicts on the file. For example, the logger service open the file to append a new line at the same time the replicator service opens the file and write "" so truncate its content.
Any suggestions to clarify my situation?
How about modifying the "read" service to rename the file first (putting a "_" in front of it is what I usually do). And then it can delete it when done. The write service should create the log file if it does not exist. This way you should have zero data loss.
If your are not tied to use a file, the use case would suggest a message queue for handing over your log messages.
I'm using asp:FileUpload control to upload a file to the server. Nothing fancy there, just
FileUploadId.Save();
File gets uploaded successfully, and everything is fine until I try to delete that file on the CLIENT. I get a good-old "File is being used by another person or program" message.
How do I make sure that file is not being accessed on the client after it's been uploaded?
EDIT
deleting the file has nothing to do with the application. i'm just trying to delete the file manually since i don't need it any more.
EDIT2
closing the browser fixed the problem ... any ideas?
Since the problem happens both in IE and FF: could it be that the file is locked by some AntiVirus software?
The issue might be the file can be locked by the aspnet process even after uploading. Once you close the IE, the aspnet process release the file
How are you trying to delete the file at the client? Unless you're hosting in WebBrowser, or using something like an ActiveX control, you only have javascript at the client - and that doesn't provide random file access.
So: what is the full setup here?
A thought. It may not be the file upload that is causing the problem. As the surrounding code isn't posted it's difficult to tell, but, for example, do you have a Zip manager object of some kind that you're not disposing of?