Solved

System.IO.DirectoryNotFoundException for remote folder

Posted on 2008-06-20
5
1,736 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
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

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Total in textboxes 9 36
Trouble connecting to SqlServer database 4 34
c# if statement weird reaction 3 30
Showdialog 8 21
Recently while returning home from work my wife (another .NET developer) was murmuring something. On further poking she said that she has been assigned a task where she has to serialize and deserialize objects and she is afraid of serialization. Wha…
Jaspersoft Studio is a plugin for Eclipse that lets you create reports from a datasource.  In this article, we'll go over creating a report from a default template and setting up a datasource that connects to your database.
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…
The viewer will learn how to use and create new code templates in NetBeans IDE 8.0 for Windows.

744 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

Need Help in Real-Time?

Connect with top rated Experts

8 Experts available now in Live!

Get 1:1 Help Now