0

So I have a weird situation that I will preface as I'm new to this, more "experienced" in VBS and have migrated a lot of my scripting to PowerShell. I'm writing a WinForms program to read an INI file stored online so I can download updates listed in the INI. In the INI each downloadable file is stored in a block of text (see below) and I need to go through each block, find the "Source=" and "Destination=" lines, download the file from the source and place it in the "Destination=" folder. On the WinForm, the user has to choose the download location so I need to append the "Destination=" to the user's input.

Web based INI file content:

[.Net4.6.1FrameworkFull]
DisplayName=.Net Framework 4.6.1 Full
Source=https://download.microsoft.com/download/E/4/1/E4173890-A24A-4936-9FC9-AF930FE3FA40/NDP461-KB3102436-x86-x64-AllOS-ENU.exe
Destination=Redist\Microsoft .net\4.6.1\Full\NDP461-KB3102436-x86-x64-AllOS-ENU.exe
Size=67681000

[.Net4.6.1FrameworkWeb]
DisplayName=.Net Framework 4.6.1 Web
Source=https://download.microsoft.com/download/3/5/9/35980F81-60F4-4DE3-88FC-8F962B97253B/NDP461-KB3102438-Web.exe
Destination=Redist\Microsoft .net\4.6.1\Web\NDP461-KB3102438-Web.exe
Size=1424328

Here's what I have so far to read the INI file and dump it to the console:

Dim inStream As StreamReader
Dim webRequest As WebRequest
Dim webresponse As WebResponse
webRequest = WebRequest.Create(DlSrc.Text)
webresponse = webRequest.GetResponse()
inStream = New StreamReader(webresponse.GetResponseStream())
Console.WriteLine(inStream.ReadToEnd)

I can send the output of inStream to the console with no problems but I can't figure out how to check each block for the Source/Destination lines so I can then download and place them into the right folders. I've tried creating an array for the string but that just bounces back with an error saying it can't be converted from a string to an object.

Like I said at the top of this post, I'm really new to this and have no idea what I'm actually doing which makes most of this a lot of CopyPasta from Google. Please do me a favour and ELI5 any help you can provide because I'll likely have no idea what you're talking about.

Ray
  • 23
  • 3
  • You could regex it (something like: `(?|(Source=(.*?)$)|(Destination=(.*?)$))` maybe; you'll have `Source` in `Group(1)` and `Destination` in `Group(2)`). Or use an INI reader: [Reading/writing an INI file](https://stackoverflow.com/q/217902/7444103). Or maybe use the classic [GetPrivateProfileSection](https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getprivateprofilesectionw) / [GetPrivateProfileString](https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getprivateprofilestringw) functions. – Jimi Feb 10 '20 at 17:06
  • Maybe alternate named groups is better: `^Source=(?.+?)$|^Destination=(?.+?)$`. Btw, you probaly just need WebClient to download a file. If you use `WebRequest`, dispose of all the objects you created (especially the Stream). – Jimi Feb 10 '20 at 17:43

1 Answers1

1

There are many ways to do what you need. This is just an example to get your started. It takes you through the string manipulation. Refer to the String class in .net. https://learn.microsoft.com/en-us/dotnet/api/system.string?view=netframework-4.8

To get the location input you will want to use one of the build in DialogBoxes. See the toolbox in design mode.

To manipulate files see the File class in System.IO (needs an Imports at the top of your code file) https://learn.microsoft.com/en-us/dotnet/api/system.io.file?view=netframework-4.8

Explanation of this code.

A StreamReader exposes a .Dipose method so it should be closed and disposed so it can release unmanaged resources. A Using...End Using block takes care of this for you even if there is an error.

I had the StreamReader provide the data by lines that I added to a list. The List is passed to a method that parses each line. I created a class to hold the data. When both the source and destination are found the properties of the class are set in the class constructor and the object is added to the SrcDest List. This list is a Form level variable so you can use the objects in it anywhere is the Form.

Private Sub OPCode()
    Dim lines As New List(Of String)
    Using inStream = New StreamReader(WebResponse.GetResponseStream())
        Dim line As String
        Do
            line = inStream.ReadLine()
            lines.Add(line)
        Loop Until line Is Nothing
    End Using
    FillSourceDestinationList(lines)
End Sub

Public Class SourceDestination
    Public Property Source As String
    Public Property Destination As String

    Public Sub New(s As String, d As String)
        Source = s
        Destination = d
    End Sub
End Class

Private SrcDes As New List(Of SourceDestination)

Private Sub FillSourceDestinationList(sourceDoc As List(Of String))

    Dim sou As String = ""
    Dim des As String = ""
    For Each line In sourceDoc
        If line.StartsWith("Source=") Then
            Dim splitString = line.Split("="c)
            sou = splitString(1)
        End If
        If line.StartsWith("Destination") Then
            Dim splitString = line.Split("="c)
            des = splitString(1)
        End If
        If sou <> "" AndAlso des <> "" Then
            Dim sd As New SourceDestination(sou, des)
            SrcDes.Add(sd)
            sou = ""
            des = ""
        End If
    Next
End Sub

Private Sub UseSourceDestinationList()
    For Each item In SrcDes
        Dim source = item.Source
        Dim destination = item.Destination
        'Use these as needed
    Next
End Sub
Mary
  • 14,926
  • 3
  • 18
  • 27