Regarding cancelling the shelled program, it's probably possible, although I'm not sure how.
Last edited by Joacim Andersson; Jul 19th, 2012 at 05:28 AM.
Reason: Removed attachement
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
Thanks for your time. That's a huge work.
Sorry, I forgot to mention, that I will use it in Excel. I have tweaked your code a bit. I can now get hWnd value for UserForm, but I don't know how get it for Module, so my example is not working ("Unicode" button). "If TypeOf This Is UserControl Then" is not working in VBA, so I have made a workaround.
There are two main problems:
1) I still don't see Unicode characters (they all are changed to "??????")
2) There is no such a thing as new line, I see "♪◙" instead.
I saw that you have a reference to vba6 in one place, but newer Office versions use vba7, not sure if that's important.
P.S. My workbook will only work on 32bit Office version, for it to work on 64bit version it needs API adaptation.
Oh, I didn't know you were going to use it in Excel. In that case, the Self-Callback routines may not work.
Have you tried checking the button through the IsWindowUnicode() function? That may be the reason you couldn't see Unicode characters.
I reorganized that code in VB6; I haven't tested it in either VBA6 or VBA7.
EDIT:
I re-attached the demo project in case someone's still interested.
To the Moderators:
Sorry about the exe, but I had the same reason as riov.
Last edited by Bonnie West; Jul 19th, 2012 at 06:23 AM.
Reason: Stripped the offending exe from the zip file
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
Controls in UserForm are not able to display Unicode characters by default. For this reason I pass STDOUT & STDERR values to cell. I also use MsgBoxW to display Unicode characters.
Can you open my worksheet and see the modifications I have made, or should I copy/paste the code somewhere?
Originally Posted by Joacim Andersson
I have removed the attachment since it contained an exe file which is against our rules. Feel free to upload it again without the exe file.
sUnicodeFolder is the folder name you gave. It should now be able to run the console app. The reason the VB TextBox corrupts the commandline is because it can't handle Unicode strings. You'll probably have to find an alternative to VB controls that can handle Unicode properly before you can pass Unicode strings to the RunCommand method.
In the ReadPipe routine, you may want to use the Left$(StrConv(..)) code instead of the OemToCharBuff to properly read the incoming data.
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
And the result is this:
1. Command is working
2. TextBox can display unicode (see 3);
3. Output is still not in unicode (see 1), I have also tried to write output to a cell & txt file - same result;
4. New line is not working (see 2).
Even in the real command prompt (cmd.exe), Unicode characters aren't displayed properly, even though you can CD into them. Unfortunately, I don't know how to go around that display limitation...
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
This has solved issue with new line, now it is displayed correctly.
Originally Posted by Bonnie West
Even in the real command prompt (cmd.exe), Unicode characters aren't displayed properly, even though you can CD into them. Unfortunately, I don't know how to go around that display limitation...
Yes, some (not all) unicode characters in cmd are not displayed, but only because of font issue (good discussion about this here). As Philipp says "It has nothing to do with encodings since the Windows console always uses Unicode internally. The characters are simply not available in the fonts you use...". So theoretically it should be possible to read unicode characters or at least it should be possible to read those that are displayed (e.g., Russian, Greek etc.).
One interesting observation: if I use cmd /u /c your code stops displaying output, STDOUT = "" (I have tried to output it to TextBox, cell, MsgBox), but Debug.Print displays it (that's the first time I see such behavior). What is the most interesting here, that in Immediate window I see not ??? where unicode characters supposed to be, but some other strange characters, it is like STDOUT contains unicode output, but I cannot visualize it anywhere, bizarre.
I'm not 100% sure I understand your question but I think you want to be able to read a UTF-8 string in to a regular Unicode string (UTF-16).
The only way that I can think of to do this with VB6 is to use an ADODB.Stream object. Set a reference to Microsoft ActiveX Data Objects Library and use code similar to this:
Code:
Public Function Utf8ToString(data() As Byte) As String
Dim adoStream As ADODB.Stream
Set adoStream = New ADODB.Stream
adoStream.Charset = "utf-8"
adoStream.Mode = adModeReadWrite
adoStream.Type = adTypeBinary
adoStream.Open
adoStream.Write data
adoStream.Flush
adoStream.Position = 0
adoStream.Type = adTypeText
Utf8ToString = adoStream.ReadText
adoStream.Close
End Function
After doing some testing, I have found one major problem with this code.
If my command is something like cmd /c echo test & program.exe this code becomes from asynchronous to synchronous. By this I mean that program hangs if program.exe is executed for let's say 1 hour. Scenario: when PeekNamedPipe checks if there is anything to read it find that echo test has outputted text, but it does not know that program.exe will be executed for 1 hour, that's where program hangs as it tries to read output with ReadFile. I think the only solution here is to use ReadFileEx instead. It could be used in a Loop by checking for WAIT_IO_COMPLETION. Problem is that I cannot find any good examples how to use this API. Maybe anyone could advice?
Update: What complicates a situation is that CreateProcess does not start program.exe, it's only started with ReadFile.