Solved

VB.NET Copy file and check if it exists to remote computer supplying credentials

Posted on 2014-02-07
9
4,626 Views
Last Modified: 2014-02-12
Hi Experts,

I would like to be able to check if a file exists on a remote computer and if not, copy the file from the PC the app is running on to the remote computer.  I know I can do that using system.io.file.copy but I also need to supply credentials.  I do not want to use tools such as psexec.

Thanks
0
Comment
Question by:FamousMortimer
  • 5
  • 3
9 Comments
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 39841883
Can you map the remote drive onto the local machine?
0
 
LVL 12

Expert Comment

by:ktaczala
ID: 39841955
0
 
LVL 10

Author Comment

by:FamousMortimer
ID: 39841981
I suppose using a mapped drive could work but this will loop on 40-50 computers and i just feel like there has to be a better way.
0
 
LVL 10

Author Comment

by:FamousMortimer
ID: 39842039
I feel like it can cause problems creating and disconnecting so many sessions.

The program settings contain credentials that have access to the admin shares on the pc's.  Is it possible to impersonate the credentials supplied and connect that way?
0
DevOps Toolchain Recommendations

Read this Gartner Research Note and discover how your IT organization can automate and optimize DevOps processes using a toolchain architecture.

 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 39842060
You would need a share on the remote machine that you can access. You may be able to use the hidden admin share if it hasn't been disabled and if your account has permissions to that share. Will your account have admin permissions?
0
 
LVL 10

Author Comment

by:FamousMortimer
ID: 39842169
I plan on using the admin share to access the file but i need to pass permissions to access it because the running users does not.
0
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 39842189
OK, then impersonation is what you will need. I haven't personally done this, but I located an article that shows how you can achieve this (though I'm a bit put-off by the need to P/Invoke; I thought you could accomplish this wholly in .NET). See if the following works for you:

http://msmvps.com/blogs/siva/archive/2007/03/01/impersonating-network-share-unc-path-access.aspx
0
 
LVL 10

Accepted Solution

by:
FamousMortimer earned 0 total points
ID: 39842440
Oddly enough I found a class that I used a while back in another app I wrote with this functionality.  As soon as I wrote 'impersonate' I realized I had run into this before.

It can be called like this...
        Dim Impersonator As New Impersonator("domain\user", "mypassword")
        Impersonator.BeginImpersonation()
        File.Copy(SourcePath, DestPath, True)
        Impersonator.EndImpersonation()

Open in new window


Here is the class...
Public Class Impersonator
    Private _username As String
    Private _password As String
    Private _domainname As String

    Private _tokenHandle As New IntPtr(0)
    Private _dupeTokenHandle As New IntPtr(0)
    Private _impersonatedUser As System.Security.Principal.WindowsImpersonationContext

#Region "Constructor"
    Public Sub New(ByVal username As String, _
                   ByVal password As String)
        Dim nameparts() As String = username.Split(Convert.ToChar("\"))
        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
#End Region

#Region "Properties"
    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
#End Region

#Region "Impersonation"
    Public Sub BeginImpersonation()
        'Const LOGON32_PROVIDER_DEFAULT As Integer = 0
        'Const LOGON32_LOGON_INTERACTIVE As Integer = 2
        Const LOGON32_LOGON_NEW_CREDENTIALS As Integer = 9
        Const LOGON32_PROVIDER_WINNT50 As Integer = 3
        Const SecurityImpersonation As Integer = 2

        Dim win32ErrorNumber As Integer

        _tokenHandle = IntPtr.Zero
        _dupeTokenHandle = IntPtr.Zero

        If Not LogonUser(_username, _domainname, _password, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_WINNT50, _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
#End Region

#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 = ""
        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
 
LVL 10

Author Closing Comment

by:FamousMortimer
ID: 39852805
it works
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Wouldn’t it be nice if you could test whether an element is contained in an array by using a Contains method just like the one available on List objects? Wouldn’t it be good if you could write code like this? (CODE) In .NET 3.5, this is possible…
Calculating holidays and working days is a function that is often needed yet it is not one found within the Framework. This article presents one approach to building a working-day calculator for use in .NET.
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…

911 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

21 Experts available now in Live!

Get 1:1 Help Now