This is a slightly tricky one, so bear with me...
I have a simple little method:
Public Overloads Shared Function DoStuff(ByVal path As String) As Boolean
If Not IO.File.Exists(ipath) Then Throw New ArgumentException
Dim result As Boolean
Using fs As FileStream = New FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)
' do stuff here, details are not important
fs.Close()
End Using
Return result
End Function
I appreciate that the method does not show how the stream is used, but the details are irrelevant as I'll explain below.
This method is sat snuggly in a Class Library; a Helper which we reference in a variety of other projects. Clearly, for the most part that code should look fine on the assumption the path is valid, accessible, etc.
Now, the issue. I have a WCF Service Library that references and consumes the aforementioned Method in the Helper assembly. The WCF Service Library is hosted within a Windows Service, which in turn resides on one of our servers. The WCF Service has an Operation that receives a UNC Path for a file, and during normal flow, calls the method above in the Helper Class.
The path I send is for a file, on a share, on our network. The line "Using fs As..." fails with the following exception:
System.UnauthorizedAccessException: Access to the path 'my file path is listed here' is denied. at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath) at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy) at System.IO.FileStream..ctor(String path, FileMode mode) at MyHelperAssemblyName.DoStuff(String filePath) in the rest of the exception is a stack trace pointing to the method, assembly, wcf service, etc"
Now, a list of things I have tried to diagnose the issue (including the stupidly obvious steps):
Copy and Paste the path listed in the Stack Trace into Windows Explorer (both on my local machine and the server) to ensure the file exists and is accessible --> Able to Access the file
Ensure that the Windows Service's account has sufficient permission on the file to read --> Effective Permissions lists the Service's Account as having Full Control
Change the Windows Service's account to use my personal admin account (temporary measure) and obviously restart the service for changes to take effect --> The same line of code fails
Copy the Directory containing the file to my local machine, and run the service against my local machine (we wanted to ensure that the NAS which hosts the file wasn't the cause) --> The same line of code fails
Create a quick console application, copy paste the code from the helper assembly's method into the application, inject the same file path, run it locally and then on the server (by on the server, I mean remote connect to the server using the same Admin account I mentioned earlier, and run it) --> The application has no problems running the code
Create a Console Application and use the bulk standard way of hosting the WCF Service Library within the Console Application. Run the Application locally, and then, using WcfStorm against the local address I specified as the base address for the console app, call the same method with the same path that the normal service fails on --> The results from WcfStorm confirm that the code had no problems
Double check the WCF Service Library's code to ensure that there isn't any perculiar conditional logic that would effect my tests --> The Helper Method is called almost immediately after the Service Operation Implementation starts (just after argument validation). It is not possible for the operation to return coherent results without running through the helper method so when I had been receiving coherent results previously and assumed the "weird" file access code had been run, it had, infact been run
Re-deployed the Service with clean rebuilds of the Windows Service Host, WCF Service Library, and Helper Assembly (wanted to make sure the code on my screen was infact the code that was running on the server) --> No change
EDIT 2011-06-24 16:32GMT - Using the console app I created earlier to host the WCF service, adjust the baseAddress accordingly and deploy on the server. Run the app using the same Admin account as mentioned above. Test the new app on the new base address using WcfStorm. --> Code works as expected and returns good results (I believe at this stage narrowing it down to being the fault of the Windows Service?)
EDIT 2011-06-27 10:21GMT - Created a simple Windows Service, referencing the helper class. Installed on the Server, the service's account set to the the same as the Live Server. --> The new Service was able to run the code and access the file
EDIT 2011-06-27 10:23GMT - Annoyed that the service had worked, I pulled open WcfStorm which I had left running over the weekend. The results were stills displayed from Friday showing the live service had failed. I resent the same request --> It worked... I'm actually more annoyed now because I have no real means of tracking the issue
So, the service is for now working correctly. Anyone have any ideas what would cause such an intermittent failing? I'm assured by co-workers that nothing was changed over the weekend (not manually at least). Baffled...
An UnauthorizedAccessException exception is thrown when the operating system denies access because of an I/O error or a security error. If you are attempting to access a file or registry key, make sure it is not read-only.
Solution for “Access to the path is denied” error The root cause is that the application pool which is hosting your web application is not able to access to the shared folder you specified in your code. Therefore, it throws “Access to the path is denied” message.
You might be able to resolve this issue by restoring your ownership of the files and folders. To take ownership of a file or a folder, follow these steps: Right-click the folder that you want to take ownership of, then click Properties. Click the Security tab, click Advanced, then click the Owner tab.
Try process monitor. It will show you what user is accessing the file and the specific windows error code that is being returned. Then you should be able to see why it is working for some files and not others.
I had something similar when my code was accessing a new file which wasn't yet fully written to disk. So waiting a few milliseconds solved it for me. Is it possible that you are trying to read that stream before it's being completely written to disk?
Does your WCF Service use impersonation?
This would explain why the new windows service can perform the action but the WCF service could not. The new service authenticates directly against the NAS. If in the old service, WCF were impersonating the caller, the client computer authenticates the user, their token is passed to your WCF service, which in turn passes the security token to the NAS, and you hit the double hop problem.
You can make the active security context revert to the service account like this:
using (WindowsIdentity.Impersontate(IntPtr.Zero))
{
DoStuff();
}
Of course, this doesn't explain why it might have been working intermittently. But it would explain the WCF service working when invoked locally on the machine that is hosting it, but not from a remote client machine.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With