7

I need to create a Symlink that lives in user roaming AppData, and points to a folder on another local drive, which is user specific. I have tried both mklink and New-Item -ItemType SymbolicLink in PowerShell 5 and both require admin rights, which makes it pretty useless in this context. I also tried putting the user environment variable in the path, like this D:\C4R\%username%, but that doesn't work either. Is there a mechanism for doing SymLinks as a regular user? Or is the whole concept of SymLinks really an admin thing?

Gordon
  • 251

2 Answers2

8

You have to use the /J option

mklink /J <link> <target>

I don't know powershell, but this seems to work as well:

New-Item -Name <link> -ItemType Junction -Value <source>
T Nierath
  • 557
0

Most of the time, the answer provided above by @TNierath is ok, although not technically correct. The problem is that it suggests using Directory Junctions instead of Symbolic Links (see: "directory junction" vs "directory symbolic link"?). While the latter is most of the time a complete replacement for the former, sometimes you really need to create a symlink with an unescalated user. In Windows, it is managed by SeCreateSymbolicLinkPrivilege privilege.

Granting such permission requires escalation, but you can grant it outside of the current session, and the privilege persists until explicitly revoked. However, to grant it is not as easy.

Option 1: Carbon.Security

To grant privilege, run the following as an admin user. This WILL INSTALL Carbon.Security external (3rd-party) module, so you are warned.

Install-Module -Name 'Carbon.Security'
Import-Module -Name 'Carbon.Security'
Grant-Privilege -Identity $Env:UserName SeCreateSymbolicLinkPrivilege

Then check with:

Get-CPrivilege -Identity $Env:UserName

After that, you need to log out, restarting terminal won't help. Finlly, you would be able to create symlinks with either New-Item -Type SymbolicLink or mklink with your current user:

PS C:\Users\Username> New-Item -Type SymbolicLink -Target .\AppData\ -Name AppDataLink
Directory: C:\Users\Username


Mode LastWriteTime Length Name


d----l 2025-05-18 19:11 AppDataLink

Option 2: No external modules

There are several commands in the native Windows environment to work with permissions, most notably ACL-commands and Get-Privilege/Set-Privilege. There's also a Microsoft-maintained downloadable utilities pack containing accesschk command. However, the Get/Set-Privilege commands are not well-documented, and on my Windows 10 Home only one of them is working:

PS C:\Users\Username> Get-Privilege

Name Status


SeIncreaseQuotaPrivilege Enabled SeSecurityPrivilege Enabled SeTakeOwnershipPrivilege Enabled SeLoadDriverPrivilege Enabled SeSystemProfilePrivilege Enabled SeSystemtimePrivilege Enabled SeProfileSingleProcessPrivilege Enabled SeIncreaseBasePriorityPrivilege Enabled SeCreatePagefilePrivilege Enabled SeBackupPrivilege Enabled SeRestorePrivilege Enabled SeShutdownPrivilege Enabled SeDebugPrivilege Enabled SeSystemEnvironmentPrivilege Enabled SeChangeNotifyPrivilege EnabledByDefault, Enabled SeRemoteShutdownPrivilege Enabled SeUndockPrivilege Enabled SeManageVolumePrivilege Enabled SeImpersonatePrivilege EnabledByDefault, Enabled SeCreateGlobalPrivilege EnabledByDefault, Enabled SeIncreaseWorkingSetPrivilege Enabled SeTimeZonePrivilege Enabled SeCreateSymbolicLinkPrivilege Enabled SeDelegateSessionUserImpersonatePrivi... Enabled

↑ Working!

PS C:\Users\Username> Set-Privilege SeCreateSymbolicLinkPrivilege
Set-Privilege : Cannot bind parameter 'Privileges'. Cannot convert the "SeCreateSymbolicLinkPrivilege" value of type "S
ystem.String" to type "Pscx.Interop.TokenPrivilege".
At line:1 char:15
+ Set-Privilege SeCreateSymbolicLinkPrivilege
+               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Set-Privilege], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Pscx.Commands.Security.SetPrivilegeCommand

PS C:\Users\Username> $oTP = New-Object PSCX.Interop.TokenPriviliege New-Object : Cannot find type [PSCX.Interop.TokenPriviliege]: verify that the assembly containing this type is loaded. At line:1 char:8

  • $oTP = New-Object PSCX.Interop.TokenPriviliege
  •    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    • CategoryInfo : InvalidType: (:) [New-Object], PSArgumentException
    • FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewObjectCommand

↑ Not working!

Unfortunately, as of now, I have not tested this accesschk and cannot provide any useful help regarding it.

See also