PowerShell 3 Parameters - powershell

Hi Basically i'm having an issue i need to load Arguments in to the following code located at the $URL & $Output but i need it to work with the Join-Path but every time i try it kicks back a load of errors i'm new to this so i am trying everything to get it working I've been asked to do this by my boss completely out my depth but never been one to shy away from a challenge
Function DownloadFileFromURL
{
Add-Type -AssemblyName Microsoft.Visualbasic
#$url = 'http://download.microsoft.com/download/F/4/2/F42AB12D-C935-4E65-9D98-4E56F9ACBC8E/wpilauncher.exe'
$url = $args[0]
$filename = Split-Path -leaf $url
$output = Join-Path $args1 + $filename
$response = [System.Net.WebRequest]::Create($url).GetResponse()
$realurl = $response.ResponseUri.OriginalString
$response.Close()
(New-Object Net.WebClient).DownloadFile($url, $output)
#################Time Taken To Download Files######################
$start_time = Get-Date
Write-Output "Time taken: $((Get-Date).Subtract($start_time).Seconds) second(s)"
}
DownloadFileFromURL ('http://download.microsoft.com/download/F/4/2/F42AB12D-C935-4E65-9D98-4E56F9ACBC8E/wpilauncher.exe','C:\Users\Martin.beardmore\Downloads\test')
Errors being Recieved
Join-Path : Cannot bind argument to parameter 'Path' because it is null.
At C:\Users\Martin.beardmore\Documents\Query download.ps1:6 char:21
+ $output = Join-Path $args[1] + $filename
+ ~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Join-Path], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.JoinPathCommand
Cannot convert argument "requestUri", with value: "System.Object[]", for "Create" to type "System.Uri": "Cannot convert the "System.Object[]" value of type "System.Object[]" to type
"System.Uri"."
At C:\Users\Martin.beardmore\Documents\Query download.ps1:7 char:1
+ $response = [System.Net.WebRequest]::Create($url).GetResponse()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument
You cannot call a method on a null-valued expression.
At C:\Users\Martin.beardmore\Documents\Query download.ps1:9 char:1
+ $response.Close()
+ ~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Cannot convert argument "address", with value: "System.Object[]", for "DownloadFile" to type "System.Uri": "Cannot convert the "System.Object[]" value of type "System.Object[]" to type
"System.Uri"."
At C:\Users\Martin.beardmore\Documents\Query download.ps1:10 char:1
+ (New-Object Net.WebClient).DownloadFile($url, $output)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument

You need to remove the + between the paths you want to join. Look at the syntax for Join-Path.
PS> Get-Command Join-Path -Syntax
Join-Path [-Path] <string[]> [-ChildPath] <string> [-Resolve] [-Credential <pscredential>] [-UseTransaction] [<CommonParameters>]
You should use it like $output = Join-Path $args1 $filename
Also, where does $args1 come from? In functions, you should name your parameters. The order in which you define them will be the order they are binded to, so they will still behave the same as arguments, but they are easier to work with.
Function DownloadFileFromURL ($url, $folder)
{
Write-Host "URL: $url"
Write-Host "Folder: $folder"
}
Sample:
PS > DownloadFileFromURL stackoverflow.com c:\folder
URL: stackoverflow.com
Folder: c:\folder
You are also calling the function wrong. Comma is used to seperate objects in an array, so DownloadFileFromURL ('http://download.microsoft.com/download/F/4/2/F42AB12D-C935-4E65-9D98-4E56F9ACBC8E/wpilauncher.exe','C:\Users\Martin.beardmore\Downloads\test') results in:
$url = $args[0] = #('http://download.microsoft.com/download/F/4/2/F42AB12D-C935-4E65-9D98-4E56F9ACBC8E/wpilauncher.exe','C:\Users\Martin.beardmore\Downloads\test')
Modify your function to use parameters and call it like I've as shown above and it should work.
Updated script:
Function DownloadFileFromURL ($url, $destination)
{
Add-Type -AssemblyName Microsoft.Visualbasic
$filename = Split-Path -Leaf $url
$output = Join-Path $destination $filename
$response = [System.Net.WebRequest]::Create($url).GetResponse()
$realurl = $response.ResponseUri.OriginalString
$response.Close()
(New-Object Net.WebClient).DownloadFile($url, $output)
#################Time Taken To Download Files######################
$start_time = Get-Date
Write-Output "Time taken: $((Get-Date).Subtract($start_time).Seconds) second(s)"
}
DownloadFileFromURL 'http://download.microsoft.com/download/F/4/2/F42AB12D-C935-4E65-9D98-4E56F9ACBC8E/wpilauncher.exe' 'C:\Users\Martin.beardmore\Downloads\test'
#or even better
#DownloadFileFromURL -url 'http://download.microsoft.com/download/F/4/2/F42AB12D-C935-4E65-9D98-4E56F9ACBC8E/wpilauncher.exe' -destination 'C:\Users\Martin.beardmore\Downloads\test'

Related

Unable to create SharePoint online list items using Power shell

I want to add list items inside a SharePoint online list, so i run this command:-
$SiteUrl = "https://***.sharepoint.com/sites/t"
$ListName= "Child2"
Connect-PnPOnline -Url $SiteUrl -UseWebLogin
$Ctx = Get-PnPContext
#Get the list Item
$List=$Ctx.Web.Lists.GetByTitle($ListName)
$Import = Import-Csv -Path "C:\CSV\finaldelta3.csv"
for ($counter=0; $counter -lt $Import.Length; $counter++){
$ListItemInfo = New-Object Microsoft.SharePoint.Client.ListItemCreationInformation
$ListItem = $List.AddItem($ListItemInfo)
#Set Column Values
$ListItem["Title"] = "Hello World!"
#Apply changes to list
$ListItem.Update()
$Ctx.ExecuteQuery()
}
now on one tenant, i will not get any error, but the list item will not get created, while on another tenant i got this exception and also the item will not get created as well:-
Cannot convert argument "parameters", with value:
"Microsoft.SharePoint.Client.ListItemCreationInformation", for
"AddItem" to type
"Microsoft.SharePoint.Client.ListItemCreationInformation": "Cannot
convert the "Microsoft.SharePoint.Client.ListItemCreationInformation"
value of type
"Microsoft.SharePoint.Client.ListItemCreationInformation" to type
"Microsoft.SharePoint.Client.ListItemCreationInformation"." At line:4
char:1 + $ListItem = $List.AddItem($ListItemInfo) +
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument
Cannot index into a null array. At line:7 char:1 + $ListItem["Title"] = "Hello World!"#$Import[$counter].'Caller Info' #
... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArray
You cannot call a method on a null-valued expression. At line:10 char:1 + $ListItem.Update() + ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
so any idea what is going on?
Thanks
Have you tried updating your SPO Management Shell:
https://www.microsoft.com/en-in/download/details.aspx?id=35588
And/or the SPO Client Component SDK:
https://www.microsoft.com/en-us/download/details.aspx?id=42038
I'm not sure if it is required by PnPOnline, but with SPOServices you need to load the assembly as well:
Add-Type -Path "$Env:ProgramFiles\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "$Env:ProgramFiles\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
Add-Type -Path "$Env:ProgramFiles\SharePoint Client Components\16.0\Assemblies\Microsoft.Online.SharePoint.Client.Tenant.dll"
Or alternatively:
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Online.SharePoint.Client.Tenant") | Out-Null
Personally, I start my script with
#Requires -Module Microsoft.Online.SharePoint.PowerShell

Cannot bind parameter 'Start' to the target. Exception setting "Start": "Cannot convert null to type "System.DateTime"."

Here is my code:
function Execute-Script($path) {
$key = (3,4,2,3,56,34,254,222,1,1,2,23,42,54,33,233,1,34,2,7,6,5,35,43)
trap { "failed"; break }
$raw = Get-Content $path
$secure = ConvertTo-SecureString $raw -Key $key
$helper = New-Object system.Management.Automation.PSCredential("asapkal", $secure)
$plain = $helper.GetNetworkCredential().Password
Invoke-Expression $plain
}
Execute-Script "D:\PDMReport\PDMReport.bin"
and I am getting below error:
Invoke-Expression : Cannot bind parameter 'Start' to the target. Exception setting "Start": "Cannot convert null to type "System.DateTime"."
At line:8 char:3
+ Invoke-Expression $plain
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (:) [Invoke-Expression], ParameterBindingException
+ FullyQualifiedErrorId : ParameterBindingFailed,Microsoft.PowerShell.Commands.InvokeExpressionCommand
Please help with the resolution, I tried running ISE with administrator but error is still there.
Instead of Invoke-Expression $plain use Write-Host $plain and you will see where the problem is.
If it will still not be clear, post the output here (if not confidential) and you may get further help.

Upload file to SharePoint

I would like to create a program in PowerShell to upload files to Sharepoint on schedule (using Task Scheduler)
I was looking for solution and I found this interesting article.
Based on this I wrote this script below:
Import-Module Microsoft.Online.Sharepoint.Powershell -DisableNameChecking;
(System.Reflection.Assembly)::LoadWithPartialName("System.IO.MemoryStream")
Clear-Host
$cred = Get-Credential "emailaddress#domain.com"
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($cred.Username, $cred.Password)
$clientContext = New-Object Microsoft.SharePoint.Client.ClientContext("https://")
$clientCOntext.Credentials = $credentials
if (!$clientContext.ServerObjectIsNull.Value) {Write-host "Connected to site" -ForegroundColor Green}
Function UploadFileToLibrary(){
$docLib - $clientContext.Web.Lists.GetByTitle("IT Documents");
$clientContext.Load($docLib);
$clientContext.ExecuteQuery();
$rootFolder = $docLib.RootFolder
$Folder = "\\10.x.x.x\xpbuild$\IT\Level0\scresult\Upload";
$FilesInRoot = Get-ChildItem - Path $Folder | ? {$_.psIsContainer -eq $False}
Foreach ($File in ($FilesInRoot))
{
$startDTM = (Get-Date)
}Write-Host "Uploading File" $File.Name "to" $docLib.Title -ForegroundColor Blue
UploadFile $rootFolder $File $false
$endDTM = (Get-Date)
Write-Host "Total Elapsed Time : $(($endDTM-$startDTM).totalseconds) seconds"
}
Function UploadFile ($SPListFolder, $File, $CheckInRequired){
$FileStream = New-Object IO.FileStream($File.FullName,[System.IO.FileMode]::Open)
$FileCreationInfo = New-Object Microsoft.SharePoint.Client.FileCreationInformation
$FileCreationInfo.Overwrite = $True
$FileCreationInfo.ContentStream = $FileStream
$FileCreationInfo.Url = $File
$UploadedFile = $SPListFolder.Files.Add($FileCreationInfo)
If($CheckInRequired){
$clientContext.Load($UploadedFile)
$clientContext.ExecuteQuery()
If($uploadedFile.CheckOutType -ne "none"){
$UploadedFile.CheckIn("Checked in by Administrator", [Microsoft.SharePoint.Client.CheckinType]::MajorCheckIn)
}
}
$clientContext.Load($UploadedFile)
$clientContext.ExecuteQuery()
}
UploadFileToLibrary
When I tried to execute this I see that connection is active but I got an error:
Method invocation failed because [Microsoft.SharePoint.Client.List] does not contain a method named 'op_Subtraction'.
At C:\PowerShell\UploadSharepoint.ps1:11 char:1
+ $docLib - $clientContext.Web.Lists.GetByTitle("IT Documents");
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (op_Subtraction:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
Cannot find an overload for "Load" and the argument count: "1".
At C:\PowerShell\UploadSharepoint.ps1:12 char:1
+ $clientContext.Load($docLib);
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodCountCouldNotFindBest
Exception calling "ExecuteQuery" with "0" argument(s): "List 'IT Documents' does not exist at site with URL 'https://'."
At C:\PowerShell\UploadSharepoint.ps1:13 char:1
+ $clientContext.ExecuteQuery();
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ServerException
I cannot tell if any new problem occur once you fix that one, but given that the 2nd and 3rd error is caused by incorrect assignment of $docLib variable, changing - to =should resolve these three:
HERE |
$docLib = $clientContext.Web.Lists.GetByTitle("IT Documents");
# Below uses $docLib so it cannot be executed properly unless $docLib is assigned correct value
$clientContext.Load($docLib);
# And below fails as the above is not executed successfully
$clientContext.ExecuteQuery();

Powershell won't read header text in word documents?

I am in need of checkingh a larger number of word documents (doc & docx) for a specific text and found a great tutorial and script by the Scripting Guys;
https://blogs.technet.microsoft.com/heyscriptingguy/2012/08/01/find-all-word-documents-that-contain-a-specific-phrase/
The script reads all documents in a directory and gives the following output;
Number of times mentioned
Total word count in all documents where the specific text is found
The directory of all files containing the specific text.
This is all I need, however their code doesn't seem to actually check the headers of any document, which incidentally is where the specific text I'm looking for is located. Any tips & tricks in making the script read header text would make me very happy.
An alternative solution might be to remove the formatting so that the header text becomes part of the rest of the document? Is this possible?
Edit: Forgot to link the script:
[cmdletBinding()]
Param(
$Path = "C:\Users\use\Desktop\"
) #end param
$matchCase = $false
$matchWholeWord = $true
$matchWildCards = $false
$matchSoundsLike = $false
$matchAllWordForms = $false
$forward = $true
$wrap = 1
$application = New-Object -comobject word.application
$application.visible = $False
$docs = Get-childitem -path $Path -Recurse -Include *.docx
$findText = "specific text"
$i = 1
$totalwords = 0
$totaldocs = 0
Foreach ($doc in $docs)
{
Write-Progress -Activity "Processing files" -status "Processing $($doc.FullName)" -PercentComplete ($i /$docs.Count * 100)
$document = $application.documents.open($doc.FullName)
$range = $document.content
$null = $range.movestart()
$wordFound = $range.find.execute($findText,$matchCase,
$matchWholeWord,$matchWildCards,$matchSoundsLike,
$matchAllWordForms,$forward,$wrap)
if($wordFound)
{
$doc.fullname
$document.Words.count
$totaldocs ++
$totalwords += $document.Words.count
} #end if $wordFound
$document.close()
$i++
} #end foreach $doc
$application.quit()
"There are $totaldocs and $($totalwords.tostring('N')) words"
#clean up stuff
[System.Runtime.InteropServices.Marshal]::ReleaseComObject($range) | Out-Null
[System.Runtime.InteropServices.Marshal]::ReleaseComObject($document) | Out-Null
[System.Runtime.InteropServices.Marshal]::ReleaseComObject($application) | Out-Null
Remove-Variable -Name application
[gc]::collect()
[gc]::WaitForPendingFinalizers()
EDIT 2: My colleague got the idea to call on the section header instead;
Foreach ($doc in $docs)
{
Write-Progress -Activity "Processing files" -status "Processing $($doc.FullName)" -PercentComplete ($i /$docs.Count * 100)
$document = $application.documents.open($doc.FullName)
# Load first section of the document
$section = $doc.sections.item(1);
# Load header
$header = $section.headers.Item(1);
# Set the range to be searched to only Header
$range = $header.content
$null = $range.movestart()
$wordFound = $range.find.execute($findText,$matchCase,
$matchWholeWord,$matchWildCards,$matchSoundsLike,
$matchAllWordForms,$forward,$wrap,$Format)
if($wordFound) [script continues as above]
But this is met with the following errors:
You cannot call a method on a null-valued expression.
At C:\Users\user\Desktop\count_mod.ps1:27 char:31
+ $section = $doc.sections.item <<<< (1);
+ CategoryInfo : InvalidOperation: (item:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At C:\Users\user\Desktop\count_mod.ps1:29 char:33
+ $header = $section.headers.Item <<<< (1);
+ CategoryInfo : InvalidOperation: (Item:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At C:\Users\user\Desktop\count_mod.ps1:33 char:26
+ $null = $range.movestart <<<< ()
+ CategoryInfo : InvalidOperation: (movestart:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At C:\Users\user\Desktop\count_mod.ps1:35 char:34
+ $wordFound = $range.find.execute <<<< ($findText,$matchCase,
+ CategoryInfo : InvalidOperation: (execute:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Is this the right way to go or is it a dead end?
if you want the header text, you can try the following:
$document.content.Sections.First.Headers.Item(1).range.text
For anyone looking at this question in the future: Something isn't quite working with my code above. It seems to return a false positive and puts $wordFound = 1 regardless of the content of the document thus listing all documents found under $path.
Editing the variables within Find.Execute doesn't seem to change the outcome of $wordFound. I believe the problem might be found in my $range, as it is the only place I get errors in while going through the code step by step.
Errors listed;
You cannot call a method on a null-valued expression.
At C:\Users\user\Desktop\Powershell\count.ps1:24 char:58
+ $range = $document.content.Structures.First.Headers.Item <<<< (1).range.Text
+ CategoryInfo : InvalidOperation: (Item:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Exception calling "MoveStart" with "0" argument(s): "The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)"
At C:\Users\user\Desktop\Powershell\count.ps1:25 char:26
+ $null = $range.MoveStart <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodCOMException
You cannot call a method on a null-valued expression.
At C:\Users\user\Desktop\Powershell\count.ps1:26 char:34
+ $wordFound = $range.Find.Execute <<<< ($findText,$matchCase,
+ CategoryInfo : InvalidOperation: (Execute:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull

Powershell 3: Convert Word to PDF

I'm fairly new to Powershell and found the following script on the web: (I've modified it for my project)
# Acquire a list of DOC files in a folder
$Word = New-Object -ComObject word.application
$formats = "Microsoft.Office.Interop.Word.WdSaveFormat" -as [type]
$Word.visible = $false
$fileTypes = "*.docx","*doc"
$complyDocPath = "i:\2014\COMPLY\DOC\"
$complyPDFPath = "i:\2014\COMPLY\PDF\"
$Files=GET-CHILDITEM $complyDocPath -include $fileTypes
Foreach ($File in $Files) {
# open a Word document, filename from the directory
#$Doc=$Word.Documents.Open($File.fullname)
$Doc=$Word.Documents.Open($File)
# Swap out .DOCX/.DOC with 5.PDF in the Filename
$fileName = [system.io.path]::GetFileNameWithoutExtension($File)
$destPath = Join-Path -path $complyPDFPath -childpath ($fileName +"5.PDF")
Add-Type -AssemblyName "Microsoft.Office.Interop.Word"
"Converting $File to pdf ... $destPath"
# Save this File as a PDF in Word 2010/2013
$Doc.SaveAs($destPath, $formats::wdFormatPDF)
$Doc.Close($false)
}
$Word.Quit()
I get the following errors:
Argument: '2' should be a System.Management.Automation.PSReference. Use [ref].
At line:25 char:5
+ $Doc.SaveAs($destPath, $formats::wdFormatPDF)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : NonRefArgumentToRefParameterMsg
Argument: '1' should be a System.Management.Automation.PSReference. Use [ref].
At line:26 char:5
+ $Doc.Close($false)
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : NonRefArgumentToRefParameterMsg
Exception calling "Open" with "1" argument(s): "Type mismatch. (Exception from HRESULT: 0x80020005 (DISP_E_TYPEMISMATCH))"
At line:14 char:5
+ $Doc=$Word.Documents.Open($File)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation
For the 1st error, I changed my code to include [ref], like these variations (but to no success):
$Doc.SaveAs([ref] $destPath, $formats::wdFormatPDF)
$Doc.SaveAs($destPath, [ref] $formats::wdFormatPDF)
$Doc.SaveAs([ref] $destPath, [ref] 17)
[Update] FYI: Files in the source directory are named like this:
I:\2014\Comply\DOC\IBM=US.DOC
I:\2014\Comply\DOC\CTC.A=CA.DOC
How can I generate a PDF from Word doc?
The above code works if the source & destination paths were the same. Since I didn't get any responses, I've decided to go the C#.Net route and implemented the code that I found in:
How do I convert Word files to PDF programmatically?