Cannot figure out why my Powershell script is getting permission errors - powershell

I cannot figure out why im getting permission errors, even though im running the script as a Domain Admin, which is in the full control group on the files/folders im trying to delete. UAC is not enabled on the pc the script is running from. I get the same errors no matter if i use enter-PSsession to the file server itself.
Its got to be how i approached the solution...ive tried other scripts that im not experienced enough to edit, they used a try/catch method with get-wmiobject and then .delete() command, and that script worked great...with no permission problems, it deletes profiles like a charm...and thats with the same credentials as my homemade script...So i really feel its not a true credential problem, and more to do with a shortcoming of the way im using the remove-item cmdlet.
here is my script...its my first homemade, not copy/pasted script, so feel free to point out the obvious bad practices... here is the script, and the errors will be below. The way i wrote this script is to try each individual command separately, then tie them together, that may be why some of it may be redundant.
##This process deletes ntuser.dat files and user profile folders
$users = (Read-Host "Enter each user (separate with comma)").split(',') | % {$_.trim()}
foreach ($user in $users) {
$datfile = "ntuser.dat"
$servers = Get-Content C:\servers.txt
$path1 = "\\fileserver\d$\TSEProfiles\$user.DOMAIN"
$path2 = "\\fileserver\d$\TSEProfiles\$user.DOMAIN.V2"
## Checks for ntuser.dat file in specified folders, if true, delete.
## Checking 4 locations on fileserver
If (Test-Path \\fileserver\d$\TSEProfiles\$user.DOMAIN\$datfile){
Remove-Item $path1\$datfile -recurse -force
}
if (Test-Path \\fileserver\d$\TSEProfiles\$user.DOMAIN.V2\$datfile){
Remove-Item $path2\$datfile -recurse -force
}
If (Test-Path \\fileserver\d$\roamingprofiles\$user.DOMAIN\$datfile){
Remove-Item $path1\$datfile -recurse -force
}
If (Test-Path \\fileserver\d$\roamingprofiles\$user.DOMAIN.V2\$datfile){
Remove-Item $path2\$datfile -recurse -force
}
## Checking 8 locations, if true, delete.
foreach ($server in $servers) {
If (Test-Path \\$server\c$\users\$user -PathType Container){
Remove-Item \\$server\c$\users\$user -recurse -force
}
}
}
Remove-Item : Access to the path '\\APPS3\c$\users\realdomainuser\AppData\Local\Application Data' is denied.
At C:\Users\admin\Documents\zoink.ps1:35 char:2
+ Remove-Item \\$server\c$\users\$user -recurse -force
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (\\APPS3\c$\users\realdomainuser:String) [Remove-Item], UnauthorizedAccessException
+ FullyQualifiedErrorId : RemoveItemUnauthorizedAccessError,Microsoft.PowerShell.Commands.RemoveItemCommand
Remove-Item : Access to the path '\\APPS4\c$\users\realdomainuser\AppData\Local\Application Data' is denied.
At C:\Users\admin\Documents\zoink.ps1:35 char:2
+ Remove-Item \\$server\c$\users\$user -recurse -force
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (\\APPS4\c$\users\realdomainuser:String) [Remove-Item], UnauthorizedAccessException
+ FullyQualifiedErrorId : RemoveItemUnauthorizedAccessError,Microsoft.PowerShell.Commands.RemoveItemCommand
django - THis is the delete profile output after running the local machine policy script. still getting auth errors.
Remove-Item : Access to the path '\\APPS7\c$\users\someuser\AppData\Local\Application Data' is denied.
At C:\Users\admin\Documents\zoink.ps1:35 char:2
+ Remove-Item \\$server\c$\users\$user -recurse -force
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (\\APPS7\c$\users\someuser:String) [Remove-Item], UnauthorizedAccessException
+ FullyQualifiedErrorId : RemoveItemUnauthorizedAccessError,Microsoft.PowerShell.Commands.RemoveItemCommand

I once was having issues running scripts due to permissions on some of our Citrix VM's that didn't have powershell scripts running, however I was able to run bat files so I created a PS scripted wrapped inside a bat file.
echo "Killing IE"
powershell -Command "stop-process -processname iexplore"
While it is nowhere near an elegant solution it is an easy hack that serves it's purpose.

Try running this script. This is an example of permanently setting your local machine policy for scripts:
# SetExecutionPolicyToRemoteSigned.ps1
Write-Output "Setting local Powershell policy to RemoteSigned"
Write-Output ""
Set-ExecutionPolicy -scope CurrentUser Undefined -Force
#Set-ExecutionPolicy -scope Process Undefined -Force
Set-ExecutionPolicy -scope LocalMachine Undefined -Force
Set-ExecutionPolicy -scope CurrentUser RemoteSigned -Force
#Set-ExecutionPolicy -scope Process RemoteSigned -Force
Set-ExecutionPolicy -scope LocalMachine RemoteSigned -Force
Write-Output "Finished."
Get-ExecutionPolicy -list
Start-Sleep -s 10
It will result in the following output:
PS C:\Users\qa> Get-ExecutionPolicy -list
Scope ExecutionPolicy
----- ---------------
MachinePolicy Undefined
UserPolicy Undefined
Process RemoteSigned
CurrentUser RemoteSigned
LocalMachine RemoteSigned
Then, you can just run a script like this one without a policy prompt. Best of all, the policy should survive rebooting your system :
# Filename: Hello.ps1
Write-Host
Write-Host 'Hello World!'
Write-Host "Good-bye World! `n"
# end of script
And another example of running a script:
powershell.exe -ExecutionPolicy Bypass -NoLogo -NonInteractive -NoProfile
-WindowStyle Hidden -File script_name

Related

how to delete a folder using invoke command in powershell

First time asking a question here after using it for a long time.
I'm currently making a powershell script to delete userdata when they left the company for a month.
I already tried deleting the folder using the normal remove-item and this works however this is a very slow process when going over the network.
I then found out about the invoke-command function which can run on a remote computer.
Now i can't seem to get this working.
I keep getting the error that the path is not found.
However it seems like powershell is changing my path.
How can i prevent this from happening?
Cannot find path 'C:\Users\admcia\Documents\P$\PERSONAL\JOBA' because it does not exist.
+ CategoryInfo : ObjectNotFound: (C:\Users\admcia...$\PERSONAL\JOBA:String) [Remove-Item], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.RemoveItemCommand
+ PSComputerName : ODNDATA
my code is the following:
Note that P$ is the local drive letter on the server.
Also note That $item.SamAccountName is used for creating foldername. (we use Samaccountname as the name of the users folder.
$localPath1 = "P$" + "\PERSONAL\" + $item.SamAccountName
$serverName = "Remotecompter"
Invoke-Command -ComputerName $serverName -ScriptBlock { Remove-Item $using:localPath1 -Force -Recurse -Confirm:$false }
If as seen from your local machine, the drive is \\Remotecomputer\P$\, then for the remote computer (where the code is executed) the path is just P:\.
To combine strings into a path, I would suggest you better use the Join-Path cmdlet rather than concatenating the strings with '+'
Try
$localPath1 = Join-Path -Path 'P:\PERSONAL' -ChildPath $item.SamAccountName
$serverName = "Remotecompter"
Invoke-Command -ComputerName $serverName -ScriptBlock { Remove-Item $using:localPath1 -Force -Recurse -Confirm:$false }
You can use -ArgumentList in Invoke command,
Invoke-Command -ComputerName $serverName -ScriptBlock {
param($localPath1)
Remove-Item $localPath1 -Force -Recurse -Confirm:$false
} -ArgumentList($localPath1)
make sure your path is correct, and if it does not work try to hardcode the path in your code.

Powershell. Loop through certificate store and remove cert based on thumbprint

I have a simple powershell script that runs via a GPO startup script.
As you can see, it takes a thumbprint an loops through the cert store and removes it if it finds it.
#thumbprint of certificate to remove
$thumb = "abcdef444444857694df5e45b68851868"
#loop through all the certs stores looking for $thumb and remove if found
get-childitem Cert:/ -recurse | where-object {$_.thumbprint -contains "$thumb"} | remove-item
When I run the above two lines from an elevated powershell prompt it works!
If I reboot my machine and let the GPO do it's thing OR if I run from an elevated powershell prompt the below:
powershell.exe -Noninteractive -ExecutionPolicy Bypass -Noprofile -file "\\mydomain.corp\SysVol\mydomain.corp\Policies\{7086C68E-D509-9169-A02B-56579826C234}\Machine\Scripts\Startup\removecerts.ps1"
Then I get the following:
remove-item : The operation is on user root store and UI is not allowed.
Any help would be appreciated.
I suspect it's prompting for confirmation, which it can't when running headless.
Adding the -Force parameter should override the confirmation prompt:
... | Remove-Item -Force
Alternatively, set the $ConfirmPreference variable to None before attempting to remove the certificates to avoid the prompt:
$ConfirmPreference = 'None'
<# rest of script goes here #>
script now looks like this:
$ConfirmPreference = 'None'
#thumbprint of certificate to remove
$thumb = "abcdef444444857694df5e45b68851868"
#loop through all the certs stores looking for $thumb and remove if found
get-childitem Cert:/ -recurse | where-object {$_.thumbprint -contains "$thumb"} | remove-item -Force
And my error:
remove-item : The operation is on user root store and UI is not allowed.
At \\mydomain.corp\SysVol\mydomain.corp\Policies\{7086C68E-D509-9169-A02B-56579826C234}\Machine\Scripts\Startup\removecerts.ps1:16 char:88
+ ... {$_.thumbprint -match "$thumb"} | remove-item -Force
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Remove-Item], InvalidOperationException
+ FullyQualifiedErrorId : System.InvalidOperationException,Microsoft.PowerShell.Commands.RemoveItemCommand
```

Several folders into a zip with PowerShell

I have several folders dir_01, dir_02, dir_03 that I want to backup in a zip file, say, backup.zip. This has to be saved in a folder with today's date. I need to get a .bat file to do the job; no additional third party executables allowed.
Here I found how to create a folder with today's date, but I am having problems to pass $destination to -DestinationPath. I created a .bat that calls PowerShell. Code giving me problems:
powershell.exe $destination = New-Item -Path 'C:\path\to\destionation' -ItemType Directory -Name ("$(Get-Date -f yyyy-MM-dd)")
powershell.exe -nologo -noprofile -command Compress-Archive -Path 'C:\path\dir_01', 'C:\path\dir_02', 'C:\path\dir_03' -DestinationPath $destination\backup.zip -Force
The error message is the following:
New-Object : Exception calling ".ctor" with "2" argument(s): "Access to the path 'C:\backup.zip' is denied."
At
C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\Microsoft.PowerShell.Archive\Microsoft.PowerShell.Archive.psm1:729
char:30
+ ... ileStream = New-Object -TypeName System.IO.FileStream -ArgumentList $ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [New-Object], MethodInvocationException
+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand
However, the code works if I hard-code the path to destination, like this:
powershell.exe -nologo -noprofile -command Compress-Archive -Path 'C:\path\dir_01', 'C:\path\dir_02', 'C:\path\dir_03' -DestinationPath 'C:\whole\path\backup.zip' -Force
But doing so, I'm unable to save backup.zip in today's folder.
Question: How can I save backup.zip in the folder that I created with today's date?
You can perform both commands in the same PowerShell session by separating them with a semicolon.
powershell.exe $destination = New-Item -Path 'C:\path\to\destionation' -ItemType Directory -Name ("$(Get-Date -f yyyy-MM-dd)"); Compress-Archive -Path 'C:\path\dir_01', 'C:\path\dir_02', 'C:\path\dir_03' -DestinationPath $destination\backup.zip -Force
That will launch PowerShell and have it create the folder and then zip things into it in the same session, rather than create a session, in that session create a folder, close the session, start a new PowerShell session, zip things up, close the second session.

How to Run script with admin rights to change execution policy

See below script:
I need to launch this script with admin rights embedded inside of the script to set execution policy to unrestricted and then at the end of the script set it back. From what I've found so far this is either not possible or very difficult to do. I'm hoping there is an easier way to do this. The users that will be running this script do not have admin rights on their PC's so they will not be able to elevate and manually run from inside of powershell.
Stop-process -Name OUTLOOK -ErrorAction SilentlyContinue -Force
Stop-process -Name communicator -ErrorAction SilentlyContinue -Force
Stop-process -Name lync -ErrorAction SilentlyContinue -Force
Stop-Process -Name UcMapi -ErrorAction SilentlyContinue -Force
Stop-Process -Name skypehost -ErrorAction SilentlyContinue -Force
Stop-Process -Name searchprotocolhost -ErrorAction SilentlyContinue -Force
$OstPath = "c:\users\$([environment]::username)"+ "\AppData" + "\local" + "\Microsoft" + "\Outlook"
$ost = get-ChildItem $OstPath | where { $_.Extension -eq ".ost"}
$ost | remove-Item -force
Start-Process Outlook
if (Test-Path 'C:\Program Files (x86)\Microsoft Office\office15\lync.exe')
{
Start-Process 'C:\Program Files (x86)\Microsoft Office\office15\lync.exe'
}
Else
{
write-host "Lync is not installed"
if (Test-Path 'C:\Program Files (x86)\Microsoft Office Communicator')
{
Start-Process 'C:\Program Files (x86)\Microsoft Office Communicator\communicator.exe'
}
Else
{
write-host "Communicator is not installed"
}
}
You can use:
$GBL_Username = "Here type your username"
$GBL_Password = ConvertTo-SecureString –String "Here type your password in plain text" –AsPlainText -Force
$GBL_Credential = New-Object –TypeName System.Management.Automation.PSCredential –ArgumentList $GBL_Username, $GBL_Password
Start-Process 'C:\Program Files (x86)\Microsoft Office\office15\lync.exe' -Credential $GBL_Credential
And use the variable $GBL_Credential with the second part (the execution of Office Comunicator)
A problem with this: the credential will show in plain text and, if someone try to edit the script with notepad, PowerShell ISE or other program, they can will see the passsword.
Have a good day.
From what I see in the script, there's no need to elevate. If this is only to overcome the ExecutionPolicy than your approach is wrong. ExecutionPolicy is there to prevent users run untrusted scripts. So far your script is one of those.
Correct way of doing it would be to sign your script with the certificate and set your ExecutionPolicy to Allsigned on all computers. Users will then only be able to run the signed scripts from now on.
If this is not possible, I see 2 options:
Users copy contents of the script and paste it into the powershell window
You set ExecutionPolicy to unrestricted. Keep in mind that users will still need to elevate if they try to do something serious, but for this script elevation is not necessary.
So all in all, ExecutionPolicy is there to prevent exactly what you are trying to do, so do not expect it will be easy to overcome. It's also not something that you turn off and on. You should think of what is acceptable for you and set it to appropriate level in your environment.

Delete broken link

I need to delete all the content of a folder which may include broken links among others. The folder path is provided by a variable. Problem is that PowerShell fails to remove the broken links.
$folderPath = "C:\folder\"
Attempt 1:
Remove-Item -Force -Recurse -Path $folderPath
Fails with error:
Remove-Item : Could not find a part of the path 'C:\folder\brokenLink'.
At line:1 char:1
+ Remove-Item -Force -Recurse -Path $folderPath
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (C:\folder\brokenLink:String) [Remove-Item], DirectoryNot
FoundException
+ FullyQualifiedErrorId : RemoveItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
Attempt 2:
Start-Job { cmd /c rmdir $folderPath }
Fails because $folderPath gets passed as is instead of its value:
Start-Job { cmd /c rmdir $folderPath } | select command
Command
-------
cmd /c rmdir $folderPath
Any suggestion besides using the .NET framework?
EDIT
By broken link I'm referring to a folder which points to a previously mounted partition, that doesn't exist anymore. The folder is still available but when attempting to navigate into it this error occurs because the destination doesn't exist anymore:
Error:
C:\folder\brokenLink refers to a location that is unavailable. It
could be on a hard drive on this computer, or on a network. Check to
make sure that the disk is properly inserted, or that you are
connected to the Internet or your network, and then try again. If it
still cannot be located, the information might have been moved to a
different location.
This will work:
$folderPath = "C:\folderContaingBrokenSymlinks\";
$items = ls $folderPath -Recurse -ea 0;
foreach($item in $items){
if($item.Attributes.ToString().contains("ReparsePoint")){
cmd /c rmdir $item.PSPath.replace("Microsoft.PowerShell.Core\FileSystem::","");
}
else{
rm -Force -Recurse $item;
}
}