Getting captions of windows - vb.net-2010

Here is my code:
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim proc As New EnumWindProc(AddressOf EnumChild), i As Int32
Dim hwnd() As Process = Process.GetProcesses
Dim FormTitle As String
Dim RetVal As Integer
For i = 0 To hwnd.GetUpperBound(0)
Children = String.Empty
EnumChildWindows(hwnd(i).MainWindowHandle, proc, IntPtr.Zero)
RetVal = GetWindowText(hwnd(i).Handle, FormTitle, Int16.MaxValue)
ListBox1.Items.Add(FormTitle & " " & hwnd(i).ToString & Convert.ToChar(Keys.Return) & Children)
Next i
End Sub
For some reason, I am only getting the first 2 lines of windows. If I remove the GetWindowTest line of code, I get all the windows, yet with no caption.
How can I fix this?

Why don try with Process, here an example to get the current opened windows titles:
For Each P As Process In (From item In Process.GetProcesses Where item.MainWindowTitle.Trim <> vbNullString)
Me.ListBox1.Items.Add(P.MainWindowTitle)
Next

Related

How do I output from a PowerShell script (PSObjects?) to a WinForms TextBox in real-time?

I am executing a PowerShell script from a Visual Basic WinForms UI, and I managed to code it so it executes on a BackgroundWorker thread so that the UI doesn't lock up while the script is running. What it does is imports a .printerExport file to add printers and drivers to a target host, and it runs great. The only issue is that I set the output of the PSObjects to a TextBox and they all get output at the end once the script is completed, rather than output in real time like it would in a PowerShell console window.
I have tried multiple things to get it to output in real-time, but I am out of ideas, and even ReportProgress doesn't manage to get the real-time output as well.
How can I get this done? Below are the three involved Sub functions I am currently using:
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim HostName As String
Dim PrintName As String
Dim SourceFilePath As String
Dim DestinationPath As String
Dim FileName As String
HostName = txtHostName.Text
PrintName = "\\" & txtHostName.Text
SourceFilePath = txtFilePath.Text
DestinationPath = PrintName & "\c$\Temp\"
If String.IsNullOrEmpty(HostName) Or String.IsNullOrEmpty(SourceFilePath) Then
MessageBox.Show("Please enter the target host name and choose a file path.")
Return
End If
FileName = Path.GetFileName(SourceFilePath)
File.Copy(SourceFilePath, Path.Combine(DestinationPath, Path.GetFileName(SourceFilePath)), True)
Dim PsEnv As New RunspaceInvoke
Dim App As String = $"Invoke-Command -ComputerName {HostName} {{C:\Windows\System32\spool\tools\Printbrm.exe -r -s {PrintName} -f ""C:\Temp\{FileName}""}}"
Dim AppObjects As Collection(Of PSObject) = PsEnv.Invoke(App)
Dim Output As New StringBuilder()
Dim id As Integer = 0
For Each psobj2 As PSObject In AppObjects
id += 1
BackgroundWorker1.ReportProgress(id, psobj2.ToString() & vbCrLf & vbCrLf)
Next
End Sub
Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
Dim userState As String = CType(e.UserState, String)
TextBox3.AppendText(userState)
End Sub
Private Sub buttonInstall_Click(sender As Object, e As EventArgs) Handles buttonInstall.Click
BackgroundWorker1.WorkerReportsProgress = True
BackgroundWorker1.RunWorkerAsync()
End Sub

Download a file from google drive

First of all, sorry for my english. Second, I want to make an app that, at every launch download a .txt file from google drive, the file is defined (I mean, it's in drive). It's just a single file, but, when I launch the app, the file is downloaded, but dosen't contain anything..
Here is my code:
Private Function ReadLine(ByVal Line As Integer, ByVal lista As List(Of String)) As String
Return lista(Line - 1)
End Function
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If My.Computer.Network.IsAvailable() = True Then
Try
My.Computer.FileSystem.DeleteFile("C:\WINDOWS\" & fisier)
Catch ex As Exception
End Try
My.Computer.Network.DownloadFile("https://doc-14-7c-docs.googleusercontent.com/docs/securesc/17t22h2a63tpkhdgv047v6i0s5a9o8bm/qgqjocmi87jt0up72gfpg9dseeo3pt84/1458396000000/07699472972018131827/07699472972018131827/0B8iVIf__yN1FUDV1STNWODJUYms?e=download&nonce=5jnki0mtgo520&user=07699472972018131827&hash=0gi5r6k7rm2uob14062tlbsk0nhpkoo1", _
"C:\WINDOWS\" & fisier)
Dim reader As New IO.StreamReader("C:\WINDOWS\" & fisier)
Dim lista As New List(Of String)
While Not reader.EndOfStream
lista.Add(reader.ReadLine)
End While
reader.Close()
If My.Computer.FileSystem.FileExists(fisier2) = False Then
lblWould.Text = ReadLine(1, lista)
Else
Dim nr As Integer
nr = Val(My.Computer.FileSystem.ReadAllText(fisier2))
nrx = nr
End If
Dim contain As String = My.Computer.FileSystem.ReadAllText("C:\WINDOWS\" & fisier)
contain = contain.Replace(lblWould.Text, "SEEN!")
My.Computer.FileSystem.WriteAllText("C:\WINDOWS\" & fisier, contain, False)
Else
MsgBox("Trebuie sa fi connectat la internet!")
Me.Close()
End If
End Sub
Private Sub btn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnYes.Click, btnNo.Click
Dim reader As New IO.StreamReader("C:\WINDOWS\" & fisier)
Dim lista As New List(Of String)
Dim a As String
While Not reader.EndOfStream
a = reader.ReadLine()
If Not a = "SEEN!" Then
lista.Add(reader.ReadLine)
End If
End While
lblWould.Text = lista(nrx + 1)
nrx += 1
Dim contain As String = My.Computer.FileSystem.ReadAllText("C:\WINDOWS\" & fisier)
contain = contain.Replace(lblWould.Text, "SEEN!")
My.Computer.FileSystem.WriteAllText("C:\WINDOWS\" & fisier, contain, False)
End Sub`
Thanks!

How to pass all value of ListBox Control to a function?

I am writing a simple application to read the value a textbox and add to a listbox control . But i have to pass the listbox control to function . Any suggestion ?
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
test("E:\Satyajit.txt")
End Sub
Public Function test(ByVal filename As String)
Dim FILE_NAME As String = filename
Dim TextLine As String
Dim result As String = Path.GetFileName(FILE_NAME)
Dim objReader As New System.IO.StreamReader(FILE_NAME)
Do While objReader.Peek() <> -1
TextLine = objReader.ReadLine()
words = TextLine.Split(New Char() {","c})
ListBox1.Items.Add(words(3) & "," & words(4))
objItem = ListView1.Items.Add(words(3) & "," & words(4))
Loop
test1(ListBox1.Items)//pass the listbox value hare
End Function
Public Function test1(ByVal value As String)
Dim Fest As String = value
MsgBox(Fest)
End Function
You're passing the contents of a ListBox to a method that is just displaying them in a MsgBox(). There are two approaches you can do to accomplish what I think you're wanting.
You can pass ListBox.Items to the method and iterate through each item concatenating them into a single String or StringBuilder, then pass the String to the MsgBox(). This approach makes your method dependent on ListBoxItems.
You can iterate through ListBox.Items concatenating them into a single String or StringBuilder, then pass the String to your method. This makes your method a little more scalable.
I recommend approach #2, something like:
Dim MyListBox As New ListBox
MyListBox.Items.Add("Item1")
MyListBox.Items.Add("Item2")
MyListBox.Items.Add("Item3")
MyListBox.Items.Add("Item4")
MyListBox.Items.Add("Item5")
Dim sb As New StringBuilder
For Each Item In MyListBox.Items
sb.AppendLine(Item)
Next
Test1(sb.ToString())
The Test1 method would look like:
Public Sub Test1(ByVal value As String)
MsgBox(value)
End Sub
Results:
You could pass the whole control to the function:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim lstbox As New ListBox
lstbox.Items.Add("Hello")
lstbox.Items.Add("Second Item")
lstbox.Items.Add("Third Item")
MsgBox("The list contains: " & Length(lstbox) & " characters")
End Sub
Function Length(ByVal ctrl As ListBox) As Integer
Dim TotalNumberOfItems As Integer = 0
For Each item As String In ctrl.Items.ToString
TotalNumberOfItems += 1
Next
Return TotalNumberOfItems
End Function
or just its items
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim lstbox As New ListBox
lstbox.Items.Add("Hello")
lstbox.Items.Add("Second Item")
lstbox.Items.Add("Third Item")
MsgBox("The list contains: " & Length(lstbox.Items) & " characters")
End Sub
Function Length(ByVal col As ListBox.ObjectCollection) As Integer
Dim TotalNumberOfCharacters As Integer = 0
For Each item As String In col
TotalNumberOfCharacters += item.Length
Next
Return TotalNumberOfCharacters
End Function

Wait X seconds between ReadLine of text file

What I want is for the app to read the first line from a text file and output it to the textReply textbox, then wait for X time before reading and outputting the next line.
Dim fileIn As New System.IO.StreamReader("C:\test.txt")
Dim strData As String = ""
While (Not (fileIn.EndOfStream))
strData = fileIn.ReadLine()
textReply.Text = textReply.Text & strData & vbCr
System.Threading.Thread.Sleep(1000)
End While
As you can see I have tried sleeping the thread (not ideal as I want the app to stay responsive but thats another matter!) but every time it reads the whole file and dumps the lot into the textbox.
The reason is eventually it will be used for a serial connection to a device which needs time for the data transfer to the device and for the device to respond to each line sent.
You can create a Queue of string add each line to the list as you are reading the file, then you can poll it with a timer and add them to your textbox one at a time.
Public Class Form1
Dim myQueue As Queue(Of String) = New Queue(Of String)
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim fileIn As New System.IO.StreamReader("C:\test.txt")
Timer1.Start()
Dim strData As String = ""
While (Not (fileIn.EndOfStream))
strData = fileIn.ReadLine()
myQueue.Enqueue(strData)
End While
End Sub
Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick
If myQueue.Count > 0 Then
textReply.Text += myQueue.Dequeue & vbCrLf
End If
End Sub
End Class

Running Different Processes In Multiple Threads Without Overlapping In VB.NET 2

I have a sub-procedure which I want to run a different process, depending on what is currently running. I thought the easiest way to do this was by using an ArrayList of each of the campaign details & adding an 'Inuse' field to check to see if the Inuse field is set to 0 or 1. The problem that I have is that when running the process it is all happening at once & the integer hasn't been changed before the next thread kicks in so my threads are running the same campaigns.
I tried to avoid the problem by adding a Thread.Sleep(100) delay inbetween starting threads but this led to exactly the same problem.
Here's an example of what I am trying to do:
Imports System.Threading
Public Class Form1
Private Campaigns As New ArrayList
Private ProcessRunning As Boolean = False
Friend StopProcess As Boolean = False
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
For i = 0 To Campaigns.Count - 1
Dim objNewThread As New Thread(AddressOf RunProcess)
objNewThread.IsBackground = True
objNewThread.Start()
Next
End Sub
Private Sub UpdateCells(ByVal CampID As Integer, ByVal Column As String, ByVal newText As String)
Dim CellItemNum As Integer
If Column = "Status" Then CellItemNum = 4
DataGridView2.Rows(CampID).Cells.Item(CellItemNum).Value = newText
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
For i As Integer = 0 To 10
Campaigns.Add({Campaigns.Count(), "Campaign " & i, "Keywords " & i, "Link " & i, 5, True, 0, 0})
Next
DataGridView2.Rows.Clear()
For Each Campaign In Campaigns
DataGridView2.Rows.Add(New String() {Campaign(1), Campaign(2), Campaign(3), Campaign(6), ""})
Next
End Sub
Private Sub RunProcess()
' Set Variables
Dim CampID As Integer
Dim CampName As String
Dim Keywords As String
Dim Link As String
Dim CheckEvery As Integer
Dim OkToUse As Boolean
Dim Sent As Integer
' Find A Free Campaign
For i As Integer = 0 To Campaigns.Count - 1
' Check If Inuse
If Campaigns(i)(7) = 1 Then Continue For Else Campaigns(i)(7) = 1 ' This Line Sets Campaign To Inuse
' Most of the time only campaign(0) and campaign(1) are selected & multiple threads are running them instead of choosing unique campaigns
' Set Campaign Details
CampID = Campaigns(i)(0)
CampName = Campaigns(i)(1)
Keywords = Campaigns(i)(2)
Link = Campaigns(i)(3)
CheckEvery = Campaigns(i)(4)
OkToUse = Campaigns(i)(5)
Sent = Campaigns(i)(6)
' Start Process
UpdateCells(CampID, "Status", "Looking Up New Links (" & CampID & ")")
Exit For
Next
While StopProcess = False
Thread.Sleep(1000)
UpdateCells(CampID, "Status", "Running Process (" & CampID & ")")
Thread.Sleep(1000)
For i = 0 To CheckEvery
UpdateCells(CampID, "Status", "Re-Checking In " & (CheckEvery - i) & " Seconds")
Thread.Sleep(1000)
Next
End While
' Closing Processes
Campaigns(CampID)(7) = 0
End Sub
End Class
You can use SyncLock to force your threads to wait.
class level so all threads access same lock
private myLock as new Object
Then use syncLock when you start your process and end it when you are done.
SyncLock myLock
'process code here
End SyncLock
More MSDN info on the subject
Try looking into QueueUserWorkItem():
Private Sub Button1_Click(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles Button1.Click
For i = 0 To Campaigns.Count - 1
ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf RunProcess), Campaigns[i])
Next
End Sub
Then change the RunProcess() method to include the Campaign object sent in by the work item:
Private Sub RunProcess(ByVal o As System.Object)
' Process the Campaign
Dim campaign As Campaign = Ctype(o, Campaign)
End Sub
There will be no need for inuse, plus threads will be managed by the managed ThreadPool!