11

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...

Community
  • 1
  • 1
Smudge202
  • 4,689
  • 2
  • 26
  • 44
  • 1
    In addition, and as a slight besides, I am 99.99999% that the file I currently have issues with, worked last night. The service actually failed on a different file (further in a loop of supplied paths) with the same error last night. I.E. I have a list of string { "PathA", "PathB", "PathC" }. Last night, PathA suceeded, PathB failed with the above error. Today, PathA fails and I don't get as far as PathB. I didn't put this in the OP directly because it's just plain confusing the matter... – Smudge202 Jun 24 '11 at 15:01
  • 1
    I take it this "network share" and the local machine are not on the same Domain? – insipid Jun 24 '11 at 15:38
  • 1
    @insipid : All the same Domain. Local Machine is my Dev Machine at work. Server is one of the machines downstairs. NAS is sat in same room as server (physcially). All on the same LAN, all on the same Domain. Not sure why you ask, but in case it's because I tested the NAS - the NAS has a hardcoded 25 simultaneous connections limit, so wanted to eliminate that as being a cause. – Smudge202 Jun 24 '11 at 15:44
  • 3
    +1 Probably one of the longest questions in SO. You must be really frsutrated! – Mrchief Jul 02 '11 at 03:47
  • 1
    @MrChief, all my questions turn out this long - it's a combination of frustration and my inability to keep things short =) – Smudge202 Jul 03 '11 at 13:35
  • 1
    what is the Security Conext of the WCF Service? – Amit Bagga Jul 03 '11 at 17:19
  • @Amit, what do you mean? – Smudge202 Jul 04 '11 at 06:21
  • 1
    I wouldn't even come close to answering this.. have no considerable experience in WCF.. but I can tell you one thing - Instead of making changes to the Service Account or changing it to your personal admin account.. Can you try giving full permissions to "Everyone"(or may be "domain\Everyone") on that file/directory as a temporary measure.. – Sekhar Jul 22 '11 at 15:43

4 Answers4

4

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.

Mike
  • 3,462
  • 22
  • 25
1

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?

Fabio
  • 730
  • 3
  • 10
  • 1
    Unfortunately not. I happen to know that this file has been sat on this network share for a little over 4 years. However, that I was able to open the file from 2 seperate locations, copy the file to my local PC, and access the file in code using test projects confirms the stream was available. Thanks for the suggestion though – Smudge202 Jun 27 '11 at 12:30
1

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.

Alex Peck
  • 4,603
  • 1
  • 33
  • 37
  • 1
    Hi Alex, I considered the same thing. The WCF Service does not use impersonation, but I did wonder what effect the Service Accounts might have. That's why in my tests I changed the accounts to admin, but it didn't seem to have any effect. Thanks for the links though! – Smudge202 Jul 02 '11 at 11:22
  • If it is a double hop problem, being admin (domain admin) won't help. Maybe you already tried this, but does it work if you invoke the WCF service from the computer on which it is hosted? – Alex Peck Jul 02 '11 at 11:29
  • 1
    Yes, one of my tests was to host the WCF Service library in a console app (the normal MSDN way). I then placed that host on the same server and started it up. Using WcfStorm I invoked the newly hosted WCF Service and the code worked fine. Strange, huh!???? – Smudge202 Jul 03 '11 at 13:42
  • If it works when invoked from the local machine, but not from a remote machine, the problem is almost certainly related to Windows attempting to delegate the security token, then finding that it cannot, and attempting to access the file share using an empty token (anonymous login) instead. This is why you get an access denied error. – Alex Peck Jul 03 '11 at 14:43
  • I invoked it remotely every time - there is not software on that server that can invoke WCF Services. – Smudge202 Jul 04 '11 at 06:20
  • In that case I would try using process monitor to see if you get any additional information about the file operation that is failing: http://technet.microsoft.com/en-us/sysinternals/bb896645 – Alex Peck Jul 04 '11 at 10:48
  • Yeh, somebody else sugggested the same thing so it's definitely on my list. I'd be (even more) baffled if it showed the file was locked by a process though, because I was able to open the file from several other locations, and the same location, using a variety of methods. Thanks for the info on the double hop though and general network security bits! – Smudge202 Jul 04 '11 at 12:08
1

I have a few hunches.

Have you tried setting 'FileAccess.Read' and/or 'FileShare.Read' to 'ReadWrite'?

Also, is it possible this warning could be a factor? From http://msdn.microsoft.com/en-us/library/5h0z48dh.aspx:

Caution

When you compile a set of characters with a particular cultural setting and retrieve those same characters with a different cultural setting, the characters might not be interpretable, and could cause an exception to be thrown.

  • 1
    thanks for your answer. I had set it to Read because the file is only required for read. In all honesty, I don't admit to knowing much about what's going on under the hood when setting those enumerations - I assume it's something similar to the types of locks in SQL Server. Next time I have this issue I will try with the Enum set to ReadWrite just out of curiosity. Regarding culture, I hadn't considered it. I don't set culture anywhere, and the server was able to run the code, just not within the service+WCF environment. – Smudge202 Jul 03 '11 at 13:40