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