2

Just laying this out there. Here is my code for downloading an application and installing it.

# File Download and Install Function
function FDL($url){
# set to the default download directory; obviously can be wherever one wants
$DL = set-location $env:USERPROFILE\downloads\
# using this to capture just the filename
$FN = $url -split("/")
$FD = $FN[$FN.Length-1]
# Download File
Start-BitsTransfer -source $url -destination $DL\$FD
# Install File
Start-Process -NoNewWindow $DL\$FD -ArgumentList $args
}

PS:> FDL "https://www.kymoto.org/downloads/ISStudio_Latest.exe"

This function works perfectly every time assuming that the URL is correct!

Then I thought, what if I were to have the functionality to place the correct arguments for the installer type. So I came up with this:

# File Download and Install Function
function FDL($url,$p){
    # set to the default download directory; obviously can be whereever one wants
    $DL = set-location $env:USERPROFILE\downloads\
    # using this to capture just the filename
    $FN = $url -split("/")
    $FD = $FN[$FN.Length-1]
    
    switch ($p){
        1 {" /passive /qb /norestart";break}
        2 {" /sp- /silent /norestart /SUPPRESSMSGBOXES /CURRENTUSERS /NORESTART /NOCANCEL /FORCECLOSEAPPLICATION /RESTARTAPPLICATIONS";break}
        3 {" /SILENT";break}
        4 {" /quiet";break}
        5 {" /S";break}
        6 {" /Q";break}
    }
    
    Start-BitsTransfer -source $url -destination $DL\$FD
    Start-Process -NoNewWindow $DL\$FD -ArgumentList $p
}

# 2 because this is an InnoSetup   installer type
PS:> FDL 'https://www.kymoto.org/downloads/ISStudio_Latest.exe', 2 

FAIL

Start-BitsTransfer : The number of items specified in the Source parameter do not match the number of items specified in the Destination parameter. Verify that the same 
number of items is specified in the Source and Destination parameters.
At [dir]\FileDownloader Function.ps1:17 char:1
+ Start-BitsTransfer -source $url -destination $DL\$FD
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Start-BitsTransfer], ArgumentException
    + FullyQualifiedErrorId : StartBitsTransferArgumentException,Microsoft.BackgroundIntelligentTransfer.Management.NewBitsTransferCommand
Start-BitsTransfer : 
At [dir]\FileDownloader Function.ps1:17 char:1
+ Start-BitsTransfer -source $url -destination $DL\$FD
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Start-BitsTransfer], Exception
    + FullyQualifiedErrorId : System.Exception,Microsoft.BackgroundIntelligentTransfer.Management.NewBitsTransferCommand
Start-Process : Cannot validate argument on parameter 'ArgumentList'. The argument is null or empty. Provide an argument that is not null or empty, and then try the 
command again.
At [dir]\FileDownloader Function.ps1:20 char:50
+ Start-Process -NoNewWindow $DL\$FD -ArgumentList ($p)
+                                                  ~~~~
    + CategoryInfo          : InvalidData: (:) [Start-Process], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.StartProcessCommand

No matter how I adjust this code it comes out with the same error. Any suggestions or assistance here will be greatly appreciated!

9
  • 3
    Each argument is separated by space in PowerShell. See about Parameters for more info Commented May 28, 2022 at 3:10
  • 3
    Also, you don't store and use the selection of your $p switch anywhere. You use $p as your argument list but this does not contain what you think it does. Commented May 28, 2022 at 3:13
  • Thank you both. Examples would be helpful as I have only been working with Powershell for about 3 months and I am not incredibly versed. The about Parameters seems to be referencing something related to the syntax but I am not sure which part of my code you are referencing. @Daniel I have attempted to, at your suggestion, to store this info using $myswitch=switch($p)... so on and so forth but it is coming up with the same error. Commented May 28, 2022 at 3:28
  • Good. Did you also update -ArgumentList $myswitch ? Commented May 28, 2022 at 3:32
  • 1
    Ok, also what Santiago was saying is when calling functions in powershell we don't use commas to separate arguments. Remove the comma before the 2 ps:>FDL 'https://www.kymoto.org/downloads/ISStudio_Latest.exe' 2 Commented May 28, 2022 at 3:54

1 Answer 1

4

Might not be exactly what you're looking for but it should give you a hint as to approach the code for a function in PowerShell.

A few pointers, parameters in PowerShell are either Positional or Named, about_Parameters explains both concepts. Most importantly, each argument is separated by a space and not by a comma.

You can parse an URL using the Uri Class, so, for getting the file name from your address, is as simple as:

# Last segment from this Uri (index -1 from the segment array)
([uri] 'https://www.kymoto.org/downloads/ISStudio_Latest.exe').Segments[-1]

-ArgumentList from Start-Process expects string[], you can pass an array of arguments instead of a single string as shown in Example 7.

You're never capturing the output from your switch ($p), which explains the error:

Start-Process : Cannot validate argument on parameter 'ArgumentList'. The argument is null or empty.

A hash table can be used instead of a switch.

Lastly, I have added a -PassThru switch, now if you call the function with the switch activated (DownloadFile -PassThru -Uri ...), the function will output the Process instance representing the started process.

function DownloadFile {
    [cmdletbinding()]
    param(
        [parameter(Mandatory)]
        [uri] $Uri,

        [parameter()]
        [ValidateSet(1,2,3,4,5,6)]
        [int] $Arguments,

        [parameter()]
        [string] $Destination = "$env:USERPROFILE\Downloads",

        [parameter()]
        [switch] $PassThru
    )

    $arg = @{
        1 = '/passive', '/qb', '/norestart'
        2 = @(
            '/sp-', '/silent', '/norestart', '/SUPPRESSMSGBOXES'
            '/CURRENTUSERS', '/NORESTART', '/NOCANCEL'
            '/FORCECLOSEAPPLICATION', '/RESTARTAPPLICATIONS'
        )
        3 = '/SILENT'
        4 = '/quiet'
        5 = '/S'
        6 = '/Q'
    }

    $destFile = Join-Path $Destination -ChildPath $Uri.Segments[-1]
    Start-BitsTransfer -Source $Uri -Destination $destFile
    $param = @{
        FilePath     = $destFile
        ArgumentList = $arg[$Arguments]
        NoNewWindow  = $true
        PassThru     = $PassThru.IsPresent
    }
    Start-Process @param
}

DownloadFile -Uri 'https://www.kymoto.org/downloads/ISStudio_Latest.exe' -Arguments 2
Sign up to request clarification or add additional context in comments.

1 Comment

This did it. Sorry for the delay; life happened. Now, I just need to figure out how to merge StackOverflow profiles as I seem to have 2. ¯_(ツ)_/¯

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.