delete windows.old remotely with powershell - windows

at the moment in our company we are upgrading our windows 10 to the newest built. after the upgrade we have the windows.old folder directly under c: sometimes this folder is extremly big. how can i delete this folder remotely with powershell.
if i try to delete this folder with the explorer with \pc-name\c$ i don't have the permissions. now i want to get the acl for the folder and all subfolders with powershell but i only get the acl for the top folder. how can i get it working for the complete directory. is there any other way to delete windows.old remotly?
$computername = read-host "enter pc"
$script = {
# set ErrorAction to 'Stop' in order to catch errors
$oldErrorAction = $ErrorActionPreference
$ErrorActionPreference = 'Stop'
# you're now running this on the remote pc, so use local path
$path = Get-ChildItem -Directory -Path "C:\windows.old\" -recurse
try {
$acl = Get-Acl -path $path.FullName
$accessrule = [System.Security.AccessControl.FileSystemAccessRule]::new('username', 'FullControl', 'ContainerInherit,ObjectInherit', 'None', 'Allow')
$acl.SetAccessRule($accessRule)
$acl | Set-Acl -path $path.FullName
# output the message
"{0}`t{1} success" -f (Get-Date).ToString(), $env:COMPUTERNAME
}
catch {
"{0}`t{1} failed" -f (Get-Date).ToString(), $env:COMPUTERNAME
}
# restore previous ErrorAction
$ErrorActionPreference = $oldErrorAction
}
$result = Invoke-Command -ComputerName $computername -ScriptBlock $script
if ($result -ne $null)
{
write-host "sucess" -ForegroundColor "green"
}
else
{
write-host "no success" -ForegroundColor "red"
}

Related

Automate user homedirectory creation Powershell

I'm automating the process of creating LocalUsers on Windows systems. So far I used the Microsoft docs on New-LocalUser which has worked fine to create the account, this is my code so far:
function New-AdminUser {
param(
[Parameter(Position=0)]
[string] $UNameLocal,
[Parameter(Position=1)]
[string] $UDescription,
[Parameter(Position=2)]
[System.Security.SecureString] $Password
)
New-LocalUser -Name $UNameLocal -Description $UDescription -Password $Password -AccountNeverExpires -Confirm
Add-LocalGroupMember -Group "Administrators" -Member $UNameLocal
}
But this command does not actually generate the homedirectory in C:\Users\username.
I can create this by manually logging into the created user, but I want to automate this in Powershell. I couldn't find anything in the LocalAccounts module.
Is there any way to automate local account setup in Windows 10 using Powershell, without having to manually log in to a new account?
If you start a process (cmd /c) as the created user, it will create his profile. Add this to your function:
$Cred = New-Object System.Management.Automation.PSCredential ("$UNameLocal", $Password)
Start-Process "cmd.exe" -Credential $Cred -ArgumentList "/C" -LoadUserProfile
Here is the code:
param([Parameter(Mandatory=$true)][String]$samAccountName)
$fullPath = "\\srv2012r2\Users\{0}" -f $samAccountName
$driveLetter = "Z:"
$User = Get-ADUser -Identity $samAccountName
if($User -ne $Null) {
Set-ADUser $User -HomeDrive $driveLetter -HomeDirectory $fullPath -ea Stop
$homeShare = New-Item -path $fullPath -ItemType Directory -force -ea Stop
$acl = Get-Acl $homeShare
$FileSystemRights = [System.Security.AccessControl.FileSystemRights]"Modify"
$AccessControlType = [System.Security.AccessControl.AccessControlType]::Allow
$InheritanceFlags = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit, ObjectInherit"
$PropagationFlags = [System.Security.AccessControl.PropagationFlags]"InheritOnly"
$AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule ($User.SID, $FileSystemRights, $InheritanceFlags, $PropagationFlags, $AccessControlType)
$acl.AddAccessRule($AccessRule)
Set-Acl -Path $homeShare -AclObject $acl -ea Stop
Write-Host ("HomeDirectory created at {0}" -f $fullPath)
}
and here is the reference:
https://activedirectoryfaq.com/2017/09/powershell-create-home-directory-grant-permissions/

powershell: delete files previously used as argument inside script

I need to periodically scan a folder for new fontfiles to install and delete them afterwards using a powershell script.
During processing I want to skip already installed files and to achieve that I need to resolve the "real" fontname of the provided file.
I figured out everything and it seems to work everything but the file deletion.
The deletion did work until I added the font name resolution using this GlythTypeInterface Object. It seems like the invoked object does "file lock" the fontfile resulting in an UnauthorizedAccessException.
Thats why I tried some garbage collection stuff I found but I can't make it work.
My code so far:
Add-Type -AssemblyName PresentationCore
$FONTS = 0x14
$Path="C:\_fonts_to_install"
$FontItem = Get-Item -Path $Path
$FontList = Get-ChildItem -Path "$FontItem\*" -Include ('*.fon','*.otf','*.ttc','*.ttf')
$objShell = New-Object -ComObject Shell.Application
$objFolder = $objShell.Namespace($FONTS)
$Fontdir = dir $Path
$username = $env:UserName
foreach($File in $FontList) {
$try = $true
$installedFonts = #(Get-ChildItem C:\Users\$username\AppData\Local\Microsoft\Windows\Fonts | Where-Object {$_.PSIsContainer -eq $false} | Select-Object basename)
$fontObject = New-Object -TypeName Windows.Media.GlyphTypeface -ArgumentList $File.fullname
$fontName = $fontObject.Win32FamilyNames.Values
Write-Host $fontName
$fontObject = $null
Remove-Variable fontObject
foreach($font in $installedFonts)
{
if ($font -match $fontName)
{
$try = $false
}
}
if ($try)
{
$objFolder.CopyHere($File.fullname)
}
Write-Host $File
Remove-Item $File -Force -Verbose
}

Continue powershell script execution after system restart from last execution point

What i'm trying to do ?
Create four files in local disk in the following order.
Note : In my local machine and not in any server remotely.
Three files to be created
Restart the system
On system startup create another file
Script i have used.
get-job | remove-job -Force
function create-file {
Param ([string] $a)
$p = "D:\" + $a
Write-Host $p
if (!(Test-Path $p))
{
New-Item -path D:\$a -type "file" -value "my new text"
Write-Host "Created new file and text content added"
}
else
{
Add-Content -path D:\$a -value "new text content"
Write-Host "File already exists and new text content added"
}
}
Workflow New-ServerSetup
{
create-file "one.txt"
create-file "two.txt"
create-file "three.txt"
Restart-Computer -ComputerName $env:COMPUTERNAME -Wait
Start-Sleep -Seconds 7
create-file "four.txt"
Unregister-ScheduledJob -Name NewServerSetupResume
}
$adm = "####"
$pwd = ConvertTo-SecureString -String "####" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential($adm, $pwd)
$AtStartup = New-JobTrigger -AtStartup
Register-ScheduledJob -Name NewServerSetupResume -Credential $cred -Trigger $AtStartup -ScriptBlock {Import-Module PSWorkflow; Get-Job -Name NewSrvSetup -State Suspended | Resume-Job}
New-ServerSetup -JobName NewSrvSetup
Issues i'm facing
The execution returns Cannot wait for local computer to restart
i'm new to powershell things if any mistakes burden me.
Thanks in advance.
Schedule a job first, then reboot without waiting.

Changing share permissions using Powershell

I'm trying to modify the share permissions of share drives on a bunch of windows servers which are running either 2008 R2 or 2012.
I worked up a script which you can find here:
Import-Module ActiveDirectory
$list = Get-ADComputer -Filter 'SamAccountName -like "*FP*"' | Select -Exp Name
foreach ($Computer in $list)
{
Grant-SmbShareAccess -Name User -CimSession Server -AccountName "username" -AccessRight Full -confirm:$false
$acl = (Get-Item \\$Computer\d$\User ).GetAccessControl('Access')
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule ("Corp\uc4serv","FullControl","ContainerInherit, ObjectInherit","None","Allow")
$acl.AddAccessRule($rule)
Set-Acl \\$Computer\d$\User $acl
Write-Host -ForegroundColor DarkGreen "Permissions granted on $Computer"
}
Write-Host -ForegroundColor DarkBlue "Command Has Completed"
But it doesn't work on 2008 servers presumably because they can't run the Get-SmbShareAccess cmdlet.
What I'm trying to do is very similar to this post here: How to set share permissions on a remote share with Powershell? but specifically on Windows servers.
I also found this code on a website (http://windowsitpro.com/powershell/managing-file-shares-windows-powershell):
$acl = Get-Acl `
\\servername\c$\Users\username\sharetest
$permission = "corp\uc4serv","FullControl","Allow"
$accessRule = New-Object `
System.Security.AccessControl.FileSystemAccessRule `
$permission
$acl.SetAccessRule($accessRule)
$acl |
Set-Acl \\servername\c$\Users\username\sharetest
But this just sets the Security on the share instead of the share permissions.
I also looked into using the Net Share command but in order to change share permissions with that, it has to delete and re-create the share drive completely.
You can use "Net Share". Use Invoke-Command to run it on each remote server.
Source - https://social.technet.microsoft.com/Forums/windowsserver/en-US/3edcabac-f1a8-4c4a-850c-8ba4697930a2/using-net-share-within-powershell
Example
Source - $server = "MYSRV" ; $user = "username" ; $SrvPath = "E:\Users\$user"
$sb = {
param($User,$SrvPath)
NET SHARE $User$=$SrvPath "/GRANT:Domain Admins,FULL" "/GRANT:$User,CHANGE" /REMARK:"Home folder for $SrvPath"
}
Invoke-Command -Computername "$Server" -ScriptBlock $sb -ArgumentList $user,$SrvPath

Run powershell script with elevated command

I have an autologon Powershell script that I'd like to run as admin when I double click on it. I tried to use different scripts but I'm out of luck.
For example:
Start-Process PowerShell –Verb RunAs
Would open another Powershell screen as administrator but without the original script that I wanna run which is:
net accounts /minpwlen:0
net user TPUser /add
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' -Name AutoAdminLogon -Value 1
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' -Name DefaultUserName -Value "TPUser"
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' -Name DefaultPassword -Value ""
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' -Name DefautDomainName -Value ""
copy c:\temp\OP.rdp c:\Users\Public\Desktop
pause
Any idea how can I get this to work ?
You are in luck because I was fighting with this issue for some time, what you need to do is make it take note of where it is at and when it starts back up the shell as an admin it needs to execute the script.
Function Test-IsAdmin {
[cmdletbinding()]
Param()
Write-Verbose "Checking to see if current user context is Administrator"
If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.NTAccount] "[WriteGroupHere]"))
{
Write-Warning "You are not currently running this under an Administrator account! `nThere is potential that this command could fail if not running under an Administrator account."
Write-Verbose "Presenting option for user to pick whether to continue as current user or use alternate credentials"
#Determine Values for Choice
$choice = [System.Management.Automation.Host.ChoiceDescription[]] #("Use &Alternate Credentials","&Continue with current Credentials")
#Determine Default Selection
[int]$default = 0
#Present choice option to user
$userchoice = $host.ui.PromptforChoice("Warning","Please select to use Alternate Credentials or current credentials to run command",$choice,$default)
#$workingDir = $PSCommandPath
#$PSCommandPath
Write-Debug "Selection: $userchoice"
#Determine action to take
Switch ($Userchoice)
{
0
{
#Prompt for alternate credentials
Write-Verbose "Prompting for Alternate Credentials"
$Credential = Get-Credential
#Write-Output $Credential
#We are not running "as Administrator" - so relaunch as administrator
Start-Process powershell.exe -ArgumentList "$PSCommandPath" -Credential $Credential
#-WorkingDirectory $workingDir
exit
}
1
{
#Continue using current credentials
Write-Verbose "Using current credentials"
Write-Output "CurrentUser"
}
}
}
Else
{
Write-Verbose "Passed Administrator check"
#$Host.UI.RawUI.WindowTitle = "Custom Powershell Environment" +
#$Host.UI.RawUI.BackgroundColor = "DarkBlue"
}
}
with this just put it in the top of your script and call the function, and you will need to change the group that it checks to know if you are an admin or not, I was using an AD group to check since it was a more functional way for me.
I have used the following before to re-launch as script as admin but there is not stopping the UAC prompt:
function IsAdministrator
{
$Identity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$Principal = New-Object System.Security.Principal.WindowsPrincipal($Identity)
$Principal.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)
}
function IsUacEnabled
{
(Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\System).EnableLua -ne 0
}
#
# Main script
#
if (!(IsAdministrator))
{
if (IsUacEnabled)
{
[string[]]$argList = #('-NoProfile', '-NoExit', '-File', $MyInvocation.MyCommand.Path)
$argList += $MyInvocation.BoundParameters.GetEnumerator() | Foreach {"-$($_.Key)", "$($_.Value)"}
$argList += $MyInvocation.UnboundArguments
Start-Process PowerShell.exe -Verb Runas -WorkingDirectory $pwd -ArgumentList $argList
return
}
else
{
throw "You must be administrator to run this script"
}
}
I actually used this script on top of mine and it worked perfectly.
# ##########################################
# Determine if we have Administrator rights
Write-Host 'Checking user permissions... '
$windowsID = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$windowsSecurityPrincipal = New-Object System.Security.Principal.WindowsPrincipal($windowsID)
$adminRole = [System.Security.Principal.WindowsBuiltInRole]::Administrator
If (!($windowsSecurityPrincipal.IsInRole($adminRole))) {
Write-Warning 'Current user does not have Administrator rights'
Write-Host 'Attempting to copy files to temporary location and restarting script'
# Get random file name
Do {
$temp = [System.IO.Path]::GetTempPath() + [System.IO.Path]::GetRandomFileName()
} Until (!(Test-Path -LiteralPath "$temp"))
# Create directory
Write-Host 'Creating temp directory... ' -NoNewLine
New-Item -Path "$temp" -ItemType 'Directory' | Out-Null
Write-Host 'done.'
# Copy script to directory
Write-Host 'Copying script to temp directory... ' -NoNewLine
Copy-Item -LiteralPath "$($myInvocation.MyCommand.Path)" "$temp" | Out-Null
Write-Host 'done.'
$newScript = "$($temp)\$($myInvocation.MyCommand.Name)"
# Start new script elevated
Write-Host 'Starting script as administrator... ' -NoNewLine
$adminProcess = New-Object System.Diagnostics.ProcessStartInfo
$adminProcess.Filename = ([System.Diagnostics.Process]::GetCurrentProcess()).Path
$adminProcess.Arguments = " -File `"$newScript`""
$adminProcess.Verb = 'runas'
Try {
[System.Diagnostics.Process]::Start($adminProcess) | Out-Null
}
Catch {
Write-Error 'Could not start process'
Exit 1
}
Write-Host 'done.'
Exit 0
}

Resources