I am trying to write data(prompts) to a m8300 barcode scanner, but I am having a few issues. The device is serial and I am getting data from it, by using a backgroundworker to pull the data from it for me. However, I can't seem to be able to find a way to write data to the device. I know the device is capable of doing it as it says so in the manual. However, I have the following code:
Private Sub Button5_Click(sender As System.Object, e As System.EventArgs) _
Handles Button5.Click
SerialPort1.Write(Chr(18) & Chr(27) & "[2JSAY MY NAME" & vbCr)
End Sub
However, it does not work consistently.
Has anyone had experience with writing to a similar device?
I must admit, I totally forgot about this one. It turns out that the chr 18 and 27 are
command params for the device; so those 2 are needed only for commands, so i wasn't needed.
The issue I was having was with the communication protocol on the device, even though
the directions required 2-way communication enabled on it, it turns out that it needed 1-way communication. I found that out when I reset the device to factory settings and sent out data to it and it worked without any issues.
Goes to show you, not to always believe in the manuals.
Related
I have the problem, I'm in a network, where everyone sends messages through msg. Through it's really annoying, I thought about killing the messageboxes process. Running under csrss.exe thats not possible. When I looked through the taskmanager I noticed, when opening the tree structure of the csrss.exe, there was the messagebox and I could kill it. Has anyone any idea, how to do that in Visual Basic.
A simple web search led me to this question, which has some good answers already.
With a little work, I came up with this solution. It find the process by name (csrss), then filters by window title (Message from).
Sub Main()
killProcesses("csrss", "Message from")
End Sub
Private Sub killProcesses(processName As String, mainWindowTitle As String)
Dim processes = Process.GetProcesses().
Where(Function(p) p.ProcessName.Contains(processName)).
Where(Function(p) p.MainWindowTitle.Contains(mainWindowTitle))
' (Where clauses can be combined into one of course)
For Each p In processes
p.CloseMainWindow()
Next
End Sub
It works like this. Send a message
C:\Users\djv>msg djv hey whats up
Get a message
Here is the task
And what the code sees
It is closed upon the p.CloseMainWindow() call. It will also close any other window which matches the description, since it's not limited to one. This should satisfy your requirement.
Just so the question hast a proper answer, I found a solution using the win32 api (PInvokes) specifically the user32.dll. It provides methods like GetWindow, GetWindowThreadProcessId and CloseWindow, which solved my problem.
I tried this to show some MsgBox when shutdown or logoff is detected.. like "You're logging off.. .
Public Class frmDetectEnd
Private Sub frmDetectEnd_Load(sender As Object, e As EventArgs) Handles MyBase.Load
AddHandler Microsoft.Win32.SystemEvents.SessionEnding, AddressOf Handler_SessionEnding
End Sub
Public Sub Handler_SessionEnding(ByVal sender As Object, ByVal e As Microsoft.Win32.SessionEndingEventArgs)
If e.Reason = Microsoft.Win32.SessionEndReasons.Logoff Then
MessageBox.Show("User is logging off")
ElseIf e.Reason = Microsoft.Win32.SessionEndReasons.SystemShutdown Then
MessageBox.Show("System is shutting down")
End If
End Sub
End Class
This detection work's OK but I want to stop shutdown/logoff process if MsgBox is shown, because at this point the shutdown/logoff process is executed and it stops with Windows message "This program is preventing to log you off...".
However, I would like that after getting message "User is logging of/System is shutting down" the user can select command button to proces something and then Shutdown or LogOff can continue.
It's pretty much impossible to cancel a shutdown/logoff after it has started. At most you can get the "This program is preventing Windows from shutting down" message, like you said in your question.
A potential solution would be to create system-wide hooks for the InitiateShutdown, InitiateSystemShutdown and InitiateSystemShutdownEx functions (requires C++ or some other kind of low-level language). However, they would need to be coded carefully and tested thoroughly, and even if you managed to get them working most of the times, there's no guarantee that the OS isn't bypassing them via some other, even deeper functions (it contains a lot of both undocumented and name-mangled functions).
Source:
I researched this heavily about two years back in an attempt to make a program that would completely block system shutdown if the user chose to. However, as mentioned above, it has proven to be extremely difficult, if not impossible. None of my attempts were a success.
You could immediately call shutdown /a when a shutdown is detected. (/a stands for "abort").
That's a built-in command-line utility in Windows, so you'd call it the usual way of calling command-line utilities within a vb app. The trick is it has to happen fast enough.
Another more hacky way you could try would be to send a CTRL+ALT+DEL and then the Task Manager (and then hide it. Maybe you can do it all so fast the user would only see a quick flash). That usually aborts a shutdown when I've manually done it.
I use (SAPI) object in my application. However, whenever I executes its function, the voice runs but the application's performance (everything else) gets paused until the voice finishes! I wonder if that has something to do with the priority of this Speaking-Object. Can I somehow lower it until the rest of the code executes first? o_O
Private Function Lara(ByVal script As String) As Object
Lara = CreateObject("SAPI.spvoice")
Lara.Voice = Lara.GetVoices.Item(1)
Return Lara.speak(script)
End Function
Private Sub Test_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Logo.Visible = True
Logo.Image = ResizeImage(My.Resources.Spell)
Lara("Welcome")
End Sub
Can (Lara) say "welcome" AFTER loading the form and its Logo?
Thank you.
Thanks to Ms. Lesley Gushurst, the voice now runs according the code order (Application shows up, its logo, then the voice). The solution was to add a (com-reference) to the project named "Microsoft Speech Object Library", then importing it in the code.
Imports SpeechLib
Private Sub Test_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Logo.Visible = True
Logo.Image = My.Resources.Spell
Dim Lara = CreateObject("SAPI.spvoice")
Lara.Voice = Lara.GetVoices.Item(1)
Lara.speak("Welcome", SpeechVoiceSpeakFlags.SVSFlagsAsync) 'It's declared now!
End Sub
If you take a look at MSDN's documentation SpVoice Speak method, it states that
"When synchronous speech is used in an application, the application's
execution is blocked while the voice speaks, and the user is
effectively locked out. This may be acceptable for simple
applications, or those with no graphical user interface (GUI), but
when sophisticated user interaction is intended, asynchronous speaking
will generally be more appropriate."
So what you'll probably want to do is look into calling speak with the SVSFlagsAsync being set. As it is right now your execution is being blocked.
I'm thinking your code would look like:
Lara.speak(script, SpeechVoiceSpeakFlags.SVSFlagsAsync)
I wish mine was that easy. Mine SWITCHES voices on the fly according to the voices embedded in the text to be read. And I am fast finding out that not too many people are trying to do that.
My apps is a Visual Basic (VS2010) verbal editing tool for writers that speaks the chapter or story so the author can HEAR typos, incoherent sentences, etc. in male or female voices, depending on which character is speaking. Right now I have only 7 voices that are available although at one time I have had 12 and with 22 different characters assigned to them.
It worked fine on windows 7, 8 and 8.1 but started having big problems windows text.
When I finally get it working I will make the code available, maybe.
I want to host a web server and want to use VBA to do it. Is this possible? I'm just doing this to prove someone wrong and really want to make this program.
So is it possible to make a really simple web server (just listens for get requests)? Help would be very much appreciated.
EDIT
I'm trying something like this
Sub startServer()
Set wunsock = CreateObject("OSWINSCK.Winsock")
wunsock.LocalPort = 80
wunsock.Listen
End Sub
Sub wunsock_ConnectionRequest(ByVal requestID As Long)
If sockMain.State <> sckClosed Then
sockMain.Close
End If
sockMain.Accept requestID
End Sub
Private Sub wunsock_DataArrival(ByVal bytesTotal As Long)
Dim strData As String
sockMain.GetData strData, vbString
txtStatus.Text = txtStatus.Text & _
strData & vbCrLf
End Sub
However it doesn't work?
Although this is a rather old question, I'd still like to mention that I built an Excel hosted REST webserver using plain VBA macros and some Winsock C calls, as proposed by Daniel A. White.
I added this as an answer instead of a comment, since it's built as a modular library, so you can adjust it to your needs, and others might need exactly this kind of library. It can serve both worksheets, basic files and also create custom hooks using an IWebController to listen on specific routes (which was mentioned by OP in a comment):
http://github.com/michaelneu/webxcel
To use it, you'll have to either import the classes/modules into your workbook, or let the build script create a new one for you. See Main.bas on how to start the server from within VBA.
http://www.ostrosoft.com/oswinsck.asp#inst
is a winsock type of library which can be used from VBA. It is possible to do what you are looking to do though is not the most efficient thing to do.
I do applaud your tenacity hope it works out for you.
I'm not sure I fully understand the question. Generally, you don't "host a web server", you host a web site.
But if you can do TCP sockets with VBA, then you can make an incredibly simple web server by following the HTTP standard protocol.
Edit: based on your comment, yes you can make a simple web server as long as you can open up a TCP socket.
Well, at the risk of violating the spirit of the question, you can always use VB's support for library functions and just create a library binding to one of a number of C-language web server options (such as http://www.acme.com/software/micro_httpd/, http://www.gnu.org/software/libmicrohttpd/ or http://code.google.com/p/mongoose/). You'd have to make DLLs out of the selected web server but that is reasonably easily done and this will work just fine in VBA.
I need to write a VB.Net 2008 applet to go through all the fixed-drives looking for some files. If I put the code in ButtonClick(), the UI freezes until the code is done:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
'TODO Find way to avoid freezing UI while scanning fixed drives
Dim drive As DriveInfo
Dim filelist As Collections.ObjectModel.ReadOnlyCollection(Of String)
Dim filepath As String
For Each drive In DriveInfo.GetDrives()
If drive.DriveType = DriveType.Fixed Then
filelist = My.Computer.FileSystem.GetFiles(drive.ToString, FileIO.SearchOption.SearchAllSubDirectories, "MyFiles.*")
For Each filepath In filelist
'Do stuff
Next filepath
End If
Next drive
End Sub
Google returned information on a BackGroundWorker control: Is this the right/way to solve this issue?
If not, what solution would you recommend, possibly with a really simple example?
FWIW, I read that Application.DoEvents() is a left-over from VBClassic and should be avoided.
Thank you.
The BackgroundWorker is a good way to solve your problem. Actually the documentation states this:
The BackgroundWorker class allows you to run an operation on a separate, dedicated thread. Time-consuming operations like downloads and database transactions can cause your user interface (UI) to seem as though it has stopped responding while they are running. When you want a responsive UI and you are faced with long delays associated with such operations, the BackgroundWorker class provides a convenient solution.
Put the process into a separate thread....
...using the BackgroundWorker component.
Disable UI components that should not be usable while the process workd.
Finished - the UI will still be responsive.
The key is to seperate the UI code from the actual functionality code.
The time-consuming functionality should run on a seperate thread. To achieve this, you can either:
Create and start a Thread object by
yourself
Create a Delegate and use
asynchronous invokation (using
BeginInvoke).
Create and start a BackgroundWorker.
As you mentioned, you should avoid Application.DoEvents(). A proper breakdown of the application's functionality will allow you to create an application which is designed to be responsive, rather than creating a non-responsive application with DoEvents "fixes" (which is costly, considered bad practice, and implies a bad design).
Since your method doesn't return a value and doesn't update the UI, the fastest solution might be creating a Delegate and using "fire and forget" asynchronous invokation:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Call New Action(AddressOf DrivesIteration).BeginInvoke(Nothing, Nothing)
End Sub
Private Sub DrivesIteration()
Dim drive As DriveInfo
Dim filelist As Collections.ObjectModel.ReadOnlyCollection(Of String)
Dim filepath As String
For Each drive In DriveInfo.GetDrives()
If drive.DriveType = DriveType.Fixed Then
filelist = My.Computer.FileSystem.GetFiles(drive.ToString, FileIO.SearchOption.SearchAllSubDirectories, "MyFiles.*")
For Each filepath In filelist
DoStuff(...)
Next
End If
Next
End Sub
BTW, For..Next blocks no longer have to end with "Next (something)", it is obsolete - VB now infers the (something) by itself, so there is no need to state it explicitly.
A. put up a PROGRESS BAR... update it and .REFRESH it ... If all you want is to show that your not dead.
B. DoEvents is evil sounds A LOT like "NEVER USE A GOTO..." pleeeeze pleeeze pleeeze there are times and circumstances where any language's syntax can be harmful AND helpful. Why jump through a million hoops just to essentially do "A" above?
<soapbox>
If you know that something takes a LONG TIME and you also know that no other operations can take place WHILE YOUR WAITING (i.e. it is essentially a serial process) than if you do ANYTHING like that and push it into "the background" then you'll be sprinkling "ITS_OK_TO_CONTINUE" booleans all through the rest of your code just waiting for the file process to end anyway.... whats the point of that? All you've done is complicate your code for the sake of... hmm... "good programming?" Not in my book.
Who cares if DoEvents is "left over" from the ICE AGE. Its EXACTLY the right thing in MANY circumstances. For example: The framework gives you ProgressBar.Refresh but you'll see that its not exactly "working" unless you post-pend a few DoEvents after it.
</soapbox>
C. A background task is just that -- background; and you generally use it to operate on NON-SERIAL tasks or at least asynchronous tasks that MAY or MAY NOT update the foreground at some point. But I'd argue that anytime a so-called background task HALTS the foreground then it is (almost) by definition --- a FOREGROUND task; regardless of HOW LONG it takes.