Change Last Writing Date using date in file name - powershell

I would like to change the Last writing date of several CSV files using the dates contained in the names of the different files
Example :
Input : File_20221210085032.CSV (LastWriteTime = 25 October 2022 16:54:25)
Output :(LastWriteTime = 10 December 2022 08:50:32)
In that extent i wrote a code based on my knowledge and some help from internet, this code should do what i want to achieve however i get some errors and i cannot find the errors.
Please find below my code :
cls
$Foldober = 'D:\Bob\Test'
$DateFormat = "yyyymmddhhmmss"
$FileList = Get-ChildItem -LiteralPath $Folder -Filter '*.csv' -File
foreach ($FL_Item in $FileList) {
$Null = $FL_Item.BaseName -match '_\d{14}'
$DateString = $Matches.DateString
$date_from_file = [datetime]::ParseExact($DateString, $DateFormat, $Null)
$FL_Item.CreationTime = $date_from_file
$FL_Item.LastWriteTime = $date_from_file
$FL_Item.LastAccessTime = $date_from_file
# show the resulting datetime info
'=' * 20
$CurrentFileInfo = Get-Item -LiteralPath $FL_Item.FullName
$CurrentFileInfo.FullName
$CurrentFileInfo.CreationTime
$CurrentFileInfo.LastWriteTime
$CurrentFileInfo.LastAccessTime
}
I get the following error
Exception calling "ParseExact" with "3" argument(s): "String was not recognized as a valid DateTime."
At C:\Users\Bob\Desktop\Script\test.ps1:15 char:5
+ $date_from_file = [datetime]::ParseExact($DateString, $DateFormat ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : FormatException
Update #2
After having got ridden of $null in the ParsExact as suggested i get the following errors :
cls
$Foldober = 'D:\Bob\Test'
$DateFormat = "yyyymmddhhmmss"
$FileList = Get-ChildItem -LiteralPath $Folder -Filter '*.csv' -File
foreach ($FL_Item in $FileList) {
$Null = $FL_Item.BaseName -match '_\d{14}'
$DateString = $Matches.DateString
$date_from_file = [datetime]::ParseExact($DateString, $DateFormat)
$FL_Item.CreationTime = $date_from_file
$FL_Item.LastWriteTime = $date_from_file
$FL_Item.LastAccessTime = $date_from_file
# show the resulting datetime info
'=' * 20
$CurrentFileInfo = Get-Item -LiteralPath $FL_Item.FullName
$CurrentFileInfo.FullName
$CurrentFileInfo.CreationTime
$CurrentFileInfo.LastWriteTime
$CurrentFileInfo.LastAccessTime
}
Cannot find an overload for "ParseExact" and the argument count: "2".
At C:\Users\Bob\Desktop\Script\test.ps1:15 char:5
+ $date_from_file = [datetime]::ParseExact($DateString, $DateFormat ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodCountCouldNotFindBest
Exception setting "CreationTime": "Cannot convert null to type "System.DateTime"."
At C:\Users\Bob\Desktop\Script\test.ps1:17 char:5
+ $FL_Item.CreationTime = $date_from_file
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Thanks in advance for your help. Best regards

Related

Append string in file name using powershell

I am trying to append string in the file name.
$cstzone = [System.TimeZoneInfo]::FindSystemTimeZoneById("India Standard Time")
$csttime = [System.TimeZoneInfo]::ConvertTimeFromUtc((Get-Date).ToUniversalTime(), $cstzone)
$d = Get-Date $csttime -f "dd-MM-yyyy"
$t = Get-Date $csttime -f "HH:mm"
Write-Host "Date : " $d
Write-Host "Time : " $t
gci C:\Result.jtl | % { rename-item –Path $_.FullName –Newname ( $_.basename + $t + $_.extension) }
Expected
Result_14:42.jtl
Error
rename-item : Cannot rename the specified target, because it represents a path or device name.
At line:10 char:25
+ ... t.jtl | % { rename-item –Path $_.FullName –Newname ( $_.basename + $t ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Rename-Item], PSArgumentException
+ FullyQualifiedErrorId : Argument,Microsoft.PowerShell.Commands.RenameItemCommand
You can't have colons in file names, they are reserved for drive letters. You can use a tostring to get date in different format:
(Get-Date).ToString("hh-mm")

Extracting attachments from SharePoint online using PowerShell

Currently I am trying to extract attachments from a list on SharePoint online. I found a code online that is supposed to do this but i get an error. The code that I found is a follows:
$webUrl = "https://mm.sharepoint.com/teams/pj-b0000"
$library = "Photos"
#Local Folder to dump files
$tempLocation = "C:\Users\C\Documents\temp"
$s = new-object Microsoft.SharePoint.SPSite($webUrl)
$w = $s.OpenWeb()
$l = $w.Lists[$library]
foreach ($listItem in $l.Items)
{
Write-Host " Content: " $listItem.ID
$destinationfolder = $tempLocation + "\" + $listItem.ID
if (!(Test-Path -path $destinationfolder))
{
$dest = New-Item $destinationfolder -type directory
}
foreach ($attachment in $listItem.Attachments)
{
$file = $w.GetFile($listItem.Attachments.UrlPrefix + $attachment)
$bytes = $file.OpenBinary()
$path = $destinationfolder + "\" + $attachment
Write "Saving $path"
$fs = new-object System.IO.FileStream($path, "OpenOrCreate")
$fs.Write($bytes, 0 , $bytes.Length)
$fs.Close()
}
}
but i get this error:
new-object : Cannot find type [Microsoft.SharePoint.SPSite]: verify that the assembly containing this type is loaded.
At C:\Users\C\Documents\SPListExtract.ps1:5 char:6
+ $s = new-object Microsoft.SharePoint.SPSite($webUrl)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidType: (:) [New-Object], PSArgumentException
+ FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewObjectCommand
You cannot call a method on a null-valued expression.
At C:\Users\C\Documents\SPListExtract.ps1:6 char:1
+ $w = $s.OpenWeb()
+ ~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Cannot index into a null array.
At C:\Users\C\Documents\SPListExtract.ps1:7 char:1
+ $l = $w.Lists[$library]
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArray
so i edited that code a bit but i only get the item in the list and not the attachments that are in the items. The code that i wrote is as follows:
Connect-PnPOnline -Url 'https://mm.sharepoint.com/teams/pj-b0000' -UseWebLogin
$tempLocation = "C:\Users\C\Documents\temp"
$list = Get-PnPListItem -List 'Photos'
foreach ($listItem in $list)
{
Write-Host " Content: " $listItem.ID
$destinationfolder = $tempLocation + "\" + $listItem.ID
if (!(Test-Path -path $destinationfolder))
{
$dest = New-Item $destinationfolder -type directory
}
foreach ($attachment in $listItem.Attachments)
{
$file = $w.GetFile($listItem.Attachments.UrlPrefix + $attachment)
$bytes = $file.OpenBinary()
$path = $destinationfolder + "\" + $attachment
Write "Saving $path"
$fs = new-object System.IO.FileStream($path, "OpenOrCreate")
$fs.Write($bytes, 0 , $bytes.Length)
$fs.Close()
}
}
I see my problem is the inside foreach loop for the $file variable I think. Would someone be able to help me with this?
Much thanks in advance.
The first line in your errors implies you do not have the assembly loaded:
new-object : Cannot find type [Microsoft.SharePoint.SPSite]: verify that the assembly containing this type is loaded.
These assemblies are only installed on a SharePoint server:
https://social.technet.microsoft.com/Forums/en-US/4a78ed2c-efde-40fa-800c-c4ecfa68a7c4/cannot-find-type-microsoftsharepointspsite-when-running-sharepoint-powerscript-in-a-windows-10?forum=sharepointdevelopment

Creating a parameter script with PowerShell to be called by another script

I have a PowerShell script that works. For maintenance reasons I want to create another script where I'll put all the parameters that I'll call from my first script.
How can I create and call the parameter file?
Here is my script:
param([string] $dataSource = "server")
$Stamp = (Get-Date).toString("yyyy/MM/dd HH:mm:ss")
$Stamp1 = (Get-Date).toString("yyyy-MM-dd")
$Logfile = "E:\PowerShell\Log\file$stamp1.log"
$file = "file$stamp1.csv"
$extractFile = #"
E:\PowerShell\Output\$file
"#
[string]$sqlCommand1 =get-content -path E:\PowerShell\SQL\sql.sql
[string]$sqlCommand =$sqlCommand1
$authentication = ("User Id= user ;Password=pswd;" -f $plainCred.Username, $plainCred.Password)
Add-Type -assemblyname system.data
$factory = [System.Data.Common.DbProviderFactories]::GetFactory ("Teradata.Client.Provider")
$connection = $factory.CreateConnection()
$connection.ConnectionString = "Data Source = $dataSource;Connection Pooling Timeout=300;$authentication"
$connection.Open()
if ($connection.State -eq 'Open') {$logstring ="Connexion réussite"} else { $logstring ="echec Connexion" }
$command = $connection.CreateCommand()
$command.CommandText = $sqlCommand
$adapter = $factory.CreateDataAdapter()
$adapter.SelectCommand = $command
$dataset = new-object System.Data.DataSet
try
{
[void] $adapter.Fill($dataset)
$dataset.Tables | Select-Object -Expand Rows
}
finally
{
$connection.Close()
}
if (!$dataset) {$logstring1 ="extraction vide"} else {$logstring1 ="extraction réussite"}
($DataSet.Tables[0] | ConvertTo-Csv -delimiter ";" -NoTypeInformation ) -replace '"', "" | Out-File $extractFile -Force
$datafileExists = Test-Path $extractFile
if ($datafileExists)
{
$logstring2 ="Fichier data créé"
}
else
{
$logstring2 ="Fichier data non créé"
}
Add-content $Logfile -value ($Stamp+':'+$logstring)
Add-content $Logfile -value ($Stamp+':'+$logstring1)
Add-content $Logfile -value ($Stamp+':'+$logstring2)
I created a file of parameters
$Stamp1 = (Get-Date).toString("yyyy-MM-dd")
$Logfile = "E:\PowerShell\Log\file$stamp1.log"
$file = "file$stamp1.csv"
$extractFile = #"
E:\PowerShell\Output\$file
"#
$authentication = ("User Id= user ;Password=paswd;" -f $plainCred.Username, $plainCred.Password)
$Stamp = (Get-Date).toString("yyyy/MM/dd HH:mm:ss")
and I call it from my first script like that :
$ScriptPath = Split-Path $MyInvocation.InvocationName
& "$ScriptPath\param.ps1"
but my variables are not recognised, I have these errors:
Out-File : Cannot bind argument to parameter 'FilePath' because it is null.
At E:\PowerShell\script\Soft.ps1:59 char:104
+ ... "" | Out-File $extractFile -Force
+ ~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Out-File], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.OutFileCommand
Test-Path : Cannot bind argument to parameter 'Path' because it is null.
At E:\PowerShell\script\Soft.ps1:61 char:29
+ $datafileExists = Test-Path $extractFile
+ ~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Test-Path], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.TestPathCommand
Add-Content : Cannot bind argument to parameter 'Path' because it is null.
At E:\PowerShell\script\Soft.ps1:78 char:14
+ Add-content $Logfile -value ($Stamp+':'+$logstring)
+ ~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Add-Content], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.AddContentCommand
Add-Content : Cannot bind argument to parameter 'Path' because it is null.
At E:\PowerShell\script\Soft.ps1:79 char:13
+ Add-content $Logfile -value ($Stamp+':'+$logstring1)
+ ~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Add-Content], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.AddContentCommand
Add-Content : Cannot bind argument to parameter 'Path' because it is null.
At E:\PowerShell\script\Soft.ps1:80 char:13
+ Add-content $Logfile -value ($Stamp+':'+$logstring2)
+ ~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Add-Content], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.AddContentCommand
IF you use '&' you execute the ps1 and the variables created are available within that scope. you can change the scope like this:
$test # default scope
$global:test # global scope
$script:test # script scope
The better solution is to use '.' in stead of '&' so you 're code from the ps1 is included in the other ps1.
so the scope is in the same because it is in the same script.

Convert Excel formats to pdf - Powershell

My question's about the error at saving file at this convert script:
https://github.com/idf/batch_dump/blob/master/office_convert.ps1
#Error
Exception when calling "InvokeMember" with "6" argument (s): "Object does not match destination type."
In the line: 28 character: 1
+ $workbook = $objExcel.Workbooks.PSBase.GetType().InvokeMember('Open', ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : TargetException
saving C:\Test\CD_FEV_1.pdf
You can not call a method on a null value expression.
In the line: 30 character: 1
+ $workbook.ExportAsFixedFormat($xlTypePDF, $filepath, $xlQualityStanda ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You can not call a method on a null value expression.
In the line: 31 character: 1
+ [void]$workbook.PSBase.GetType().InvokeMember('Close', [Reflection.Bi ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
As i haven't experience in powershell i don't understand the metod they call at script.
I'm still new to powershell myself, so can't answer specifically what was causing the error, however I think I found the solution. It seemed to be with only the Excel conversion. The Word and PPT conversions worked flawless. I've changed the code for that portion and it seems to be working now:
$folderpath = $(get-location)
Add-type -AssemblyName office
#Convert Word formats to pdf
$wdFormatPDF = 17
$word = New-Object -ComObject word.application
$word.visible = $false
$fileTypes = "*.docx","*doc"
$wordFiles = Get-ChildItem -path $folderpath -include $fileTypes -Recurse
foreach ($d in $wordFiles) {
$path = ($d.fullname).substring(0,($d.FullName).lastindexOf("."))
"Converting $path to pdf ..."
$doc = $word.documents.open($d.fullname)
$doc.saveas([ref] $path, [ref]$wdFormatPDF)
$doc.close()
}
$word.Quit()
#Convert Excel formats to pdf
$xlFixedFormat = "Microsoft.Office.Interop.Excel.xlFixedFormatType" -as [type]
$excelFiles = Get-ChildItem -Path $folderpath -include *.xls, *.xlsx -recurse
$objExcel = New-Object -ComObject excel.application
$objExcel.visible = $false
foreach($wb in $excelFiles)
{
$filepath = Join-Path -Path $folderpath -ChildPath ($wb.BaseName + ".pdf")
$workbook = $objExcel.workbooks.open($wb.fullname, 3)
$workbook.ActiveSheet.PageSetup.Orientation = 2
$objExcel.PrintCommunication = $false
$workbook.ActiveSheet.PageSetup.FitToPagesTall = $false
$workbook.ActiveSheet.PageSetup.FitToPagesWide = 1
$objExcel.PrintCommunication = $true
$workbook.Saved = $true
"saving $filepath"
$workbook.ExportAsFixedFormat($xlFixedFormat::xlTypePDF, $filepath)
$objExcel.Workbooks.close()
}
$objExcel.Quit()
#Convert Powerpoint formats to pdf
$ppFormatPDF = 2
$ppQualityStandard = 0
$p = new-object -comobject powerpoint.application
$p.visible = [Microsoft.Office.Core.MsoTriState]::msoTrue
$ppFiletypes = "*.pptx","*ppt"
$ppFiles = Get-ChildItem -path $folderpath -include $ppFiletypes -Recurse
foreach ($s in $ppFiles) {
$pppath = ($s.fullname).substring(0,($s.FullName).lastindexOf("."))
"Converting $pppath to pdf ..."
$ppt = $p.presentations.open($s.fullname)
$ppt.SavecopyAs($pppath, 32) # 32 is for PDF
$ppt.close()
}
$p.Quit()
$p = $null
[gc]::collect()
[gc]::WaitForPendingFinalizers()

PowerShell v4 Get-Content : A parameter cannot be found that matches parameter name 'Delimiter'

I am hoping someone can give me the push I need to get this done, but I have had no luck with this exact situation online.
I need to use PowerShell (unfortunately I can't use Python or .NET to so this:( ) to parse though a list of files to determine if they contain a line termination of /r rather than /r/n. This script was previously in production and working, when single files were passed.
I am making adjustments so that multiple files can be accommodated.
I am getting the list of filenames and putting them into an array (which is working) but when I tey to loop the files through the if statement I get this error.
Here is my code:
param(
#[Parameter(Mandatory=$True)]
[String]$FileName = "C:\LineTermTest\*C*.txt"
)
$FileNameArray = Get-ChildItem -Path $FileName | where {!$_.psicontainter }| Select-Object fullname
for ($i=0; $i -le $FileNameArray.Length -1; $i++ )
{
$File = $FileNameArray[$i]
if (Get-Content -path $File -Delimiter "`0" | Select-String "[^`r]`n" )
{
$content = Get-Content $File
$content | Set-Content $File -Replace "`n", "'r'n" -Encoding ASCII
[gc]::collect()
[gc]::WaitForPendingFinalizers()
}
}
and here is the error I get
Get-Content : A parameter cannot be found that matches parameter name 'Delimiter'.
At line:13 char:39
+ if (Get-Content -path $File -Delimiter <<<< "0" | Select-String "[^r]`n" )
+ CategoryInfo : InvalidArgument: (:) [Get-Content], ParameterBindingException
+ FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.GetContentCommand
Get-Content : A parameter cannot be found that matches parameter name 'Delimiter'.
At line:13 char:39
+ if (Get-Content -path $File -Delimiter <<<< "0" | Select-String "[^r]`n" )
+ CategoryInfo : InvalidArgument: (:) [Get-Content], ParameterBindingException
+ FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.GetContentCommand
Get-Content : A parameter cannot be found that matches parameter name 'Delimiter'.
At line:13 char:39
+ if (Get-Content -path $File -Delimiter <<<< "0" | Select-String "[^r]`n" )
+ CategoryInfo : InvalidArgument: (:) [Get-Content], ParameterBindingException
+ FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.GetContentCommand
in your script, $File is a 'PSCustomObject', not a FileInfo object, so you need to use its property 'fullname' like this: Get-Content -path $File.fullname -Delimiter "`0". This is because the objects in $FileNameArray are created by using Select-Object.
You can avoid this by leaving out "| Select-Object fullname" when creating $FileNameArray. That way, the $FileNameArray contains FileInfo objects, and Get-Content can use those directly. This is the preferred way.
So this line:
$FileNameArray = Get-ChildItem -Path $FileName | where {!$_.psicontainter }| Select-Object fullname
becomes this line:
$FileNameArray = Get-ChildItem -Path $FileName | where {!$_.psicontainter }