Process.Start() with "manage-bde.exe" crashing in VB.NET - vb.net

I'm trying to start manage-bde.exe as a new process in VB.net but when it tries to start the proc, Bitlocker crashes. Could anyone please tell me what I'm doing wrong here? This code was converted from C# where it works all day long....
Code:
Private Sub btnLock_Click(sender As Object, e As EventArgs) Handles btnLock.Click
Dim drvSelected As String = cmbDriveSelect.SelectedValue.ToString()
Dim sysDirWithBDE As String = Environment.SystemDirectory + "\manage-bde.exe"
Dim lockStatus As String = String.Empty
' This is the code for the base process
Dim myProcess As New Process()
' Start a new instance of this program
Dim myProcessStartInfo As New ProcessStartInfo(sysDirWithBDE, " -lock " + drvSelected.Remove(2))
'Set Use Shell to false so as to redirect process run info to application
myProcessStartInfo.UseShellExecute = False
myProcessStartInfo.RedirectStandardOutput = True
myProcess.StartInfo = myProcessStartInfo
Try
myProcess.Start()
lblDriveLockMsg.Show()
Catch err As Exception
lblDriveLockMsg.Text = err.Message
End Try
'Read the standard output of the process.
lockStatus = myProcess.StandardOutput.ReadToEnd()
If lockStatus.Contains("code 0x80070057") Then
lblDriveLockMsg.Text = "Drive selected is not Bit Locker encrypted"
ElseIf lockStatus.Contains("code 0x80070005") Then
lblDriveLockMsg.Text = "Drive selected is in use by an application on your machine, force dismounting might result in data loss, please check and close any applications using the drive"
Else
lblDriveLockMsg.Text = lockStatus
End If
myProcess.WaitForExit()
myProcess.Close()
End Sub

Related

standard outputread does not read anything until process is closed vb.net

I am trying to redirect the output from xfoil.exe with downloadables here. The issue is when I am redirecting the standardoutput, my code will not read anything until I use the "quit" command which closes the external xfoil.exe and hence, I cannot run any further commands.
first defining variables
Dim p as process = New Process()
Dim startinfo = New ProcessStartInfo()
Dim bt As Threading.Thread
I start the process using
With startinfo
.FileName = Application.StartupPath & "\appdata\xfoil.exe"
.Arguments = ""
.WorkingDirectory = Application.StartupPath
.RedirectStandardError = True
.RedirectStandardOutput = True
.RedirectStandardInput = True
.UseShellExecute = False
.CreateNoWindow = True
End With
p.StartInfo = startinfo
p.EnableRaisingEvents = True
If Not IsNothing(bt) Then bt.Abort()
bt = New Threading.Thread(AddressOf ReadThread)
bt.IsBackground = True
bt.Start()
p.Start()
The definition for the ReadThread is
Private Sub ReadThread()
Dim rLine As String
Do Until Leaving
Try
rLine = p.StandardOutput.Read()
logtext += (Chr(rLine))
If p.StandardOutput.Peek = -1 Then
Me.Invoke(Sub() txtLog.AppendText(logtext))
logtext = ""
End If
Catch ex As Exception
Console.WriteLine("error " & ex.Message)
End Try
Loop
End Sub
This setup works perfectly with another app from the same developer Mark Drela. When I use the other app AVL with download link here everything works fine. However, xfoil does not work with this setup and I have spent some hours on this without any luck. I am using VB.net on Windows 10 in Visual Studio.NET 2019 community edition.
Edit
Both methods using threading and events were implemented and no luck.
A sample code using both methods in VB.net is now available on Github for review comments. Let me know if anyone has any experience with this and can help. This would really help my students in the class!

How to create a function that can wait for multiple processes to exit?

I am creating a windows service that will write all the start time and exit time for specific process that I wanted to monitor. The problem is when I am trying to monitor the process to wait for exit, I have no idea on how to wait multiple process to exit. Below are my code for writing the start time of the process.
Try
Using regkey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64).OpenSubKey("SOFTWARE\MonitoringApplication\Login", RegistryKeyPermissionCheck.Default)
childrenID = regkey.GetValue("Login User").ToString
End Using
If childrenID.Equals("admin") Then
Else
Dim connection As New SqlConnection("Server=DESKTOP-FTJ3EOA\SQLEXPRESS;Initial Catalog=MonitorDB;User ID = admin; Password = admin")
Dim command As New SqlCommand("SELECT App.ApplicationName FROM App INNER JOIN ChildrenApplication ON App.ApplicationID = ChildrenApplication.ApplicationID WHERE ChildrenID = #a", connection)
command.Parameters.Add("#a", SqlDbType.VarChar).Value = childrenID
Dim adapter As New SqlDataAdapter(command)
Dim table As New DataTable()
adapter.Fill(table)
Using sw As StreamWriter = New StreamWriter(AppDomain.CurrentDomain.BaseDirectory + "\MonitoringApplication.txt", True)
For Each row As DataRow In table.Rows
p = Process.GetProcessesByName(row.Item(0))
Using myprocess = New Process
If p.Count > 0 Then
myprocess.StartInfo.FileName = row.Item(0)
myprocess.EnableRaisingEvents = True
sw.WriteLine(row.Item(0) + "running")
End If
End Using
Next row
End Using
Const SLEEP_AMOUNT As Integer = 100
Do While Not eventHandled
elapsedTime += SLEEP_AMOUNT
If elapsedTime > 30000 Then
Exit Do
End If
Thread.Sleep(SLEEP_AMOUNT)
Loop
End If
Catch ex As Exception
Using sw As StreamWriter = New StreamWriter(AppDomain.CurrentDomain.BaseDirectory + "\MonitoringApplication.txt", True)
sw.WriteLine(ex)
End Using
End Try
Private Sub myProcess_Exited(ByVal sender As Object, ByVal e As System.EventArgs) Handles myProcess.Exited
eventHandled = True
Using sw As StreamWriter = New StreamWriter(AppDomain.CurrentDomain.BaseDirectory + "\MonitoringApplication.txt", True)
sw.WriteLine("Exited")
End Using
End Sub
Is there any ways to monitor multiple process to exit? Thanks in advance.
You're now using Process.GetProcessesByName() to retrieve an array of running processes, if any.
You can use the returned array of processes and subscribe to the Exited event of each one to log the exit time of any of the processes in the array.
Setting EnableRaisingEvent is necessary to raise the Exited event, but you also need to subscribe to event, using AddHandler along with the address of a method or a Lambda:
AddHandler [Process].Exited, AddressOf [Handler]
' or
AddHandler [Process].Exited, Sub() [Lambda]
This method accepts a process name and the path to a file where to store the name of the process and its exit time when the Exited event is raised.
If your current loop:
For Each row As DataRow In table.Rows
'(...)
Next
You can insert a call to this method:
For Each row As DataRow In table.Rows
SubscribeProcExit(row.Item(0), Path.Combine(Application.StartupPath, "MonitoringApplication.txt"))
Next
If the log file doesn't exit, it will be created and a new line is added each time one of the Processes exits, logging the Process.ProcessName and Process.ExitTime.
Note that row.Item(0) must contain the friendly name of the Process. For example, notepad.exe must be referenced as just "notepad".
Private Sub SubscribeProcExit(processName As String, fileName As String)
Dim processes As Process() = Process.GetProcessesByName(processName)
If processes.Length = 0 Then Return
For Each p As Process In processes
p.EnableRaisingEvents = True
AddHandler p.Exited,
Sub()
Using sw As StreamWriter = File.AppendText(fileName)
sw.WriteLine($"Process: {p?.ProcessName}, Exit Time: {p?.ExitTime}")
p?.Dispose()
End Using
End Sub
Next
End Sub

More Efficient Way To Wait/Listen for a Process

I have a tool that I have been using but it is hit or miss. It uses sendkeys to open a pdf from another application. I then check to see if the pdf opened, close that pdf by killing the process, then use sendkeys again to go to the next document. However, I have found that if there is any lag time between network and/or filesize, the program doesn't detect the process and the program stops functioning. Is there a better way to listen to a process?
Sub ProcessPDF()
Dim z As Integer = Next1
AppActivate("Hyperspace")
For i = 1 To z
SendKeys.SendWait("{ENTER}")
p = Process.GetProcessesByName("Acrobat")
If p.Count > 0 Then
p(0).CloseMainWindow()
SendKeys.SendWait("{LEFT}")
SendKeys.SendWait("^Q")
SendKeys.SendWait("{DOWN}")
Else
label2.Text = "An error has occurred! Please try again."
MsgBox("An error has occurred! Please try again.")
End If
Next1 = Next1 - 1
label2.Text = Next1 & " PDFs Left!"
Next
End Sub
Way 1:
wait:
For Each p In Process.GetProcesses
If p.ProcessName = ("Acrobat") Then
Threading.Thread.Sleep(1000)
GoTo wait
End If
Next
Way2:
Private Function Run(ByVal process As String, ByVal parameters As String) As String
Dim psi As ProcessStartInfo = New ProcessStartInfo(process)
psi.Arguments = "your commands"
psi.RedirectStandardError = True
psi.UseShellExecute = False
Dim output As String = String.Empty
Dim proc As Process = System.Diagnostics.Process.Start(psi)
proc.WaitForExit()
Dim outputStream As StreamReader = proc.StandardError
output = outputStream.ReadToEnd
proc.Close()
Return output
End Function
Force Kill:
waitkill:
For Each p In Process.GetProcesses
If p.ProcessName = ("Acrobat") Then
p.Kill()
GoTo waitkill
End If
Next

How to start a visible process

I have the following code to start the program R (even though I think that the program is not relevent for the problem here) and run a script:
Public Shared Sub RunRScript(rCodeFilePath As String, rScriptExecutablePath As String, args As String)
Dim file As String = rCodeFilePath
Dim result As String = String.Empty
Try
Dim info = New ProcessStartInfo()
info.FileName = rScriptExecutablePath
info.WorkingDirectory = Path.GetDirectoryName(rScriptExecutablePath)
info.Arguments = rCodeFilePath & " " & args
info.RedirectStandardInput = False
info.RedirectStandardOutput = True
info.UseShellExecute = False
info.CreateNoWindow = True
Using proc = New Process()
proc.StartInfo = info
proc.Start()
result = proc.StandardOutput.ReadToEnd()
proc.Close()
End Using
Catch ex As Exception
Throw New Exception("R Script failed: " & result, ex)
End Try
End Sub
Problem is, if there is an error in the script I run within R I dont get an error message because the instance is invisible. I tried to make it visible with
.WindowStyle = ProcessWindowStyle.Normal
in all combinations of .UseShellExcecute and .CreateNoWindow but this is not working. Could anyone help me to can make my process visible?
Since you are redirecting StandardInput and StandardOutput, you should now redirect StandardError to trap the errors also.
More info available on MSDN

Get data from Text file Print to Label

Just to keep this short I am working on a simple game to be played with anyone in the world who be interested in it, and because I am creating said game I decided to work on a simple launcher for the game one that pings the website for a version, checks that version with a stored text file with the game already installed and see if its a difference in version. If its a difference in version the launcher downloads the game. If the person does not already have the game installed it downloads the game for them.
Now for my problem why I am posting here, I am trying to get the text file already stored on the computer from the AppData directory to be read by the launcher and use it as an comparison with the version on the website. This is what I have for the on launch:
On Launch:
Private Sub MainForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim wc As New Net.WebClient
Text = wc.DownloadString("https://dl.dropboxusercontent.com/u/47132467/version.txt")
If My.Computer.FileSystem.FileExists("C:\Program Files\SC\SC.exe") Then
StartBtn.Enabled = True
StartBtn.Visible = True
Else
StartBtn.Enabled = False
StartBtn.Visible = False
End If
If My.Computer.FileSystem.FileExists("C:\Program Files\SC\Readme.txt") Then
ReadMeBtn.Visible = True
Else
ReadMeBtn.Visible = False
End If
End Sub
In short I am trying to figure out how to make a text file from the computer itself stored in AppData under Environ("AppData") & "\SC\version.txt" Been trying to figure out how to get the program to Read the local stored text file and put it as a variable where the program will compare it with the text file online. Thanks in Advanced! Sorry if I confuse anyone my brain is in derp mode trying to figure this out for a while now.
Here are 2 Functions Read & Write:
Public Function GetFileContents(ByVal FullPath As String, _
Optional ByRef ErrInfo As String = "") As String
Dim strContents As String
Dim objReader As StreamReader
Try
objReader = New StreamReader(FullPath)
strContents = objReader.ReadToEnd()
objReader.Close()
Return strContents
Catch Ex As Exception
ErrInfo = Ex.Message
End Try
End Function
Public Function SaveTextToFile(ByVal strData As String, _
ByVal FullPath As String, _
Optional ByVal ErrInfo As String = "") As Boolean
Dim Contents As String
Dim bAns As Boolean = False
Dim objReader As StreamWriter
Try
objReader = New StreamWriter(FullPath)
objReader.Write(strData)
objReader.Close()
bAns = True
Catch Ex As Exception
ErrInfo = Ex.Message
End Try
Return bAns
End Function
Call:
Dim File_Path as string = Environ("AppData") & "\SC\version.txt"
Dim versionStr as String = GetFileContents("File_Path")
Label1.text = versionStr
Label1.text.refresh ''// Sometimes this may be required depending on what you are doing!
if you want to read the version directly, rather than a text file, have a look at this code:
If My.Computer.FileSystem.FileExists(fn) Then
Dim fv As FileVersionInfo = FileVersionInfo.GetVersionInfo(fn)
If fv Is Nothing Then Return -1 'file has no version info
Return fv.FileMajorPart * 100000 + fv.FileMinorPart * 1000 + fv.FileBuildPart
Else
Return 0 'file does not exist
End If