I've created a Windows Application using VB.Net that uses Sub Main to determine if the application should run a specific process or just open as a form for user interaction. Everything works great except for when I try to schedule my application via Windows Task Scheduler. I kept getting the result code of 0xFF. I then tried running my application directly through the command prompt. When doing this, I received a System.ArgumentNullException error. The other information provided is very lacking so I'm struggling to determine where my issue actually lies. I can run my application from the form using a System.Diagnostics.Process command and passing the arguments to it that way. I can also successfully run it by entering command line arguments in the Debug tab of the application Properties. Below is a general outline of what my code looks like. I'm using the Command Line Parser Library to decipher the arguments. Any help or guidance would be greatly appreciated
Imports CommandLine
Imports CommandLine.Text
Module Startup
Public Sub Main()
Dim Args() As String = Environment.GetCommandLineArgs
Dim Options As New Arguments
Dim Parser As New Parser
If Parser.ParseArguments(Args, Options) Then
' Run application
Else
' Open windows form
End If
End Sub
Public Class Arguments
<[Option]("p", "process", Required:=True)> Public Property ProcessOption As String
<[Option]("r", "run", Required:=True)> Public Property RunOption As String
<[Option]("d", "date", Required:=False, DefaultValue:=Nothing)> Public Property DateOption As Date
<[Option]("u", "user", Required:=False, DefaultValue:="")> Public Property UserOption As String
End Class
End Module
I was able to run this on my testing machine with a debugger and found where my issue is. It actually has nothing to do with the arguments being passed by the command prompt. It's with another sub call I make. I will have to play with it and if I can't figure it out I will open another question. Thank you for your help.
Related
I have an really strange error. I have an sub in a class (API.vb) called OpenApp(). It accepts a form argument (Public Sub OpenApp(app As Form)).
Now I have a few other forms called Settings, devtools, login and so on.
When I try API.OpenApp(Settings) or API.OpenApp(devtools) however, it gives me this error:
Value of type 'devtools' cannot be converted to 'Form'.'
There is nothing else in the solution declaring devtools, Settings and so on as other things apart from Forms in their classes. Even more, it used to work but it just randomly started doing this.
Edit: As some people asked here's how all of them are declared:
Public Class devtools
And settings:
Public Class Settings
I think you're getting the point now. Oh, and here's the API.OpenApp sub
Public Shared Sub OpenApp(app As Form)
Dim open As Form = OpenProgram(app)
app.Show()
End Sub
I think you have pretty much answered it yourself, in your comment. You need to pass an instance of the form to the sub eg:
Dim frm as new DevTools
API.OpenApp(frm)
I'm maintaining a DLL with logging feature. I wanted to add a ListBox parameter to a method of this DLL to allow on display logging.
Basically this dll could be described this way :
' Class loggingDll.loggingObject
Public Function processIt([...], aLogBox As Object)
' Simple test code lines...
Dim l As VB.ListBox
Set l = aLogBox
' [...]
End Function
The EXE comes with a GUI, a VB.ListBox included. This ListBox (let's call it LogBox) is passed to the DLL in a way looking like this :
' Exe DllCaller.Exe
Private Sub Form_Load()
Dim aLoggingObject as loggingDll.loggingObject
Set aLoggingObject = New loggingDll.loggingObject
aLoggingObject.processIt(LogBox)
End Sub
This works perfectly fine when I run the EXE. But when running the DLL in debug mode whith this EXE (Project->Properties->Debugging tab option "Start program" with the path to the EXE), I get an ugly "Type Mismatch" at Set l = aLogBox.
I added a spy on the aLogBox variable. TypeName(aLogBox) returns "ListBox", but the content of aLogBox is empty (although a VB.ListBox object is full of properties).
What's happening ? Why debug mode has not the same behaviour ?
I use the IBM Host Access Class Library for COM Automation as a way to communicate with an IBM AS400 (aka iSeries, IBM i, green screen, 5250) through a terminal emulator. I notice that when you issue a "SendKeys" instruction, control returns to your application before the IBM emulator finishes with the command. This can lead to timing problems because you might then send another "SendKeys" instruction before the system is ready to accept it.
For example:
Imports AutPSTypeLibrary
Imports AutConnListTypeLibrary
Imports AutSessTypeLibrary
Sub Example
Dim connections As New AutConnList
connections.Refresh()
If connections.Count < 1 Then Throw New InvalidOperationException("No AS400 screen can currently be found.")
Dim connection As IAutConnInfo = DirectCast(connections(1), IAutConnInfo)
_Session = New AutSess2
_Session.SetConnectionByHandle(connection.Handle)
Dim _Presentation As AutPS = DirectCast(_Session.autECLPS, AutPS)
_Presentation.SendKeys("PM70[enter]", 22, 8)
_Presentation.SendKeys("ND71221AD[enter]", 22, 20)
End Sub
would work correctly when stepping through code in a debugger, but would fail when running normally because the second instruction was sent too soon.
One way to work with this is to put a timer or loop after each command to slow the calling program down. I consider this less than ideal because the length of time is not always predictable, you will often be waiting longer than necessary to accommodate an occasional hiccup. This slows down the run time of the entire process.
Another way to work around this is to wait until there is a testable condition on the screen as a result of your sent command. This will work sometimes, but some commands do not cause a screen change to test and if you are looking to abstract your command calling into a class or subroutine, you would have to pass in what screen condition to be watching for.
What I would like to find is one of the "Wait" methods that will work in the general case. Options like the autECLScreenDesc class seem like they have to be tailored to very specific conditions.
The autECLPS (aka AutPS) class has a number of Wait methods (Wait, WaitForCursor, WaitWhileCursor, WaitForString, WaitWhileString, WaitForStringInRect, WaitWhileStringInRect, WaitForAttrib, WaitWhileAttrib, WaitForScreen, WaitWhileScreen) but they also seem to be waiting for specific conditions and do not work for the general case. The general case it important to me because I am actually trying to write a general purpose field update subroutine that can be called from many places inside and outside of my .dll.
This example is written in VB.NET, but I would expect the same behavior from C#, C++, VB6, Java; really anything that uses IBM's Personal Communications for Windows, Version 6.0
Host Access Class Library.
The "Operator Information Area" class seems to provide a solution for this problem.
My general case seems to be working correctly with this implementation:
Friend Sub PutTextWithEnter(ByVal field As FieldDefinition, ByVal value As String)
If IsNothing(field) Then Throw New ArgumentNullException("field")
If IsNothing(value) Then Throw New ArgumentNullException("value")
_Presentation.SendKeys(Mid(value.Trim, 1, field.Length).PadRight(field.Length) & "[enter]", field.Row, field.Column)
WaitForEmulator(_Session.Handle)
End Sub
Private Sub WaitForEmulator(ByVal EmulatorHandle As Integer)
Dim Oia As New AutOIATypeLibrary.AutOIA
Oia.SetConnectionByHandle(EmulatorHandle)
Oia.WaitForInputReady()
Oia.WaitForAppAvailable()
End Sub
I give thanks to a user named "khieyzer" on this message board for pointing our this clean and general-purpose solution.
Edit:
After a few weeks debugging and working through timing and resource release issues, this method now reads like:
Private Sub WaitForEmulator(ByRef NeededReset As Boolean)
Dim Oia As New AutOIA
Oia.SetConnectionByHandle(_Presentation.Handle)
Dim inhibit As InhibitReason = Oia.InputInhibited
If inhibit = InhibitReason.pcOtherInhibit Then
_Presentation.SendKeys("[reset]")
NeededReset = True
WaitForEmulator(NeededReset)
Marshal.ReleaseComObject(Oia)
Exit Sub
End If
If Not Oia.WaitForInputReady(6000) Then
If Oia.InputInhibited = InhibitReason.pcOtherInhibit Then
_Presentation.SendKeys("[reset]")
NeededReset = True
WaitForEmulator(NeededReset)
Marshal.ReleaseComObject(Oia)
Exit Sub
Else
Marshal.ReleaseComObject(Oia)
Throw New InvalidOperationException("The system has stopped responding.")
End If
End If
Oia.WaitForInputReady()
Oia.WaitForAppAvailable()
Marshal.ReleaseComObject(Oia)
End Sub
I'm building a program in VB whose purpose is to run in the background and automatically update other programs I've created. To do this, it has to check if those programs are still running and, if they are, wait for them to close.
Unfortunately, the program won't compile. The exception states: GetProcessesByName is not a member of String. (The string it refers to is the Process parameter shown in the code below.)
I can't understand why this is happening, because this method has always worked without problems. I'm using Visual Studio 2015. For your reference, here's the code block:
Private Function CheckIfRunning(Process As String) As Boolean
Dim MyProcess() As Process
MyProcess = Process.GetProcessesByName("ProcessName")
If MyProcess.Count > 0 Then
Return True
Else
Return False
End If
End Function
Try using System.Diagnostics.Process.GetProcessesByName("ProcessName")
Since you've declared Process as a string parameter, Process.GetProcessesByName refers to the string instead of the System.Diagnostics method. Alternatively, you can use a different name for the string parameter.
I've been googling and trying different things, but I can't seem to figure out a way to debug my service :(
Typically I just use NLog to debug, but the service doesn't seem to want to create log files :( So - I need to debug step-by-step, if possible.
I have used VS to attach to the process (can only do that with no program/solution loaded into VS)... but it says 'Source Not Available'.
Any help would be greatly appreciated.
One way to debug a service is to run it as a non-service. In the following example, use System.ServiceProcess.ServiceBase.Run(New serviceclassname) to run as a service, or the dim and runConsole lines to run as a normal process. Do While True is ugly, but it works for debugging.
Shared Sub main()
System.ServiceProcess.ServiceBase.Run(New serviceclassname)
' use these two lines to debug (instead of the one above)
'Dim ps As New serviceclassname
'ps.runConsole(Nothing)
End Sub
Sub runConsole(ByVal args() As String)
' This is only used for console debugging (even though nothing goes to the console)
Call OnStart(args) ' onStart Override -- if you need it.
Console.ReadLine()
Do While True
Loop
Call OnStop()
End Sub