Check excel file is open by other user - vb.net

I have a excel file place on server.
I am using a application which written by VB.NET to open file in read only mode.
User 1 open file in read only mode.
How can user 2 detect that file is open or not status?
Thanks,
An

You need to test the file Read Only as ReadWrite will fail if the file is ReadOnly status.
Below are some methods. Not sure where I got them all from except the last one by Randy Birch.
Speed tests favour FileIsOpen3 and FileIsOpen4.
Function FileIsOpen1(ByVal pathfile As String) As Boolean
Dim ff As Integer
If System.IO.File.Exists(pathfile) Then
Try
ff = FreeFile()
Microsoft.VisualBasic.FileOpen(ff, pathfile, OpenMode.Binary, OpenAccess.Read, OpenShare.LockReadWrite)
Return False
Catch
Return True
Finally
FileClose(ff)
End Try
Return True
End If
End Function
Function FileIsOpen2(ByVal pathfile As String) As Boolean
Dim stream As FileStream = Nothing
Dim fi As FileInfo = Nothing
If System.IO.File.Exists(pathfile) Then
Try
fi = New System.IO.FileInfo(pathfile)
stream = fi.Open(FileMode.Open, FileAccess.Read, FileShare.None)
Return True
Catch generatedExceptionName As IOException
Return False
Finally
If stream IsNot Nothing Then
stream.Close()
End If
fi = Nothing
End Try
Return True
End If
End Function
Private Function FileIsOpen3(ByVal pathfile As String) As Boolean
Try
Dim fs As IO.FileStream = IO.File.Open(pathfile, IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.None)
fs.Close()
fs.Dispose()
fs = Nothing
Return False
Catch ex As IO.IOException ' File open
Return True
Catch ex As Exception ' Unknown error
Return True
End Try
End Function
Private Declare Function CreateFile Lib "kernel32" _
Alias "CreateFileA" _
(ByVal lpFileName As String, _
ByVal dwDesiredAccess As Long, _
ByVal dwShareMode As Long, _
ByVal lpSecurityAttributes As Long, _
ByVal dwCreationDisposition As Long, _
ByVal dwFlagsAndAttributes As Long, _
ByVal hTemplateFile As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" _
(ByVal hFile As Long) As Long
' Method
Shared Function FileIsOpen4(ByVal pathfile As String) As Boolean
' Is File In Use ©1996-2009 Randy Birch
' http://vbnet.mvps.org/index.html?code/fileapi/createfile_inuse.htm
Const GENERIC_READ As Long = &H80000000
Const INVALID_HANDLE_VALUE As Long = -1
Const OPEN_EXISTING As Long = 3
Const FILE_ATTRIBUTE_NORMAL As Long = &H80
Dim hFile As Long
If System.IO.File.Exists(pathfile) Then
Try
' note that FILE_ATTRIBUTE_NORMAL (&H80) has a different value than VB's constant vbNormal (0)!
hFile = CreateFile(pathfile, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0&)
' this will evaluate to either -1 (File in use) or 0 (File free)
Return hFile = INVALID_HANDLE_VALUE
Catch ex As Exception
MessageBox.Show(ex.ToString)
Finally
CloseHandle(hFile)
End Try
Else
Return True
End If
End Function

The second user can try to open the file in read-write mode to know if the file is being used.

Related

Clearing office clipboard is not working after Office 365 update

I have a macro that copies rtf format word document to outlook email for sending it to many recipients. However, due to this a copy of the text is also saved on the clipboard and the code crashes if many recipients are there. I was using the below code for clearing the clipboard but the code is no longer working after the office 365 update. I tried changing the declare functions to include 'Ptrsafe' but still not able to run it. Any help would be greatly appreciated. Thanks
Declare Function AccessibleObjectFromWindow Lib "oleacc" ( _
ByVal hwnd As Long, ByVal dwId As Long, _
riid As tGUID, ppvObject As Object) As Long
Declare Function AccessibleChildren Lib "oleacc" _
(ByVal paccContainer As IAccessible, ByVal iChildStart As Long, _
ByVal cChildren As Long, rgvarChildren As Variant, _
pcObtained As Long) As Long
Declare Function FindWindow Lib "User32" Alias "FindWindowA" ( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
Declare Function GetParent Lib "User32" (ByVal hwnd As Long) As Long
Declare Function EnumChildWindows Lib "User32" (ByVal hwndParent _
As Long, ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
Declare Function GetClassName Lib "User32" Alias "GetClassNameA" (ByVal hwnd As Long, _
ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Declare Function SendMessage Lib "User32" Alias "SendMessageA" (ByVal hwnd As Long, _
ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long
Declare Function FindWindowEx Lib "User32" Alias "FindWindowExA" (ByVal hWnd1 As Long, _
ByVal hWnd2 As Long, ByVal lpClass As String, ByVal lpCaption As String) As Long
Const CHILDID_SELF = 0&
Const ROLE_PUSHBUTTON = &H2B&
Const WM_GETTEXT = &HD
Type tGUID
lData1 As Long
nData2 As Integer
nData3 As Integer
abytData4(0 To 7) As Byte
End Type
Type AccObject
objIA As IAccessible
lngChild As Long
End Type
Dim lngChild As Long
Dim strClass As String
Dim strCaption As String
'Using Active Accessibility to clear Office clipboard
'Assumption:
'this is running within Word or Excel as a macro, thus the global Application object is available
Sub ClearOfficeClipboard()
Static accButton As AccObject
If accButton.objIA Is Nothing Then
Dim fShown As Boolean
fShown = CommandBars("Office Clipboard").Visible 'Office 2013+ version
If Not (fShown) Then
CommandBars("Office Clipboard").Visible = True 'Office 2013+ version
End If
accButton = FindAccessibleChildInWindow(GetOfficeClipboardHwnd(Application), "Clear All", ROLE_PUSHBUTTON)
End If
If accButton.objIA Is Nothing Then
MsgBox "Unable to locate the ""Clear All"" button!"
Else
accButton.objIA.accDoDefaultAction accButton.lngChild
End If
CommandBars("Office Clipboard").Visible = False
End Sub
'Retrieve window class name
Function GetWndClass(ByVal hwnd As Long) As String
Dim buf As String
Dim retval As Long
buf = Space(256)
retval = GetClassName(hwnd, buf, 255)
GetWndClass = Left(buf, retval)
End Function
'Retrieve window title
Function GetWndText(ByVal hwnd As Long) As String
Dim buf As String
Dim retval As Long
buf = Space(256)
retval = SendMessage(hwnd, WM_GETTEXT, 255, buf)
GetWndText = Left(buf, InStr(1, buf, Chr(0)) - 1)
End Function
'The call back function used by EnumChildWindows
Function EnumChildWndProc(ByVal hChild As Long, ByVal lParam As Long) As Long
Dim found As Boolean
EnumChildWndProc = -1
If strClass > "" And strCaption > "" Then
found = StrComp(GetWndClass(hChild), strClass, vbTextCompare) = 0 And _
StrComp(GetWndText(hChild), strCaption, vbTextCompare) = 0
ElseIf strClass > "" Then
found = (StrComp(GetWndClass(hChild), strClass, vbTextCompare) = 0)
ElseIf strCaption > "" Then
found = (StrComp(GetWndText(hChild), strCaption, vbTextCompare) = 0)
Else
found = True
End If
If found Then
lngChild = hChild
EnumChildWndProc = 0
Else
EnumChildWndProc = -1
End If
End Function
'Find the window handle of a child window based on its class and titie
Function FindChildWindow(ByVal hParent As Long, Optional cls As String = "", Optional title As String = "") As Long
lngChild = 0
strClass = cls
strCaption = title
EnumChildWindows hParent, AddressOf EnumChildWndProc, 0
FindChildWindow = lngChild
End Function
'Retrieve the IAccessible interface from a window handle
'Reference:Jean Ross,Chapter 17: Accessibility in Visual Basic,Advanced Microsoft Visual Basic 6.0, 2nd Edition
Function IAccessibleFromHwnd(hwnd As Long) As IAccessible
Dim oIA As IAccessible
Dim tg As tGUID
Dim lReturn As Long
' Define the GUID for the IAccessible object
' {618736E0-3C3D-11CF-810C-00AA00389B71}
With tg
.lData1 = &H618736E0
.nData2 = &H3C3D
.nData3 = &H11CF
.abytData4(0) = &H81
.abytData4(1) = &HC
.abytData4(2) = &H0
.abytData4(3) = &HAA
.abytData4(4) = &H0
.abytData4(5) = &H38
.abytData4(6) = &H9B
.abytData4(7) = &H71
End With
' Retrieve the IAccessible object for the form
lReturn = AccessibleObjectFromWindow(hwnd, 0, tg, oIA)
Set IAccessibleFromHwnd = oIA
End Function
'Recursively looking for a child with specified accName and accRole in the accessibility tree
Function FindAccessibleChild(oParent As IAccessible, strName As String, lngRole As Long) As AccObject
Dim lHowMany As Long
Dim avKids() As Variant
Dim lGotHowMany As Long, i As Integer
Dim oChild As IAccessible
FindAccessibleChild.lngChild = CHILDID_SELF
If oParent.accChildCount = 0 Then
Set FindAccessibleChild.objIA = Nothing
Exit Function
End If
lHowMany = oParent.accChildCount
ReDim avKids(lHowMany - 1) As Variant
lGotHowMany = 0
If AccessibleChildren(oParent, 0, lHowMany, avKids(0), lGotHowMany) <> 0 Then
MsgBox "Error retrieving accessible children!"
Set FindAccessibleChild.objIA = Nothing
Exit Function
End If
'To do: the approach described in http://msdn.microsoft.com/msdnmag/issues/0400/aaccess/default.aspx
' are probably better and more reliable
On Error Resume Next
For i = 0 To lGotHowMany - 1
If IsObject(avKids(i)) Then
If StrComp(avKids(i).accName, strName) = 0 And avKids(i).accRole = lngRole Then
Set FindAccessibleChild.objIA = avKids(i)
Exit For
Else
Set oChild = avKids(i)
FindAccessibleChild = FindAccessibleChild(oChild, strName, lngRole)
If Not FindAccessibleChild.objIA Is Nothing Then
Exit For
End If
End If
Else
If StrComp(oParent.accName(avKids(i)), strName) = 0 And oParent.accRole(avKids(i)) = lngRole Then
Set FindAccessibleChild.objIA = oParent
FindAccessibleChild.lngChild = avKids(i)
Exit For
End If
End If
Next i
End Function
Function FindAccessibleChildInWindow(hwndParent As Long, strName As String, lngRole As Long) As AccObject
Dim oParent As IAccessible
Set oParent = IAccessibleFromHwnd(hwndParent)
If oParent Is Nothing Then
Set FindAccessibleChildInWindow.objIA = Nothing
Else
FindAccessibleChildInWindow = FindAccessibleChild(oParent, strName, lngRole)
End If
End Function
'Retrieve the window handle of the task pane
Function GetOfficeTaskPaneHwnd(app As Object) As Long
GetOfficeTaskPaneHwnd = FindChildWindow(app.hwnd, _
"MsoCommandBar", Application.CommandBars("Task Pane").NameLocal)
End Function
'Retrieve the window handle of the clipboard child window inside task pane
'The window title of the clipboard window seems to be language independent,
'making it a better start point to searching our UI element than the task pane window
Function GetOfficeClipboardHwnd(app As Object) As Long
GetOfficeClipboardHwnd = FindChildWindow(app.hwnd, , "Collect and Paste 2.0")
End Function```
We can clear the clipboard using a MsForms.DataObject. The code below creates one without the need to reference the MsForms library.
Sub ClearClipBoard()
With CreateObject("new:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
.SetText ""
.PutInClipBoard
End With
End Sub

VB6 StrPtr Function to VB.NET

Trying to convert VB6 line of code to VB.net. Code will serve as identification if printer is OFF or ON
Thanks
"PRINTERFOUND = OpenPrinterW(StrPtr(PrinterName), hPrinter)" Particular StrPtr function...
Can't get OpenPrinter to work - Tries to print I simply want to to know if printer is OFF or ON
changing line to
PRINTERFOUND = OpenPrinterW(PrinterName.Normalize(), hPrinter, Nothing)
does not work, thanks
Tried to convert VB6 declaration to VB.net per previous suggestions but it still a same error cant convert String to Integer please see below
'Private Declare Function GetPrinterApi Lib "winspool.drv" Alias "GetPrinterA" (ByVal hPrinter As Long, ByVal Level As Long, ByRef BUFFER As Long, ByVal pbSize As Long, ByRef pbSizeNeeded As Long) As Long
<DllImport("winspool.Drv", EntryPoint:="GetPrinterA", SetLastError:=True, CharSet:=CharSet.Ansi, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
Public Function GetPrinterApi(<MarshalAs(UnmanagedType.LPStr)> ByVal hPrinter As String, ByVal Level As IntPtr, ByVal BUFFER As IntPtr, ByVal pbSize As IntPtr, ByRef pbSizeNeeded As IntPtr) As Boolean
End Function
'Private Declare Function OpenPrinterW Lib "winspool.drv" (ByVal pPrinterName As Long, ByRef phPrinter As Long, Optional ByVal pDefault As Long = 0) As Long
<DllImport("winspool.Drv", SetLastError:=True, CharSet:=CharSet.Ansi, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
Public Function OpenPrinterW(ByVal pPrinterName As IntPtr, ByVal phPrinter As Int32, <[In](), MarshalAs(UnmanagedType.LPStruct)> ByVal pDefault As IntPtr) As Boolean
End Function
'Private Declare Function ClosePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long
<DllImport("winspool.Drv", EntryPoint:="ClosePrinter", SetLastError:=True, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
Public Function ClosePrinter(ByVal hPrinter As IntPtr) As Boolean
End Function
'Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByRef Destination As Long, ByRef Source As Long, ByVal Length As Long)
<DllImport("kernel32.dll", SetLastError:=True, EntryPoint:="RtlMoveMemory")> _
Public Function CopyMemory(ByRef Destination As Long, ByVal Source As IntPtr, ByVal Length As String) As IntPtr
End Function
Full code Below
'Acknowledgements : This program has been written making extensive use of the
'Merrion article http://www.merrioncomputing.com/Programming/PrintStatus.htm
'It has also benefited from the contributors to VBForums thread # 733849
'http://www.vbforums.com/showthread.php?t=733849&goto=newpost - especially the code
'suggested by "Bonnie West"
'Program written 14 Sept. 2013 by C.A. Moore
Option Explicit
Dim PRINTERFOUND As Long
Dim GETPRINTER As Long
Dim BUFFER() As Long
Dim pbSizeNeeded As Long
Dim PRINTERINFO As PRINTER_INFO_2
Dim N As Integer
Dim M As Integer
Dim CHAR As String
Dim prnPrinter As Printer
Dim BUF13BINARY As String
' Note : PRINTERREADY as an Integer variable is Dim'd
'"Public PRINTERREADY As Integer" at Form1 Option Explicit
Private Type PRINTER_INFO_2
pServerName As String
pPrinterName As String
pShareName As String
pPortName As String
pDriverName As String
pComment As String
pLocation As String
pDevMode As Long
pSepFile As String
pPrintProcessor As String
pDatatype As String
pParameters As String
pSecurityDescriptor As Long
Attributes As Long
Priority As Long
DefaultPriority As Long
StartTime As Long
UntilTime As Long
Status As Long
JobsCount As Long
AveragePPM As Long
End Type
Private Declare Function GetPrinterApi Lib "winspool.drv" Alias "GetPrinterA" (ByVal hPrinter As Long, ByVal Level As Long, BUFFER As Long, ByVal pbSize As Long, pbSizeNeeded As Long) As Long
Private Declare Function OpenPrinterW Lib "winspool.drv" (ByVal pPrinterName As Long, ByRef phPrinter As Long, Optional ByVal pDefault As Long) As Long
Private Declare Function ClosePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Public Function StringFromPointer(lpString As Long, lMaxLength As Long) As String
'this service function extracts a string (sRet) when fed with a pointer (lpstring)
'from a buffer
Dim sRet As String
Dim lret As Long
If lpString = 0 Then
StringFromPointer = ""
Exit Function
End If
'\\ Pre-initialise the return string...
sRet = Space$(lMaxLength)
CopyMemory ByVal sRet, ByVal lpString, ByVal Len(sRet)
If Err.LastDllError = 0 Then
If InStr(sRet, Chr$(0)) > 0 Then
sRet = Left$(sRet, InStr(sRet, Chr$(0)) - 1)
End If
End If
StringFromPointer = sRet
End Function
Public Function IsPrinterReady(ByRef PrinterName As String)
Form1.PRINTERREADY = 0
'first select the named printer and check if it is installed
For Each prnPrinter In Printers
CHAR = prnPrinter.DeviceName
If CHAR = PrinterName Then
Set Printer = prnPrinter 'sets this as printer
Form1.PRINTERREADY = 1
End If
Next
If Form1.PRINTERREADY = 0 Then GoTo Line1000 'exit. printer not installed
Dim hPrinter As Long
Dim PI6 As PRINTER_INFO_2
PRINTERFOUND = 0
Form1.PRINTERREADY = 0
PRINTERFOUND = OpenPrinterW(StrPtr(PrinterName), hPrinter)
'(OpenPrinterW(ByVal pPrinterName As Long, ByRef phPrinter As Long) As Long)
If PRINTERFOUND = 0 Then 'ie. printer not found
Form1.PRINTERREADY = 0
Debug.Assert ClosePrinter(hPrinter)
GoTo Line100
End If
'If we get here named printer was found and accessed and its hPrinter handle is
'known
'Dim BUFFER() As Long
'Dim pbSizeNeeded As Long
ReDim Preserve BUFFER(0 To 1) As Long
GETPRINTER = GetPrinterApi(hPrinter, 2&, BUFFER(0), UBound(BUFFER), pbSizeNeeded)
ReDim Preserve BUFFER(0 To (pbSizeNeeded / 4) + 3) As Long
GETPRINTER = GetPrinterApi(hPrinter, 2&, BUFFER(0), UBound(BUFFER) * 4, pbSizeNeeded)
If GETPRINTER = 0 Then 'ie. some problem with printer access
Form1.PRINTERREADY = 0
GoTo Line100
End If
'If we get here then GETPRINTER = 1, ie. printer found and accessed OK
With PRINTERINFO '\\ This variable is of type PRINTER_INFO_2
'These quantities are defined here because the Merrion article
'so specifies. However they are not used by this program, and most
'have been found to be void
.pServerName = StringFromPointer(BUFFER(0), 1024)
.pPrinterName = StringFromPointer(BUFFER(1), 1024)
.pShareName = StringFromPointer(BUFFER(2), 1024)
.pPortName = StringFromPointer(BUFFER(3), 1024)
.pDriverName = StringFromPointer(BUFFER(4), 1024)
.pComment = StringFromPointer(BUFFER(5), 1024)
.pLocation = StringFromPointer(BUFFER(6), 1024)
.pDevMode = BUFFER(7)
.pSepFile = StringFromPointer(BUFFER(8), 1024)
.pPrintProcessor = StringFromPointer(BUFFER(9), 1024)
.pDatatype = StringFromPointer(BUFFER(10), 1024)
.pParameters = StringFromPointer(BUFFER(11), 1024)
.pSecurityDescriptor = BUFFER(12)
.Attributes = BUFFER(13)
.Priority = BUFFER(14)
.DefaultPriority = BUFFER(15)
.StartTime = BUFFER(16)
.UntilTime = BUFFER(17)
.Status = BUFFER(18)
.JobsCount = BUFFER(19)
.AveragePPM = BUFFER(20)
End With
'This next code is for interest and program development only.
'It writes into List1 the value of each buffer 1 - 20
'To by-pass it, add a "Go To Line15" statement at this point.
Form1.List1.Clear
N = 0
Line5:
On Error GoTo Line15
Form1.List1.AddItem "Buffer No. " & N & " Buffer Value " & BUFFER(N)
N = (N + 1)
If N = 21 Then GoTo Line15
GoTo Line5
'Now to convert the decimal value of Buffer(13) into a binary
'bit pattern and store this in BUF13BINARY
Line15: 'and to show Buffer(13) as a binary bit pattern at Form1.Label1
N = BUFFER(13)
BUF13BINARY = ""
M = 4196
Line16:
If N < M Then
BUF13BINARY = BUF13BINARY & "0"
GoTo Line20
End If
BUF13BINARY = BUF13BINARY & "1"
N = (N - M)
Line20:
If M = 1 Then GoTo Line10
M = M / 2
GoTo Line16
Line10: 'BUF13BINARY is now the 13 bit binary value of Buffer(13)
'eg. 0011000100010
Form1.Label1.Caption = BUF13BINARY 'display this binary value at form 1
'we now examine the value of the third binary bit in BUF13BINARY
If Mid$(BUF13BINARY, 3, 1) = "0" Then Form1.PRINTERREADY = 1
If Mid$(BUF13BINARY, 3, 1) = "1" Then Form1.PRINTERREADY = 0
Line100:
ClosePrinter (hPrinter)
Line1000:
End Function
and
Option Explicit
Public PRINTERREADY As Integer
Private Sub Command1_Click()
IsPrinterReady ("Brother QL-500")
'IsPrinterReady ("EPSON Stylus CX5400")
MsgBox PRINTERREADY '0 = Not Ready 1 = Ready
End Sub
You cannot convert VarPtr, StrPtr, or ObjPtr, because in .NET you do not directly control memory. These functions were used to extract a pointer from an instance, a variable, or a Unicode string. But in .NET, object locations in memory is managed by the garbage collector, and the GC can move objects around in memory at any time.
Consider the following code, but do not use it! I put it here only to explain why these functions do not exist in .NET.
Private Function VarPtr(ByVal obj As Object) As Integer
' Obtain a pinned handle to the object
Dim handle As GCHandle = GCHandle.Alloc(obj, GCHandleType.Pinned)
Dim pointer As Integer = handle.AddrOfPinnedObject.ToInt32
' Free the allocated handle. At this point the GC can move the object in memory, this is
' why this function does not exist in .NET. If you were to use this pointer as a destination
' for memcopy for example, you could overwrite unintended memory, which would crash the
' application or cause unexpected behavior. For this function to work you would need to
' maintain the handle until after you are finished using it.
handle.Free()
Return pointer
End Function
Edit:
The correct way to get the printer status is through the managed interface for it, in this case through WMI:
Imports System.Management
Public Class Form1
Private Enum PrinterStatus As Integer
Other = 1
Unknown = 2
Idle = 3
Printing = 4
Warmup = 5
Stopped = 6
Offline = 7
End Enum
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim mos = New ManagementObjectSearcher("SELECT * FROM Win32_Printer")
For Each p In mos.Get()
Debug.Print(p.Properties("Name").Value.ToString() & " : " & CType(CInt(p.Properties("PrinterStatus").Value), PrinterStatus).ToString())
Next
End Sub
End Class
You can get more information about the Win32_Printer class here: https://msdn.microsoft.com/en-us/library/aa394363(v=vs.85).aspx
In particular take note of this:
Note If you are retrieving PrinterStatus = 3 or PrinterState = 0, the
printer driver may not be feeding accurate information into WMI. WMI
retrieves the printer information from the spoolsv.exe process. It is
possible the printer driver does not report its status to the spooler.
In this case, Win32_Printer reports the printer as Idle.
From there you can get information about and manage just about any peripheral connected. Just figure out the appropriate WMI classes and read up on the docs.
Thanks Everyone, especially Drunken Code Monkey for all the information provided, I was able to finally achieve what I wanted after reading on https://msdn.microsoft.com/en-us/library/aa394363(v=vs.85).aspx figured need to is boolean WorkOffline; Pew... made it more simple then VB6 language even using that feels kinda hmm old. Also lucky me found codes that did the same thing as I wanted here is link to VB.NET "https://bytes.com/topic/visual-basic-net/answers/524957-detecting-if-printer-connected-pc" And my modification of this code below
Imports System.Management
Public Class Form1
Public Class CheckPrinterStatus
Public Function PrinterIsOnline(ByVal sPrinterName As String) As Boolean
'// Set management scope
Dim scope As ManagementScope = New ManagementScope("\root\cimv2")
scope.Connect()
'// Select Printers from WMI Object Collections
Dim searcher As ManagementObjectSearcher = New ManagementObjectSearcher("SELECT * FROM Win32_Printer")
Dim printerName As String = String.Empty
For Each printer As ManagementObject In searcher.Get()
printerName = printer("Name").ToString() '.ToLower()
If (printerName.Equals(sPrinterName)) Then
MsgBox(printerName)
If (printer("WorkOffline").ToString().ToLower().Equals("true")) Then
MsgBox("Offline")
' Printer is offline by user
Return False
Else
' Printer is not offline
MsgBox("Online")
Return True
End If
End If
Next
Return False
End Function ' PrinterIsOnline
End Class
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim PrinterSatus As New CheckPrinterStatus
PrinterSatus.PrinterIsOnline("Brother QL-500") 'Name of The printer HERE
End Sub
End Class

visual studio host stopping sometimes and marshal objective throwing error some times when we save notepad to desktop folder

This is code to save untitled notepad to desktop or given path. when we run this code visual studio host stopping some times and some times marshal object throwing error, when we have more than one notepad opened some files are saving .. after that program stopping automatically.. we are passing path as Environment.SpecialFolder.Desktop
Private Const WM_GETTEXT As Integer = &HD
Private Const WM_GETTEXTLENGTH As Integer = &HE
Declare Auto Function SendMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal msg As Integer, _
ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function FindWindowEx(ByVal parentHandle As IntPtr, _
ByVal childAfter As IntPtr, _
ByVal lclassName As String, _
ByVal windowTitle As String) As IntPtr
End Function
Declare Auto Function FindWindow Lib "user32.dll" (ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
Sub saveNotepad(pat As String)
Try
Dim processes() As Process
Dim procName As String = "notepad"
processes = Process.GetProcessesByName(procName)
If processes IsNot Nothing Then
For Each proc In processes
If Not proc.MainWindowTitle = "" Then
Dim Hwnd As IntPtr = FindWindow(Nothing, proc.MainWindowTitle)
Dim ChildHandle As IntPtr = FindWindowEx(Hwnd, IntPtr.Zero, "Edit", Nothing)
Dim size As Int32 = SendMessage(CInt(ChildHandle), WM_GETTEXTLENGTH, 0, 0).ToInt32()
Dim Hndl As IntPtr = Marshal.AllocHGlobal(size + 1)
Dim NumText As Integer = SendMessage(ChildHandle, WM_GETTEXT, size + 1, Hndl)
Dim Text As String = Marshal.PtrToStringUni(Hndl)
Dim savePath As String = System.IO.Path.Combine(pat, "Terminator")
Dim fs As FileStream = File.Create(IO.Path.Combine(savePath, proc.MainWindowTitle & DateTime.Now.ToString("yyyyMMdd_HHmmss")) & ".txt")
Dim info As Byte() = New UTF8Encoding(True).GetBytes(Text)
fs.Write(info, 0, info.Length)
fs.Close()
Marshal.FreeHGlobal(Hndl)
End If
Next
End If
Catch ex As Exception
Common.LogDebuggerData("Error: " & ex.Message & vbCrLf & ex.StackTrace)
Finally
GC.Collect()
GC.WaitForPendingFinalizers()
End Try
End Sub
Replacing
Marshal.AllocHGlobal(size + 1)
with
Marshal.AllocHGlobal(2 * (size + 1))
will solve the problem

Get url from all open tabs in Google Chrome using VB .Net and UI Automation

Hello I have this code working to get current url on Chrome, but only get active tab url. I need to get url from all open tabs using UI Automation.
My working code:
Function GetChromeUrl(ByVal proc As Process) As String
If proc.MainWindowHandle = IntPtr.Zero Then
Return Nothing
End If
Dim element As System.Windows.Automation.AutomationElement = AutomationElement.FromHandle(proc.MainWindowHandle)
If element Is Nothing Then
Return Nothing
End If
Dim edit As System.Windows.Automation.AutomationElement = element.FindFirst(TreeScope.Children, New PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit))
Return (edit.GetCurrentPattern(ValuePattern.Pattern)).Current.Value.ToString
End Function
and call it using this code in Form Load event:
For Each proc As Process In Process.GetProcessesByName("chrome")
MsgBox(proc.MainWindowTitle + " " + GetChromeUrl(proc))
Next
you better try this way
Imports NDde.Client 'import the NDde library for firefox
Imports System.Runtime.InteropServices
'For Chrome
Private Const WM_GETTEXTLENGTH As Integer = &He
Private Const WM_GETTEXT As Integer = &Hd
<DllImport("user32.dll")> _
Private Shared Function SendMessage(hWnd As IntPtr, Msg As UInteger, wParam As Integer, lParam As Integer) As Integer
End Function
<DllImport("user32.dll")> _
Private Shared Function SendMessage(hWnd As IntPtr, Msg As UInteger, wParam As Integer, lParam As StringBuilder) As Integer
End Function
<DllImport("user32.dll", SetLastError := True)> _
Private Shared Function FindWindowEx(parentHandle As IntPtr, childAfter As IntPtr, className As String, windowTitle As String) As IntPtr
End Function
Public Shared Function getChromeUrl(winHandle As IntPtr) As String
Dim browserUrl As String = Nothing
Dim urlHandle As IntPtr = FindWindowEx(winHandle, IntPtr.Zero, "Chrome_AutocompleteEditView", Nothing)
Const nChars As Integer = 256
Dim Buff As New StringBuilder(nChars)
Dim length As Integer = SendMessage(urlHandle, WM_GETTEXTLENGTH, 0, 0)
If length > 0 Then
SendMessage(urlHandle, WM_GETTEXT, nChars, Buff)
browserUrl = Buff.ToString()
Return browserUrl
Else
Return browserUrl
End If
End Function
Public shared Function GetChromeHandle() As Intptr
Dim ChromeHandle As IntPtr = Nothing
Dim Allpro() As Process = Process.GetProcesses();
For Each pro As Process in Allpro
if pro.ProcessName = "chrome"
ChromeHandle = pro.MainWindowHandle
Exit For
End if
Next
Return ChromeHandle
End Function
'USAGE FOR CHROME
Dim CHandle As IntPtr = GetChromeHandle()
If Not CHandle,Equals(Intptr.Zero)
Dim url As String = getChromeUrl(CHandle)
End If
Source and read more
EDIT :
i found my own way and it worked for me
Dim appAs String = "chrome"
Dim proc As System.Diagnostics.Process = GetBrowser(app)
...
Private Function GetBrowser(ByVal appName) As System.Diagnostics.Process
Dim pList() As System.Diagnostics.Process =
System.Diagnostics.Process.GetProcessesByName(app)
For Each proc As System.Diagnostics.Process In pList
If proc.ProcessName = appThen
Return proc
End If
Next
Return Nothing
End Function
usage :
If proc IsNot Nothing Then
Dim browserName as string = "Google Chrome"
Dim className as String = "Edit"
Dim s As String =
GetCurrentUrl(proc.MainWindowHandle, browserName, className, ComboBox1)
If s <> "" Then
Msgbox.show(s)
ComboBox1.SelectedIndex = 0 'Window list
Else
End If
Else
Label1.Text = browserName & " is not available"
end If
hope it helps :))))

VB Retrieve file directory path from a process

I've worked with VBA for a few years, but I'm switching to VB to utilize more powerful coding practices.
I have the following VB code to attach an Excel workbook to an open instance:
Dim FullFilePath as String = "C:\Temp"
Dim WrkBk = as Excel.Workbook
WrkBk = System.Runtime.InteropServices.Marshal.BindToMoniker(FullFilePath)
This seems to require the workbook's directory path.
I have the following code to cycle through Excel processes.
FileName = "ABCD.xlsm"
For Each P As Process In System.Diagnostics.Process.GetProcessesByName("EXCEL")
With P
If .MainWindowTitle.ToLower.Contains(FileName.ToLower) Then
'don't know the code to get the directory where the p process is located
WrkBk = System.Runtime.InteropServices.Marshal.BindToMoniker(FilePath)
Exit For
End If
End With
Next
The path to ABCD.xlsm is not always the same for my application. Everything I've googled for getting a directory of the process returns the EXCEL.EXE path or returns the path of the vb project's working directory. I really need it to return something like: "C:\Temp\Tools\ABCD.xlsm" so I can attach WrkBk to the process.
Any Ideas? Is there an easier way to do this?
Dim xl As Excel.Application
xl = GetObject(, "Excel.Application")
For Each wb As Excel.Workbook In xl.Workbooks
MsgBox(wb.FullName)
Next wb
xl = Nothing
I finally found it.
Windows API....
Private Delegate Function EnumWindowsProc(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As Boolean
Private Declare Function EnumChildWindows Lib "user32.dll" (ByVal hWndParent As IntPtr, ByVal lpEnumFunc As EnumWindowsProc, ByVal lParam As IntPtr) As Boolean
Private Declare Function GetClassName Lib "user32.dll" Alias "GetClassNameA" (ByVal hwnd As IntPtr, ByVal lpClassName As String, ByVal nMaxCount As Int32) As Int32
Private Const MAX_TITLE As Int32 = 256
Private Const S_OK As Int32 = &H0
Private Function GetClassName(ByVal hwnd As IntPtr) As String
Dim name As New String(" "c, MAX_TITLE)
Dim len = GetClassName(hwnd, name, MAX_TITLE)
If len = 0 Then Return Nothing
Return name.Remove(len)
End Function
Private Declare Function AccessibleObjectFromWindow Lib "OLEACC.dll" (ByVal hwnd As IntPtr, ByVal dwId As Int32, ByVal riid As Byte(), ByRef ppvObject As IntPtr) As Integer
Private Const OBJID_NATIVEOM As Int32 = &HFFFFFFF0
Private IID_IDispatch As New Guid("{00020400-0000-0000-C000-000000000046}")
function...
Function EnumCWindows(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As Boolean
Dim name = GetClassName(hwnd)
If name = "EXCEL7" OrElse name = "EXCEL10" Then
Dim ptr As IntPtr
If AccessibleObjectFromWindow(hwnd, OBJID_NATIVEOM, IID_IDispatch.ToByteArray(), ptr) = S_OK Then
Dim win = CType(Marshal.GetObjectForIUnknown(ptr), Excel.Window)
Dim sheet = CType(win.ActiveSheet, Excel.Worksheet)
Dim book = CType(sheet.Parent, Excel.Workbook)
If book.FullName.ToLower.Contains("wpp tools") Then
FoundTheFile = True
WPPFilePath = book.FullName
Exit Function
End If
End If
End If
Return True
End Function
then in your code....
For Each p In Process.GetProcesses
If p.ProcessName = "EXCEL" Then
EnumChildWindows(p.MainWindowHandle, AddressOf EnumCWindows, IntPtr.Zero)
If FoundTheFile = True Then Exit For
End If
Next
If FoundTheFile = False Then
MsgBox("Targeted file was not found.", MsgBoxStyle.OkOnly, "File Find Error")
End
End If
I hope this can help someone else as I've searched for a week now!