Using Invoke-WebRequest to Read a File

An interesting problem came up recently where we needed to standardize the creation of VPNs on new user laptops. To do that, I knew I needed to use the Add-VPNConnection cmdlet (more on that in a another post, soon.) But in order to populate the parameters of Add-VPNConnection, I needed to store the values somewhere. The easy answer was on my desktop, but that's not terribly portable, especially since I routinely work on any of 3 or 4 different computers. The answer was to store the parameters in a file on my OneDrive for Business (ODB) site, and suck the contents of the file down to whatever machine I happened to be on with Invoke-WebRequest. The file needed to be a CSV file with three fields for each VPN--Name, IP Address, and the L2TP Pre-Shared Key. Easy enough, I know how to parse a CSV file. (If you want a useful example, see Importing Users into Active Directory). But first, I have to get the contents of that CSV file. The answer was a cmdlet I hadn't had occasion to use before -- Invoke-WebRequest. To make this work, you'll need a link to the document in your OneDrive for Business site. (This will work identically with consumer OneDrive, but since these are business assets, they belong in ODB.) That link will look something like: your code here

To download the file with Invoke-WebRequest, and save it to a file on your local hard drive, use:

Invoke-WebRequest -Uri '' -Credential (Get-Credential) -Outfile 'C:\Temp\Content.txt'

That's one ugly long command line, but mostly that's because ODB creates seriously long links to documents! However, it's really pretty simple -- only 3 parameters: The link to the document (-Uri), a Credential parameter, and the location to save the content to (-OutFile).

An important caveat here -- by using -OutFile, we've forced Invoke-WebRequest to just give us the content of the file. But if you're running this in a script where you're not saving to a file, but want to use it directly with ConvertFrom-CSV, for example, you need to access the Content property ToString method of the file. So, you might have something like this:

$BaseURI = ''
$DocID = '123456789abcdef0123456789abcdef01'
$authKey = 'ABcDEFGH01IJkl2MnopQRSt'
$FullUri = $BaseURI + "DocID=$DocID" + "&AuthKey=$authKey"
# $VPNParams = ConvertFrom-CSV (Invoke-WebRequest -Uri $FullUri -Credential $cred).Content
$VPNParams = ConvertFrom-CSV (Invoke-WebRequest -Uri $FullUri -Credential $Cred).ToString()

(Thanks to Ricardo Heredero for the initial suggestion!)


ETA: It appears Microsoft, in their infinite wisdom, have changed the link format for OneDrive for Business links. You'll want to adjust accordingly, of course. Sigh.

ETA2: OK, so there's a bug in this! If you use the .Content property, it gives you the byte string. NOT what you want. The cleanest solution is to use the ToString method. This means you need:

$VPNParams = ConvertFrom-CSV (Invoke-WebRequest -Uri $FullUri -Credential $Cred).ToString()

Sorry about that!