Cannot find who has file open - vb.net

I have this code that find who has a file opened. The files are on network drives that use our old username as authenication. Our username use to be john.doe, it is now a number 12345. The code does not find a username. Is there something I'm overlooking or need to do to find out who has the file opened? Curious if and when we are on the actual new network that host the username 12345, that we will be able to find see the username 12345. The error message i do get is:
"The trust relationship between this workstation and the primary domain failed"
Public Shared Function GetFileOwner(ByVal strFileName)
Try
Dim objSD As Object = Nothing
Dim objWMIService = GetObject("winmgmts:")
Dim objFileSecuritySettings =
objWMIService.Get("Win32_LogicalFileSecuritySetting='" & strFileName & "'")
Dim intRetVal = objFileSecuritySettings.GetSecurityDescriptor(objSD)
If intRetVal = 0 Then
GetFileOwner = objSD.Owner.Name
Else
GetFileOwner = "Unknown"
End If
Catch ex As Exception
MsgBox("Error :" & Date.Today.ToString & " " & ex.Message)
GetFileOwner = "Unknown"
End Try
End Function

Do you know that this option is available on your server? You can easily do this..
Open the Computer Management snap-in on your file server (or connect to the server remotely from the management console running on your computer) and go to System Tools -> Shared Folders -> Open files. The list of files opened on the remote server is displayed on the right side of the window.
Many times i tried to access my server on the domain and it gave me that error, domains hate custom made apps :)

Related

System.AccessViolationException occurs with MS Access databases just over WiFi connection

I'm developing a desktop application for my company (it's just a prototype, actually) for bringing simple services to production department (tool and process instructions, presence records, product traceability, etc).
I'm using VB.net and wpf; some MS Access databases are the backend. It uses Access Database Engine 2016.
I have a simple function used to update database records, here's it:
Public Function UpdateDatabaseRecord(DatabaseNumber As Integer, tblName As String, SearchInColumn As String, SearchBy As String, UpdateColumn As String, UpdateTo As String) As Integer
Try
Using ServerConnection As New OleDbConnection(ConnectionSelector(DatabaseNumber))
Dim CommandString As String
If SearchInColumn <> "ID" Then
CommandString = "UPDATE [" & tblName & "] SET [" & UpdateColumn & "]=#UpdateColumn WHERE [" & SearchInColumn & "] = " & DQ & SearchBy & DQ
Else
CommandString = "UPDATE [" & tblName & "] SET [" & UpdateColumn & "]=#UpdateColumn WHERE [" & SearchInColumn & "] = " & SearchBy
End If
Dim CommandUpdate As New OleDbCommand(CommandString, ServerConnection) With {.CommandTimeout = 10000}
With CommandUpdate.Parameters
.AddWithValue("#UpdateColumn", UpdateTo)
End With
ServerConnection.Open()
CommandUpdate.ExecuteNonQuery()
ServerConnection.Close()
End Using
UpdateDatabaseRecord = 0
SetCentralTimeStamp(DatabaseNumber, tblName)
Catch ex As Exception
Msg(Reflection.MethodBase.GetCurrentMethod.Name & NewLine & ex.Message & NewLine & "Err. Number " & Err.Number, "Database Error", MessageBoxButton.OK, MessageBoxImage.Error)
UpdateDatabaseRecord = Err.Number
End Try
End Function
Sometimes the application uses this function in the main thread; sometimes it runs it from scheduled task (clocked by a forms.timer every two minutes). This tasks aren't obviously in the main thread, but the code has been used succesfully for a couple of months with computers directly connected to company network via LAN cable. Recently I tried my application on a laptop connected via wifi to the company network, and I get an exception that's crashing my app. I installed VS on that laptop to debug the code, and I found that an AccessViolationException is raised on line "CommandUpdate.ExecuteNonQuery".
I tried to google it but it seems that this exception shouldn't be raised from managed code.
The error occours only with laptop connected via wifi.
Also, another function reads data from the databases: sometimes I get the same error in it, in the line where the connection is being opened (connection.open).
What should I check?
Thanks in advance.
ps "ConnectionSelector" is a simple function which returns the appropriate ConnectionString based on database number.
EDIT 1 - The WiFi network is created plugging directly a LAN cable from the actual wired network, using a common wireless router. IP addresses are automatically assigned and the connection works, since the app is able to get data from databases.
I solved the problem myself and I'm posting here the solution I found: I hope it will help someone in the future.
I resolved simply enabling all OLEDB Services for the database connection. It looks like connection pooling really help stability and performance, especially when using a wifi network like I'm forced to do. If you want, Google "OLEDB Services" and look for enabling them all.

Is there a direct way to copy files from ServerA to ServerB when only one of them requires impersonation?

I am trying to copy files from Server A to Server B.
So basically, it's fast and easy, File.Copy.
File.Copy("\\ServerA\c$\CopyImageTest\Server61.txt", "\\ServerB\c$\CopyImageTest\Server61.txt")
File.Copy("\\ServerB\c$\CopyImageTest\Server182.txt", "\\ServerA\c$\CopyImageTest\Server182.txt")
Since Server A requires login to use, it's obvious that I got this error:
System.IO.IOException: Logon failure: unknown user name or bad password.
I've looked around and found that I should use Impersonation in order to access that server and copy the files. I found this answer which is in C# and converted it to VB.NET.
Here's the code that I am using:
Module Module1
<PermissionSetAttribute(SecurityAction.Demand, Name:="FullTrust")> _
Sub Main()
Try
'Some declarations omitted for clearance.
Const LOGON32_PROVIDER_DEFAULT As Integer = 0
Const LOGON32_LOGON_INTERACTIVE As Integer = 2
Const LOGON32_LOGON_NEW_CREDENTIALS As Integer = 9
Try
Dim bImpersonated As Boolean = LogonUser(sUsername, sDomain, sPassword, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT, pExistingTokenHandle)
If (Not bImpersonated) Then
Dim nErrorCode As Integer = Marshal.GetLastWin32Error()
Return
End If
Dim bRetVal As Boolean = DuplicateToken(pExistingTokenHandle, SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, pDuplicateTokenHandle)
If (Not bRetVal) Then
Dim nErrorCode As Integer = Marshal.GetLastWin32Error()
CloseHandle(pExistingTokenHandle)
Return
Else
Dim newId As WindowsIdentity = New WindowsIdentity(pDuplicateTokenHandle)
Dim impersonateduser As WindowsImpersonationContext = newId.Impersonate()
'Shouldn't I be copying now?
File.Copy("\\ServerA\c$\CopyImageTest\Server61.txt", "\\ServerB\c$\CopyImageTest\Server61.txt")
File.Copy("\\ServerB\c$\CopyImageTest\Server182.txt", "\\ServerA\c$\CopyImageTest\Server182.txt")
sResult = sResult & "After impersonation: " & WindowsIdentity.GetCurrent.Name & Environment.NewLine
impersonateduser.Undo()
End If
Catch ex As Exception
'Omitted
Finally
If (Not pExistingTokenHandle = IntPtr.Zero) Then
CloseHandle(pExistingTokenHandle)
End If
If (Not pDuplicateTokenHandle = IntPtr.Zero) Then
CloseHandle(pDuplicateTokenHandle)
End If
End Try
Catch ex As Exception
'Omitted
End Try
End Sub
' DLL Imports and Enum Omitted.
End Module
Some code to output the results has been omitted, but here's the results from the console:
User was able to login. (This is used after LogonUser()) (Previously it was throwing an error (1326) Logon failure: unknown user name or bad password)
Before impersonation: User-PC\User (Result of WindowsIdentity.GetCurrent().Name; Before Impersonate())
After impersonation: User-PC\User (Result of WindowsIdentity.GetCurrent().Name; After Impersonate())
System.IO.IOException: Logon failure: unknown user name or bad password.
What's confusing is that the name before and after impersonation is the same as my local PC. However the login is working. (I am positive about that because, as stated, it was failing previously.)
Secondly, the file still doesn't get copied with same error as before:
Logon failure: unknown user name or bad password.
Is this how actually Impersonation should be working, or am I missing something obvious?
After digging a bit more, I also found this answer and I used the same exact code from the answer, but with no luck at all.
Some information about the Server A that I am trying to access and copy the files from:
I can connect through remote desktop connecting using the same username/password.
I can open the file explorer from my own PC using the server IP address as shown in the code: \\ServerA\c$\CopyImageTest.
Both my PC and the server are on the same network, but different domains.
Update:
#Esko's comment guided me to make two or three tests.
Here's the scenario:
With Impersonation I tried this code:
File.Copy("\\ServerA\c$\CopyImageTest\Server61.txt", "C:\CopyImageTest\Server61.txt")
File.Copy("C:\CopyImageTest\Server182.txt", "\\ServerA\c$\CopyImageTest\Server182.txt")
Which means that I only copied the files from ServerA to local and vice versa.
Result: Passed.
With Impersonation
File.Copy("C:\CopyImageTest\Server61.txt", "\\ServerB\c$\CopyImageTest\Server61.txt")
File.Copy("\\ServerB\c$\CopyImageTest\Server182.txt", "C:\CopyImageTest\Server182.txt")
Which means I tried to copy from ServerB to local and vice verca
Result: Failed
Without impersonation
File.Copy("C:\CopyImageTest\Server61.txt", "\\ServerB\c$\CopyImageTest\Server61.txt")
File.Copy("\\ServerB\c$\CopyImageTest\Server182.txt", "C:\CopyImageTest\Server182.txt")
Copying from and to ServerB
Result: Passed
So at the end, I think the problem is that when Impersonating the user to access ServerA it fails to access ServerB, knowing that ServerB doesn't require username password when trying to access it from my PC. Maybe because my PC and ServerB uses same domain on same network but ServerA uses another domain on same network?
Is there any workaround to access both servers with a single impersonation?
Note: I am aware of being able to copy files from ServerA to local then undo impersonation and copy to ServerB, I am just looking for a more straight way.

Deleting a file located in root directory with FtpWebRequest method

I'm facing a problem while implementing some FTP operation in a small tool (windows form) for data management on several FTP servers. Basically I need to connect to a list of ftp://xxx.xxx.xxx.xxx servers with credentials, look for any *.csv file available, download it to local hard disk and then delete it on ftp server.
I did most of the job like following:
Created a loop for connecting on all ftp server in the list
For each connection, get the file list, download each file of the list and delete it from the server
My problem is that the Delete Sub I created give me a 550 exception (not regular file). Looking deep it seems that is try to delete "/filename.csv" instead of "filename.csv", so that is the reason for the error.
I think this is related to the fact that the file is in the root directory and the URI that I pass as argument for the ftpwebrequest is in the form of "ftp://xxx.xxx.xxx.xxx/filename.csv", but I don't know other ways to get around this.
Can anybody give me a tip?
Thanks
EDIT: I'm thinking that maybe sending a "cd /" command before requesting the delete could solve the situation, but I don't know how to implement it inside the FTP_Delete function. Any ideas? Thanks
Sub FTP_Delete(filename As String, ftp_adress As String, user As String, password As String)
FileFullPath = ftp_adress & "/" & filename
'Create Request To Delete File'
Dim wrDelete As FtpWebRequest = CType(WebRequest.Create(FileFullPath), FtpWebRequest)
'Specify That You Want To Delete A File'
wrDelete.Method = WebRequestMethods.Ftp.DeleteFile
'Specify Username & Password'
wrDelete.Credentials = New NetworkCredential(user, password)
'Response Object'
Dim rDeleteResponse As FtpWebResponse
Try
rDeleteResponse = CType(wrDelete.GetResponse(), FtpWebResponse) ' ** Eccezione
Catch errore As WebException
rDeleteResponse = DirectCast(errore.Response, FtpWebResponse)
Me.UpdateHistory("Delete Error: " & rDeleteResponse.StatusCode & "-" & rDeleteResponse.StatusDescription)
End Try
'Close'
rDeleteResponse.Close()
End Sub

Check for UNC connectivity

I need to verify that my app can connect to the default C$ share on a remote server on the network. Does anyone have a really bulletprrof way I can do this? Initially I was doing something like this:
Dim ProcessStartInfo As New System.Diagnostics.ProcessStartInfo
ProcessStartInfo.FileName = "net"
ProcessStartInfo.Arguments = "use \\" & strComputer & "\c$ /USER:" & strUsername & " " & strPassword
ProcessStartInfo.WindowStyle = ProcessWindowStyle.Hidden
System.Diagnostics.Process.Start(ProcessStartInfo)
But this can be flakey sometimes and hang, take too long to return etc. Whatever method I use needs to be able to supply credentials and if at all possible, when the connection fails I need to know why it failed.
I solved this another way but can't find the thread.
Dim dir As New IO.DirectoryInfo("\\10.101.1.200\c$")
dir.exists will then tell you if it was able to connect.
This will try to connect as the account the program was run from. If you need different credentials you may need to look in to Impersonation.
You could directly call the windows functions via pInvoke, but that gets more complex. An example can be found here. C#: How to logon to a share when using DirectoryInfo

Getting the size of a remote folder via classic ASP

I'm trying to something pretty simple but am having headaches with it. I'm pretty sure all I have here is a permissions issue I don't know how to solve but I could be wrong.
Here is my scenario...
I have 3 servers...
Server A - Web Server (Windows 2003) - Anonymous Access Enabled
Server B - Red 5 Media Server
Server C - NAS
The website on Server A allows for recording/uploading of video to Server B where the video is processed/transcoded.
A Cron job on Server B then moves the videos over to Server C for storage.
Users can then watch their videos from Server A via a virtual directory thats been set up in IIS that points to Server C and connects as a domain user account.
I need to some how use the ASP File System Object to get the size of a folder on Server C that contains the videos.
I've mapped the parent folder of the folder on Server C where the videos are stored to a drive letter on Server A using a UNC path (\servername\videos).
I've tried using the FileSystemObject's folderExists() method for debugging purposes and it returns false if I pass in the mapped letter drive or a UNC path. It gives a path not found error. Just to be sure I did a response.write of the path being passed into the folderExists() method and it is the correct path. All of this leads me to believe this is really a permissions issue which I just don't know how to solve.
Thanks,
Ryan
Mapped network drives are no use to you in ASP on IIS6 since they are part of a user profile. User profiles are not fully loaded in services like IIS6.
Assuming a pure ASP environment (you can't install other dlls etc) then you will need the anonymous user to have access to the network share where the videos are stored and use the UNC path.
Now typically the IUSR account is local guest account which has no access to the network. You will need to create a user on the domain that the NAS belongs to and specify that users credentials as the anonymous user account for those pages that need to do your "Get Size" task ( you don't need change anonymous user for the whole application).
The foregoing assumes Server A is a member of the same domain as Server C. If not then you need to create user on the domain the Server A belongs to as well that mirrors the one on Server C including its password (or jump through trust relationship hoops).
With that in place you can go ahead and use FileSystemObject.
You need to work with the FSO.Drives collection to get to your NAS. Have a look at this article (just googled it but it seems ok):
http://www.stardeveloper.com/articles/display.html?article=2001050301&page=1
Try running this and seeing if you drives are available, should help narrow down if its a permissions problem
<%
Dim fso
Set fso = Server.CreateObject("Scripting.FileSystemObject")
Dim drives
Set drives = fso.Drives
Dim isReady
For Each drive in drives
isReady = drive.IsReady
If isReady Then
Response.Write "DriveLetter: " & drive.DriveLetter & "<br>"
Response.Write "Path: " & drive.Path & "<br>"
Response.Write "FileSytem: " & drive.FileSystem & "<br>"
Response.Write "TotalSize: " & drive.TotalSize & "<br>"
Response.Write "FreeSpace: " & drive.FreeSpace & "<br>"
Else
Response.Write "Driv Letter: " & drive.DriveLetter & "<br>"
Response.Write drive.Path & "<br>"
Response.Write "No other information available."
End If
Next
%>
Have a play with that and see if you are still having problems, if so we will dig a bit deeper :)
Not sure if this is the right thing to do but to remedy this I had to map the network drive via ASP (as the IUSR_machine) account like so...
dim objNetwork
Set objNetwork = CreateObject("WScript.Network")
objNetwork.MapNetworkDrive "X:", "UNC path", "profile", "user", "password"
objNetwork.RemoveNetworkDrive "X:"
set objNetwork = nothing
Then I was able to access the mapped drive letter (X in this case) via the FileSystemObject.