Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

VFP app to check if a USB device is connected or not 2

Status
Not open for further replies.

a1sifat

Programmer
Aug 22, 2018
11
BD
I want to create a VFP app that will check if a specific USB device is connected or not. I have one form and two labels. If that specific USB device is connected then it will change the label caption to "Connected" else "Not Connected". I know this can be done by using C# language but i want to know if there is any way to achieve the same using VFP. TIA
 
VFP is not hardware agnostic, but so is C# core language, you will use a specific assembly in C#, which mostly base on some System API anyway, and those can be leveraged in VFP via DECLARE DLL, too.

One higher level interface to hardware are WMI queries, of eg Win32_Devices, but as so often, there are multiple ways to do similar things.

The samples of VFP include "Binding to Windows Message Events" and one of them is captioned Media, which describes itself this way:
Sample Media Change Events said:
The operating system broadcasts a message to all running applications whenever a power management event occurs such as system stand-by or hibernation. Additionally, messages are broadcast when one attempts to shutdown Windows. You can trap for these events and perform necessary actions or even prevent the power suspension or shutdown from occurring.

Sample: to run the sample, click on the Enable Event button. Once the event is active, click on the Start menu and select Shut Down. When the dialog appears, select either Stand by or Hibernate. A dialog will appear asking if you want to go in Stand By mode. All responses are recorded to the edit box on the right side. In fact, if you select Yes, when you resume from Stand By mode, power events will still be received. You are also prompted if you attempt to shutdown Windows.

Details:

This sample uses the following binding to detect power management changes:
BINDEVENT(_VFP.hWnd, WM_POWERBROADCAST, THIS, "handlewinmsg")

You can find additional information about Power Management events in MSDN:
System Shutdown events
WM_QUERYENDSESSION Message

Power Management events
WM_POWERBROADCAST Message

Click on the Constants button to view values for the #DEFINES.

You can detect a change to the hardware configuration of a device or the computer. For example, you may want to detect when media such as USB drive is inserted into the computer and act upon that event.
Sample: to run the sample, click on the Enable Event button. Once the event is active, insert a USB drive or other device. If you insert a USB drive, the sample will display JPEG and MP3 files.

Details:
This sample uses the following binding to handle media detection:
BINDEVENT(_VFP.hWnd, [highlight #FCE94F]WM_DEVICECHANGE[/highlight], THIS, "handlewinmsg")
BINDEVENT(_VFP.hWnd, WM_USER_SHNOTIFY, THIS, "handlewinmsg")

Note: WM_USER_SHNOTIFY is based on the WM_USER message
In addition, this sample uses a number of Shell functions to detect device changes.

You can find additional information about shell events in MSDN:
WM_DEVICECHANGE Message
WM_USER Message
Shell Programmer’s Guide
SHChangeNotifyRegister function

Click on the Constants button to view values for the #DEFINES.

The most interesting seems to be the WM_DEVICECHANE event, so you could concentrate on binding to that and finding out about the device changed, i.e whether it is your USB device.
You find the source code for that solution formk in Addbs(_samples)+"solution\europa\windowsevents.scx"

Bye, Olaf.

Olaf Doschke Software Engineering
 
A1sifat, is this any particular kind of USB device? Or is it specifically a USB disk drive (that is, a memory stick)?

The reason I ask is that, if is a disk drive that you are interested in, there is a simpler solution, involving a function in the FoxTools library. If you like, I can give you some code for that. But I won't bother if it is not what you are looking for, so let me know either way.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
If it's a drive, you can detect via VFPs DRIVETYPE() function. If you meant that, Mike, that's part of the VFP language without Foxtools.FLL, as many foxtools libarary functions have become part of the language.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Olaf, yes I did mean DRIVETYPE(). I didn't know that it was now part of the language. Thanks for pointing it out.

A1sifat, be aware that DRIVETYPE() detects a removable disk, but doesn't distinguish betweem USB sticks and floppy drives. Both return 2.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
@Mike Yes, the USB device is a Samsung Mobile. If you can provide me some codes for that then that will be really helpful. I looked at the sample application suggested by @Olaf which is closer to what i want to achieve, only problem is that i want my app to detect if the Samsung mobile is connected or not. If connected then show "connected" and if removed then show "disconnected".
 
A1sifat,

Sorry, but in my tests, a mobile phone doesn't appear as a removable disk drive - even though you can see the files in Windows Explorer, copy files to and from it, etc. I think that might be because the phone doesn't have a drive letter (at least, that's how it looks in my system).

For what it's worth, this is the code I used to test it. You might be able to adapt it to get it to work with your device. It might also be of use to anyone who wants to detect a conventional USB memory stick being connected, which should work fine.

Code:
FOR lnI = 0 TO 25
  lcDrive = CHR(65 + lnI) + ":"
  lnType = DriveType(lcDrive)
  IF lnType = 2
    lnCount = ADIR(laDrives, lcDrive, "V")
    IF lnCount > 0
      ? "Drive " + lcDrive + " - " + ;
        IIF(UPPER(laDrives(1)) = "SAMSUNG MOBILE", "Connected", "Not Connected")
     ENDIF 
   ENDIF 
ENDFOR

Obviously you will need to substitute the name of your own device for "SAMSUNG MOBILE".

Source: I adapted the code from this page: "Determining drive types in Visual FoxPro".

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
a1sifat,

does an event occur, if you run this sample form as given? If so, it's worth isolating the event that's happening to get your connected/disconnected status.
If not, it might be easiest you take the C# code you have and create an EXE that detects the device and signals it by creating or deleting a sepcifc file you could then detect in VFP.

Or you integrate this via the dotnet bridge from West Wind:
Bye, Olaf.

Olaf Doschke Software Engineering
 
Some years ago I experimented with FSO, Windows Management Instrumentation a.s.o. to test different ways to get more info about connected drives.
The following code was the simplest solution (using FSO). You will see that a Smartphone in mass storage mode isn't named. It is shown as a removable drive as well as SD-Cards and USB harddrives. However, the drives serialnumber is visible.

Code:
* // declare vars	
LOCAL laDrivetype(6), lcFont, oFSO
laDrivetype(1) = [unknown]
laDrivetype(2) = [removable drive]
laDrivetype(3) = [local harddrive]
laDrivetype(4) = [network drive]
laDrivetype(5) = [CD/DVD-ROM drive]
laDrivetype(6) = [RAM disk]
lcFont = _screen.FontName
_screen.FontName = [Courier New]

oFSO = CREATEOBJECT([Scripting.FileSystemObject])

CLEAR

* // display column names (headline)
? PADR( [VO] , 3 , [ ] )
?? PADR( [Type] , 21 , [ ] )
?? PADR( [Filesystem] , 11 , [ ] )
?? PADL( [SerialNo] , 13 , [ ] )
?? [ ]
?? PADR( [Volumename] , 33 , [ ] )
?? PADR( [Total Size] , 20 , [ ] )
?? PADR( [Free      ] , 20 , [ ] )
?? PADR( [Available ] , 20 , [ ] )

FOR EACH oDrive IN oFSO.Drives
	WITH oDrive
		? PADR( .DriveLetter + [:] , 3 , [ ] )
		?? PADR( laDriveType( .DriveType + 1 ) , 21 , [ ] )
		IF .Isready
			?? PADR( .FileSystem , 11 , [ ] )
			?? PADL( CheckSerialNo( .SerialNumber ) , 13 , [ ] )
			?? [ ]
			?? PADR( IIF( .DriveType = 3 , .ShareName, .VolumeName ) , 32 , [ ] )
			?? TRANSFORM( .TotalSize / 1000 / 1000 , [999,999] ) + [ MB (]
			?? PADL( .TotalSize / 1024 / 1024 / 1024 , 4 , [ ] ) + [ GB)]
			?? TRANSFORM( .FreeSpace / 1000 / 1000 , [999,999] ) + [ MB (]
			?? PADL( .FreeSpace / 1024 / 1024 / 1024 , 4 , [ ] ) + [ GB)]
			?? TRANSFORM( .AvailableSpace / 1000 / 1000 , [999,999] ) + [ MB (]
			?? PADL( .AvailableSpace / 1024 / 1024 / 1024 , 4 , [ ] ) + [ GB)]
		ELSE
			?? [not accessible]
		ENDIF
	ENDWITH
ENDFOR

_screen.FontName = lcFont
RELEASE laDrivetype, lcFont, oFSO

FUNCTION CheckSerialNo as Integer
LPARAMETERS vInt as Integer 
	RETURN IIF( vInt > 0 , vInt , INT( 2 ^ 32 + vInt ) )
ENDFUNC

OTOH, it might be enough to let the user select the drive as soon as it is available. As soon as this has happened you should have a drive number (i.e. 'H:')
Now you can read the drives serialnumber and store it. Based on the following little code snippet, you could write some code to recognize the drive as soon as it is connected.

Code:
LOCAL lcComputerName, loWMIService, loItems, loItem, lcVolumeSerial
lcComputerName = "."
loWMIService = GETOBJECT("winmgmts:\\" + lcComputerName + "\root\cimv2")
loItems = loWMIService.ExecQuery("Select * from Win32_LogicalDisk")
FOR EACH loItem IN loItems
    lcVolumeSerial = loItem.VolumeSerialNumber
    IF !ISNULL(lcVolumeSerial)
        ? "Name: " + loItem.NAME
        ? "Volume Serial Number: " + loItem.VolumeSerialNumber
        ?
    ENDIF
ENDFOR

-Tom
 
A1sifat,

You can port the script in to check for a USB device connection.

A non-optimized (but functional) version:

Code:
CLEAR

LOCAL CheckIfConnected AS String
LOCAL IsConnected AS Logical

#DEFINE JUST_CHECK_IF_CONNECTED	.T.
* otherwise, list all connected devices

m.CheckIfConnected = "[highlight #FCE94F]identify-your-device-here[/highlight]"
m.IsConnected = .F.

LOCAL WMIService, AllUSBControllerDevices, USBControllerDevice
LOCAL USBDevices, USBDevice
LOCAL WMIQuery AS String

LOCAL DeviceName AS String

m.WMIService = GETOBJECT("winmgmts:\\.\root\cimv2")

m.WMIQuery = "SELECT * FROM Win32_USBControllerDevice"
m.AllUSBControllerDevices = m.WMIService.ExecQuery(m.WMIQuery, , 32)

FOR EACH m.USBControllerDevice IN m.AllUSBControllerDevices
	
	m.DeviceName = STREXTRACT(STRTRAN(m.USBControllerDevice.Dependent, '"', ""), "=", "")

	m.WMIQuery = TEXTMERGE("SELECT * FROM Win32_PnPEntity WHERE DeviceID = '<<m.DeviceName>>'")
	m.USBDevices = m.WMIService.ExecQuery(m.WMIQuery, , 32)

	FOR EACH m.USBDevice IN m.USBDevices
#IF JUST_CHECK_IF_CONNECTED
		IF m.USBDevice.Name == m.CheckIfConnected
			m.IsConnected = .T.
			EXIT
		ENDIF
#ELSE
		? m.USBDevice.Description, m.USBDevice.Name
#ENDIF
	ENDFOR

#IF JUST_CHECK_IF_CONNECTED
	IF m.IsConnected
		EXIT
	ENDIF
#ENDIF

ENDFOR

#IF JUST_CHECK_IF_CONNECTED
? TEXTMERGE("<<m.CheckIfConnected>> is <<IIF(m.IsConnected, '', 'not ')>>connected.")
#ENDIF
 
I have a piece of code I use for detecting whether a USB is connected in a drive entered by the user. It also creates the relevant directory on that drive/device (USB) if it doesn't already exist.

I'm not sure if this is what you mean but here you go:

Code:
STORE " " TO mdrive

*  Show a form with a field to accept the drive letter

DO FORM COPYDBF WITH mdrive

IF mdrive=" "
   RETURN
ENDIF

IF mdrive="C"	&&	Refuse the option to back up to the C Drive
   =MESSAGEBOX("Exporting to the C Drive is not allowed"+ ;
     SPACE(10),0+64+0,"System Message")
   RETURN
ENDIF
	
STORE " " TO musb
STORE mdrive+":\" TO musb

CLOSE DATABASES
	
IF .NOT. DIRECTORY(musb)
   =MESSAGEBOX("Either you have selected an invalid drive letter or there is no "+ ;
     "USB memory device present in drive: "+ ;
     UPPER(musb)+space(10),0+16+0,"System Message")
   RETURN
ELSE
   WAIT "Copying data files, please wait...." WINDOW NOWAIT
		
*  Run your code here. Mine deals with backing up tables to the drive selected

   IF .NOT. DIRECTORY(musb+"MYBACKUP")
      MKDIR musb+"MYBACKUP"
   ENDI
   COPY FILE SYS(2003)+"\"+"mytable.dbf" TO musb+"\mytable\mytable.dbf"

*  More copy commands etc....

   WAIT CLEAR
   =MESSAGEBOX("Files have been copied to your selected device/drive: [ "+musb+"MYBACKUP ] "+ ;
     space(10),0+64+0,"System Message")
ENDIF

Thank you

Steve Williams
VFP9, SP2, Windows 10
 
Steve,

Thanks for posting your code. However, there is a problem with it (which is not your fault).

The problem is in the line containing your second message box. This line is 168 characters wide. Becasue of a bug in the forum software, wide lines of code cause a problem with some monitors. The effect is to push the entire thread off the right-hand end of the screen, making it very difficult to read.

It would be very helpful if you could edit your code so as to break the line in question into several shorter lines.

I stress this is not your fault. The forum management are aware of the issue and are working to resolve it.

Thanks.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Yes, to show the bug just shrink down the width of your browser. In mine the post width only goes down as much, so the line in question is partly shrinking:
scrollbug1_xdrm67.png

The scroll bar on the code section already appears, but the code section doesn't shrink down further.

After applying a known solution the thread width can shrink much more, so the experience even is OK on mobile devices:
scrollbug2_gpfvfh.png


Bye, Olaf.

Olaf Doschke Software Engineering
 
Just changed the line Mike. How is that now?

I also take your point Olaf but it is something beyond all of our control

Thank you

Steve Williams
VFP9, SP2, Windows 10
 
I don't know what you mean. I just told how to see the problem and reported that there is a solution, but it still takes time to incorporate it into the system.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Thanks, Steve. That's much better.

If you didn't see the problem yourself, that's probably because you have a particularly large monitor. It's only on screens below a certain width where the issue arises. As I said earlier, the forum management are very much aware of the issue, and I hope will be able to resolve it.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top