winsock connect function is working only on high speed connection - vba

I'm using winsock in my VB6 application, this is my code:
Private Sub Form_Load()
With Winsock1
.Close
.RemoteHost = Hostip
.RemotePort = port number
.Connect
End With
End Sub
My problem is when I'm using a high speed connection (4G) the connection works fine but using other connections like (3G,wise...) it returns the following message:
the attempt to connect timed out
How do I remedy this?

It sounds like you need to set a longer connection timeout. There is no way to do this directly with the control. Below is a modified sample from a retired KB article. The orignal code does not include the SO_SNDTIMEO, or SO_RCVTIMEO options.
Option Explicit
' Error returned by Winsock API.
Const SOCKET_ERROR = -1
' Level number for (get/set)sockopt() to apply to socket itself.
Const SOL_SOCKET = 65535 ' Options for socket level.
Const IPPROTO_TCP = 6 ' Protocol constant for TCP.
' option flags per socket
Const SO_DEBUG = &H1& ' Turn on debugging info recording
Const SO_ACCEPTCONN = &H2& ' Socket has had listen() - READ-ONLY.
Const SO_REUSEADDR = &H4& ' Allow local address reuse.
Const SO_KEEPALIVE = &H8& ' Keep connections alive.
Const SO_DONTROUTE = &H10& ' Just use interface addresses.
Const SO_BROADCAST = &H20& ' Permit sending of broadcast msgs.
Const SO_USELOOPBACK = &H40& ' Bypass hardware when possible.
Const SO_LINGER = &H80& ' Linger on close if data present.
Const SO_OOBINLINE = &H100& ' Leave received OOB data in line.
Const SO_DONTLINGER = Not SO_LINGER
Const SO_EXCLUSIVEADDRUSE = Not SO_REUSEADDR ' Disallow local address reuse.
' Additional options.
Const SO_SNDBUF = &H1001& ' Send buffer size.
Const SO_RCVBUF = &H1002& ' Receive buffer size.
Const SO_ERROR = &H1007& ' Get error status and clear.
Const SO_TYPE = &H1008& ' Get socket type - READ-ONLY.
' TCP Options
Const TCP_NODELAY = &H1& ' Turn off Nagel Algorithm.
' linger structure
Private Type LINGER_STRUCT
l_onoff As Integer ' Is linger on or off?
l_linger As Integer ' Linger timeout in seconds.
End Type
'timeout structure
Private Type TIMEOUT_STRUCT
tv_sec As Long 'seconds
tv_usec As Long 'milliseconds
End Type
'Timeout options
Const SO_SNDTIMEO = &H1005& 'send timeout
Const SO_RCVTIMEO = &H1006& 'receive timeout
' Winsock API declares
Private Declare Function setsockopt Lib "wsock32.dll" (ByVal s As Long, ByVal level As Long, ByVal optname As Long, optval As Any, ByVal optlen As Long) As Long
Private Declare Function getsockopt Lib "wsock32.dll" (ByVal s As Long, ByVal level As Long, ByVal optname As Long, optval As Any, optlen As Long) As Long
Private Sub Command1_Click()
' Read all the options and present in a message box.
Dim socket As Long
socket = Winsock1.SocketHandle
If socket = 0 Then
MsgBox "No Socket"
Else
MsgBox "Socket Options:" & vbCrLf & _
" SO_DEBUG: " & CStr(GetSocketOption(socket, SOL_SOCKET, SO_DEBUG)) & vbCrLf & _
" SO_ACCEPTCONN: " & CStr(GetSocketOption(socket, SOL_SOCKET, SO_ACCEPTCONN)) & vbCrLf & _
" SO_REUSEADDR: " & CStr(GetSocketOption(socket, SOL_SOCKET, SO_REUSEADDR)) & vbCrLf & _
" SO_KEEPALIVE: " & CStr(GetSocketOption(socket, SOL_SOCKET, SO_KEEPALIVE)) & vbCrLf & _
" SO_DONTROUTE: " & CStr(GetSocketOption(socket, SOL_SOCKET, SO_DONTROUTE)) & vbCrLf & _
" SO_BROADCAST: " & CStr(GetSocketOption(socket, SOL_SOCKET, SO_BROADCAST)) & vbCrLf & _
" SO_USELOOPBACK: " & CStr(GetSocketOption(socket, SOL_SOCKET, SO_USELOOPBACK)) & vbCrLf & _
" SO_LINGER: " & CStr(GetSocketOption(socket, SOL_SOCKET, SO_LINGER)) & vbCrLf & _
" SO_OOBINLINE: " & CStr(GetSocketOption(socket, SOL_SOCKET, SO_OOBINLINE)) & vbCrLf & _
" SO_DONTLINGER: " & CStr(GetSocketOption(socket, SOL_SOCKET, SO_DONTLINGER)) & vbCrLf & _
" SO_EXCLUSIVEADDRUSE: " & CStr(GetSocketOption(socket, SOL_SOCKET, SO_EXCLUSIVEADDRUSE)) & vbCrLf & _
" SO_SNDBUF: " & CStr(GetSocketOption(socket, SOL_SOCKET, SO_SNDBUF)) & vbCrLf & _
" SO_RCVBUF: " & CStr(GetSocketOption(socket, SOL_SOCKET, SO_RCVBUF)) & vbCrLf & _
" SO_ERROR: " & CStr(GetSocketOption(socket, SOL_SOCKET, SO_ERROR)) & vbCrLf & _
" SO_TYPE: " & CStr(GetSocketOption(socket, SOL_SOCKET, SO_TYPE)) & vbCrLf & vbCrLf & _
"TCP Options:" & vbCrLf & _
" TCP_NODELAY: " & CStr(GetSocketOption(socket, IPPROTO_TCP, TCP_NODELAY))
End If
End Sub
Private Sub Command2_Click()
Dim lResult As Long ' Results of 1st option.
Dim tout As TIMEOUT_STRUCT
If (Winsock1.Protocol = sckTCPProtocol) Then
tout.tv_sec = 10
tout.tv_usec = 0
lResult = setsockopt(Winsock1.SocketHandle, SOL_SOCKET, SO_SNDTIMEO, tout, LenB(tout))
If (lResult = SOCKET_ERROR) Then
MsgBox "Error setting SO_SNDTIMEO option: " & Translate_DLL_Error(Err.LastDllError)
Else
MsgBox "SO_SNDTIMEO option set."
End If
End If
End Sub
Public Function GetSocketOption(lSocket As Long, lLevel As Long, lOption As Long) As Long
Dim lResult As Long ' Result of API call.
Dim lBuffer As Long ' Buffer to get value into.
Dim lBufferLen As Long ' len of buffer.
Dim linger As LINGER_STRUCT
' Linger requires a structure so we will get that option differently.
If (lOption <> SO_LINGER) And (lOption <> SO_DONTLINGER) Then
lBufferLen = LenB(lBuffer)
lResult = getsockopt(lSocket, lLevel, lOption, lBuffer, lBufferLen)
Else
lBufferLen = LenB(linger)
lResult = getsockopt(lSocket, lLevel, lOption, linger, lBufferLen)
lBuffer = linger.l_onoff
End If
If (lResult = SOCKET_ERROR) Then
GetSocketOption = Err.LastDllError
Else
GetSocketOption = lBuffer
End If
End Function
Private Sub Form_Load()
Winsock1.Bind 8377 ' Set up socket enough to get nonzero socket. handle
End Sub
You can find the original article at https://support.microsoft.com/en-us/kb/237688

Related

Start Octave Script from VBA with a batch file and wait for Octave to finish before continuing with vba

i would like to call an Octave script from VBA with a batch file and passing some arguments to it.
The Octave script creates a .csv file which is needed in the VBA code later on.
The Problem is, that the VBA code doesn't wait for Octave creating the .csv file and i get an error message that the file is not there. So i need a way to wait until Octave has created the file.
Here is my VBA code:
Public Sub LinkOctave(ByVal Projekt As String, ByVal Winddaten As String, ByVal Ak As String, ByVal Typ As String, _
ByVal Anz As Double, ByVal NH As Double, ByVal Netto As Double, _
ByVal StartGW As Double, ByVal EndGW As Double, _
ByVal StartP As Double, ByVal EndP As Double)
Dim PID As Variant
Dim BatchFilePath As String
Dim ProjektBat As String
Dim WinddatenBat As String
Dim AkBat As String
Dim TypBat As String
Dim AnzBat As Double
Dim NHBat As String
Dim NettoBat As String
Dim StartGWBat As String
Dim EndGWBat As String
Dim StartPBat As String
Dim EndPBat As String
ProjektBat = "'" & Projekt & "'"
WinddatenBat = "'" & Winddaten & "'"
AkBat = "'" & Ak & "'"
TypBat = "'" & Typ & "'"
AnzBat = Anz
NHBat = str(NH)
NettoBat = str(Netto)
StartGWBat = str(StartGW)
EndGWBat = str(EndGW)
StartPBat = str(StartP)
EndPBat = str(EndP)
BatchFilePath = "C:\Users\bla\Documents\Octave\PFM\runfctPFM.bat"
PID = Shell(BatchFilePath & " " & ProjektBat & " " & WinddatenBat & " " & AkBat & " " & _
TypBat & " " & AnzBat & " " & NHBat & " " & NettoBat & " " & StartGWBat & " " & _
EndGWBat & " " & StartPBat & " " & EndPBat)
End Sub
I already found the way to do it with wsh.Run like this:
Dim wsh As Object
Set wsh = VBA.CreateObject("WScript.Shell")
Dim waitOnReturn As Boolean: waitOnReturn = True
Dim windowStyle As Integer: windowStyle = 1
Dim lngErrorCode As Long
lngErrorCode = wsh.Run(BatchFilePath & " " & ProjektBat & " " & WinddatenBat & " " & AkBat & " " & _
TypBat & " " & AnzBat & " " & NHBat & " " & NettoBat & " " & StartGWBat & " " & _
EndGWBat & " " & StartPBat & " " & EndPBat, windowStyle, waitOnReturn)
If lngErrorCode <> 0 Then
MsgBox "Something went wrong with the batch file!"
Exit Sub
End If
But it still doesn't wait for Octave to finish.
What did i wrong? Or is there another solution?
This is the code of the bat file, where i call the octave script:
#echo off
set OCT_HOME=C:\Octave\Octave-5.1.0.0\mingw64\
set "PATH=%OCT_HOME%\bin;%PATH%"
set SCRIPTS_DIR=%~dp0
set ProjektBat=%1
set WinddatenBat=%2
set AkBat=%3
set TypBat=%4
set AnzBat=%5
set NHBat=%6
set NettoBat=%7
set StartGWBat=%8
set EndGWBat=%9
shift /1
set StartPBat=%9
shift /1
set EndPBat=%9
start octave-cli.exe --eval "cd(getenv('SCRIPTS_DIR')); fctPFM(%ProjektBat%, %WinddatenBat%, %AkBat%, %TypBat%, %AnzBat%, %NHBat%, %NettoBat%, %StartGWBat%, %EndGWBat%, %StartPBat%, %EndPBat%); quit;"
Thanks for your support
Cheers
The bat file has a 'start' command in it which according to the Microsoft docs opens a separate command prompt for the command - so its not going to wait for the separate command window to finish.
https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/start
Note also in windows, you should probably not be calling the octave executables directly, rather use the .bat files that come with it, as they set up expected environment variables in order for octave to run correctly.

Continue for loop if a file is created in VB.NET

I'm using a COM interface to export animations from a third-party program. I'm sending an exporting COM command with script from my tool with a shell command.
There's a problem with when I send the animation export command to the third-party tool. It starts to export, but my tool is sending a second animation export command while the last one is not finished. How can I prevent from this situation?
I'd like to sending my shell command from the for loop after the file was created.
My code is like below.
Private Sub tlbCheckSolveEvaCtrl_exportmodeshape_Click(sender As Object, e As EventArgs) Handles tlbCheckSolveEvaCtrl_exportmodeshape.Click
Try
Dim strArgument As String
Dim strfilePathEV As String
Dim strfilePathANI As String
Dim strfilePathPIC As String
strfilePathEV = strProjMdlDir & My.Settings.txtCheckSolverOuputDir & strProjMdlName & ".ev.sbr"
strfilePathANI = strProjMdlDir & "\" & My.Settings.txtProjDirDOC & "\" & My.Settings.txtProjDirANI & "\"
strfilePathPIC = strProjMdlDir & "\" & My.Settings.txtProjDirDOC & "\" & My.Settings.txtProjDirPIC & "\"
For i As Integer = 0 To dgvCheckSolveEva.RowCount - 1
strArgument = strfilePathEV & " " & _
strfilePathANI & strProjMdlName & "_" & i & ".mpg" & " " & _
i
Shell(My.Settings.txtSpckDir & "simpack-post.exe -s qs_mode_shape.qs " & strArgument)
Next
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
I'd like to continue my for loop if strfilePathANI & strProjMdlName & "_" & i & ".mpg", the animation file was created, so I can start to export the next one.
The best way would be to use the .NET Process class and call the WaitForExit() method in order to wait for simpack-post.exe to close itself.
Shell() is an outdated function from the VB6-era which exists purely for partial backwards compatibility with that language. It shouldn't be used in new code.
Basic example:
Dim filePath As String = Path.Combine(My.Settings.txtSpckDir, "simpack-post.exe")
Process.Start(filePath, "-s qs_mode_shape.qs " & strArgument).WaitForExit()
The problem with this of course is that it might block the UI thread and thus cause it to freeze, depending on how long it takes for the process to exit. Therefore we should wrap it in a Task:
Dim c As Integer = dgvCheckSolveEva.RowCount - 1
Task.Run( _
Sub()
For i As Integer = 0 To c
strArgument = strfilePathEV & " " & _
strfilePathANI & strProjMdlName & "_" & i & ".mpg" & " " & _
i
Dim filePath As String = Path.Combine(My.Settings.txtSpckDir, "simpack-post.exe")
Process.Start(filePath, "-s qs_mode_shape.qs " & strArgument).WaitForExit()
Next
End Sub _
)
Just note that you cannot directly access the UI from within the task. If you want to do so you need to Invoke.
EDIT:
If you are targeting .NET Framework 3.5 or lower, or using VS 2008 or lower, tasks aren't available and we have to resort to using regular threads and/or regular methods instead of lamba expressions.
Note that the same rules apply, though - you cannot access the UI without invoking.
.NET 3.5 (or lower) using VS 2010 (and higher):
Dim c As Integer = dgvCheckSolveEva.RowCount - 1
Dim t As New Thread( _
Sub()
For i As Integer = 0 To c
strArgument = strfilePathEV & " " & _
strfilePathANI & strProjMdlName & "_" & i & ".mpg" & " " & _
i
Dim filePath As String = Path.Combine(My.Settings.txtSpckDir, "simpack-post.exe")
Process.Start(filePath, "-s qs_mode_shape.qs " & strArgument).WaitForExit()
Next
End Sub _
)
t.IsBackground = True
t.Start()
.NET 3.5 (or lower) using VS 2008 (or lower):
Private Sub tlbCheckSolveEvaCtrl_exportmodeshape_Click(sender As Object, e As EventArgs) Handles tlbCheckSolveEvaCtrl_exportmodeshape.Click
...your code...
Dim c As Integer = dgvCheckSolveEva.RowCount - 1
Dim t As New Thread(New ParameterizedThreadStart(AddressOf ExportAnimationsThread))
t.IsBackground = True
t.Start(c)
...your code...
End Sub
Private Sub ExportAnimationsThread(ByVal Count As Integer)
For i As Integer = 0 To Count
strArgument = strfilePathEV & " " & _
strfilePathANI & strProjMdlName & "_" & i & ".mpg" & " " & _
i
Dim filePath As String = Path.Combine(My.Settings.txtSpckDir, "simpack-post.exe")
Process.Start(filePath, "-s qs_mode_shape.qs " & strArgument).WaitForExit()
Next
End Sub

Get CPU Name, Architecture and Clock Speed in VB

How do I find my CPU Name, Architecture and Clock Speed as a string in Visual Basic? I want it to display like it does in System Properties: Intel(R) Core(TM) i5-3210M CPU # 2.50GHz
I need the answer in VB.net. I have found other answers in C#, C++, C and Java.
VBA cannot do that directly, but you can invoke the Windows Management Interface.
Please see the information from http://www.asap-utilities.com/excel-tips-detail.php?categorie=9&m=78 (copied below)
Sub ProcessorSpeed()
' shows the processor name and speed of the computer
Dim MyOBJ As Object
Dim cpu As Object
Set MyOBJ = GetObject("WinMgmts:").instancesof("Win32_Processor")
For Each cpu In MyOBJ
MsgBox(cpu.Name.ToString + " " + cpu.CurrentClockSpeed.ToString + " Mhz", vbInformation)
Next
End Sub
i use a similar routine for my use.
Option Explicit
Private Declare PtrSafe Sub GetSystemInfo Lib "kernel32" (lpSystemInfo As SYSTEM_INFO)
Type SYSTEM_INFO
dwOemID As Long
dwPageSize As Long
lpMinimumApplicationAddress As Long
lpMaximumApplicationAddress As Long
dwActiveProcessorMask As Long
dwNumberOfProcessors As Long
dwProcessorType As Long
dwAllocationGranularity As Long
dwReserved As Long
End Type
'Sub DisplaySystemInfo()
' Dim lpSysInfo As SYSTEM_INFO
' GetSystemInfo lpSysInfo
' Debug.Print "Number of processors: " & lpSysInfo.dwNumberOfProcessors
' Debug.Print "Processor type: " & lpSysInfo.dwProcessorType
'End Sub
Function GetCPUData() As String
Dim result As String
Dim objCPUItem As Object
Dim objCPU As Object
Err.Clear
On Error Resume Next
Set objCPUItem = GetObject("winmgmts:").InstancesOf("Win32_Processor")
If Err.Number <> 0 Then
result = "Error getting Win32_Processor " & _
"information." & vbCrLf
Else
result = "Number of processors incl. Co-CPUs: " & Trim$(str$(objCPUItem.Count)) & vbCrLf & vbCrLf
For Each objCPU In objCPUItem
result = result & "Processor: " & objCPU.DeviceID & vbCrLf
result = result & "Description: " & Trim$(objCPU.Name) & vbCrLf
result = result & "Frequency (MHz): " & objCPU.MaxClockSpeed & vbCrLf
result = result & "CPU-ID: " & objCPU.ProcessorId & vbCrLf
result = result & vbCrLf
Next
Set objCPUItem = Nothing
End If
On Error GoTo 0
GetCPUData = result
End Function
Function cpu3() As Long 'this sets the multi threading to max number of cpu used by excel
With Application
.MultiThreadedCalculation.Enabled = True
.MultiThreadedCalculation.ThreadMode = xlThreadModeAutomatic 'set to max cores
cpu3 = .MultiThreadedCalculation.ThreadCount
.MultiThreadedCalculation.ThreadMode = xlThreadModeManual
End With
End Function
Sub testinggg()
Dim strComputer$
Dim i&
Dim objWMIService As Object, colItems As Object, objItem As Object
strComputer = "." 'Local machine, can be adjusted to access remote workstations
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colItems = objWMIService.ExecQuery( _
"SELECT * FROM Win32_PerfFormattedData_PerfOS_Processor", , 48)
For Each objItem In colItems
i = i + 1 '1=cpu all
Debug.Print "-----------------------------------"
Debug.Print "Processor " & i
'Debug.Print "-----------------------------------"
Debug.Print "usage: " & objItem.PercentProcessorTime
Next
Set objWMIService = Nothing
Set colItems = Nothing
Set objItem = Nothing
End Sub
Works for me on Win 7 HB x64
MsgBox CreateObject("WScript.Shell").RegRead("HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\0\ProcessorNameString")

Send Raw Data to ZPL Printer using Visual Basic (MS Access 2000)

This is all that I can find, none of them work.
Option Compare Database
Option Explicit
Private Type DOCINFO
pDocName As String
pOutputFile As String
pDatatype As String
End Type
Private Declare Function ClosePrinter Lib "winspool.drv" (ByVal _
hPrinter As Long) As Long
Private Declare Function EndDocPrinter Lib "winspool.drv" (ByVal _
hPrinter As Long) As Long
Private Declare Function EndPagePrinter Lib "winspool.drv" (ByVal _
hPrinter As Long) As Long
Private Declare Function OpenPrinter Lib "winspool.drv" Alias _
"OpenPrinterA" (ByVal pPrinterName As String, phPrinter As Long, _
ByVal pDefault As Long) As Long
Private Declare Function StartDocPrinter Lib "winspool.drv" Alias _
"StartDocPrinterA" (ByVal hPrinter As Long, ByVal Level As Long, _
pDocInfo As DOCINFO) As Long
Private Declare Function StartPagePrinter Lib "winspool.drv" (ByVal _
hPrinter As Long) As Long
Private Declare Function WritePrinter Lib "winspool.drv" (ByVal _
hPrinter As Long, pBuf As Any, ByVal cdBuf As Long, _
pcWritten As Long) As Long
Private Sub TEST()
Dim lhPrinter As Long
Dim lReturn As Long
Dim lpcWritten As Long
Dim lDoc As Long
Dim sWrittenData As String
Dim MyDocInfo As DOCINFO
lReturn = OpenPrinter("ZDesigner LP 2844", lhPrinter, 0)
If lReturn = 0 Then
MsgBox "The Printer Name you typed wasn't recognized."
Exit Sub
End If
MyDocInfo.pDocName = "AAAAAA"
MyDocInfo.pOutputFile = vbNullString
MyDocInfo.pDatatype = vbNullString
lDoc = StartDocPrinter(lhPrinter, 1, MyDocInfo)
Call StartPagePrinter(lhPrinter)
sWrittenData = "N" & vbFormFeed
sWrittenData = sWrittenData & "q609" & vbFormFeed
sWrittenData = sWrittenData & "Q203,26" & vbFormFeed
sWrittenData = sWrittenData & "B26,26,0,UA0,2,2,152,B," & Chr(34) & "603679025109" & Chr(34) & vbFormFeed
sWrittenData = sWrittenData & "A253,26,0,3,1,1,N," & Chr(34) & "SKU 6205518 MFG 6354" & Chr(34) & vbFormFeed
sWrittenData = sWrittenData & "A253,56,0,3,1,1,N," & Chr(34) & "2XIST TROPICAL BEACH" & Chr(34) & vbFormFeed
sWrittenData = sWrittenData & "A253,86,0,3,1,1,N," & Chr(34) & "STRIPE SQUARE CUT TRUNK" & Chr(34) & vbFormFeed
sWrittenData = sWrittenData & "A253,116,0,3,1,1,N," & Chr(34) & "BRICK" & Chr(34) & vbFormFeed
sWrittenData = sWrittenData & "A253,146,0,3,1,1,N," & Chr(34) & "X-LARGE" & Chr(34) & vbFormFeed
sWrittenData = sWrittenData & "P1,1" & vbFormFeed
lReturn = WritePrinter(lhPrinter, ByVal sWrittenData, _
Len(sWrittenData), lpcWritten)
lReturn = EndPagePrinter(lhPrinter)
lReturn = EndDocPrinter(lhPrinter)
lReturn = ClosePrinter(lhPrinter)
End Sub
Method 2
Option Compare Database
Private Sub crtLabel()
Dim prtDevice As String
Dim strQuote As String
strQuote = Chr(34)
prtDevice = "ZDesigner LP 2844" ' whatever device Access currently has as the default. I have the user select a printer prior to printing, which sets the Access defaut printer
' open printer port
Open prtDevice For Output As #1
' initialize printer
Print #1, "OD" & vbCrLf
Print #1, "N" & vbCrLf
Print #1, "O" & vbCrLf
Print #1, "Q545,B12+23" & vbCrLf
Print #1, "q262" & vbCrLf
Print #1, "UN" & vbCrLf
Print #1, "rN" & vbCrLf
Print #1, "N" & vbCrLf
Print #1, "A4,94,3,3,1,1,N," & strQuote & "1803" & strQuote & vbCrLf
Print #1, "A36,74,3,3,1,1,N," & strQuote & "B" & strQuote & vbCrLf
Print #1, "A64,94,3,3,1,1,N," & strQuote & "079" & strQuote & vbCrLf
Print #1, "A112,8,0,2,1,1,N," & strQuote & strQuote & vbCrLf ' you can replace any string like "1803" with a string variable like SID or AID that gets passed to the sub
Print #1, "A112,32,0,3,1,1,N," & strQuote & strQuote & vbCrLf ' same here
Print #1, "A112,64,0,1,1,1,N," & strQuote & "04/13/2009" & strQuote & vbCrLf
Print #1, "A130,100,0,1,1,1,N," & strQuote & "SWAB, NASO" & strQuote & vbCrLf
Print #1, "A4,100,0,1,1,1,N," & strQuote & "C146536" & strQuote & vbCrLf
Print #1, "B53,130,0,1,1,0,47,N," & strQuote & "2009-06868" & strQuote & vbCrLf
Print #1, "A112,188,0,1,1,1,N," & strQuote & "" & strQuote & vbCrLf
Print #1, "P1,1" & vbCrLf
Print #1, "O" & vbCrLf
' close printer port
Close #1
End Sub
Nothing happens after running the function. It's like the printer is not touched at all by the code.
UPDATE
Method 1 is the closest thing I can get to printing the file. After executing the command, there is a printer icon at the status bar show that the printer has been called and receiving data from my code, but still, no printing at all. Help...
if it is mapped to a parallel or com port, you can open that directly:
open "LPT1:" For Output as #1
' or open "COM1:"
print #1, "SomeData"
Close #1
What I like to do is do something similar to your Method 2, but save it to a file (the raw printer data) and then do a file copy to the UNC path.
file copy "C:\label.txt" \computername\sharename
That works for me.
Okay so this is how I managed to get thing this work. Not a best option as I wanted but ... it works.
1) I use the same function, but written in C++, taken from here http://support.microsoft.com/kb/138594/EN-US
// RawDataToPrinter - sends binary data directly to a printer
//
// Params:
// szPrinterName - NULL terminated string specifying printer name
// lpData - Pointer to raw data bytes
// dwCount - Length of lpData in bytes
//
// Returns: TRUE for success, FALSE for failure.
//
BOOL RawDataToPrinter(LPSTR szPrinterName, LPBYTE lpData, DWORD dwCount)
{
HANDLE hPrinter;
DOC_INFO_1 DocInfo;
DWORD dwJob;
DWORD dwBytesWritten;
// Need a handle to the printer.
if( ! OpenPrinter( szPrinterName, &hPrinter, NULL ) )
return FALSE;
// Fill in the structure with info about this "document."
DocInfo.pDocName = "My Document";
DocInfo.pOutputFile = NULL;
DocInfo.pDatatype = "RAW";
// Inform the spooler the document is beginning.
if( (dwJob = StartDocPrinter( hPrinter, 1, (LPSTR)&DocInfo )) == 0 )
{
ClosePrinter( hPrinter );
return FALSE;
}
// Start a page.
if( ! StartPagePrinter( hPrinter ) )
{
EndDocPrinter( hPrinter );
ClosePrinter( hPrinter );
return FALSE;
}
// Send the data to the printer.
if( ! WritePrinter( hPrinter, lpData, dwCount, &dwBytesWritten ) )
{
EndPagePrinter( hPrinter );
EndDocPrinter( hPrinter );
ClosePrinter( hPrinter );
return FALSE;
}
// End the page.
if( ! EndPagePrinter( hPrinter ) )
{
EndDocPrinter( hPrinter );
ClosePrinter( hPrinter );
return FALSE;
}
// Inform the spooler that the document is ending.
if( ! EndDocPrinter( hPrinter ) )
{
ClosePrinter( hPrinter );
return FALSE;
}
// Tidy up the printer handle.
ClosePrinter( hPrinter );
// Check to see if correct number of bytes were written.
if( dwBytesWritten != dwCount )
return FALSE;
return TRUE;
}
I got the file RAWPRN.EXE from there, put my EPL code in a txt file. Finally, use Shell to execute it
Dim RetVal
RetVal = Shell("cmd .exe /c C:\rawprint\RawPrint.exe ""ZDesigner LP 2844"" ""C:\eplcode.txt""", 1)
My solution for Zebra
Creating a generic/text printer in windows then sending to raw file to this printer
In Zebra printers advanced settings --> others,
there is a passthrough characters. You can send raw text with this to this printer.
I use this solution, works perfect.
make a generic text printer, following this recipe
Map the printer to LPT1, using "net use lpt1 \\computername\printername /persistent:yes
Send files to the printer, using:
VBA
Public function runCmd(cmd as String) as Boolean
Dim wsh As Object
Dim cmdToRun As String
Dim Sts As Integer
Set wsh = VBA.CreateObject("WScript.Shell")
cmdToRun = "cmd.exe /c " & Quote(cmd)
'Run & wait to complete
Sts = wsh.Run(cmdToRun, 0, 1)
If Sts = 0 Then
runCmd = True
Else
MsgBox cmd & vbCrLf & "Failed with error code " & Sts
End If
Set wsh = Nothing
End Function
Using cmd : : "cd {dir} & Print \D:LPT1 [file [file]]"

MS Script Control in VBA

I generally use VB.Net for programming but I have been delegated to a VBA project that would benefit from using script control for running script. Here is sample code but errors out on the .Run line of code. I can do this in VB.Net easy but can't get it to work in vba.
ERROR = Wrong number of arguments or invalid property assignent
Option Explicit
Dim sc As New ScriptControl
Sub RunFunctions()
MsgBox (Eval("2 * PI"))
End Sub
Function Eval(expr As String) As Object
Dim code As String
code = "Dim PI" & vbCrLf & _
"PI = 3.1416" & vbCrLf & _
" " & vbCrLf & _
"Function Result" & vbCrLf & _
" Result = " & expr & vbCrLf & _
"End Function"
sc.Language = "VBScript"
sc.AllowUI = True
sc.AddCode (code)
Dim myparams() as variant
Eval = sc.Run("Result", myparams)
End Function
Using the .Eval function from the script control object runs ok in vba but does not run scripts. Here is an example of that if someone cares to know...
Sub SimpleTask()
Dim expr As String
sc.Language = "VBScript"
expr = "2 + 2 * 50"
MsgBox sc.Eval(expr)
End Sub
I think the issue is with your parameters to sc.Run. Try changing this call from
Eval = sc.Run("Result", myparams)
to
Eval = sc.Run("Result")
Update
Here is a complete form using your code that compiles and runs correctly:
Option Explicit On
Option Strict On
Imports MSScriptControl
Public Class Form1
Dim sc As New ScriptControl
Sub RunFunctions()
MsgBox(Eval("2 * PI"))
End Sub
Function Eval(expr As String) As Object
Dim code As String
code = "Dim PI" & vbCrLf & _
"PI = 3.1416" & vbCrLf & _
" " & vbCrLf & _
"Function Result" & vbCrLf & _
" Result = " & expr & vbCrLf & _
"End Function"
sc.Language = "VBScript"
sc.AllowUI = True
sc.AddCode(code)
Dim myparams() As Object
Eval = sc.Run("Result")
End Function
Sub SimpleTask()
Dim expr As String
sc.Language = "VBScript"
expr = "2 + 2 * 50"
MsgBox(sc.Eval(expr))
End Sub
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
SimpleTask()
RunFunctions()
End Sub
End Class
Here is the final working code for VBA. competent_tech has one for VB.Net.
Option Explicit
Dim sc As New ScriptControl
Sub RunFunctions()
MsgBox (Eval("2 * PI"))
End Sub
Function Eval(expr As String) As String
Dim code As String
code = "Dim PI" & vbCrLf & _
"PI = 3.1416" & vbCrLf & _
" " & vbCrLf & _
"Function Result" & vbCrLf & _
" Result = " & expr & vbCrLf & _
"End Function"
sc.Language = "VBScript"
sc.AllowUI = True
sc.AddCode (code)
Eval = sc.Run("Result")
End Function