Powershell ftp download failed - exception

I'm having issues downloading files from an ftp in powershell, this script tries to setup the connection, search for some files (I got this part right) and then download it in the working directory, I got issues don't know why, please help!!
Here's the code:
#IP address of DNS of the target % protocol
$protocol="ftp"
$target = "XXXX"
$connectionString = $protocol+"://"+$target
#Method to connect
$Request = [System.Net.WebRequest]::Create($connectionString)
$Request.Method = [System.Net.WebRequestMethods+Ftp]::ListDirectoryDetails
# Set Credentials "username",password
$username = "XXXXXXX"
$password = "XXXXXX"
# Read Username/password
$Request.Credentials = New-Object System.Net.NetworkCredential $username,$password
$Response = $Request.GetResponse()
$ResponseStream = $Response.GetResponseStream()
# Select Pattern to search
$pattern = "CCS"
# Set directory for download Files
$directory = [IO.Directory]::GetCurrentDirectory()
# Read and display the text in the file
$Reader = new-object System.Io.StreamReader $Responsestream
$files = ($Reader.ReadToEnd()) -split "`n" | Select-String "$pattern" | foreach { $_.ToString().split(” “)[28]}
$uri = (New-Object System.Uri($connectionString+"/"+$file))
$download = New-Object System.Net.WebRequestMethods+Ftp
foreach ($file in $files) {
$destinationFile = $directory+"\"+$file
$sourceFile = $uri.OriginalString
$download.DownloadFile($sourceFile, $destinationFile)
}
# Close Reader and Response objects
$Reader.Close()
$Response.Close()
When I run it I got this output:
Exception calling "DownloadFile" with "2" argument(s): "An exception occurred during a WebClient request."
At C:\CRIF\BatchScripts\FTPCHECK\01.FTP_Check.ps1:44 char:5
+ $download.DownloadFile($sourceFile, $destinationFile)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : WebException
I'm running this on Powershell 3.0 (Windows Server 2012). Please help!

Details about the problem are hidden in the inner exception of this generic exception. You should dig a bit deeper in the error to find out what the real problem is.
Since PowerShell errors are stores into $error you could, immediatly after getting the error, try the following command to check out the inner exception of the last error
$error[0].Exception.InnerException
To get the most out of error messages you could use functions people wrote like Resolve-Error.
If you want your script in this case to always display a better error message, you could use a try catch block to catch the error and display it better. Something like this:
try {
$download.DownloadFile($sourceFile, $destinationFile)
}
catch [System.Net.WebException] {
if ($_.Exception.InnerException) {
Write-Error $_.Exception.InnerException.Message
} else {
Write-Error $_.Exception.Message
}
}

Related

Powershell REST request wont return server response if 404

I am still new to Powershell and haven't been able to find anything on this. I am running a REST GET request to a URI which I know for a fact returns a 404 from the server since the resource is not found.
I would like to be able to run a conditional that checks if it's a 404 and skip over it for further processing if this is the case however when I assign the request to a variable, then calling on that later, it just gives me the contents of what my request was. I have never seen anything like this before in other languages...
My basic premise is the following. I first fetch all group names, then loop through that array of names, include the current one in a new URL and make an additional request for that specific group which looks for a SHIFT which will always have the same name. If the group doesn't have that shift by name I want to skip to the next group, otherwise alter some attributes of that newly found shift object.
Here is what my code looks like, as you can see it's not acting correctly
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$user = '******'
$pass = ConvertTo-SecureString '*******' -AsPlainText -Force
$cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $user, $pass
$req = Invoke-WebRequest -Credential $cred -Uri https://********-np.xmatters.com/api/xm/1/groups
$res = ConvertFrom-Json $req.Content
$content = $res.data
$base = "https://********-np.xmatters.com/api/xm/1/groups"
$group_name = $content[0].targetName
$path = "$base/$group_name/shifts/MAX-Default Shift"
$shift = Invoke-RestMethod -Credential $cred -Uri $path
Write-Host '-----------------------'
Write-Host $shift
Write-Host '-----------------------'
... RESPONSE BELOW ....
Invoke-RestMethod : The remote server returned an error: (404) Not Found.
At \\MMFILE\********$\MyDocuments\Group Supers PReliminary.ps1:16 char:10
+ $shift = Invoke-RestMethod -Credential $cred -Uri $path
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
-----------------------
#{id=***********; group=; name=MAX-Default Shift; description="; start=2018-08-21T04:00:00.000Z; end=2018-08-22T04:00:00.000Z; timezone=America/New_York; recurrence=;
links=}
-----------------------
PS C:\WINDOWS\system32>
What I would like to do is something like, in shorthand code, if $shift.code == 404 ... skip ... else ... run additional query
You need to use a try ... catch.
$code = ""
try{
$shift = Invoke-RestMethod -Credential $cred -Uri $path
}
catch{
$code = $_.Exception.Response.StatusCode.value__
}
if($code -eq "404")
{
continue
# Other things
}
else
{
Write-Host '-----------------------'
Write-Host $shift
Write-Host '-----------------------'
}
You could suppress the error message via Try..Catch and in so doing allow the script to continue:
Try {
$Shift = Invoke-RestMethod http://www.google.com/fakeurl -ErrorAction Stop
#Do other things here if the URL exists..
} Catch {
if ($_.Exception -eq 'The remote server returned an error: (404) Not Found.') {
#Do other things here that you want to happen if the URL does not exist..
}
}
Note this will hide all terminating errors from Invoke-ResetMethod. You could then use an if statement to see if the exception was a 404 and then perform further actions accordingly.

Uploading a CSV File to MySQL Server

I am using a PowerShell script to upload a CSV file to my database. The end goal is to download the most recent CSV file uploaded to our FTP (which I have completed), and then upload this CSV file to our database. These CSV files are always in the same format, and I have created the database to match this format.
I am using a script I found online as a sort of outline to help me, however it still doesn't seem to be working. Below is the script and I am hoping someone can help me figure out either a better way to complete this objective, or what I am doing wrong.
# Database variables
$sqlserver = "****"
$database = "****"
$table = "****"
$user = "****"
$pass = "****!"
# CSV variables
$csvfile = "C:\Users\Lucy\Documents\FTPFiles\vc_report_20171211.csv"
$csvdelimiter = ","
$FirstRowColumnNames = $true
################### No need to modify anything below ###################
Write-Host "Script started..."
$elapsed = [System.Diagnostics.Stopwatch]::StartNew()
[void][Reflection.Assembly]::LoadWithPartialName("System.Data")
[void][Reflection.Assembly]::LoadWithPartialName("System.Data.SqlClient")
# 50k worked fastest and kept memory usage to a minimum
$batchsize = 50000
# Build the sqlbulkcopy connection, and set the timeout to infinite
$connectionstring = "Data Source=$sqlserver;User Id=$user;Password=$pass;Initial Catalog=$database;"
$bulkcopy = New-Object Data.SqlClient.SqlBulkCopy($connectionstring, [System.Data.SqlClient.SqlBulkCopyOptions]::TableLock)
$bulkcopy.DestinationTableName = $table
$bulkcopy.bulkcopyTimeout = 0
$bulkcopy.batchsize = $batchsize
# Create the datatable, and autogenerate the columns.
$datatable = New-Object System.Data.DataTable
# Open the text file from disk
$reader = New-Object System.IO.StreamReader($csvfile)
$columns = (Get-Content $csvfile -First 1).Split($csvdelimiter)
if ($FirstRowColumnNames -eq $true) { $null = $reader.readLine() }
foreach ($column in $columns) {
$null = $datatable.Columns.Add()
}
# Read in the data, line by line, not column by column
while (($line = $reader.ReadLine()) -ne $null) {
$null = $datatable.Rows.Add($line.Split($csvdelimiter))
# Import and empty the datatable before it starts taking up too much RAM, but
# after it has enough rows to make the import efficient.
$i++;
if (($i % $batchsize) -eq 0) {
$bulkcopy.WriteToServer($datatable)
Write-Host "$i rows have been inserted in $($elapsed.Elapsed.ToString())."
$datatable.Clear()
}
}
# Add in all the remaining rows since the last clear
if ($datatable.Rows.Count -gt 0) {
$bulkcopy.WriteToServer($datatable)
$datatable.Clear()
}
# Clean Up
$reader.Close(); $reader.Dispose()
$bulkcopy.Close(); $bulkcopy.Dispose()
$datatable.Dispose()
Write-Host "Script complete. $i rows have been inserted into the database."
Write-Host "Total Elapsed Time: $($elapsed.Elapsed.ToString())"
$i = 0;
# Sometimes the Garbage Collector takes too long to clear the huge datatable.
[System.GC]::Collect()
Our database is hosted by SiteGround so I need to connect to the database. At first I was getting the following error:
Exception calling "WriteToServer" with "1" argument(s): "A network-related or
instance-specific error occurred while establishing a connection to SQL Server.
The server was not found or was not accessible. Verify that the instance name is
correct and that SQL Server is configured to allow remote connections. (provider:
Named Pipes Provider, error: 40 - Could not open a connection to SQL Server)"
At C:\Users\Lucy\Documents\FTPFiles\upload.ps1:61 char:5
+ $bulkcopy.WriteToServer($datatable)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : SqlException
Then I added the port 3306, to the end of the $sqlserver = "servername,3306". When I did the I new get the error:
Exception calling "WriteToServer" with "1" argument(s): "A network-related or
instance-specific error occurred while establishing a connection to SQL Server.
The server was not found or was not accessible. Verify that the instance name is
correct and that SQL Server is configured to allow remote connections. (provider:
Named Pipes Provider, error: 40 - Could not open a connection to SQL Server)"
At C:\Users\Lucy\Documents\FTPFiles\upload.ps1:63 char:5
+ $bulkcopy.WriteToServer($datatable)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : SqlException

Resolve DNS, export to Excel and HTML, then send mail

I was almost done with my script and did some late night editing and written over my old version so I cannot go back.
The script was running fine, still needed some tweaks but now it ha come to a complete halt.
The idea is to GC a list of IP's. Resolve the IP's and place them in an excel sheet. Then save the sheet to htm and xlsx. And finally mailing those to me.
Now it gets stuck on sorting the sheet, saving AND mailing...
Can someone give me some insight on what I did wrong here?
it gets stuck on sorting the sheet, saving AND mailing.
It no longer sorts B3:B$Count:
Exception calling "Sort" with "1" argument(s): "The sort reference is not valid. Make sure that it's within the data you want to sort, and the first Sort By box isn't the same or blank."
At C:\Folder\Scripts\Get-IP.ps1:137 char:5
+ [void] $objRange.Sort($objRange2)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation
It no longer saves the xlsx file, but does save the HTM file. It is clearly not overwriting something. I even restarted to make sure.
Exception calling "SaveAs" with "1" argument(s): "Microsoft Excel cannot access the file 'C://Folder/BlockedIP/HTML/2014-07-08/0BCEF810'. workbook."
At C:\Folder\Scripts\Get-IP.ps1:160 char:5
+ $b.SaveAs("$FileXML")
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation
And finally, it will no longer send me e-mails:
New-Object : Exception calling ".ctor" with "2" argument(s): "The specified string is not in the form required for an e-mail address."
At C:\Folder\Scripts\Get-IP.ps1:217 char:13
+ $SMTP = New-Object System.Net.Mail.MailMessage($SMTP, 587)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [New-Object], MethodInvocationException
+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand
The script:
#Get current date
$Date = get-date -format yyyy-MM-dd
#Define all files/Paths.
$Path = "C:/Folder/BlockedIP"
md "$Path/HTML/$Date" -Force
$path2 = "$Path/HTML/$Date"
$PathWeb = "/HTML/$Date"
#Define File's used or created in this script.
$File = "$Path/IP-$Date.txt"
$FileHtml = "$Path2/IP-$Date.htm"
$FileXML = "$Path2/IP-$Date.xlsx"
$FileHTMLWeb = "$PathWeb/IP-$date.htm"
#Get content from given IP list.
$colComputers = #(get-content $File | Sort -unique)
$count = $colComputers.Count
write-output "$Count IP's detected."
#Define error actions.
#$erroractionpreference = "SilentlyContinue"
#Open Excel.
$a = New-Object -comobject Excel.Application
#Since we want this script to look like it's being used without excel I set it's visibility to false.
$a.visible = $True
#Disable excel confirmations.
$a.DisplayAlerts = $False
#Create sheets in Excel.
$b = $a.Workbooks.Add()
$c = $b.Worksheets.Item(1)
#Create a Title for the first worksheet and adjust the font
$row = 1
$Column = 1
target="_parent">Creator'
$c.Cells.Item($row,$column)= "Blocked IP's $Date"
$c.Cells.Item($row,$column).Font.Size = 18
$c.Cells.Item($row,$column).Font.Bold=$True
$c.Cells.Item($row,$column).Font.Name = "Cambria"
$c.Cells.Item($row,$column).Font.ThemeFont = 1
$c.Cells.Item($row,$column).Font.ThemeColor = 4
$c.Cells.Item($row,$column).Font.ColorIndex = 55
$c.Cells.Item($row,$column).Font.Color = 8210719
$range = $c.Range("a1","e1")
$range.Merge() | Out-Null
$range.VerticalAlignment = -4160
#Define subjects.
$c.Name = "Blocked IP's ($Date)"
$c.Cells.Item(2,1) = "Given IP"
$c.Cells.Item(2,2) = "Resolved DNS"
$c.Cells.Item(2,3) = "Returned IP"
$c.Cells.Item(2,5) = "Company name"
#Define cell formatting from subjects.
$c.Range("A2:E2").Interior.ColorIndex = 6
$c.Range("A2:E2").font.size = 13
$c.Range("A2:E2").Font.ColorIndex = 1
$c.Range("A2:E2").Font.Bold = $True
#Define the usedrange for autofitting.
$d = $c.UsedRange
#Make everything fit in it's cell
$D.EntireColumn.AutoFit() | Out-Null
#Define html code for Excel save to .htm.
$xlExcelHTML = 44
#Define rows to alter in excel.
$iRow = 3
$intRow = 3
#Time to run the script.
foreach ($strComputer in $colComputers)
{
#Place IP's from text in the excel sheet
$c.Cells.Item($intRow, 1) = $strComputer.ToUpper()
$d.EntireColumn.AutoFit() | Out-Null
#Create a status bar for the script
$i = 1
Write-Progress -Activity `
"Creating a usable 'Blocked IP' list ($i/$count)" `
-PercentComplete ($i/$colComputers.Count*100) `
-Status "Please stand by"
try {
$dnsresult = [System.Net.DNS]::GetHostEntry($strComputer)
}
catch {
$dnsresult = "$null"
}
#Clear screen on every checked IP to remove the 'True' statement.
#cls
#Do something with $dnsresults.
#Display information about host
#Give hostname Entry in Cell2
$c.Cells.Item($intRow,2) = $dnsresult.HostName
#IP listed in Cell 3
$c.Cells.Item($intRow,3) = $dnsresult.AddressList[0].IpAddressToString
#Make everything fit in it's cell.
$d.EntireColumn.AutoFit() | Out-Null
#Define row for the IP list.
$intRow = $intRow + 1
#Set background color for the IP list.
$d.Range("A$($iRow):E$($intRow)").interior.colorindex = 15
#Sort all IP's on resolved name.
$objWorksheet = $b.Worksheets.Item(1)
$objRange = $objWorksheet.UsedRange
$objRange2 = $objworksheet.Range("B3:B($Count)")
[void] $objRange.Sort($objRange2)
#Define borders here.
<# Insert script :D #>
#Define Filters here. (Picking out blank DNS and giving those a name)
<# Insert script :D #>
#Define Filters here. (Picking out specific DNS name and give them color code)
<# Insert script :D #>
#Make everything fit in it's cell.
$d.EntireColumn.AutoFit() | Out-Null
#Clear screen on every checked IP to remove the 'True' statement.
#cls
}
#Save the file as .xlsx on every placed IP to ensure the file is not lost due to any reason.
$b.SaveAs("$FileXML")
#Save final result as a .htm file
$b.SaveAs("$FileHTML",$xlExcelHTML)
#Close and quit Excel.
$b.Close()
get-process *Excel* | Stop-Process -force
#Move .txt file to the correct HTML folder.
move-item $file $path2 -Force
#Clear screen, again. (Let's keep things tidy.)
#cls
#Variables for public IP
# I am defining website url in a variable
$url = "http://checkip.dyndns.com"
# Creating a new .Net Object names a System.Net.Webclient
$webclient = New-Object System.Net.WebClient
# In this new webdownlader object we are telling $webclient to download the
# url $url
$IpPublic = $webclient.DownloadString($url)
# Just a simple text manuplation to get the ipadress form downloaded URL
# If you want to know what it contain try to see the variable $IpPublic
$IpPublic2 = $IpPublic.ToString()
$ipPublic3 = $IpPublic2.Split(" ")
$ipPublic4 = $ipPublic3[5]
$ipPublic5 = $ipPublic4.replace("</body>","")
$FinalIPAddress = $ipPublic5.replace("</html>","")
#Variables e-mail.
$From = "Blocked IP <###g##.com>"
$To = "IT Dept <#####.nl>"
$CC = "Someone <##r###.nl"
$SMTP = "smtp.gmail.com"
$Subject = "Blocked IPs for $date ($Count Total)"
#The href should point to the htm file in your iis/apache folder.
$WebLink = $FinalIPAddress+$FileHtmlWeb
$here = "<a href='http://$Weblink'><b>Here</b></a>"
#Define the body of your e-mail, in this case it displays a message and shows the server it is send from with it's local IP.
#A link to the .htm file, how many IP's were blocked and the date of the message.
$Body = "This is an automated message generated by server: $env:COMPUTERNAME, $IP</br></br>
Please see the attachment or click $here to get the $Count blocked IP's of $date. </br> </br></br>"
#Variables e-mail user.
$username = "#####.com"
$password = "##"
$secstr = New-Object -TypeName System.Security.SecureString
$password.ToCharArray() | ForEach-Object {$secstr.AppendChar($_)}
$Cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $secstr
$ip = (Get-WmiObject -class win32_NetworkAdapterConfiguration -Filter 'ipenabled = "true"').ipaddress[0]
#Clear screen, again. (Let's keep things tidy.)
#cls
#Send output as e-mail.
$SMTP = New-Object System.Net.Mail.MailMessage($SMTP, 587)
$SMTP.EnableSsl = $true
$SMTP.Credentials = New-Object System.Net.NetworkCredential("$username", "$password");
$SMTP.isbodyhtml= $true
$SMTP.Send($From, $To, $Subject, $FileXML, $Body)
send-mailmessage -BodyAsHtml -from $From -to $To -cc $CC -subject $Subject -Attachments $FileXML -body $Body -priority High -smtpServer $SMTP -credential ($cred) -usessl
#Create a function to relase Com object at end of script.
function Release-Ref ($ref) {
([System.Runtime.InteropServices.Marshal]::ReleaseComObject(
[System.__ComObject]$ref) -gt 0)
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
}
#Release COM Object
[System.Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$a) | Out-Null
#Clear screen for the final time. (Let's keep things tidy.)
#cls
#Exit powershell
exit
Any help will be greatly appreciated!
Exception calling "Sort" with "1" argument(s): "The sort reference is not valid. Make sure that it's within the data you want to sort, and the first Sort By box isn't the same or blank."
Double-check that $objRange and $objRange2 reference the correct ranges:
$objRange.Address()
$objRange2.Address()
Not much else I can tell you here without seeing your actual data.
Exception calling "SaveAs" with "1" argument(s): "Microsoft Excel cannot access the file 'C://Folder/BlockedIP/HTML/2014-07-08/0BCEF810'. workbook."
If the path really were C://Folder/... you'd be getting a different exception. Please do not fabricate error messages.
New-Object : Exception calling ".ctor" with "2" argument(s): "The specified string is not in the form required for an e-mail address."
You're confusing MailMessage and SmtpClient class. Not to mention that you don't even need either of them, since you're using Send-MailMessage anyway. Just remove the following 5 lines:
$SMTP = New-Object System.Net.Mail.MailMessage($SMTP, 587)
$SMTP.EnableSsl = $true
$SMTP.Credentials = New-Object System.Net.NetworkCredential("$username", "$password");
$SMTP.isbodyhtml= $true
$SMTP.Send($From, $To, $Subject, $FileXML, $Body)
Solved the sorting problem by altering the code to:
$objRange = $c.Range("A$($iRow):E$($intRow)")
$objRange2 = $c.Range("B$($iRow):B$($intRow)")
[void] $objRange.Sort($objRange2)
Turns out it got stuck on the header in the xml file
Replaced mailing with:
$From = "Blocked IP <#####.##>"
$To = "IT Dept <#####.##>"
$CC = "Someone <#####.##"
$Subject = "Blocked IPs for $date ($Count Total)"
#The href should point to the htm file in your iis/apache folder.
$WebLink = $FinalIPAddress+$FileHtmlWeb
$here = "<a href='http://$Weblink'><b>Here</b></a>"
#Define the body of your e-mail, in this case it displays a message and shows the server it is send from with it's local IP.
#A link to the .htm file, how many IP's were blocked and the date of the message.
$body = "Dear <font color=black>$to</font>,<br><br>"
$SMTPServer = "smtp.gmail.com"
$SMTPPort = "587"
$Username = "###gmail.com"
$Password = "##"
$message = New-Object System.Net.Mail.MailMessage
$message.IsBodyHTML = $true
$message.ReplyTo = $From
$message.Sender = $From
$message.subject = $subject
$message.body = $body
$message.to.add($to)
$message.from = $username
$message.attachments.add($MailXML)
$smtp = New-Object System.Net.Mail.SmtpClient($SMTPServer, $SMTPPort);
$smtp.EnableSSL = $true
$smtp.Credentials = New-Object System.Net.NetworkCredential($Username, $Password);
$smtp.send($message)
The saving of the file turned out to be a misguided path.
Since the excel sheet was created from folder1 it wouldnt save instandly to folder 2 since its temp save file would remain in folder1.

Cannot convert value of type "Microsoft.SqlServer.Management.Smo.Server" to type "Microsoft.SqlServer.Management.Smo.Server"

I'm trying to use SMO to restore a database via Powershell, however when I try to define and use a server object it gives me the following error:
Cannot convert argument "srv", with value: "[MJNHNX4]", for "SqlRestore" to type "Microsoft.SqlServer.Management.Smo.Server": "Cannot convert the "[MJNHNX4]" value of type
"Microsoft.SqlServer.Management.Smo.Server" to type "Microsoft.SqlServer.Management.Smo.Server"."
At line:38 char:1
+ $smoRestore.SqlRestore($server)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument
Here is my code in full (there's not a lot to it):
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoExtended") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.ConnectionInfo") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoEnum") | Out-Null
#clear screen
cls
#get backup file
$backupFile = "D:\databases\Perfmon.bak"
$servername = "MJNHNX4"
$server = New-Object Microsoft.SqlServer.Management.Smo.Server($servername)
$backupDevice = New-Object ("Microsoft.SqlServer.Management.Smo.BackupDeviceItem") ($backupFile, "File")
$smoRestore = new-object("Microsoft.SqlServer.Management.Smo.Restore")
#settings for restore
$smoRestore.NoRecovery = $false;
$smoRestore.ReplaceDatabase = $true;
$smoRestore.Action = "Database"
#show every 10% progress
$smoRestore.PercentCompleteNotification = 10;
$smoRestore.Devices.Add($backupDevice)
#read db name from the backup file's backup header
$smoRestoreDetails = $smoRestore.ReadBackupHeader($server)
#display database name
"Database Name from Backup Header : " + $smoRestoreDetails.Rows[0]["DatabaseName"]
$smoRestore.Database = $smoRestoreDetails.Rows[0]["DatabaseName"]
#restore
$smoRestore.SqlRestore($server)
"Done"
The error occurs regardless of what I try to pass to Microsoft.SqlServer.Management.Smo.Server and I'm really not sure why it would be giving me that particular error. I've read through the TechNet articles on the Server Constructor and I really have no idea what's going on there. Any ideas?
After some further testing and reading about the SMO syntax, it looks like I don't need to define the $server as a new object. Instead, just passing the name of the server to $server works fine.

Powershell download file not working properly

I am trying to write a powershell script that will set a download directory variable based on the current directory, and download a file to that directory.
The code I have is:
cd downloads
$DevDownloadDirectory = [IO.Directory]::GetCurrentDirectory
$clnt = New-Object System.Net.WebClient
# download and extract the file
$url = “fileurl/file.zip"
$file = "$DevDownloadDirectory\file.zip"
$clnt.DownloadFile($url,$file)
The problem I get is whenever I get to this part of the code it pumps out:
Exception calling "DownloadFile" with "2" argument(s): "An exception
occurred during a WebClient request." At C:\directory\script.ps1:462
char:20
$clnt.DownloadFile <<<< ($url,$file)
CategoryInfo : NotSpecified: (:) [], MethodInvocationException
FullyQualifiedErrorId : DotNetMethodException
Could anyone please help me figure out why this is happening?
$DevDownloadDirectory = [IO.Directory]::GetCurrentDirectory
Should be
$DevDownloadDirectory = [IO.Directory]::GetCurrentDirectory()
GetCurrentDirectory() is a Method and if you dont use the "()", it will just return the same name but not the current directory.
#Dowload File
function Download-File-Func($url, $targetFile)
{
"Downloading $url"
$uri = New-Object "System.Uri" "$url"
$request = [System.Net.HttpWebRequest]::Create($uri)
$request.set_Timeout(600000) #10 minutes
$response = $request.GetResponse()
$totalLength = [System.Math]::Floor($response.get_ContentLength()/1024)
$responseStream = $response.GetResponseStream()
$targetStream = New-Object -TypeName System.IO.FileStream -ArgumentList $targetFile, Create
$buffer = new-object byte[] 10KB
$count = $responseStream.Read($buffer,0,$buffer.length)
$downloadedBytes = $count
while ($count -gt 0)
{
[System.Console]::CursorLeft = 0
[System.Console]::Write("Downloaded {0}K of {1}K", [System.Math]::Floor($downloadedBytes/1024), $totalLength)
$targetStream.Write($buffer, 0, $count)
$count = $responseStream.Read($buffer,0,$buffer.length)
$downloadedBytes = $downloadedBytes + $count
}
"Finished Download"
$targetStream.Flush()
$targetStream.Close()
$targetStream.Dispose()
$responseStream.Dispose()
}