I'm calling the following code from Windows service that was written with C#:
try
{
ServerManager m = new ServerManager();
if(m != null)
{
SiteCollection sites = m.Sites; //I get exception here
}
}
catch (Exception ex)
{
}
I get this exception:
{"Filename: redirection.config\r\nError: Cannot read configuration
file\r\n\r\n":null}
What does that mean? And is there any way to predict it in ServerManager or my m variable before it's thrown?
Update: After looking at your comment now I can answer the question fully, the problem is your application is referencing the wrong Microsoft.Web.Administration.dll, seeing the error tells me you are referencing the IIS Express version and not the "full" IIS Version (7.0.0.0). So please modify your application code to add a reference to the one that is in c:\windows\system32\inetsrv\Microsoft.Web.Administration.dll instead.
This is a permissions problem.
You will need to make sure to run the Windows Service as an identity that is either a member of the Administrators group or SYSTEM. My guess is you might be running the service as Local Serivce or Network Service and those do not have permission to read the configuration files that sit in %windows%\system32\inetsrv\config.
Other Info:
Redirection.config is a file that IIS uses to determine if it should read its configuration from the normal path (%windir%\system32\inetsrv\config\applicationHost.config) or should read it from say an external UNC file share when centralized configuration is used for many servers. That is why this is one of the first files to be parsed and hence you get that access denied error for that specific file.
Regarding the predicting, the best thing to do would be to create it within a try/catch and handle that. There are many exceptions that could happen when reading configuration, such as permissions (you could predict this one by making sure you can read (say File.OpenText()) to Redirection.config, ApplicationHost.config in %windir%\system32\inetsrv\config but that is guessing and there are others such as access to encryption keys for passwords, invalid config, etc, etc.)
Related
Im having trouble with writing files to remote directory via network. The following code fails when I try to check if the directory exists:
if (!Directory.Exists(processingPath))
Directory.CreateDirectory(processingPath);
processingPath is composed like
processingPath = xxxObject.serverPath + "processing\\";
xxxObject.serverPath contains something like this
\\machineNetworkName\sharedFolder\
Its working properly, but when many requests are processing (running as tasks asynchronously), it stops working and failing into exception:
System.IO.IOException: The network path was not found.
Could you please help me what could be the problem and why it is failing after some time on network path???
Thanks for your solutions
I got the same error before, it was about authentication problems.
You have to be sure that you set properly the user on IIS, because it use a Default App Pool's identity which can't access to your NFS.
You can also use IIS virtual folders to set the identity.
(on IIS manager, see App Pool settings -> Identity and also virtual folders settings -> identity).
In my case, it worked better by using the Impersonation directly in the code, so I recommend you to use the VladL WrappedImpersonationContext Object: How to provide user name and password when connecting to a network share
Last thing to check, the owner of the files on your NFS server, if they were created under the root user, it might not work.
I had the same problem and solved it. The problem in my code and I see it in yours, too, is that you have the slash at the end of the network path.
Instead of processingPath = xxxObject.serverPath + "processing\\"; write: processingPath = xxxObject.serverPath + "processing";
I deployed my internal web application to server A and got an error when creating a file to a network drive on server B. If I run locally, the file got created on server B successfully.
System.UnauthorizedAccessException: Access to the path '\\b\folder\test.pdf' is denied.
The identity of the application pool is networkservice. And I gave networkservice full control on the destination folder on server B. I even gave Everyone full control, but it still got the error.
Server A runs .NET 7.5. Code to create file:
var byteArray = generateArray();
var destination = "\\\\b\\folder\\test.pdf";
try {
var destinationFile = new FileInfo(destination);
if (destinationFile.Exists) {
destinationFile.Delete();
}
System.IO.File.WriteAllBytes(destination, byteArray);
} catch (UnauthorizedAccessException) {
//
}
I've seen someone got the exact same problem here. But it didn't solve mine.
Solution:
I changed the identity to administrator account instead of using network service for the application pool. It works but I don't fully understand why it works. Because the network service on A is different than the one on B?
Even though you provided access to everyone, certain applications have to receive specific permission. This was apart of the UAC System introduced in Window's Vista. This move was to increase security, so an application couldn't run under any user and basically have full access.
What you should do, is on the directory provide the following access:
IIS AppPool\NameOfAppPool
That will provide specific access to your hosted web application to that directory, for IIS will be able to correctly manipulate the directory. Some code you could implement to help validate before you write or read, would be:
public static bool ValidateIOPermission(string path)
{
try
{
if(Directory.Exist(path))
return true;
else { Directory.CreateDirectory(path); }
}
catch(Exception ex) { return false; }
}
The above code is a small sample, basically try to perform the action and catch the exception, that way you know if you have access or not.
I have a piece of code in a Web API app:
private Stream ConvertWorkBookToStream(WorkBook workBook)
{
var tempFileName = Path.GetTempFileName();
// The following line throws a NullReferenceException
workBook.write(tempFileName);
// Remainder elided for brevity
}
Neither workBook nor tempFileName are null.
On a whim, I changed the app pool to run under a domain administrator account, to eliminate any permissions issues (since I've observed some general wonkiness on my machine of late) and re-ran it. The same exception was thrown.
Then I created a console application and copied the method, verbatim, into the app and ran it. No exception was thrown.
Now, it bears noting that just yesterday, I ran into a similar puzzling behavior regarding File.Exists.
Consider the following call:
var exists = File.Exists(#"\\myshare\\myexistingfile.ext");
Assuming that the path refers to a file that actually exists:
Under a web app, exists returns false on my machine.
The same operation, in a console application, returns true.
My coworkers are experiencing the opposite behaviors.
Can anyone explain this? I'm rather at my wits' end.
Check to see if the return from Path.GetTempFileName is different from the console app and the web app. Windows could be playing tricks with you. I had similar issues attempting to write log files. I just gave up and put them int the same directory as my web service.
In your IIS Authentication settings, are you only having Anonymous Authentication enabled? If I remember correctly Anonymous Authentication impersonates the IUSR account with restricted privileges.
I have built an app that works only when not run as a Windows service. Well, the service runs, but it doesn't do what it should. The service uses the Local Service account. So to kick off debugging, I thought I'd start with something simple: have it create a directory when it starts:
Directory.CreateDirectory(
Environment.SpecialFolder.LocalApplicationData + "\\MyService");
When I started the service, it stopped almost immediately and Windows reported that fact. When I commented out the above statement, recompiled and re-installed, the service ran without stopping.
Obviously the above line throws an exception of some sort. I have no way of logging the error because I can't write to the file system. Any ideas why Local Service can't create a directory in its own %LOCALAPPDATA%?
You should use GetFolderPath with LocalApplicationData like so:
string folderName = Path.Combine(Environment.GetFolderPath(
Environment.SpecialFolder.LocalApplicationData),
"MyService");
Directory.CreateDirectory(folderName)
I think this might be because there is no special folder. When running as the local service account you are running under that user, not the logged in user. so you are requesting a special folder that probably wont exist, as I don't think the local service has a profile. (I may be wrong) - I was wrong :p
Just in case anyone pops by:
C:\Windows\ServiceProfiles\LocalService
is the local service profile folder, so it will end up in there.
If you want to debug it surround that line with a try catch, and then write the error to a file:
try
{
Directory.CreateDirectory(Environment.SpecialFolder.LocalApplicationData + "\\MyService");
}
catch (Exception ex)
{
System.IO.StreamWriter file = new System.IO.StreamWriter(#"C:\MyServicelog.txt",true);
file.WriteLine(ex.Message);
file.Close();
}
At least then you can see whats causing the error
Martyn
I suggest you write the exception details to the event log. All user accounts have permission to write to the event log as long as the log and source names have already been created by an administrator (which you can do simply by running the app as yourself first).
As to the root cause of the error, it may be because LocalService doesn't normally get a full set of profile folders created by default. I'm not sure whether this is by design, or simply what I have observed on various machines.
I work on a thick-client app that often runs into "issues" accessing network shares. Before doing any IO with the server, my app tests whether the share (usually of the form \\server\share$) exists. This works fine for detecting those scenarios in which the client has lost its connection to the server, but there are still those odd scenarios where the hidden share exists but the user does not have the rights to read from the within the share. Can someone share (no pun intended) the C# code required to test whether the current user can read files on a share? Should I be querying the share's ACL or the files within the share? What if the share is empty? What if the user is a local non-admin in a mixed environment (XP Pro workstation, Windows 2003 server without a domain on a Novell network)?
The easiest way is to just do it (i.e. try to read a file, for example). As Jared mentioned, there is no way to make sure that you will be able to read in the future (network failure, change of permissions, etc).
As far as code goes, you could use the DirectoryInfo class for some attempts at an answer:
string remotePath = #"\\server\share$";
bool haveAccess = false;
DirectoryInfo di = new DirectoryInfo(remotePath);
if (di.Exists)
{
try
{
// you could also call GetDirectories or GetFiles
// to test them individually
// this will throw an exception if you don't have
// rights to the directory, though
var acl = di.GetAccessControl();
haveAccess = true;
}
catch (UnauthorizedAccessException uae)
{
if (uae.Message.Contains("read-only"))
{
// seems like it is just read-only
haveAccess = true;
}
// no access, sorry
// do something else...
}
}
There are many shortcomings in the above code (such as the hard-coded "read-only" test), but it is just an example used to illustrate what you could do. DirectoryInfo has a few other helper methods that you can use to list the files in the folder. If you don't have access, the methods will throw an UnauthorizedAccessException exception which you can use to test why the access failed. Check out the info on GetAccessControl for further details on the exceptions it throws.
The #1 most reliable way to determine if you used to have permission to read from the share is to
Try and read from the share
Handle errors that could occur while reading and consider that a failed attempt
Unfortunately though based on your description you are trying to determine if you will have read permission to the share. There is no way to reliably determine this.
No matter how many ACLs, directories, etc ... you look at the moment you're done looking at them you could lose access to the share via any number of mechanisms. The most obvious one is the network share going down. All you can determine is that you used to have permission to the share.