Access To the Path is Denied (PowerShell Rename-Item Script)

10,416

You need to add an access control entry that grants you sufficient control, but to do that you first need to be the owner of the file. Administrators can make themselves the owner of any file, but the process doing the adjustment must have the SeTakeOwnershipPrivilege privilege enabled. Enabling that requires fiddling with unmanaged code, which Lee Holmes has done for us. I've reformatted and slightly tweaked his script, which you will need to save to a file (e.g. privs.ps1):

param(    ## The privilege to adjust. This set is taken from
    ## http://msdn.microsoft.com/en-us/library/bb530716(VS.85).aspx
    [ValidateSet(
        "SeAssignPrimaryTokenPrivilege", "SeAuditPrivilege", "SeBackupPrivilege",
        "SeChangeNotifyPrivilege", "SeCreateGlobalPrivilege", "SeCreatePagefilePrivilege",
        "SeCreatePermanentPrivilege", "SeCreateSymbolicLinkPrivilege", "SeCreateTokenPrivilege",
        "SeDebugPrivilege", "SeEnableDelegationPrivilege", "SeImpersonatePrivilege", "SeIncreaseBasePriorityPrivilege",
        "SeIncreaseQuotaPrivilege", "SeIncreaseWorkingSetPrivilege", "SeLoadDriverPrivilege",
        "SeLockMemoryPrivilege", "SeMachineAccountPrivilege", "SeManageVolumePrivilege",
        "SeProfileSingleProcessPrivilege", "SeRelabelPrivilege", "SeRemoteShutdownPrivilege",
        "SeRestorePrivilege", "SeSecurityPrivilege", "SeShutdownPrivilege", "SeSyncAgentPrivilege",
        "SeSystemEnvironmentPrivilege", "SeSystemProfilePrivilege", "SeSystemtimePrivilege",
        "SeTakeOwnershipPrivilege", "SeTcbPrivilege", "SeTimeZonePrivilege", "SeTrustedCredManAccessPrivilege",
        "SeUndockPrivilege", "SeUnsolicitedInputPrivilege")]
    $Privilege,
    $ProcessId = $pid,
    [Switch] $Disable
)

$definition = @'
using System;
using System.Runtime.InteropServices;
public class AdjPriv
{

[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall,
ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);

[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);

[DllImport("advapi32.dll", SetLastError = true)]
internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);

[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct TokPriv1Luid
{
public int Count;
public long Luid;
public int Attr;
}

internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
internal const int SE_PRIVILEGE_DISABLED = 0x00000000;
internal const int TOKEN_QUERY = 0x00000008;
internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;

public static bool EnablePrivilege(long processHandle, string privilege, bool disable)
{
bool retVal;
TokPriv1Luid tp;
IntPtr hproc = new IntPtr(processHandle);
IntPtr htok = IntPtr.Zero;
retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
tp.Count = 1;
tp.Luid = 0;
if(disable)
{
tp.Attr = SE_PRIVILEGE_DISABLED;
}
else
{
tp.Attr = SE_PRIVILEGE_ENABLED;
}
retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid);
retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
return retVal;
}
}
'@

$processHandle = (Get-Process -id $ProcessId).Handle
try { Add-Type $definition } catch {}
[AdjPriv]::EnablePrivilege($processHandle, $Privilege, $Disable)

If you haven't already, you'll need to follow the instructions in the Enabling Scripts section of the PowerShell tag wiki. Then we can put everything together:

.\privs.ps1 -Privilege SeTakeOwnershipPrivilege
$acl = Get-Acl C:\Windows\HelpPane.exe
$acl.SetOwner([System.Security.Principal.NTAccount]::new('Administrators'))
$rule = [System.Security.AccessControl.FileSystemAccessRule]::new('Administrators', 'FullControl', 'None', 'None', 'Allow')
$acl.AddAccessRule($rule)
Set-Acl C:\Windows\HelpPane.exe $acl

That adjusts the ACL, giving you permission to rename the file:

Rename-Item C:\Windows\HelpPane.exe HelpPane_.exe
Share:
10,416

Related videos on Youtube

jippyjoe4
Author by

jippyjoe4

Updated on September 18, 2022

Comments

  • jippyjoe4
    jippyjoe4 over 1 year

    I got annoyed with the F1 key bringing up Windows help all the time because I think it's pretty useless. So the solution is to rename the "HelpPane.exe" file in the "C:\Windows" directory to something else so that pressing F1 never does anything anymore. However, I would like to automate this with a script.

    Using PowerShell, I can try the following script:

    Rename-Item -Force -Path "C:\Windows\HelpPane.exe" -NewName "C:\Windows\HelpPane1.exe"
    

    However, whenever I run the script, whether as administrator or not, I receive the following error: enter image description here

    This is because Windows has some security permission on the file. I know that I can remove them manually by messing around in Properties/Security/Advanced, but I need an automated way to do this within the PowerShell script itself; I don't want to do this manually every time. Unfortunately, I'm not sure how to manage these types of advanced permission from directly within PowerShell.

    What do I need to add to my PowerShell script to make sure that the file gets renamed successfully? Thanks.

    For reference, I'm running Windows 10 Enterprise 1607 build 14393.

    • Ramhound
      Ramhound almost 6 years
      What permissions exactly are preventing you from renaming the file? Edit your question to include this vital information.
  • jippyjoe4
    jippyjoe4 almost 6 years
    This worked perfectly, thank you very much. I'm surprised it was this difficult.