how to identify application instance name along with its user in vb.net 3.5? - vb.net

I am using the below code to identify instance of the application also if we need to check that which user is using this application what will be the code for it?
Function PrevInstance() As Boolean
If Ubound(Diagnostics.Process.GetProcessesByName(Diagnostics.Process.GetCurrentProcess.ProcessName)) > 0 Then
Return True
Else
Return False
End If
End Function
My requirement is if same user tries to open the application then it should display pop up message like "application already opened".
Please advice...
abhay

Thanks a lot guys.... solution on my problem as follows:
> Function PrevInstance() As Boolean
> If UBound(Diagnostics.Process.GetProcessesByName(Diagnostics.Process.GetCurrentProcess.ProcessName))
> > 0 Then
> Dim CurUser As Boolean = GetProcessOwner(Diagnostics.Process.GetCurrentProcess.ProcessName)
> Return CurUser
> Else
> Return False
> End If
> End Function
Function GetProcessOwner(ByVal ProcessName As String) As Boolean
Dim boolVal As Boolean
Dim CurUserName As String
Dim CountInstance As Integer
CountInstance = 0
CurUserName = System.Environment.UserName
Dim selectQuery As SelectQuery = New SelectQuery("Select * from Win32_Process Where Name = '" + ProcessName + ".exe' ")
Dim searcher As ManagementObjectSearcher = New ManagementObjectSearcher(selectQuery)
Dim y As System.Management.ManagementObjectCollection
y = searcher.Get
For Each proc As ManagementObject In y
Dim s(1) As String
proc.InvokeMethod("GetOwner", CType(s, Object()))
Dim n As String = proc("Name").ToString()
If n = ProcessName & ".exe" Then
If s(0) = CurUserName Then
CountInstance = CountInstance + 1
If CountInstance > 1 Then
boolVal = True
End If
End If
End If
Next
Return boolVal
End Function
I have called PrevInstance() in my Form_Load() and its working perfectly.

PrevInstance Property
Returns a value indicating whether a previous instance of an application is already running.
Syntax
object.PrevInstance
The object placeholder represents an object expression that evaluates to an object in the Applies To list.
Remarks
You can use this property in a Load event procedure to specify whether a user is already running an instance of an application. Depending on the application, you might want only one instance running in the Microsoft Windows operating environment at a time.
Note Since a computer running Windows NT can support multiple desktops, if you use a component designed to work with distributed COM, it can result in the following scenario:
A client program in a user desktop requests one of the objects the component provides. Because the component is physically located on the same machine, the component is started in the user desktop.
Subsequently, a client program on another computer uses distributed COM to request one of the objects the component provides. A second instance of the component is started, in a system desktop.
There are now two instances of the component running on the same NT computer, in different desktops.
This scenario is not a problem unless the author of the component has placed a test for App.PrevInstance in the startup code for the component to prevent multiple copies of the component from running on the same computer. In this case, the remote component creation will fail.
Send feedback to MSDN.Look here for MSDN Online resources.
Session
The above tells you if it's already running. This tells you what session. An interactive user is always session1 on Vista and later. 0 for XP and earlier.
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select * From Win32_Process")
For Each objItem in colItems
msgbox objitem.name & " PID=" & objItem.ProcessID & " SessionID=" & objitem.sessionid
Next
PS
The rules for single instance programs is just before you exit you switch windows to the previous instance.
PPS
Due to problems introduced by 32 bit computing previnstance (Win32's one rather than VB's) becomes less meaningful. The common way to do this now is to open and lock a file on startup (Windows also has memory constructs you can use such as mailslots, pipes, etc). If a program can't lock then another is already running.

Related

Check for valid connection between frontend and backend Access database

I have an Access database application that I've split into a Frontend and Backend. The backend sits on a shared network drive that all users can access. My issue is that when a user launches the frontend of this app, and they don't have a connection to the backend because the shared drive may not have been mounted locally, the initial form to be displayed when the app is launched, doesn't open and leaves the user questioning what's going on. I already have code to check if the backend is connected although for some reason, when it isn't connected the intro screen form never is displayed and the access app just sits there
Private Sub Form_Open(Cancel As Integer)
Dim strBackEndPath, LResult As String
Dim i, j, lenPath As Integer
'initialize variable status to 0
Me.BEDB_Status = 0
'define what to check in backend database
strBackEndPath = CurrentDb.TableDefs("VersionInfo-Available").Connect
' Now remove the datebase & password prefix
j = InStrRev(strBackEndPath, "=") + 1
strBackEndPath = Mid(strBackEndPath, j)
'Checking access to Backend database files...
Me.MessageText = "Checking access to Backend database files..."
On Error Resume Next
LResult = Dir(strBackEndPath)
'Set status to Length of LResult
Me.BEDB_Status = Len(LResult)
'Check length of BEDB_Status, if greater than 0, backend is connected. If 0, backend is not connected.
If Me.BEDB_Status > 0 Then
'length is greater than 0 so continue opening the app
DoCmd.OpenForm "IntroScreen"
Else
'length is 0 so backend is not connected. Alert user and quit the app
Me.MessageText = "The database isn't currently accessible. Program will now exit. Please ask the support team for assistance"
DoCmd.Quit acQuitSaveNone
End If
End Sub
It may be simpler and much faster to attempt opening one of the linked tables and ignore the error:
Public Function IsLinkedTable(ByVal TableName As String) As Boolean
Dim LinkOk As Boolean
On Error Resume Next
LinkOk = (DCount("*", TableName) >= 0)
IsLinkedTable = LinkOk
End Function
And do use the OnLoad event of the form as this allows the form to open.
Implemented Gustav's suggestion to use the On Load event rather than the On Open event along with his IsLinkedTable function and it's working great.
Thanks Gustav.

Already running application now gets socket error 10013

I have an application done in VB.NET that listen on a specific UDP port and answer through the same port to the IP that send the packet.
It was working ok from a couple of years to the last month; now when try to answer crash due to socket error 10013.
I even try an older version that I know it was working too and get the same crash.
I try disabling Microsoft Security Essentials real time protection and Windows firewall and didn't work.
In the code I have the line
MyUdpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, True)
I have no clue about what to do, I'm lost.
Any idea how to solve this?
Edit:
Here's the code
#Region "UDP Send variables"
Dim GLOIP As IPAddress
Dim GLOINTPORT As Integer
Dim bytCommand As Byte() = New Byte() {}
#End Region
Dim MyUdpClient As New UdpClient()
Private Sub StartUdpBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StartUdpBtn.Click
If StartUdpBtn.Tag = 0 Then
' If Not UdpOpen Then
StartUdpReceiveThread(CInt(ListeningPortLbl.Text))
'End If
Else
If ThreadReceive.IsAlive Then
ThreadReceive.Abort()
MyUdpClient.Close()
PrintLog("UDP port closed")
StartUdpBtn.Tag = 0
UdpOpen = False
StartUdpBtn.Text = "Start UDP"
End If
End If
If UdpOpen Then
StartUdpBtn.Tag = 1
StartUdpBtn.Text = "Stop UDP"
Else
StartUdpBtn.Tag = 0
StartUdpBtn.Text = "Start UDP"
TimerUDP.Enabled = False
TiempoUDP.Stop()
TiempoUdpLbl.Text = "--:--:--"
End If
End Sub
Private Sub StartUdpReceiveThread(ByVal Port As Integer)
Dim UdpAlreadyOpen As Boolean = False
Try
If Not UdpOpen Then
MyUdpClient = New UdpClient(Port)
MyUdpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, True)
UdpAlreadyOpen = True
Else
Me.Invoke(Sub()
TiempoUDP.Restart()
If TimerUDP.Enabled = False Then
TimerUDP.Enabled = True
End If
End Sub)
End If
ThreadReceive = New System.Threading.Thread(AddressOf UdpReceive)
ThreadReceive.IsBackground = True
ThreadReceive.Start()
UdpOpen = True
If UdpAlreadyOpen Then
PrintLog(String.Format("UDP port {0} opened, waiting data...", Port.ToString))
End If
Catch ex As Exception
PrintErrorLog(ex.Message)
PrintErrorLog(ex.StackTrace)
End Try
End Sub
Private Sub UdpReceive()
Dim receiveBytes As [Byte]() = MyUdpClient.Receive(RemoteIpEndPoint)
DstPort = RemoteIpEndPoint.Port
IpRemota(RemoteIpEndPoint.Address.ToString)
Dim BitDet As BitArray
BitDet = New BitArray(receiveBytes)
Dim strReturnData As String = System.Text.Encoding.ASCII.GetString(receiveBytes)
If UdpOpen Then
StartUdpReceiveThread(CInt(ListeningPortLbl.Text))
End If
PrintLog("From: " & RemoteIpLbl.Text & ":" & ListeningPortLbl.Text & " - " & strReturnData)
AnswersProcessor(strReturnData)
End Sub
Private Sub UdpSend(ByVal txtMessage As String)
Dim pRet As Integer
GLOIP = IPAddress.Parse(RemoteIpLbl.Text)
'From UDP_Server3_StackOv
Using UdpSender As New System.Net.Sockets.UdpClient()
Dim RemoteEndPoint = New System.Net.IPEndPoint(0, My.Settings.UDP_Port)
UdpSender.ExclusiveAddressUse = False
UdpSender.Client.SetSocketOption(Net.Sockets.SocketOptionLevel.Socket, Net.Sockets.SocketOptionName.ReuseAddress, True)
UdpSender.Client.Bind(RemoteEndPoint)
UdpSender.Connect(GLOIP, DstPort)
bytCommand = Encoding.ASCII.GetBytes(txtMessage)
pRet = UdpSender.Send(bytCommand, bytCommand.Length)
End Using
PrintLog("No of bytes send " & pRet)
End Sub
10013 is WSAEACCES, which is documented as follows:
Permission denied.
An attempt was made to access a socket in a way forbidden by its access permissions. An example is using a broadcast address for sendto without broadcast permission being set using setsockopt(SO_BROADCAST).
Another possible reason for the WSAEACCES error is that when the bind function is called (on Windows NT 4.0 with SP4 and later), another application, service, or kernel mode driver is bound to the same address with exclusive access. Such exclusive access is a new feature of Windows NT 4.0 with SP4 and later, and is implemented by using the SO_EXCLUSIVEADDRUSE option.
In the comments you mentioned:
I tried the program on a XP x32 and works ok but on Windows 7 x32/x64 don't, even if I disable the firewall and Microsoft Security Essentials Live Protection.
Maybe it sounds almost obvious but you could try to start your program in all of the available Windows XP compatibility modes. You didn't say that you already tried this but maybe you're lucky and the problem will be "solved" by this workaround.
If the problem still exists afterwards and considering the error code of 10013, I would try or check the following things:
I know you disabled "Microsoft Security Essentials" and the Windows Firewall, but double check whether there are other security related programs/services like anti virus protection, anti malware tools etc. running. It really sounds like something is blocking your socket creation/bind.
In case your program created log output/data which allows you to see exactly when it started to fail:
Any new software installed at that time?
Were Windows Updates (maybe automatically) installed at that time? Especially security updates regarding network security?
Any other noticeable changes in your environment? What about log entries in your Windows system log?
Just as a little test to verify if the error occurs only with your UDP socket: Try to use a TCP socket instead of UDP.
Start the machine in Windows Safe Mode with network support and execute your program from there.
Run your program on another Windows 7 machine and see if the same problem occurs there. It could be a valuable starting point (in terms of localization) to know if the problem occurs only on specific versions of Windows.
Single step through your code with a debugger and carefully watch what happens. Perhaps this can reveal some additional info on what's going wrong.
Maybe some of the ideas above can help you to track down the problem a little bit more. Good luck!

How do I check if an ftp server is online and get the error that it generates if it is not connected?

I am new to programming in vb.net. I have come a long ways in my development and understanding of vb, but there is one hurtle I can not seem to fix. I am hosting an ftp server on my pc and I am making an app for it to connect to my server and download files. The problem with all the sample code is that everyone ASSUMES the server WILL be ONLINE. My pc may not be running 24/7 and I also may not have the ftp service running.In the first case it shouldnt even register that it is connected. In the second case, it WILL say that is connected b/c the pc is on, but it will return that the machine ou are trying to connect to is actively refusing the connection. Is there a way to TRULY check if the program is indeed connected to the server WITHOUT generating a bunch of Exceptions in the debugger? All I want is a call like:
Dim ftponline As Boolean = False 'Set default to false
ftponline = checkftp()
If ftponline Then
'continue program
Else
'try a different server
End If
So it would be a function called checkftp that returns a boolean value of true or false.
Here is my info:
Using Visual Studio 2010 Pro
Using .Net framework 4
Can anyone help?
Thanks!
I have tried the rebex ftp pack as well as the Ultimate FTP Pack.
Here is the updated code:
Public Function CheckConnection(address As String) As Boolean
Dim logonServer As New System.Net.Sockets.TcpClient()
Try
logonServer.Connect(address, 21)
Catch generatedExceptionName As Exception
MessageBox.Show("Failed to connect to: " & address)
End Try
If logonServer.Connected Then
MessageBox.Show("Connected to: " & address)
Return True
logonServer.Close()
Else
Return False
End If
End Function
Public Sub ConnectFtp()
types.Clear()
models.Clear()
ListBox1.Items.Clear()
ListBox2.Items.Clear()
TextBox2.Clear()
Dim request As New Rebex.Net.Ftp
If CheckConnection(*) Then
Dim tempString As String()
request.Connect(*)
request.Login(*, *)
request.ChangeDirectory("/atc3/HD_Models")
Dim list As Array
list = request.GetNameList()
Dim item As String = ""
For Each item In list
tempString = item.Split(New Char() {" "c})
If types.Contains(tempString(0)) = False Then
types.Add(tempString(0))
End If
If models.Contains(item) = False Then
models.Add(item)
End If
Next
request.Disconnect()
request.Dispose()
ElseIf CheckConnection(*) Then
request.Connect(*)
request.Login(*, *)
request.ChangeDirectory(*)
Dim list2 As Array
list2 = request.GetNameList()
Dim item2 As String = ""
Dim tempString2 As String()
For Each item2 In list2
MessageBox.Show(item2)
tempString2 = item2.Split(New Char() {" "c})
If types.Contains(tempString2(0)) = False Then
types.Add(tempString2(0))
End If
If models.Contains(item2) = False Then
models.Add(item2)
End If
Next
request.Disconnect()
request.Dispose()
End If
End Sub
No matter what I do, the second server will not connect. I even put a messagebox to show what items were being returned in the second server, but there are no messageboxes apearing when I run the program with my server offline. Is there anyone who can help?
If your code is designed with proper exception catching, it shouldn't be generating a "bunch" of exceptions. The first exception you catch should be your indication that the connection failed and your code should cease attempting to communicate at that point. If for some reason you really need to check the connectivity before attempting the FTP connection, you should be able to simply attempt to synchronously open a TCP socket to the FTP server's port. If that works, it's up and running.
You could simply open a socket to the server's IP address on Port 21 (assuming default FTP port).
I'm not much of a VB.Net programmer, but here's a link to sample code:
http://vb.net-informations.com/communications/vb.net_Client_Socket.htm
If you can establish the socket connection, you know that something is listening on that port (though you have not yet proven it's an FTP server, or that it will accept your login credentials...).
If you wish to simply avoid exceptions in the debugger, you could place the connection code in a method and apply the DebuggerHidden attribute to that method.

ASP.NET - Deleting Computer Accounts Within AD

I'm building out a decommissioning application that will allow an individual to provide an computer name and the utility will go out and purge the computer record from various locations. I'm running into a problem when attempting to delete a computer account from Active Directory. I'm impersonating a service account that only has rights to "Delete All Child Objects" within a particular OU structure. The code below works if I run it with my domain admin account; however fails with an "Access Denied" when I run it with the impersonated service account. I have verified that the permissions are correct within AD as I can launch Active Directory Users and Computers using a "runas" and providing the service account credentials and I can delete computer objects perfectly fine.
Wondering if anyone has run into this before or has a different way to code this while still utilizing my current OU permissions. My gut tells me the "DeleteTree" method is doing more then just deleting the object.
Any assistance would be appreciated.
Sub Main()
Dim strAsset As String = "computer9002"
Dim strADUsername As String = "serviceaccount#domain.com"
Dim strADPassword As String = "password"
Dim strADDomainController As String = "domaincontroller.domain.com"
Dim objDirectoryEntry As New System.DirectoryServices.DirectoryEntry
Dim objDirectorySearcher As New System.DirectoryServices.DirectorySearcher(objDirectoryEntry)
Dim Result As System.DirectoryServices.SearchResult
Dim strLDAPPath As String = ""
Try
objDirectoryEntry.Path = "LDAP://" & strADDomainController
objDirectoryEntry.Username = strADUsername
objDirectoryEntry.Password = strADPassword
objDirectorySearcher.SearchScope = DirectoryServices.SearchScope.Subtree
objDirectorySearcher.Filter = "(&(ObjectClass=Computer)(CN=" & strAsset & "))"
Dim intRecords As Integer = 0
For Each Result In objDirectorySearcher.FindAll
Console.WriteLine(Result.Path)
Diagnostics.Debug.WriteLine("DN: " & Result.Path)
Dim objComputer As System.DirectoryServices.DirectoryEntry = Result.GetDirectoryEntry()
objComputer.DeleteTree()
objComputer.CommitChanges()
intRecords += 1
Next
If intRecords = 0 Then
Console.WriteLine("No Hosts Found")
End If
Catch e As System.Exception
Console.WriteLine("RESULT: " & e.Message)
End Try
End Sub
If you're on .NET 3.5 and up, you should check out the System.DirectoryServices.AccountManagement (S.DS.AM) namespace. Read all about it here:
Managing Directory Security Principals in the .NET Framework 3.5
MSDN docs on System.DirectoryServices.AccountManagement
Basically, you can define a domain context and easily find users and/or groups in AD:
' set up domain context
Dim ctx As New PrincipalContext(ContextType.Domain, "DOMAIN", strADUsername, strADPassword)
' find a computer
Dim computerToDelete As ComputerPrincipal = ComputerPrincipal.FindByIdentity(ctx, strAsset)
If computerToDelete IsNot Nothing Then
' delete the computer, if found
computerToDelete.Delete()
End If
The new S.DS.AM makes it really easy to play around with users and groups in AD!
Delete Tree is different from delete. You're going to need the Delete Subtree permission on the child computer objects for this to work.

VB.Net: How To Display Previous Shadow Copy Versions of File Allowing User to Choose One

I'm writing an Excel file recovery program with VB.Net that tries to be a convenient place to gather and access Microsoft's recommended methods. If your interested in my probably kludgy, error filled, and lacking enough cleanup code it's here: http://pastebin.com/v4GgDteY. The basic functionality seems to work although I haven't tested graph macro table recovery yet.
It occurred to me that Vista and Windows 7 users could benefit from being offered a list of previous versions of the file within my application if the Shadow Copy Service is on and there are previous copies. How do I do this?
I looked at a lot of web pages but found no easy to crib code. One possibility I guess would be to use vssadmin via the shell but that is pretty cumbersome. I just want to display a dialogue box like the Previous Versions property sheet and allow users to pick one of the previous versions. I guess I could just display the previous version property sheet via the shell by programmatically invoking the context menu and the "Restore previous versions choice", however I also want to be able to offer the list for Vista Home Basic and Premium Users who don't have access to that tab even though apparently the previous versions still exist. Additionally if it possible I would like to offer XP users the same functionality although I'm pretty sure with XP only the System files are in the shadow copies.
I looked at MSDN on the Shadow Copy Service and went through all the pages, I also looked at AlphaVSS and AlphaFS and all the comments. I'm kind of guessing that I need to use AlphaVss and AlphFS and do the following?
Find out the list of snapshots/restore points that exist on the computer.
Mount those snapshots.
Navigate in the mounted volumes to the Excel file the user wants to recover and make a list of those paths.
With the list of paths handy, compare with some kind of diff program, the shadow copies of the files with the original.
Pull out the youngest or oldest version (I don't think it matters) of those shadow copies that differ from the recovery target.
List those versions of the files that are found to be different.
This seems cumbersome and slow, but maybe is the fastest way to do things. I just need some confirmation that is the way to go now.
I finally decided to go ahead and start coding. Please make suggestions for speeding up the code or what do with files that are found to be different from the recovery file target. Is there a simpler way to do this with AlphaVSS and AlphaFS?
Private Sub Button1_Click_2(sender As System.Object, e As System.EventArgs) Handles Button1.Click
'Find out the number of vss shadow snapshots (restore
'points). All shadows apparently have a linkable path
'\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy#,
'where # is a simple one, two or three digit integer.
Dim objProcess As New Process()
objProcess.StartInfo.UseShellExecute = False
objProcess.StartInfo.RedirectStandardOutput = True
objProcess.StartInfo.CreateNoWindow = True
objProcess.StartInfo.RedirectStandardError = True
objProcess.StartInfo.FileName() = "vssadmin"
objProcess.StartInfo.Arguments() = "List Shadows"
objProcess.Start()
Dim burp As String = objProcess.StandardOutput.ReadToEnd
Dim strError As String = objProcess.StandardError.ReadToEnd()
objProcess.WaitForExit()
Dim xnum As Integer = 0
Dim counterVariable As Integer = 1
' Call Regex.Matches method.
Dim matches As MatchCollection = Regex.Matches(burp, _
"HarddiskVolumeShadowCopy")
' Loop over matches.
For Each m As Match In matches
xnum = xnum + 1
'At the max xnum + 1 is the number of shadows that exist
Next
objProcess.Close()
Do
'Here we make symbolic links to all the shadows, one at a time
'and loop through until all shadows are exposed as folders in C:\.
Dim myProcess As New Process()
myProcess.StartInfo.FileName = "cmd.exe"
myProcess.StartInfo.UseShellExecute = False
myProcess.StartInfo.RedirectStandardInput = True
myProcess.StartInfo.RedirectStandardOutput = True
myProcess.StartInfo.CreateNoWindow = True
myProcess.Start()
Dim myStreamWriter As StreamWriter = myProcess.StandardInput
myStreamWriter.WriteLine("mklink /d C:\shadow" & counterVariable _
& " \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy" _
& counterVariable & "\")
myStreamWriter.Close()
myProcess.WaitForExit()
myProcess.Close()
' Here I compare our recovery target file against the shadow copies
Dim sFile As String = PathTb.Text
Dim sFileShadowPath As String = "C:\shadow" & _
counterVariable & DelFromLeft("C:", sFile)
Dim jingle As New Process()
jingle.StartInfo.FileName = "cmd.exe"
jingle.StartInfo.UseShellExecute = False
jingle.StartInfo.RedirectStandardInput = True
jingle.StartInfo.RedirectStandardOutput = True
jingle.StartInfo.CreateNoWindow = True
jingle.Start()
Dim jingleWriter As StreamWriter = jingle.StandardInput
jingleWriter.WriteLine("fc """ & sFile & """ """ _
& sFileShadowPath & """")
jingleWriter.Close()
jingle.WaitForExit()
Dim jingleReader As StreamReader = jingle.StandardOutput
Dim JingleCompOut As String = jingleReader.ReadToEnd
jingleReader.Close()
jingle.WaitForExit()
jingle.Close()
Dim jingleBoolean As Boolean = JingleCompOut.Contains( _
"no differences encountered").ToString
If jingleBoolean = "True" Then
MsgBox(jingleBoolean)
Else
'I haven't decided what to do with the paths of
'files that are different from the recovery target.
MsgBox("No")
End If
counterVariable = counterVariable + 1
Loop Until counterVariable = xnum + 1
End Sub