Powershell back up script - windows

So a couple of years ago I created a script that could be used and executed Windows PC that would make a backup / copy of all PDFs in a user's document folder to a flash drive regardless of username. The script also does not use the drive letter to identify the flash drive, instead, it uses the drives Volume name. So that no matter where it was used, which pc, user or letter of the flash drive, it always worked.
However now I just recreated it and for some reason, the script runs without a hitch, it is not copying the pdfs to the flash drive any longer. Any help figuring out why would be nice. I am not a pro at Powershell.
param([parameter(mandatory=$true)]$VolumeName) $backupPath = $null
get-wmiobject win32_logicaldisk | % { if ($_.VolumeName -eq $VolumeName) { $backupDrive = $_.DeviceID } }
$backupPath = $backupDrive + "\"
robocopy $env:username\Documents\ *.pdf $backupDrive /MIR /Z /XJD
Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU' -Name '*' -ErrorAction SilentlyContinue
Remove-Item -path $env:username\Downloads\backup.ps1 -recurse

You create the variable $backupPath but you use the variable backupDrive in your robocopy commandline. Instead of $env:UserPorfile you use $env:userName. I doubt that this script run sucessfully once. And you have some unrelated code lines in it.
param(
[parameter(mandatory = $true)]
$VolumeName
)
$backupDrive = (Get-CimInstance -ClassName Win32_LogicalDisk | Where-Object -Property VolumeName -EQ -Value $VolumeName).DeviceID
$backupPath = $backupDrive + '\'
robocopy $Env:USERPROFILE\Documents\ $backupPath *.pdf /S /Z /XJD /NDL /PURGE
You might have asked the author where you downloaded this script to fix it. ;-)

Related

Why no commandline/powershell command can copy a snapshot image of a open PST file, yet File explorer copy can?

I am trying to automate some backing up of important stuff in a computer, specifically I want to automate backing up local Outlook archives (.pst). The thing is that these computer's users might be using the computer (and thus, outlook and the pst files that Outlook reads/writes to) at the same time.
I figured that the "easy enough" fix was to automate a VSS copy, and then copy the file in the Shadow Copy. I tested it, but it didn't work! paradoxically, it seemed to work just fine if I copied the file BY HAND, in file explorer, but if I try to use xcopy, robocopy or copy-Item, it throws an error.
I can't manage to avoid the problem of "you can't copy a file that's being acessed"... Not even by using a VSS!
This is a code I managed to put together that creates a Volume Shadow copy, copies the file from the shadow copy and deletes the shadow copy afterwards:
#Data
$SourceDir=$env:USERPROFILE+'\Documents\Outlook Files' #Location of PST files
$TargetDir='\\NetworkLocation\Resource\Folder'
$logFile='"'+$SourceDir+'\Outlook-backup.log"'
if (-not (Test-Path -LiteralPath $SourceDir)){
throw "Source: `"$SourceDir`" does not exist"
}
if (-not (Test-Path -LiteralPath $TargetDir)){
throw "Target: `"$SourceDir`" does not exist"
}
$SourceDir = Get-Item -LiteralPath $SourceDir
$TargetDir = Get-Item -LiteralPath $TargetDir
#Create Volume Shadow Copy
$s1 = (Get-WmiObject -List Win32_ShadowCopy).Create("C:\\", "ClientAccessible")
try{
$s2 = Get-WmiObject Win32_ShadowCopy | Where-Object { $_.ID -eq $s1.ShadowID }
$d = $s2.DeviceObject + "\\"
#Create symlink to the snapshot for easy access
cmd /c mklink /d C:\shadowcopy "$d"
#Find file location inside snapshot
$null=$SourceDir.FullName -match "(?<=^[a-z]:\\).*$"
$ShadowSource = "C:\shadowcopy\"+$Matches[0]
if (-not (Test-Path -LiteralPath $ShadowSource)){
throw "Shadow source: `"$ShadowSource`" does not exist"
}
$ShadowSource = $ShadowSource | Get-Item
#Copy file from snapshot
robocopy.exe $ShadowSource.FullName $TargetDir.fullname /MIR /COPY:DAT /J /Z /COMPRESS /R:3 /W:5 /NP /UNILOG:$logFile #/L
#ROBOCOPY FAILS TO COPY THE FILES
}
catch{
Write-Host "Error occurred $($_.ScriptStackTrace)"
Write-Host $_
}
finally{
#Delete snapshot (In two different ways just in case)
"vssadmin delete shadows /Shadow=""$($s1.ShadowID.ToLower())"" /Quiet" | iex
"vssadmin delete shadows /Shadow=""$($s2.ID.ToLower())"" /Quiet" | iex
#Delete Junction
cmd.exe /c "rmdir C:\shadowcopy\ & exit"
}
The error logged by robocopy for every PST file is:
ERROR 33 (0x00000021) [...]The process cannot access the file because another process has locked a portion of the file.
How is this possible? Aren't Snapshots supposed to be read-only? Why does it work fine when doint it by hand in file explorer?

Using the matched wildcards in cmd

Can we access the matched character in wildcards?
I have some files in my current directory name as Labx.pdsprj and I want to copy them to a subfolder in the same directory based on their file names such that "Lab3.pdsprj" goes to the subfolder ".//subfolder_name//lab3" as ".//subfolder_name//lab3//Lab3.pdsprj"
I was trying something like
copy Lab?.pdsprj .//subfolder_name//lab(something here to access the matched number)
Its not necessary to use the above command only, any help is appreciated.
This may seem excessive if your requirement is not to have a case difference in the filename "Lab*" and the subdirectory "lab" as indicated by #dave_thompson_085. Although, that solution presumes that the "lab*" subdirectory already exists. I could be changed to do this.
FOR %%A IN (Lab?.pdsprj) DO (
MKDIR "%%~nA"
COPY %%A .\subfolder\%%~nA\%%~nxA
)
If there must be a case difference, this could be used. This will run on a windows command-line batch-file running under cmd. If you are on a supported Windows system, PowerShell was installed with it on the system.
powershell -NoLogo -NoProfile -File "C:\src\t\Do-CopyPdsprjFiles.ps1"
=== C:\src\t\Do-CopyPdsprjFiles.ps1
Get-ChildItem -File -Filter 'Lab*.pdsprj' |
ForEach-Object {
if ($_.Name -match 'Lab(\d+).pdsprj') {
$LabNumber = $Matches[1]
$LabDir = Join-Path -Path '.' -ChildPath "lab$($LabNumber)"
if (-not (Test-Path -Path $LabDir)) { mkdir $Labdir | Out-Null }
Copy-Item -Path $_.FullName -Destination $LabDir
}
}

Execute PS from bat for Intune Win32

I am so confused and actually also not so familiar with PS and bat after my troubles with them.
I want to set the Lockscreen in Windows 10 with Intune through an IntuneWin file (WIN32 application).
I have a folder with the image, which I want to set, a copy.bat which should copy the image in the directory and also execute the PS file for setting the login image and a del.bat for deleting the image.
copy.bat
md %AllUsersProfile%\sz
copy /Y Wallpaper.jpg %AllUsersProfile%\sz
powershell -ExecutionPolicy Bypass -File Set-Lockscreen.ps1 -verb RunAs
del.bat
del /Y %AllUsersProfile%\sz\Wallpaper.jpg
Set-Lockscreen.ps1
$RegKeyPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\PersonalizationLS"
$LockScreenPath = "LockScreenImagePath"
$LockScreenStatus = "LockScreenImageStatus"
$LockScreenUrl = "LockScreenImageUrl"
$StatusValue = "1"
$path = "C:\ProgramData\Elinvar"
$LockScreenImageValue = "C:\ProgramData\sz\Wallpaper.jpg"
sIf ((Test-Path -Path $path) -eq $false)
{
New-Item -Path $path -ItemType directory
}
if (!(Test-Path $RegKeyPath))
{
Write-Host "Creating registry path $($RegKeyPath)."
New-Item -Path $RegKeyPath -Force | Out-Null
}
New-ItemProperty -Path $RegKeyPath -Name $LockScreenStatus -Value $StatusValue -PropertyType DWORD -Force | Out-Null
New-ItemProperty -Path $RegKeyPath -Name $LockScreenPath -Value $LockScreenImageValue -PropertyType STRING -Force | Out-Null
New-ItemProperty -Path $RegKeyPath -Name $LockScreenUrl -Value $LockScreenImageValue -PropertyType STRING -Force | Out-Null
RUNDLL32.EXE USER32.DLL, UpdatePerUserSystemParameters 1, True
I pack all these files with Microsoft Win32 Content Prep Tool and upload this in Intune as Win32 file.
Upload works, assigning to a group works, installation is successful. All good so far, I thought.
If I check the directory, the image is in %AllUsersProfile%\sz.
But when I check the reg, the entry is not set.
When I run the copy.bat file manually, It doesn't work. Only when I run it as administrator.
When I run the last line in cmd as administrator, so
powershell -ExecutionPolicy Bypass -File Set-Lockscreen.ps1 -verb RunAs
It works as well.
I think Intune is not running the script as administrator.
In Intune there is no configuration to say, run this command as administrator.
Maybe with a syntax? Does anyone know this?
Something like
copy.bat RunAs
I also export the reg file and import this with
reg import PersonalizationLS.reg
It didn't work.
I think there must be a way to execute the installation command in intune to run the script as admin.
It needs just for the last line the administrator privilege , md and copy work without administrator privileges. (same also for important reg file).

Copy all .jpg from subfolders to a single folder by cmd

I have a folder that has 148 folders in it, and in each of these folders they have a .jpg file. I need to get all these .jpg and put in a single folder
each folder is at least 1 .jpg
I can do this on Linux as well
`#!/bin/bash
for file in `find source -name * .jpg`;
of the mv "$ file" Destination;
done;
but I can not play this in Windows. Only the find command that I can reproduce the same result: dir /S /B *.jpg
for /r %f in (*.jpg) do move %f %destination%
Note: This is the interactive version. In a command script, you need to protect the %f's from too-early variable substitution.
for /r %%f in (*.jpg) do move %%f %destination%
Another way to do it using PowerShell. When you see that the files are being moved as you expect, remove the WhatIf from the Move-Item cmdlet.
Get-ChildItem -Recurse -File -Filter '*.jpg' |
ForEach-Object { Move-Item -Path $_.FullName -Destination 'C:\the\other\dir' -WhatIf }
You can run this in a cmd.exe shell or .bat script.
powershell -NoLogo -NoProfile -Command ^
"Get-ChildItem -Recurse -File -Filter '*.jpg' |" ^
"ForEach-Object { Move-Item -Path $_.FullName -Destination 'C:\the\other\dir' -WhatIf }"
The easiest way to achieve this is in Windows is to open to root folder with the Windows Explorer at which you want to start searching all the elements. Then go to the small input field for searching and enter *.jpg the result will show all the jpg in the root folder and all subfolders. Then you can simply copy and paste the files to your destination folder.

Bat script to retrieve folder size (windows)

I need to write a script .bat that give me the free space of a certain disk and the detail of all folders with the relative dimension and write it in a simple text file (just to check the distribution of used space).
Thanks a lot in advance!
dir /a /s | findstr /b /c:" " > file.txt
The FileSystemObject can do this for you. It is accessible from PowerShell (among other sources).
PowerShell -NoProfile -Command "$fso = New-Object -COMObject Scripting.FileSystemObject; Get-ChildItem YOUR_ROOT_DIRECTORY -Recurse -Directory | %% { $f = $fso.GetFolder($_.FullName); '{0},{1}' -f $f.Size,$_.FullName };"

Resources