system.device.location without connection - location

Is it possible to use system.device.location on a windows tablet without any type of connection (wifi, 4G, etc.)? My GeoCoordinateWatcher position location always returns IsUnknown. However, it works when I use wifi.

I believe it does. It can use a variety of methods to get your location such as GPS, Wi-Fi triangulation, and cell phone tower triangulation (see here). Here is a simple example. For some reason when you call it the first time it always returns Unknown, so I immediately call it a second time and it shows coordinates. I hope it works for you as well.
FYI - I'd leave your Wi-Fi active on the tablet, but unplug your router or internet connection instead.
Example:
Public Sub GetLocationProperty()
Dim watcher As New System.Device.Location.GeoCoordinateWatcher()
watcher.TryStart(False, TimeSpan.FromMilliseconds(1000))
Dim coord As GeoCoordinate = watcher.Position.Location
If coord.IsUnknown <> True Then
msgbox(coord.Latitude & " x " & coord.Longitude)
Else
'msgbox("Unknown latitude and longitude.")
'Try a 2nd time
GetLocationProperty()
End If
End Sub `

Related

Find MAC address using VB6

I want to find the MAC address of network adopter, I have a working code too but my problem is it only works if IP addres is enabled otherwise it won't get the address is there any solution to find MAC address even if IP Enabled is false
if its possible update me with sample code
Here is my code to find MAC
Dim myWMI As Object, myObj As Object, Itm
Set myWMI = GetObject("winmgmts:\\.\root\cimv2")
Set myObj = myWMI.ExecQuery("SELECT * FROM " & _
"Win32_NetworkAdapterConfiguration " & _
"WHERE IPEnabled = True")
For Each Itm In myObj
Dim macme As String
Dim NewMac As String
macme = Itm.MACAddress
NewMac = Replace(macme, ":", "")
Text1.Text = NewMac
Exit For
Next
Querying the heavyweight WMI service is not the best choice for application programs. It is a convenience feature meant only for admin scripting. The service could be disabled or even uninstalled on older versions of Windows.
Instead you can go directly to the source. The GetAdaptersInfo function is one of the more obvious candidates.
Using this involves more code than can be conveniently inlined here. Look for the many examples of use in VB6 posted with working source code at more programmer-friendly sites that permit uploaded attachments.
No matter how you go about it the value of doing this is questionable anyway. Many integrated network adapters allow users to insert their own MAC Address values anyway. Quite a few PCs today rely on USB network adapters that are not even plugged in all the time and may get swapped around between devices.

Vb 6.0 Move mouse cursor to prevent sleep

i need to run a vb program which will copy all the data from different production database to our reporting database. it will run atleast for 5 hours . so in order to prevent the machine to go to sleep how can i move mouse cursor by 1 pixed at specified interval of time . as per my client company laws i cant do this in the computer power settings. so im trying to do within my program itself.
i tried with sendkeys ie by sending down arrow at specified interval of time but it is causing problem for me
thanks in advance
try this
Enum Execution_State
ES_SYSTEM_REQUIRED = &H1
ES_DISPLAY_REQUIRED = &H2
ES_USER_PRESENT = &H4
ES_CONTINUOUS = &H80000000
End Enum
Declare Sub SetThreadExecutionState Lib "kernel32" (ByRef esFlags As EXECUTION_STATE)
Public Sub DoNotSleep()
SetThreadExecutionState(esFlags:=Execution_State.ES_SYSTEM_REQUIRED Or Execution_State.ES_DISPLAY_REQUIRED Or Execution_State.ES_CONTINUOUS)
End Sub
picked from http://forums.codeguru.com/showthread.php?492366-How-to-run-a-very-long-SQL-statement
Why not just use the PowerQuerySuspend Event of the standard VB6 SysInfo control?
This allows your program to cancel autosleep or even user-initiated sleep requests (unlike the older SetThreadExecutionState API call).

Bluetooth RSSI/Inquiry scan on Mac - proximity detection to iPhone without connecting?

I have to dash away from the computer frequently, and I want to trigger some commands to run when my iPhone is close enough/far enough from my iMac (next to it vs. 2-3 metres away/other side of a wall). A couple of minutes latency is fine.
Partial solution: proximity
I've downloaded reduxcomputing-proximity and it works, but this only triggers when the device goes in to/out of range of bluetooth, but my desired range is much smaller.
(Proximity polls [IOBluetoothDevice -remoteNameRequest] to see if the device is in bluetooth range or not.)
Enhancement: rawRSSI
I've used [IOBluetoothDevice -rawRSSI] to get the RSSI when I am connected to the iPhone (when disconnected this just returns +127), but in order to save the battery life of my iPhone I'd rather avoid establishing a full bluetooth connection.
Am I correct in thinking that maintaining a connection will consume more battery life than just polling every couple of minutes?
I've overridden the isInRange method of proximity here to give me a working solution that's probably relatively battery intensive compared to the previous remoteNameRequest: method:
- (BOOL)isInRange {
BluetoothHCIRSSIValue RSSI = 127; /* Valid Range: -127 to +20 */
if (device) {
if (![device isConnected]) {
[device openConnection];
}
if ([device isConnected]) {
RSSI = [device rawRSSI];
[device closeConnection];
}
}
return (RSSI >= -60 && RSSI <= 20);
}
(Proximity uses synchronous calls - if and when I fit it to my needs I will edit it to be asynchronous but for now that's not important.)
Under Linux: l2ping - inquiry scan?
This SO post references getting an RSSI during an 'inquiry scan' which sounds like what I want, but it talks about using the Linux Bluez library, whilst I am on a Mac - I'd rather do it without having to stray too far if possible! (I have considered using a VM with USB pass-thru to hook up a second bluetooth device... But a simpler solution would be preferable!)
I see there is a IOBluetoothDeviceInquiry class, but I am not sure if this is useful to me. I don't intend to learn bluetooth protocol just for this simple problem!
The commands
For interest, and not particularly relevant to the solution, here are the Apple Scripts I currently trigger when
in range:
tell application "Skype"
send command "SET USERSTATUS ONLINE" script name "X"
do shell script "afplay '/System/Library/Sounds/Blow.aiff'"
end tell
out of range:
tell application "Skype"
send command "SET USERSTATUS AWAY" script name "X"
do shell script "afplay '/System/Library/Sounds/Basso.aiff'"
end tell
Though these are likely to get longer!
You are correct that making a connection will cost more energy. However, I'm not aware of APIs on mac OS that will give you access to the RSSI from inquiry scan packets. You could get access to the raw packets from your BT adapter using Mac OS PacketLogger. See this post Bluetooth sniffer - preferably mac osx
You could programmaticly put your device in discovery every couple of minutes, capture the inquiry scan packets with the packetlogger, and parse out the RSSI. You can use WireShark to help you understand how to decode the packets and find RSSI.
Your simplest option is probably to just periodically create a connection, measure RSSI, and then tear down the connection.
In terms of tradeoffs for your use case doing a continuous or periodic inquiry will consume same or even a bit more energy as doing a periodic connect / read RSSI and disconnect. Depending on the use case it sometimes may be more efficient to maintain the connection in a low power mode (sniff with 2.56 sec interval) and remain connected if the device is in range. And use RSSI to monitor proximity (although it is not accurate as interference due to objects change rssi drastically even though the device might be in proximity)

USB_MASS_STORAGE driver crashes after vb script modify USBSTOR key

I have this script written by myself.
Basically what I wanted was script that "unlock" the front usb only for specific device.
The situation is such that we have a workstation with registry key USBSTOR\Start set to 4(disable) so the front usb is not available without some additional work of our IT department - this way we control who can access the usb
But the employees must use a camera to take pictures for specific needs and to send them through email clients.So we want to automate the "lock/unlock" phase.
The usb is unlocked when the device of interest is inserted,it stays "unlocked" while the device is in usb and after the device is plugged out,the script "lock" the usb again.
I have decided to use .vbs.The script works as I expected,but after the "lock" phase,the USB_MASS_STORAGE driver get crashed.I must uninstall it and restart the Windows for the driver to be reloaded again and to work properly.After I have run the script several times,the registry value in USBSTOR\Start does not affect the usb,i.e the usb is unlocked even if there is 4.If I change the value from 4 to 3 the driver crashes.
I am looking for some advices.
Here is the code for usbstor.vbs script. I have used a lot of comments,some of them explain a pretty obvious things,but I have decide so.
' Script for access to Front Usb (a.k.a USB MASS STORAGE)
' The usb is locked by default(the value in Registry Key USBSTOR/Start is 4 - disable).It is enabled(the value in Registry Key USBSTOR/Start is 3 - enable) when the device of interest is put into front usb.
' The usb is in "enable" state ,while the device is into it. After it is removed,the Registry Key USBSTOR/Start value is set to 4(disable).
' The device is recognized by hardware id ,which is known in advance by searching USBSTOR,when the device is inserted. This script is for pc,where what we want is access to front usb only for spcecific device(a camera in our case).
' For everything else the usb should be disabled.The script is loaded in RAM and if the while loop condition isn't change to false,we must kill the process within TaskManager
' The CPU time is high > 98 while the script runs.I came to this solution for my problem,but any ideas for improvements or for different logic are highly welcomed.
Option Explicit On
Dim Shell,Start,Hwid,Enum_0,Enum_1,Count,Flag_0,Flag_1,Check_0,Check_1 'Dimension of varables we are going to use in the script.
Set Shell = CreateObject("WScript.Shell") 'Create an object to work with Windows Registry.
'Start = Shell.RegRead("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\USBSTOR\Start") 'Save the value of the registry key into Start variable
Hwid = "USB\Vid_0930&Pid_6545\001D92A866B8B8B1934703FE" 'hardawre id of device of interest.We get it from the registry and the script scan for this id.It is constant string
Count = 1 'Initialize the Count variable with value of 1.We use it as a condition in endless while() loop.It makes script run in real-time,so it can scan uninterupted for changes in the registry
QueryEnum0 ' The subroutines QueryEnum0 and QueryEnum1.The id is either in USBSTOR\Enum\0 or in USBSTOR\Enum\1 .That is for sure.
QueryEnum1 ' Declaration before definition - not exactly explanation.
'The purpose of these two subroutines is: create an object everytime the sub is called ,thus read the value in Enum\0 or in Enum\1 constantly as "scanning"
'Probably not so elegant solution to somebody,but actually it works.
Sub QueryEnum0 ' Enter the sub
Dim Flag_Enum_0,Shell ' Declare local variables.They will be created each time the sub is invoked.
Set Shell = CreateObject("WScript.Shell") 'Create an object to work wirh registry any time the sub is called
On Error Resume Next 'Error handling
Flag_Enum_0 = Shell.RegRead("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\USBSTOR\Enum\0") 'Try to read reg value into Flag_Enum_0. The purpose
On Error GoTo 0
Flag_0 = Flag_Enum_0 'Assign the value to variable Flag_0,outside of sub.The memory for Flag_0 is set once and lasts while the script runs.
End Sub
' Same as QueryEnum0
Sub QueryEnum1
Dim Flag_Enum_1,Shell
Set Shell = CreateObject("WScript.Shell")
On Error Resume Next
Flag_Enum_1 = Shell.RegRead("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\USBSTOR\Enum\1")
On Error GoTo 0
Flag_1 = Flag_Enum_1
End Sub
Do While Count = 1 'Real-time loop,the code within while is running while count is equal to 1. The script is loaded in memory constanlty.
On Error Resume Next
Enum_0 = Shell.RegRead("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\USBSTOR\Enum\0") ' Try to read hardware id if it is in Enum\0
On Error GoTo 0 '
On Error Resume Next
Enum_1 = Shell.RegRead("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\USBSTOR\Enum\1") 'Try to read hardware id if it is in Enum\1
On Error GoTo 0
If StrComp(Hwid,Enum_0) <> 0 And StrComp(Hwid,Enum_1) <> 0 Then 'Check if both reg keys are empty
MsgBox "There is no device in the front usb.Please put the device or see the connection"
ElseIf StrComp(Hwid,Enum_0) = 0 Then 'If the hardware id is in Enum\0,thus assigned to Enum_0
Shell.RegWrite "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\USBSTOR\Start",3 'Enable the usb by "unlock" it
On Error Resume Next
QueryEnum0 'Invoke sub QueryEnum0.If the id we looking for is in Enum\0,we know that it is assigned to Flag_0 also
Check_0 = Flag_0 'Use another variable to copy value from Flag_0.
On Error GoTo 0
If StrComp(Hwid,Check_0) = 0 Then 'Compare the constant Hwid with the value in Check_0,test for id
Msgbox "Check_0 still holds the hardware id" 'Some messages to inform us whats happening
else
MsgBox "Check_0 does not contain the hardware id anymore"
Shell.RegWrite "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\USBSTOR\Start",4 'Disable the front usb
Count = 2 'End the while loop,count is 2,so the condition is false .The loop breaks.
End If
ElseIf StrComp(Hwid,Enum_1) = 0 Then 'If the hardware is in Enum\1....same as above mentioned
Shell.RegWrite "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\USBSTOR\Start",3
On Error Resume Next
QueryEnum1
Check_1 = Flag_1
On Error GoTo 0
If StrComp(Hwid,Check_1) = 0 Then
MsgBox "Check_1 still holds the hardware id"
MsgBox Check_1
else
MsgBox "Check_0 does not contain the hardware id anymore"
Shell.RegWrite "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\USBSTOR\Start",4
Count = 2
End If
End If
Loop
' Useful information for me
'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\USBSTOR -> value name -> Start ,value data = 3(enable) = 4(disable)
'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\USBSTOR\Enum -> value name -> 1 or 0 ,value data we look for is -> USB\Vid_04da&Pid_2372\5&2f621ee5&0&8
' USB\Vid_04da&Pid_2372\5&2f621ee5&0&8 - camera id in our case
' fantom value - USB\Vid_03f0&Pid_032a\000000000Q912WFBSI1c - name: 0 ,type: REG_SZ,in the key Enum.This is another hardware id,which is strange somehow,because I do not have any device
' inserted in my usb.However,I take this value into account,thus use both keys 0 and 1 within Enum to scan for the id I need.
According to the Microsoft documentation the data in the CurrentControlSet Registry tree is used during start up and driver initialization.
Also with Windows 7 and later any changes to HKEY_LOCAL_MACHINE must be made by a utility running as an Administrator. Otherwise the changes will be made to a user clone of HKEY_LOCAL_MACHINE and changes will affect only the user under whose account the utility was run.
See HKLM\SYSTEM\CurrentControlSet\Services Registry Tree which states
"A driver can store global driver-defined data under its key in the
Services tree. Information that is stored under this key is available
to the driver during its initialization."
Everything that I have found thus far concerning additional security for USB storage devices by setting this value indicates that it is done once as a preventive measure. So it would appear that the approach you outlined is not a feasible solution.
There may also be an initial state issue in that the until a USB mass storage device is plugged in, the device driver is not fully initialized hence this data may not have yet been accessed. Readings also seem to imply that it will depend on whether the device has been previously plugged in successfully, creating the necessary Registry data and driver initialization or not.
I think it is pretty safe to say that changing the Registry value on the fly in this way was not design intent for Windows USB drivers.
See also this page of Microsoft Knowledge Base article 103000, CurrentControlSet\Services Subkey Entries for details about the data in this Registry entry. This article says the following about the Start keyword values.
0x3 (Load on demand) Available, regardless of type, but will not be started until the user starts it (for example, by using the Devices icon in Control Panel).
0x4 (disabled) NOT TO BE STARTED UNDER ANY CONDITIONS.
See also the following stackoverflow posts.
C# Disable/Enable USB ports
Enable and Disable USB port
Win32 API function to programmatically enable/disable device

Need a fast programming language that can drive two printers [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 9 months ago.
Improve this question
I have a rather unusual application that isn't working the way I need, and I hope someone here will have some suggestions or at least a direction to investigate.
We have a museum exhibit that has a computer at the entrance driving two small receipt printers. There are two buttons on a console, wired to the left and right buttons of a disemboweled mouse. The two printers and associated buttons are for girls and boys, each button does a random selection from a database of names and prints a small ticket on the appropriate printer with a graphic image, a few words about the exhibit and the randomly chosen name.
Conceptually all is well, but it hangs quite often. I got the project at the last minute, because the original designer got bogged down and couldn't deliver, so the exhibit's author asked me the day before opening, whether I could write something that would work.
I did it in Word, since I am an experienced VBA programmer. Several other avenues I attempted first all lead to dead ends - one couldn't do graphics, another couldn't handle two printers, yet another couldn't change fonts and so on. The problem is that it simply isn't fast enough - Word can only drive one printer at a time and changing the active printer takes a long time. Not by office standards, where a second or two of delay before a printer starts working on your document is not an issue, but here I need more or less instant response. If kids press a button and nothing happens, they press it over and over until something does happen, resulting in maybe half a dozen commands being sent before the printer starts reacting. Sometimes it jams the program completely, since boys and girls will be pressing the two buttons simultaneously and Word locks up, and even when it doesn't jam, the printers then spit out a stream of tickets, making a mess. The kids start squabbling over which ticket is whose, pulling them out of the printers, snarling the paper tape, jamming the printer and generally making a mess of the whole affair, often necessitating the exhibit caretakers having to restart the computer and clear torn bits of paper out the printers.
What I need is some sort of fast programming language that can drive two printers *-simultaneously-*, not the MSOffice claptrap of having to switch the active printer, that can react to both left and right mouse button click events, can print a small graphic image and can print in different font sizes and styles and. I don't need many, but it's not all in one typeface.
Can anyone suggest what I might use for this? I don't even know if it's possible at all under Windows, whether the "single active printer" garbage is an Office artifact, or a Windows restriction. My little Commodore-64 twenty-five years ago had two printers attached to it and drove both simultaneously with no difficulties - it doesn't seem to me it should be such an impossible requirement today.
Being a Python programmer myself, I would use something like MSWinPrint.py, and render the documents directly using Python. It looks like it supports text and images, and you can easily select any printer in the system by name.
You would need to:
Install Python.
Install Python for Windows Extensions.
Install PIL.
Install MSWinPrint.
Then, you would need to write a program to do the printing. Something like the following.
#python
import sys
import Image, ImageWin
import MSWinPrint
# workaround for PIL namespace change
MSWinPrint.ImageWin = ImageWin
def print_name(name, printer_name):
doc = MSWinPrint.document(printer_name)
doc.begin_document('nametag for %s' % name)
# print the name at position 20,20
text_pos = 20, 20
doc.text(text_pos, name)
# add an image for this person
img_pos = 40, 40
img_size = 100, 100
doc.image(img_pos, get_image(), img_size)
doc.end_document()
def get_image():
image_filename = 'my image.jpg'
return Image.open(image_filename)
if __name__ == '__main__':
name, printer_name = sys.argv[1:]
print_name(name, printer_name)
If you save this as print_tag.py, then you can execute it with two command line arguments, the name to be printed and the image filename.
print_tag.py Sally "EPSON Artisan 810"
I ran this code and it worked great. I didn't know creating a custom print job could be so easy.
You can of course run the program as often as you like on as many printers as you would like. There's certainly more you can do to customize when an how the print job is run. You could customize the code to always run and interpret the mouse clicks (for that you might need wxPython), or you might have another program that just executes the script.
As other have said, the programming language isn't going to make much difference. However (and this is a BIG however), the print libraries built into most scripting languages, such as VBA and .NET, either only support printing to the system default printer (most common, and cannot be worked around by having two instances open simultaneously, as the system default printer is a global setting) or require you to configure a global variable to specify the active printer (this only affects one process, so could be worked around using two instances).
Instead, you will have to invoke the windows API directly. It most certainly allows printing directly to any printer on the system. Here is an example of how to use the default printer. Note that only one line of code (calling the GetDefaultPrinter function) ties this to the default printer. Supplying a different printer name to CreateDC gets you a different printer.
If you instead call the EnumPrinters function, you can find out ANY or ALL of the printer names, not just the default. Or have the administrator preconfigure the printer names to use in a registry setting or text file.
In any case, you can have device contexts for all printers open simultaneously. Of course, once you have the printer device context, you have to create a print job, send your content, and end the print job. There's a great deal of information available on MSDN.
All the examples are in C, which makes C++ the obvious language for printing to non-default printers, but as long as you know how to call WinAPI functions from your language, you can use it instead. In VBA, that'd require Declare Function XYZ Lib "gdi32" (params here)
This is not a problem with the programming language, its just a limitation of the printer stack you are using.
I am not sure if .NET would support it (or Windows for that matter) would support sending printing on a thread. You could put each printer in its own thread and block the UI from accepting more print requests.
You could also try to turn on print spooling for both printers. That will render it locally and return then print.
I wrote something a few years ago (in VB6 so could probably be ported to VBA easily) that bypassed the printer driver (a printer must be set up but the actual driver used was irrelevant) and sent raw commands to the printer. Depending on what sort of printer you are using this may or may not be an issue (some use complex escape sequences). If you want to print graphics, this could add another layer of complication - although it can be done if you know what commands the printer supports. I managed to get bitmaps printing on a dot matrix printer, but it wasn't a 5 minute task. If this is something you are interested in I can try and dig out the code?
The Code is as follows:
Public Type DOCINFO
pDocName As String
pOutputFile As String
pDatatype As String
End Type
Declare Function ClosePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long
Declare Function EndDocPrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long
Declare Function EndPagePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long
Declare Function OpenPrinter Lib "winspool.drv" Alias "OpenPrinterA" (ByVal pPrinterName As String, phPrinter As Long, ByVal pDefault As Long) As Long
Declare Function StartDocPrinter Lib "winspool.drv" Alias "StartDocPrinterA" (ByVal hPrinter As Long, ByVal Level As Long, pDocInfo As DOCINFO) As Long
Declare Function StartPagePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long
Declare Function WritePrinter Lib "winspool.drv" (ByVal hPrinter As Long, pBuf As Any, ByVal cdBuf As Long, pcWritten As Long) As Long
Public Function PrintRawData(ByVal sPrinter As String, ByVal sDocName As String, ByVal sData As String) As Boolean
On Error GoTo PrintErr:
Dim lhPrinter As Long, lReturn As Long, lpcWritten As Long
Dim lDoc As Long, sWrittenData As String
Dim MyDocInfo As DOCINFO
Dim pOutput As Printer
Dim p As Printer
For Each p In Printers
If p.DeviceName = sPrinter Then
Set pOutput = p
GoTo StartPrinting
End If
Next p
MsgBox "Unable to find the specified printer [" & sPrinter & _
"] in the list of currently installed printers" & vbCrLf & _
"Printing will be aborted", vbCritical
Exit Function
StartPrinting:
lReturn = OpenPrinter(pOutput.DeviceName, lhPrinter, 0)
If lReturn = 0 Then
MsgBox "Print was unsuccessful. Make sure there is a printer installed on the port you are trying to print to"
Exit Function
End If
MyDocInfo.pDocName = sDocName
MyDocInfo.pOutputFile = vbNullString
MyDocInfo.pDatatype = vbNullString
lDoc = StartDocPrinter(lhPrinter, 1, MyDocInfo)
Call StartPagePrinter(lhPrinter)
sWrittenData = sData
lReturn = WritePrinter(lhPrinter, ByVal sWrittenData, Len(sWrittenData), lpcWritten)
lReturn = EndPagePrinter(lhPrinter) 'need this??
lReturn = EndDocPrinter(lhPrinter)
lReturn = ClosePrinter(lhPrinter)
Exit Function
PrintErr:
MsgBox "Print was unsuccessful. Make sure there is a printer installed on the port you are trying to print to"
Exit Function
End Function
To use it you need to install a printer that uses the correct port using any driver (I generally use the Generic / text Only Driver) and then call it as follows replacing the Hello with the data you want to send to the printer including control characters etc:
PrintRawData "Generic / Text Only", "My Document", "Hello"
Updated and completely overhauled Answer :
Pete, have you considered an entirely different kind of printer? The setting, changing and sending PostSCript commands can take, indeed, a lot of time.
A strange solution you might call it, but our instant B/W laser Brother label printer prints out instantly on a press of the button. Their specialty rock solid in house developed P-Touch Editor 5.4 Software is created in such a way as to output to multiple printers simeltaneously(!!), each printing the same or different lables (for example different serial numbers or dates from a database).
Its snappy: when letting go of a return button, just when my finger has reached half a centimeter in the button already IIIIEEEUUUUUU (1 second after release of return key) the entire lable is out. Albeit in black and white.
Aside lables there are also paper lables without sticky backs 102mm wide rols by either original or third party brands makes.
Cost: 100$ ~ 400$ per unit incl software to design and customise connections with database.
I know that those instant printers use much less windows-based drivers and more embedded technologies, relieving the system from standardized print jobs.
Perhaps this solves your problem or brings you on a new idea.

Resources