Solved

System.IO.DirectoryNotFoundException for remote folder

Posted on 2008-06-20
5
1,782 Views
Last Modified: 2013-11-07
Our setup:
- computer 1: Windows 2003 running IIS 6.0
- computer 2: Windows Storage Server on a Network Attached Storage (NAS), where all data stored
                       We have shared a folder on this computer, and computer 1 has mapped this folder as the
                       D-drive.
- We are using a 3rd pary .NET control that allows users to upload files to our this folder sitting on our NAS.
 
The problem to solve:
 - We get an error "System.IO.DirectoryNotFoundException for remote folder", whenever it calls the function System.IO.Directory.CreateDirectory("D:\uploads\newfolder")

I think it has something to setting up the .NET security permissions in the machine.config file or web.config file, but I am have tried lots of settings and I am stuck at this point. For you information if the  data were all stored on a folder on computer 1, then everything would works just fine.

0
Comment
Question by:putza
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
5 Comments
 
LVL 53

Accepted Solution

by:
Dhaest earned 168 total points
ID: 21831061
On a local machine, it should execute just fine if the ASP.NET process has read/write permissions both in the NTFS file system and also in IIS. If both are not in sync, then the opertaion will fail.

http://learn.iis.net/page.aspx/194/configuring-share-and-ntfs-permissions/
0
 
LVL 5

Assisted Solution

by:JuckMan
JuckMan earned 166 total points
ID: 21833313
This is permission issue.

In IIS 6.0 every web application runs in a "Application pool"; Find out under which application pool your web site/web application is using. Righ click on your application pool and select properties.
Click on Identity tab. Enter a domain user account, who has necessary access to the folder where you are trying to create file.

Alos note that this domain account needs to have certain privileges as well (for ex: needs to pbe part of IIS_WPG group etc;)
0
 
LVL 7

Assisted Solution

by:Dauhee
Dauhee earned 166 total points
ID: 21838039
The code below uses the attached code snippit. Basically you can elevate your access to a domain account with permissions for the other server. You can then revert directly after. Be warned that will need to do error handling on page to revert regardless of any error or else user has potential for continuously elevated privledges which would not be good :(

I believe this is the most resilient and scalable solution because setting password in web.config file is too open to prying eyes (identity impersonate="true") and if trying to synchronise the iusr_xxx on the other box means if its ever replaced then ya have to go "jigging" around with settings to get it going again - sure as anything, 3 years down the line nobody will be able to remember!!

You can retrieve the domain user password from an encrypted source so nothing is available for internal network sniffing or file peeking :)

The attached class for impersonation was created by somebody considerably much smarter than I alas I cannot make claim to it :)

            Try
                'set the password details
                clsImpersonate = New AliasAccount(strUserName, strPassword, gstrPDCDomain)
                clsImpersonate.BeginImpersonation()
            Catch ex As Exception
            End Try

'copy over file here

        'undo impersonation regardless of success
        If Not IsNothing(clsImpersonate) Then
            clsImpersonate.EndImpersonation()
        End If
Public Class AliasAccount
    Private _username, _password, _domainname As String
 
    Private _tokenHandle As New IntPtr(0)
    Private _dupeTokenHandle As New IntPtr(0)
    Private _impersonatedUser As System.Security.Principal.WindowsImpersonationContext
 
 
    Public Sub New(ByVal username As String, ByVal password As String)
        Dim nameparts() As String = username.Split("\")
        If nameparts.Length > 1 Then
            _domainname = nameparts(0)
            _username = nameparts(1)
        Else
            _username = username
        End If
        _password = password
    End Sub
 
    Public Sub New(ByVal username As String, ByVal password As String, ByVal domainname As String)
        _username = username
        _password = password
        _domainname = domainname
    End Sub
 
 
    Public Sub BeginImpersonation()
        Const LOGON32_PROVIDER_DEFAULT As Integer = 0
        Const LOGON32_LOGON_INTERACTIVE As Integer = 2
        Const SecurityImpersonation As Integer = 2
 
        Dim win32ErrorNumber As Integer
 
        _tokenHandle = IntPtr.Zero
        _dupeTokenHandle = IntPtr.Zero
 
        If Not LogonUser(_username, _domainname, _password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, _tokenHandle) Then
            win32ErrorNumber = System.Runtime.InteropServices.Marshal.GetLastWin32Error()
            Throw New ImpersonationException(win32ErrorNumber, GetErrorMessage(win32ErrorNumber), _username, _domainname)
        End If
 
        If Not DuplicateToken(_tokenHandle, SecurityImpersonation, _dupeTokenHandle) Then
            win32ErrorNumber = System.Runtime.InteropServices.Marshal.GetLastWin32Error()
 
            CloseHandle(_tokenHandle)
            Throw New ImpersonationException(win32ErrorNumber, "Unable to duplicate token!", _username, _domainname)
        End If
 
        Dim newId As New System.Security.Principal.WindowsIdentity(_dupeTokenHandle)
        _impersonatedUser = newId.Impersonate()
    End Sub
 
 
    Public Sub EndImpersonation()
        If Not _impersonatedUser Is Nothing Then
            _impersonatedUser.Undo()
            _impersonatedUser = Nothing
 
            If Not System.IntPtr.op_Equality(_tokenHandle, IntPtr.Zero) Then
                CloseHandle(_tokenHandle)
            End If
            If Not System.IntPtr.op_Equality(_dupeTokenHandle, IntPtr.Zero) Then
                CloseHandle(_dupeTokenHandle)
            End If
        End If
    End Sub
 
 
    Public ReadOnly Property username() As String
        Get
            Return _username
        End Get
    End Property
 
    Public ReadOnly Property domainname() As String
        Get
            Return _domainname
        End Get
    End Property
 
 
    Public ReadOnly Property currentWindowsUsername() As String
        Get
            Return System.Security.Principal.WindowsIdentity.GetCurrent().Name
        End Get
    End Property
 
 
#Region "Exception Class"
    Public Class ImpersonationException
        Inherits System.Exception
 
        Public ReadOnly win32ErrorNumber As Integer
 
        Public Sub New(ByVal win32ErrorNumber As Integer, ByVal msg As String, ByVal username As String, ByVal domainname As String)
            MyBase.New(String.Format("Impersonation of {1}\{0} failed! [{2}] {3}", username, domainname, win32ErrorNumber, msg))
            Me.win32ErrorNumber = win32ErrorNumber
        End Sub
    End Class
#End Region
 
 
#Region "External Declarations and Helpers"
    Private Declare Auto Function LogonUser Lib "advapi32.dll" (ByVal lpszUsername As [String], _
            ByVal lpszDomain As [String], ByVal lpszPassword As [String], _
            ByVal dwLogonType As Integer, ByVal dwLogonProvider As Integer, _
            ByRef phToken As IntPtr) As Boolean
 
 
    Private Declare Auto Function DuplicateToken Lib "advapi32.dll" (ByVal ExistingTokenHandle As IntPtr, _
                ByVal SECURITY_IMPERSONATION_LEVEL As Integer, _
                ByRef DuplicateTokenHandle As IntPtr) As Boolean
 
 
    Private Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Boolean
 
 
    <System.Runtime.InteropServices.DllImport("kernel32.dll")> _
    Private Shared Function FormatMessage(ByVal dwFlags As Integer, ByRef lpSource As IntPtr, _
            ByVal dwMessageId As Integer, ByVal dwLanguageId As Integer, ByRef lpBuffer As [String], _
            ByVal nSize As Integer, ByRef Arguments As IntPtr) As Integer
    End Function
 
 
    Private Function GetErrorMessage(ByVal errorCode As Integer) As String
        Dim FORMAT_MESSAGE_ALLOCATE_BUFFER As Integer = &H100
        Dim FORMAT_MESSAGE_IGNORE_INSERTS As Integer = &H200
        Dim FORMAT_MESSAGE_FROM_SYSTEM As Integer = &H1000
 
        Dim messageSize As Integer = 255
        Dim lpMsgBuf As String = String.Empty
        Dim dwFlags As Integer = FORMAT_MESSAGE_ALLOCATE_BUFFER Or FORMAT_MESSAGE_FROM_SYSTEM Or FORMAT_MESSAGE_IGNORE_INSERTS
 
        Dim ptrlpSource As IntPtr = IntPtr.Zero
        Dim prtArguments As IntPtr = IntPtr.Zero
 
        Dim retVal As Integer = FormatMessage(dwFlags, ptrlpSource, errorCode, 0, lpMsgBuf, messageSize, prtArguments)
        If 0 = retVal Then
            Throw New System.Exception("Failed to format message for error code " + errorCode.ToString() + ". ")
        End If
 
        Return lpMsgBuf
    End Function
 
#End Region
 
End Class

Open in new window

0

Featured Post

Instantly Create Instructional Tutorials

Contextual Guidance at the moment of need helps your employees adopt to new software or processes instantly. Boost knowledge retention and employee engagement step-by-step with one easy solution.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

How to install Selenium IDE and loops for quick automated testing. Get Selenium IDE from http://seleniumhq.org Go to that link and select download selenium in the right hand column That will then direct you to their download page. From that p…
This article shows how to deploy dynamic backgrounds to computers depending on the aspect ratio of display
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.
The viewer will learn how to use NetBeans IDE 8.0 for Windows to connect to a MySQL database. Open Services Panel: Create a new connection using New Connection Wizard: Create a test database called eetutorial: Create a new test tabel called ee…

615 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question