Recently, I had a need to create a symbolic link while running a scan on some systems and found that there was not a native way in PowerShell to accomplish this. Now I can use mklink.exe to make this work, but this will only work under cmd.exe. This means that I cannot actually call mklink.exe under PowerShell.

mklink.exe

Instead, I have to first call cmd.exe followed by mklink.exe in order to access the command.

cmd.exe /c mklink.exe

So you might think that I would be satisfied with this result. Well, I am not. I shouldn’t have to rely on calling cmd.exe first before using mklink.exe to create a symbolic link. And thanks to using Pinvoke to get into the Win32 API, I do not have to accept this fate!

I had to add the ‘public’ keyword at the beginning so this function will be available when I add it into my session. This isn’t all of the code, just what was available on the site. I had to do a little C# coding to make this into a type that I can import into my PowerShell session using Add-Type.

Now I have a type that can be used to create a symbolic link. All it requires is a Path to use for the link and the actual SymName and then either a 0 (File) or a 1 (Directory) to decide what kind of symbolic link will be created. The resulting value is a boolean value that can be easily added into a If/Else statement to handle the rest of the actions.

The Process block (I am allowing pipeline input for the Path parameter) is where I use my type to create the symbolic link and watch for any issues during this process. As an added item, I will output an object showing the symbolic link and the target path that the link is referencing.

15 Responses to Creating a Symbolic Link using PowerShell

I’m trying to make a symbolic link to a shadow copy.
I can do this using mklink, e.g.:
mklink /D c:\temp\SB_C5_1 “\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy7”
(it will not be directly accessable through explorer, but robocopy can access it)
I cannot do this using you function, e.g.:
New-Symlink -Path \?\GLOBALROOT\Device\HarddiskVolumeShadowCopy7 -SymName “c:\temp\SBL_1” -Directory -Verbose
I get an error saying the path doesn’t exist.
Any way to get this to work?

Unfortunately, New-Item has some limitations. For example it can’t make symlink from shadow copy too… It seems that we must wait for some next PS version for complete implementation of functionality from MKLINK. ;o(

Thanks so much for your script. This is killer… I am, however, running into an issue.

I’ve been attempting to run this over a PSSession. I run a loop in which I connect to a pool of servers each in turn, run the script, then disconnect the session. I load the New-SymLink function on each iteration, since it needs be loaded into each session.

Using New-SymLink to create a local symlink works normally. For example, “new-symlink -symname c:\foo2 -path c:\foo” works great. But, if I attempt to symlink to a network location through the session, “new-symlink -SymName C:\foo2 -Path \server\foo”, it fails with the following error:

UAC is not enabled on these servers. Invoking mklink via cmd functions normally. I was hoping to do an all Powershell script to create these network path symlinks. I’ll fall back on the CMD version of my script for the time being, but I’d love to know if you have a suggestion to get around this issue.

Cool script, better than calling mklink or junction from PowerShell which is what I have been doing in the past. Perhaps a check for local administrative credentials or the #Requires -RunAsAdministrator tag could be used as the current error for not running with administrative credentials is not very descriptive.

Yes, that module is a great one and has those cmdlets available. But for those who cannot use 3rd party modules in their environment, this provides a way to still have be able to create the symbolic links without the need of the module. Also, this article provides a way to show people how this was built and where I was able to come up with the code to do so.