Disappearing Command Prompt VB Script - vb.net

Problem: Simple GUI with a button which triggers a batch file to run via cmd. Works for simple and fast scripts (ie mkdir foo), but more advanced scripts which need time to finish, it fails. The problem seems to surround cmd closing before the script can finish. I have included a WaitForExit() clause, but it seems to be ignored.
Private Sub RunButton_Click(sender As Object, e As EventArgs) Handles RunButton.Click
Dim foo as String = IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "Foo\Scripts\foo.bat")
Dim p As New Process
Application.DoEvents()
p.StartInfo.FileName = foo
p.Start()
p.WaitForExit()
End Sub
Any ideas how to correct this issue? I see lots of posts about WScript and creating a shell object; do I really need to do it like that? This process seems to work, but it just closes out before the process finishes.

Related

Exe working only if started manually but I want it to start automatically

I have done a simple VB application with this code:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim procName As String = Process.GetCurrentProcess().ProcessName
Dim processes As Process() = Process.GetProcessesByName(procName)
If processes.Length > 1 Then
Process.GetProcessesByName("keyinput")(0).Kill()
End If
End Sub
Public Sub type(ByVal int As Double, str As String)
For Each c As Char In str
SendKeys.Send(c)
System.Threading.Thread.Sleep(int * 1000)
Next
End Sub
Sub vai()
Dim line As String = ""
If File.Exists("trans.txt") Then
Using reader As New StreamReader("trans.txt")
Do While reader.Peek <> -1
line = reader.ReadLine()
type(0.155, line)
'SendKeys.Send(line)
SendKeys.Send("{ENTER}")
Loop
End Using
File.Delete("trans.txt")
End If
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
vai()
End Sub
Basically the timer in it check if a file exists, read it and type the content simulating the keyboard.
I want this exe to start automatically when user login, it does it, apparently, I can see the form1 pop up but doesn't really works. Everyting is fine only if I run it manually by double-clicking the icon. Why and what can I do? Thanks
ps. i already tried to execute it with windows task manager, or putting a shortcut in the windows startup folder, or calling it from a cmd
EDIT:
when app starts automatically , process is running, but windows form is showing like this
Instead starting manually is showing like this:
I don't know this for a fact but I suspect that the issue is the fact that you are not specifying the location of the file. If you provide only the file name then it is assumed to be in the application's current directory. That current directory is often the folder that the EXE is in but it is not always and it can change. DO NOT rely on the current directory being any particular folder. ALWAYS specify the path of a file. If the file is in the program folder then specify that:
Dim filePath = Path.Combine(Application.StartupPath, "trans.txt")
If File.Exists(filePath) Then
Using reader As New StreamReader(filePath)
EDIT:
If you are running the application at startup by adding a shortcut to the user's Startup folder then, just like any other shortcut, you can set the working directory there. If you haven't set the then the current directory will not be the application folder and thus a file identified only by name will not be assumed to be in that folder.
If you are starting the app that way (which you should have told us in the question) then either set the working directory of the shortcut (which is years-old Windows functionality and nothing to do with VB.NET) or do as I already suggested and specify the full path when referring to the file in code. Better yet, do both. As I already said, DO NOT rely on the current directory being any particular folder, with this being a perfect example of why, but it still doesn't hurt to set the current directory anyway if you have the opportunity.
It was a Windows task scheduler fault, that for some reason didn't executed the exe correctly at logon. I've solved the issue by using Task Till Down and everything works fine now.

Import-Module not working from within WinForms Application

I have a VB.net app where I invoke Import-Module on a PowerShell from within my vb.net Window Application but the error says it could not find the module. Error as below.
Import-Module : The specified module 'MSOnline' was not loaded because no valid module file was found in any module directory.
When I load the same Module by launching the PowerShell externally in the usual way it works fine. Image as below.
The VB script is as below
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim procStartInfo As New ProcessStartInfo
Dim procExecuting As New Process
With procStartInfo
.UseShellExecute = True
.FileName = "powershell.exe"
.WindowStyle = ProcessWindowStyle.Normal
.Verb = "runas" 'add this to prompt for elevation
Dim psscript As String = My.Resources.mymsolPS
procStartInfo.Arguments = psscript
procExecuting = Process.Start(procStartInfo)
End With
End Sub
My PowerShell Script is saved in my.resource as a txt file. My PowerShell Script is as below.
Import-Module Msonline
Connect-msolService
I replaced the PowerShell script to Get-Help and that works only it dosnt work when I use Import-Module Msonline.
One more information that can be shared is the module is stored in the below location.
C:\Windows\System32\WindowsPowerShell\v1.0\Modules\MSOnline\MSOnline.psd1
Any Help is greatly appreciated.
Thanks in Advance
Update 2:
More fiddling with it found some thing which i am not sure if is relevant.
If I launch the powershell from within my VB.net and run the below command I cant see the MSOnline module.
PS C:\windows\system32>> cd $env:WINDIR\System32\WindowsPowerShell\v1.0\Modules\
PS C:\windows\System32\WindowsPowerShell\v1.0\Modules>> dir
If I run the PowerShell directly from my system and run the above script I can see the Module
d----- 11/22/2017 2:59 PM MSOnline
Still a mystery for me which I cant crack. :(
A difference I notice is when launching from your app, or locally, the directory is either your user, or system.. so maybe the way PS is being loaded it can't find the module.
What about if you provide a full path to the module?
I've had much better luck using RunSpace - I use it to pass any powershell commands - here are a snippet from one of the sites and some examples to look at:
'Create the runspace.
Using R As System.Management.Automation.Runspaces.Runspace = _
System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace()
'Create the pipeline
Using P As System.Management.Automation.Runspaces.Pipeline = R.CreatePipeline()
'Open the runspace.
R.Open()
'Create each command (in this case just one)...
Dim Cmd As New System.Management.Automation.Runspaces.Command("C:\script.ps1", True)
'...and add it to the pipeline.
P.Commands.Add(Cmd)
'Execute the commands and get the response.
Dim Result As System.Collections.ObjectModel.Collection(Of _
System.Management.Automation.PSObject) = P.Invoke()
'Close the runspace.
R.Close()
'Display the result in the console window.
For Each O As System.Management.Automation.PSObject In Result
Console.WriteLine(O.ToString())
Next
End Using
End Using
http://www.winsoft.se/2009/08/execute-a-cmdlet-or-ps1-script-from-visual-basic/
https://social.msdn.microsoft.com/Forums/vstudio/en-US/5d2279c8-e02c-45eb-a631-951c56067bb5/run-powershell-script-from-vbnet?forum=vbgeneral
https://code.msdn.microsoft.com/windowsdesktop/VBPowerShell-6b4f83ea
The last one provides a pretty solid breakdown of what it's doing. Let me know if you can't get it to work, I can try to see if this import works on an app.
I actually found the solution after hours of pain. This is pretty silly solution.
Went I went to my application Properties I found that the Preferred run was set to 32 bit hence when my PowerShell was launched from within it was looking for the module under SYSWOW where its suppose to look it under System32. I unchecked the "Preferred 32 BIT" and not it imports the module from system 32.
Thought I should share this silly miss so that others should not suffer the same.

Executing multiple bat files with Visual basics

I'm working on a program created with Visual Studio 2013. The program does a few things and I'm nearly complete, but one last issue appears.
Within the program I have three buttons. One "Force restart", "manual start" and one "force stop". The "force stop" stops a bunch of programs, and the "force restart" stops them and then starts them again. The "manual start" starts all the programs. I will use "manual start" as example further down.
What happens behind these buttons is that it launches a bunch of bat-files that does the job. The batfiles contains tasskill /f /im program.exe and start "c:\program.exe". Then a second with timeout and exits.
The issue:
So far so good. The issue is that when the batch starts a program, VB program doesnt move on the the next bat file. It leaves a cmd.exe running. Even tho I have exit in the batch. Now If I'd go in and manually close the program or cmd.exe, then it would start on the next bat file.
It basically goes like this now: VB button -> batch starts -> batch runs program -> batch doesn't close AKA VB doesn't move to the next batch.
It should be like this: VB button -> batch starts -> batch runs program -> batch exits -> next batch starts -> batch runs program -> batch exits ->...
Here is what I got so far in that section of VB script:
Private Sub btnManualStart_Click(sender As Object, e As EventArgs) Handles btnManualStart.Click
If MessageBox.Show("Do you want to manually start all programs and services?", "OBS", MessageBoxButtons.YesNo, MessageBoxIcon.Question) = Windows.Forms.DialogResult.Yes Then
Timer2.Start()
Dim FileNum As Integer = FreeFile()
FileClose(FileNum)
TextBox1.Text &= Environment.NewLine & TimeOfDay & (" Manual start made")
Dim shell
shell = CreateObject("wscript.shell")
shell.run("C:\RestartApps\Scripts\Start_program1.bat", 0, True)
shell.run("C:\RestartApps\Scripts\Start_program2.bat", 0, True)
shell.run("C:\RestartApps\Scripts\Start_program3.bat", 0, True)
shell.run("C:\RestartApps\Scripts\Start_program4.bat", 0, True)
shell = Nothing
end if
Hopefully this was understandable.
I do not know exactly what your batches are doing, but it seems to me that you can simply use the Shell shortcut:
Dim commands As String() = {
"C:\RestartApps\Scripts\Start_program1.bat",
"C:\RestartApps\Scripts\Start_program2.bat",
"C:\RestartApps\Scripts\Start_program3.bat",
"C:\RestartApps\Scripts\Start_program4.bat"
}
For Each cmd As String In commands
Shell(cmd, AppWinStyle.Hide, False)
Next
Make sure that you set the third argument to FALSE on the overload (String,AppWinStyle,Boolean). This boolean ensures that the execution is set to "fire and forget". (which is the same as the one you're already passing, as TRUE (will wait for exit code)).
EDIT: Changed the AppWinStyle to Hide, which will run your batches silently
You need to improve start used in your batch script(s) as follows:
start "" /B "c:\program.exe"
Start command: start a program, command or batch script (opens in a new window). Note:
"" always include a TITLE this can be a simple string or just a pair of empty quotes "";
/B start application without creating a new window.
Another approach: use call instead of start "" as follows:
call "c:\program.exe"

close an open folder programmatically in vb.net

I have searched but cannot find a function that can close a folder in vb.net. You can kill a running app by finding its handle/windows-title/id, then issuing process.kill() command, but the same does not work on folders. For example, suppose:
C:\downloads\videos\
is open on my computer and I want to programmatically close it. How do I do that?
Make a folder in your c disk names Test
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim myfolder As String = "C:\Test"
Dim OpenFolder As Object = CreateObject("shell.application")
For Each item In OpenFolder.Windows
'ComboBox1.Items.Add(item.document.folder.self.Path)
If item.document.folder.self.Path = myfolder Then
item.Quit()
End If
Next
End Sub
I see your dilemma: open folders are just one part of the explorer.exe process. Killing that process would have undesirable side effects. To get around this, you have to send the right command to that process, instead of just killing it.
One place I would look to accomplish this is the SendKeys class. You might be able to focus the window and send the Alt-F4 keys to close just that window.

cmd call opening multiple cmd's

i have the following lines in a vb.net project im making
Private Sub yesButton_Click() Handles yesButton.Click
Shell("CMD.exe", AppWinStyle.NormalFocus)
SendKeys.SendWait("start firefox")
SendKeys.Send("{ENTER}")
Close()
End Sub
i want the button click to open Firefox using cmd then close, it works however it opens 20-30 cmd windows and about 5 fireofx's in the process, why? and more important how can i prevent this?
i am running visual-studio-2012. this is not the same as my other question.
--edit--
the same result is with this code
Private Sub yesButton_Click() Handles yesButton.Click
Shell("CMD.exe", AppWinStyle.NormalFocus)
SendKeys.Send("start firefox {ENTER}")
End Sub
Simply use this
Shell("CMD.EXE /C start firefox")
this will open a cmd command window and start firefox. the /C parameter is used to execute the command string following /C and then terminates.
type Run -> cmd -> cmd /? to see full list of cmd parameters available.