Directory creation failure and no errors - powershell

I made a function and I thought it worked well. In my primary script I am importing the function and then calling it. The idea of the function is simply to make a filename with a path.
At the end of the function I added a portion that would check if the directory exists and if not create it.
Here are the problems.
I get no errors.
The directory is not always created`.
When the primary script runs and attempts to export the csv it doesn't because the directory doesn't exist.
3a) if I create the directory everything works.
The folder it tries to create is "C:\Reports" but I am an admin on the computer and I understand it should be in special folders. I suppose I can force that if you folks want. But I would think I would get an error if the directory could not create as written below.
Portion of the function that should be working.
$ProcessError = $null
IF (!(test-path $DirectoryName)) {
New-Item -Path $DirectoryName -ItemType Directory -ErrorAction SilentlyContinue -ErrorVariable ProcessError -Force
If ($ProcessError) {
Write-Warning "Problem trying to create $DirectoryName."
}
Return [string]$FullPath
}
This is the primary call to the function and what is strange is I get no error here as well in section 2 primary below!!
section 1 primary
If ($SimChange -eq $True) {
$ResultFileName = MRNAP -ReportName "ExampleGoogleLicenseReport" -Move -JustDate
}
Else {
$ResultFileName = MRNAP -ReportName "GoogleLicenseReport" -Move -JustDate
}
Section 2 primary
$ProcessError = $null
$Results | Export-Csv $ResultFileName -NoTypeInformation -ErrorVariable ProcessError -ErrorAction SilentlyContinue
If ($ProcessError) {
Write-Warning "Unable to save report output to $ResultFileName"
}
url to function that creates the filename.
https://github.com/dcazman/MRNAP/blob/main/MRNAP.ps1
I find this all very frustrating and Section 2 primary above. Should be giving me that warning as written....I thought.

In the comments there is chat about a bug and using try catch. Additionally, we have talked about this problem on stack before with
Create directory if it does not exist
and
Function return value in PowerShell
What I did for now that works.
IF (!(test-path $DirectoryName)) {
$Dircreate = New-Item -ItemType Directory -Force -Path $($DirectoryName.Substring(0, 3)) -Name $($DirectoryName.Substring(3)) -ErrorAction SilentlyContinue -ErrorVariable ProcessError | Out-Null
If ($ProcessError) {
Write-Warning "Problem trying to create $DirectoryName."
[bool]$Created = $False
}
Else {
[bool]$Created = $true
}
}
If ($Created) {
If ($FullPath -as [string]) {
Return [string]$FullPath
}
Else {
Return [string]$FullPath[1]
}
}
This above doesn't use a try catch but I will give that a shot later.
For some bug reason creating the directory was changing $fullpath from a string to an array and that is why the test above works using the -as [string]

Related

Error on Move-Item moving home area to file server

This is the last section of my script that I use to transfer student leavers areas to an archive file server. The script runs and does everything as expected but still throws an error out saying
Move-Item : Cannot find path '\\domain\students$\E-J$\MH201507' because it does not exist. The script does find this path and moves the home area so I'm not sure why I get this error. Or is there any way to fix this or is it easier to hide the error somehow?
The CSV document contains a list of the sam account name and contains their home area location on the domain so it knows where to copy the path over from.
Any help would be massively appreicaited! Kind Regards
#Declaring the .csv file that contains a list of all leavers home directories.
$HomeDirectoryList = Import-CSV "C:\Scripts\Leavers\HomeDirectoryExport.csv"
$Username = $HomeDirectoryList.samAccountName
$HomeDirectory = $HomeDirectoryList.HomeDirectory
$Archive = "\\myfileserver.ac.uk\D$\21-22 Leavers"
ForEach ($Username in $HomeDirectoryList)
{
Move-Item -Path $HomeDirectory -Destination $Archive
}
Sample data with which the error occurs:
samAccountName HomeDirectory
WB214589 \\domain\students$\A-D$\WB214589
MH201507 \\domain\students$\E-J$\MH201507
You are setting the variable $HomeDirectory outside the loop, so that will contain an array of home directory paths.
Then you use variable $Username to iterate the data from the CSV file, but inside that loop you never use it.
Try:
$HomeDirectoryList = Import-CSV 'C:\Scripts\Leavers\HomeDirectoryExport.csv'
$Archive = '\\myfileserver.ac.uk\D$\21-22 Leavers'
foreach ($student in $HomeDirectoryList) {
Write-Host "Moving HomeDirectory folder for student '$($student.samAccountName)'"
Move-Item -Path $student.HomeDirectory -Destination $Archive -Force
}
If you need to catch errors happening, change the loop to:
foreach ($student in $HomeDirectoryList) {
Write-Host "Moving HomeDirectory folder for student '$($student.samAccountName)'"
try {
Move-Item -Path $student.HomeDirectory -Destination $Archive -Force -ErrorAction Stop
}
catch {
Write-Warning "Error moving homedirectory '$($student.HomeDirectory)':`r`n$($_.Exception.Message)"
}
}

Powershell Test-Path in loop, variable path

I started learning Powershell yesterday.
I want to write a script that run batches in multiple folders, however only if subfolder contain work_folder.
I have the following folder structure
*folder1
--work_folder
--script.bat
*folder2
--script.bat
*folder3
--script.bat
*test.ps1
powershell
cd C:\a\test\
Get-ChildItem -Path $PWD\*\script.bat | ForEach-Object {
if ( -not ( Test-Path $PWD\*\work_folder -PathType Container ) )
{
Write-host "Not exist"
return
} else {
Write-host "Exist"
}
& $_
}
If I use
powershell
$myPath = "$PWD\*\"
it will not work as I want.
Please give me a hint or example.
There's a couple problems with your code. Because you use the return keyword if the work_folder directory doesn't exist, your script ends entirely on the first folder it spots like this. I think you meant to use the continue keyword, which would skip to the next iteration of the loop.
Also, you were iterating on every instance of script.bat, when you should have been iterating on every directory containing script.bat.
You can write your code a lot cleaner if you do it this way:
(Get-ChildItem -Path $PWD -Directory).FullName | ForEach-Object {
if (Test-Path "$_/work_folder" -PathType Container)
{
Write-host "Exist"
& "$_/script.bat"
} else {
Write-host "Not exist"
}
}

Powershell Scripting Variables

I have set some variables in PowerShell. The variables are created at the beginning of my script. However, the values for the variables are being executed at start which in turns gives and error message. Ex:
$checker = get-item -path C:\users\user\desktop\Foldername
$finder = Test-path -Path $checker
if($finder -eq $finder )
{
}
Else
{
Create-Item -Path C:/users/user/desktop -name "Foldername" -itemtype Directory
}
I do know that if I run this it will give me an error because the directory never existed and I can just change the variable order to avoid errors.
My question is that this script is going to be more lines of code than this and I would have to create the variable right when its needed to avoid errors.
How can I use these variables like a regular programming language where the variables are ignored until called upon.
Using Get-Item and checking with Test-Path afterwards is not a good design. Two better ways:
Use Get-Item only and check for $null to check for its existence:
$checker = Get-Item -Path C:\users\user\desktop\Foldername -ErrorAction SilentlyContinue
if ($checker) {
# do something with the existing folder
} else {
Create-Item -Path C:/users/user/desktop -Name "Foldername" -ItemType Directory
}
Use Test-Path only to check for its existence:
if (Test-Path -Path C:\users\user\desktop\Foldername) {
# do something with the existing folder
} else {
Create-Item -Path C:/users/user/desktop -Name "Foldername" -ItemType Directory
}

Handle Directory Exists Exception

I am new to PowerShell. I have a piece of code which checks whether a folder "ilalog" exists or not. When I run this script first time, it is checking for the folder "ilalog",if it does not exist,it is creating. When I run the script second time. I receive the error below:
An item with the specified name D:\Temp\ilalog already exists
"FullyQualifiedErrorId :
DirectoryExist,Microsoft.PowerShell.Commands.NewItemCommand".
how to handle this exception
I have tried using try and Catch block
$rgflder="ilalog"
[bool]$checkrg=Test-Path D:\Gdump\$rgfolder -PathType Any
if ( $checkrg -eq $False)
{
try{
New-Item -Path "D:\Gdump" -Name "$rgflder" -ItemType "directory"
}
catch [System.IO.IOException]
{
if ($_.CategoryInfo.Category -eq $resExistErr) {Write-host "Dir Exist"}
}
}
else
{
Write-Output "Directory Exists"
}
If you want to continue processing your script while taking action based on an error type, a simple way is to just examine the $error variable. Using Trap may be an option as well.
$error.clear()
New-Item -Path "D:\Gdump" -Name "$rgflder" -ItemType "directory"
if ($error[0].Exception.GetType().Fullname -eq 'System.IO.IOException') {
"Dir Exists"
}
else {
"Dir was created"
}
If you want to use try-catch, you need to treat your non-terminating error as a terminating error to activate the catch block. You can do this with -ErrorAction Stop.
try {
New-Item -Path "D:\Gdump" -Name "$rgflder" -ItemType "directory" -ErrorAction Stop
}
catch [System.IO.IOException]
{
"Exception caught!"
}
Alternatively, you can manage this within your session by setting $ErrorActionPreference = 'Stop', which will apply to all commands within that session.
Keep in mind that the value passed to -ErrorAction overrides the setting in $ErrorActionPreference. Also, error action settings have no affect on terminating errors. So you cannot expect to set -ErrorAction Continue and have code continue processing on a terminating error.
Many commands return objects that may or may not be terminating errors. You will find more success explicitly, specifying when you want to throw a terminating error.
You can read more about error action preference at About Common Parameters. I actually like Everything About Exceptions for exception handling in PowerShell.
Why not simply do like below?
$rgflder="ilalog"
# combine the path and foldername
$rgPath = Join-Path -Path 'D:\Gdump' -ChildPath $rgflder
# test if the folder already exists
if (Test-Path $rgPath -PathType Container) {
Write-Output "Directory Exists"
}
else {
# if not, create the new folder
try {
$null = New-Item -Path $rgPath -ItemType Directory -ErrorAction Stop
Write-Output "Created directory '$rgPath'"
}
catch {
# something terrible happened..
Write-Error "Error creating folder '$rgPath': $($_.Exception.Message)"
}
}

New-Item executed even though it's within an 'if' statement

I created a script to pull JPEG snapshots from 2 IP cameras. For me to keep them organized I added some lines to check the date and create a folder matching it. The script also checks if the folder exists and if it does, should skip to the snapshot capture.
Everything works fine as intended but it seems for one reason or another the script still tries to create the folder and shows and error in my PS console that the directory exists.
$chk_path = Test-Path "C:\SnapShots\$((Get-Date).ToString('yyyy-MM-dd'))"
$Make_SnapShot_Folder = New-Item -ItemType Directory -Path "C:\SnapShots\$((Get-Date).ToString('yyyy-MM-dd'))"
$Camera_A = (new-object System.Net.WebClient).DownloadFile('http://10.0.0.132/snap.jpeg',"C:\SnapShots\$((Get-Date).ToString('yyyy-MM-dd'))\Camera_A$((Get-Date).ToString('HH-mm-ss')).jpeg")
$Camera_B = (new-object System.Net.WebClient).DownloadFile('http://10.0.0.132/snap.jpeg',"C:\SnapShots\$((Get-Date).ToString('yyyy-MM-dd'))\Camera_B$((Get-Date).ToString('HH-mm-ss')).jpeg")
if (-not ($chk_path) ) {
write-host "C:\SnapShots doesn't exist, creating it"
$Make_ScrapShot_Folder
} else {
write-host "C:\SnapShots exists, Saving SnapShots"
}
Camera_A
Camera_B
Unlike other languages probably you've used, PowerShell will execute the code when you assign it to a variable not when the variable is called.
So you're actually creating the folder with this line:
$Make_SnapShot_Folder = New-Item -ItemType Directory -Path "C:\SnapShots\$((Get-Date).ToString('yyyy-MM-dd'))"
You just can re-arrange your code to make it do what you want, and to be more efficient:
$day = Get-Date -Format 'yyyy-MM-dd'
$snapshots_dir = "C:\SnapShots\$day"
if (Test-Path $snapshots_dir) {
Write-Host "$snapshots_dir exists, Saving SnapShots"
} else {
Write-Host "$snapshots_dir doesn't exist, creating it"
New-Item -ItemType Directory -Path $snapshots_dir
}
$timestamp = Get-Date -Format 'HH-mm-ss'
(New-Object System.Net.WebClient).DownloadFile('http://10.0.0.132/snap.jpeg',"$snapshots_dir\Camera_A$timestamp.jpeg")
(New-Object System.Net.WebClient).DownloadFile('http://10.0.0.132/snap.jpeg',"$snapshots_dir\Camera_B$timestamp.jpeg")
The following code snippet should work:
$str_path = "C:\SnapShots\$((Get-Date).ToString('yyyy-MM-dd'))"
$chk_path = Test-Path $str_path
if ($chk_path) {
$Make_SnapShot_Folder = Get-Item -Path $str_path
} else {
$Make_SnapShot_Folder = New-Item -ItemType Directory -Path $str_path
}
$Make_SnapShot_Folder ### this outputs a DirectoryInfo
Move this line:
$Make_SnapShot_Folder =
New-Item -ItemType Directory -Path "C:\SnapShots\$((Get-Date).ToString('yyyy-MM-dd'))"
To here:
if (-not ($chk_path) ) {
<-- Here
write-host "C:\SnapShots doesn't exist, creating it"
$Make_ScrapShot_Folder <-- Remove this line