Recentemente, eu tinha a necessidade de criar um link simbólico enquanto executava uma varredura em alguns sistemas e descobri que não havia uma maneira nativa no PowerShell para realizar isso. Agora eu posso usar o mklink.exe para fazer isso funcionar, mas isso só funcionará em cmd.exe. Isto significa que não posso realmente chamar mklink.exe sob PowerShell.
mklink.exe
![]()
Em vez disso, tenho de chamar primeiro cmd.exe seguido de mklink.exe para aceder ao comando.
cmd.exe /c mklink.exe
![]()
Por isso podem pensar que eu ficaria satisfeito com este resultado. Bem, eu não estou. Eu não deveria ter que confiar em chamar cmd.exe antes de usar o mklink.exe para criar um link simbólico. E graças a usar Pinvoke para entrar na API do Win32, eu não tenho que aceitar esse destino!
Sair para pinvoke.net, eu vejo sob o kernel32 que existe uma função chamada CreateSymbolicLink que atende ao que eu estou procurando.
![]()
O básico do que eu preciso está abaixo:
public static extern bool CreateSymbolicLink(strin
Tive de adicionar a palavra-chave ‘public’ no início para que esta função esteja disponível quando eu a adicionar à minha sessão. Isto não é todo o código, apenas o que estava disponível no site. Tive que fazer um pequeno código C# para fazer um tipo que eu possa importar para minha sessão PowerShell usando o Add-Type.
Add-Type @"using System;using System.Runtime.InteropServices; namespace mklink{ public class symlink { public static extern bool CreateSymbolicLink(string lpSymlinkFileName, string lpTargetFileName, int dwFlags); }}"@
| get-member -static
![]()
Agora eu tenho um tipo que pode ser usado para criar um link simbólico. Tudo o que ele requer é um Caminho para usar para o link e o verdadeiro SymName e depois ou um 0 (Arquivo) ou um 1 (Diretório) para decidir que tipo de link simbólico será criado. O valor resultante é um valor booleano que pode ser facilmente adicionado a uma declaração If/Else para lidar com o resto das ações.
::CreateSymbolicLink('C:\Users\Administrator\Desktop\SQL2008Install',"\dc1\SharedStorage\SQL 2008",1)
![]()
Localizando o link simbólico SQL2008Install, você vê pelos atributos que é um link simbólico como é rotulado como ReparsePoint:
![]()
Com isso, eu agora tenho um link simbólico no meu desktop que aponta para a pasta de instalação SQL2008 no meu servidor remoto.
Sendo que este método requer algum trabalho, é natural que isto se torne uma função reutilizável.
New-SymLink
Esta função faz basicamente o que lhe mostrei, mas de uma forma funcional que é portátil e mais fácil de usar. Isto permite que você crie um link simbólico para um diretório ou um arquivo.
A parte Begin da minha função envolve verificar se eu já carreguei meu tipo pinvoke e se não, adicionar o tipo usando Add-Type.
Begin { Try { $null = } Catch { Add-Type @" using System; using System.Runtime.InteropServices; namespace mklink { public class symlink { public static extern bool CreateSymbolicLink(string lpSymlinkFileName, string lpTargetFileName, int dwFlags); } }"@ }}
O bloco Process (Eu estou permitindo a entrada do pipeline para o parâmetro Path) é onde eu uso o meu tipo para criar o link simbólico e observar qualquer problema durante este processo. Como um item adicionado, eu irei sair um objeto mostrando o link simbólico e o caminho de destino que o link está referenciando.
Process { #Assume target Symlink is on current directory if not giving full path or UNC If ($SymName -notmatch "^(?::\)|(?:\\\w+\$)") { $SymName = "{0}\{1}" -f $pwd,$SymName } $Flag = @{ File = 0 Directory = 1 } If ($PScmdlet.ShouldProcess($Path,'Create Symbolic Link')) { Try { $return = ::CreateSymbolicLink($SymName,$Path,$Flag) If ($return) { $object = New-Object PSObject -Property @{ SymLink = $SymName Target = $Path Type = $PScmdlet.ParameterSetName } $object.pstypenames.insert(0,'System.File.SymbolicLink') $object } Else { Throw "Unable to create symbolic link!" } } Catch { Write-warning ("{0}: {1}" -f $path,$_.Exception.Message) } }}
Vejamos isso em ação!
New-SymLink -Path "C:\Users\Administrator\Downloads" -SymName Downloads -Directory -Verbose
![]()
E com isso, a função cria um link simbólico para a minha pasta de downloads no meu desktop. O link para baixar esta função está abaixo. Deixe-me saber o que você acha desta função!
Download
Repositório de Script