1
votes

Hello Stack Overflow Community,

at the moment I'm struggling with this code (it's not that beautiful):

$filepath = "C:\inetpub\logs\LogFiles"
$filearchivepath = "C:\inetpub\logs"
$daystoarchive = 1
$_ = "";

function create-7zip([String] $aDirectory, [String] $aZipfile){
    #change the path where you downloaded the 7z exe
    [string]$pathToZipExe = "C:\Users\kschweiger\Downloads\7za.exe";
    [Array]$arguments = "a", "-tzip", "$aZipfile", "$aDirectory";
    & $pathToZipExe $arguments;
}


#Create a new folder with the specific date
$ArchiveFolder = (Get-Date -Format dd.MM.yyyy) + " - Logs-Archive"
if(Test-Path "$filearchivepath\$ArchiveFolder"){
    Write-Host "Folder already exists!"
}else{
    New-Item -Path $filearchivepath -Name $ArchiveFolder -ItemType directory
}


#Save alle files older than X days into $Files
$Files = Get-ChildItem -Path $filepath -Recurse | where {$_.LastWriteTime -lt (Get-Date).AddDays(-$daystoarchive)}

#Copy/Move files and keep folder structure
foreach ($File in $Files){

    $NewPath = $File.DirectoryName.Replace($filepath,"")

    if (!(Test-Path "$filearchivepath\$ArchiveFolder\$NewPath"))
    {
        New-Item -Path "$filearchivepath\$ArchiveFolder\$NewPath" -ItemType Directory
    }

    $File | Copy-Item -Destination "$filearchivepath\$ArchiveFolder\$NewPath"
}

#Compress folder
if(Test-Path "$filearchivepath\$ArchiveFolder.zip"){
    Write-Host "Archive-File already exists!"
}else{
    #[IO.Compression.ZipFile]::CreateFromDirectory("$filearchivepath\$ArchiveFolder","$filearchivepath\$ArchiveFolder.zip")
    create-7zip "$filearchivepath\$ArchiveFolder"  "$filearchivepath\$ArchiveFolder.zip"
    #Delete Folder
    Remove-Item -Path "$filearchivepath\$ArchiveFolder" -Recurse -Force
}

The code works. but I also get a error message called:

You cannot call a null-valued expression

Error Message

How can I resolve this?

1
Add -File to your Get-ChildItem to exclude folders (they have no DirectoryName). - Robert Dyjas
@KevinSchweiger: Fortunately, robdy seems to have spotted your problem, but in the future please consider posting a minimal reproducible example (or as close as you can get to one) to reduce the amount of code in the question. This makes it easier for potential answerers as well as future readers to understand the problem. - mklement0
Thank you for the comment. I already had the added -File to this line. But if I do so, the programm doesnt work at all and I get the error message "A parameter cannot be found that mateches parameter name "File". - User404
On my Windows 10 PC it works fine but on the Windows Web Server 2008 R2 not - User404
BTW It doesn't make sense to initialize the automatic variable $_ which is only accessible in a pipe to reference the currently processed object. See Get-Help about_Automatic_Variables - user6811411

1 Answers

2
votes

Get-ChildItem by default returns files and folders. If you need only files, you should use -File. Otherwise, your $Files will contain folders too (as they have LastWriteTime property).

If you try to run .DirectoryName.Replace($filepath,"") on a folder, it'll return such error as you cannot run replacing on $null.

Update: for PowerShell 2.0 you can use | where { ! $_.PSIsContainer } (source)


How can I troubleshoot it by myself?

In your error you can see which line is broken:

$NewPath = $File.DirectoryName.Replace($filepath,"")

All you have to do to troubleshoot such situations is to list all the involved variables and check their values. You could do it like this:

$File
$File.DirectoryName
Pause

$NewPath = $File.DirectoryName.Replace($filepath,"")

Using Pause can be useful as it'll wait for you to press Enter before continuing.