Solved

.NET File.Copy createing new zero length files when using local accounts with Windows Service

Posted on 2009-05-06
3
244 Views
Last Modified: 2013-11-08
Greetings,

I have an interesting problem with a Win32 service I wrote in VB.NET that uses a FileSystemWatcher object in a Windows Service to catch new files in a directory and move them to a file share on a different domain server. The service is using the File.Copy method to copy the files and rename them. The server with the service / File.Copy code is not part of a domain and uses a local admin account (pospay) to run the service. The domain server with the destination file share has a matching pospay user account with a synchronized password. The service starts fine and successfully works ONCE to copy the new file to the share but after the initial success in copying the file intact all subsequent File.Copy operations result in new, zero length files until I restart the server. This includes changing the service to not use the domain file share location and instead use it's own desktop folder. The files are still new, zero length files with the same name as the originating file.
Imports System.IO

Imports System.Xml

Imports System.ComponentModel

Imports System.ServiceProcess
 
 

Public Class PositivePayWatcher
 

  Inherits System.ServiceProcess.ServiceBase
 

  Const ApDestination As String = "\\tundra2\Workgrps\FNSB\Wf Positive Pay\jct_test\ap"

  Const PyDestination As String = "\\tundra2\Workgrps\FNSB\Wf Positive Pay\jct_test\py"

  Const ApWatchLocation As String = "c:\\fnsb\pospay\ap"

  Const PyWatchLocation As String = "c:\\fnsb\pospay\py"

  Const TransferLogLocation As String = "\\tundra2\Workgrps\FNSB\Wf Positive Pay\jct_test\pospay.xml"

  Private TransferType As String

  Private LoggingXmlDoc As New XmlDocument
 
 

  Protected Overrides Sub OnStart(ByVal args() As String)
 

    'AP -------------------------------------------------------------------									

    fswAP.Path = ApWatchLocation

    fswAP.NotifyFilter = IO.NotifyFilters.FileName  'watch operation/task
 

    'PY -------------------------------------------------------------------

    fswPY.Path = PyWatchLocation

    fswPY.NotifyFilter = IO.NotifyFilters.FileName  'watch operation/task
 

    'Log ------------------------------------------------------------------

    If File.Exists(TransferLogLocation) Then LoggingXmlDoc.Load(TransferLogLocation)
 

  End Sub
 
 
 

  Private Sub WatchForChanges_Payroll(ByVal sender As Object, ByVal e As System.IO.FileSystemEventArgs) Handles fswPY.Created
 

    Dim filename As String = e.Name
 

    Try

      TransferType = "PY"

      File.Copy(e.FullPath, PyDestination & "\" & filename, True) 'use built in file transfer utility to move the file and rename it csv

      LogTranfer(filename, PyDestination & "\" & filename, TransferType)

    Catch ex As Exception

      Dim logdata As New IO.StreamWriter("c:\fnsb\wf.txt", True, Text.Encoding.ASCII)

      logdata.Write(ex.Message.ToString & vbCrLf)

      logdata.Close()

    End Try
 

  End Sub

Open in new window

0
Comment
Question by:akjtr
  • 2
3 Comments
 
LVL 15

Assisted Solution

by:oobayly
oobayly earned 100 total points
ID: 24324364
Can we assume that no errors are being logged?
0
 

Author Comment

by:akjtr
ID: 24328812
No errors are being logged through the stream writer object nor app event log on the server. There are no security errors on the domain file share either.
0
 

Accepted Solution

by:
akjtr earned 0 total points
ID: 24498269
I used the following class as a workaround. I fired ImpersonateStart prior to calling the file.move or file.copy. Also I just thought about one reason why the original code may not have worked and that is our McAfee virus engines are paranoid. It may have been unrelated to security and more to do with VE. Anyway the class:


Imports System

Imports System.Runtime.InteropServices

Imports System.Security.Principal

Imports System.Security.Permissions

Imports Microsoft.VisualBasic

<Assembly: SecurityPermissionAttribute(SecurityAction.RequestMinimum, UnmanagedCode:=True), _

 Assembly: PermissionSetAttribute(SecurityAction.RequestMinimum, Name:="FullTrust")> 
 

Public Class RunAs_Impersonator

#Region "Private Variables and Enum Constants"

  Private tokenHandle As New IntPtr(0)

  Private dupeTokenHandle As New IntPtr(0)

  Private impersonatedUser As WindowsImpersonationContext

#End Region

#Region "Properties"
 

#End Region

#Region "Public Methods"

  Public Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Boolean
 

  Public Declare Auto Function DuplicateToken Lib "advapi32.dll" (ByVal ExistingTokenHandle As IntPtr, _

    ByVal SECURITY_IMPERSONATION_LEVEL As Integer, _

    ByRef DuplicateTokenHandle As IntPtr) As Boolean
 

  ' Test harness.

  ' If you incorporate this code into a DLL, be sure to demand FullTrust.

  <PermissionSetAttribute(SecurityAction.Demand, Name:="FullTrust")> _

  Public Sub ImpersonateStart(ByVal Domain As String, ByVal userName As String, ByVal Password As String)

    Try

      tokenHandle = IntPtr.Zero

      ' Call LogonUser to obtain a handle to an access token.

      Dim returnValue As Boolean = LogonUser(userName, Domain, Password, 2, 0, tokenHandle)
 

      'check if logon successful

      If returnValue = False Then

        Dim ret As Integer = Marshal.GetLastWin32Error()

        Console.WriteLine("LogonUser failed with error code : {0}", ret)

        Throw New System.ComponentModel.Win32Exception(ret)

        Exit Sub

      End If
 

      'Logon succeeded
 

      ' Use the token handle returned by LogonUser.

      Dim newId As New WindowsIdentity(tokenHandle)

      impersonatedUser = newId.Impersonate()

    Catch ex As Exception

      Throw ex

      Exit Sub

    End Try

    ' MsgBox("running as " & impersonatedUser.ToString & " -- " & WindowsIdentity.GetCurrent.Name)

  End Sub

  <PermissionSetAttribute(SecurityAction.Demand, Name:="FullTrust")> _

  Public Sub ImpersonateStop()

    ' Stop impersonating the user.

    impersonatedUser.Undo()
 

    ' Free the tokens.

    If Not System.IntPtr.op_Equality(tokenHandle, IntPtr.Zero) Then

      CloseHandle(tokenHandle)

    End If

    'MsgBox("running as " & Environment.UserName)

  End Sub

#End Region

#Region "Private Methods"

  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
 

  <DllImport("kernel32.dll")> _

  Public 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

#End Region
 

End Class

Open in new window

0

Featured Post

DevOps Toolchain Recommendations

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

Question has a verified solution.

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

This document covers how to connect to SQL Server and browse its contents.  It is meant for those new to Visual Studio and/or working with Microsoft SQL Server.  It is not a guide to building SQL Server database connections in your code.  This is mo…
For those of you who don't follow the news, or just happen to live under rocks, Microsoft Research released a beta SDK (http://www.microsoft.com/en-us/download/details.aspx?id=27876) for the Xbox 360 Kinect. If you don't know what a Kinect is (http:…
Along with being a a promotional video for my three-day Annielytics Dashboard Seminor, this Micro Tutorial is an intro to Google Analytics API data.
Windows 10 is mostly good. However the one thing that annoys me is how many clicks you have to do to dial a VPN connection. You have to go to settings from the start menu, (2 clicks), Network and Internet (1 click), Click VPN (another click) then fi…

896 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

12 Experts available now in Live!

Get 1:1 Help Now