Skip to content

Commit 55d4da0

Browse files
committed
Adds SymLinks.ps1
1 parent 0bae625 commit 55d4da0

File tree

1 file changed

+58
-0
lines changed

1 file changed

+58
-0
lines changed

SymLinks.ps1

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
$code = @"
2+
using System;
3+
using System.Text;
4+
using System.Runtime.InteropServices;
5+
using Microsoft.Win32.SafeHandles;
6+
using System.ComponentModel;
7+
8+
namespace SymLinkInterop {
9+
public sealed class SymLinkManager
10+
{
11+
private const int FILE_SHARE_READ = 1;
12+
private const int FILE_SHARE_WRITE = 2;
13+
14+
private const int CREATION_DISPOSITION_OPEN_EXISTING = 3;
15+
16+
private const int FILE_FLAG_BACKUP_SEMANTICS = 0x02000000;
17+
18+
[DllImport("kernel32.dll", EntryPoint = "GetFinalPathNameByHandleW", CharSet = CharSet.Unicode, SetLastError = true)]
19+
public static extern int GetFinalPathNameByHandle(IntPtr handle, [In, Out] StringBuilder path, int bufLen, int flags);
20+
21+
[DllImport("kernel32.dll", EntryPoint = "CreateFileW", CharSet = CharSet.Unicode, SetLastError = true)]
22+
public static extern SafeFileHandle CreateFile(string lpFileName, int dwDesiredAccess, int dwShareMode,
23+
IntPtr SecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile);
24+
25+
public static string GetSymbolicLinkTarget(string symlinkpath)
26+
{
27+
SafeFileHandle directoryHandle = CreateFile(symlinkpath, 0, 2, System.IntPtr.Zero, CREATION_DISPOSITION_OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, System.IntPtr.Zero);
28+
if(directoryHandle.IsInvalid)
29+
throw new Win32Exception(Marshal.GetLastWin32Error());
30+
31+
StringBuilder path = new StringBuilder(512);
32+
int size = GetFinalPathNameByHandle(directoryHandle.DangerousGetHandle(), path, path.Capacity, 0);
33+
if (size<0)
34+
throw new Win32Exception(Marshal.GetLastWin32Error());
35+
if (path[0] == '\\' && path[1] == '\\' && path[2] == '?' && path[3] == '\\')
36+
return path.ToString().Substring(4);
37+
else
38+
return path.ToString();
39+
}
40+
}
41+
}
42+
"@
43+
44+
Add-Type -TypeDefinition $code
45+
46+
function Get-SymbolicLinkTarget
47+
{
48+
[CmdletBinding()]
49+
param
50+
(
51+
[parameter(Mandatory=$true, ValueFromPipeline=$true)]
52+
[string]$Path
53+
)
54+
PROCESS
55+
{
56+
return [SymLinkInterop.SymLinkManager]::GetSymbolicLinkTarget($Path)
57+
}
58+
}

0 commit comments

Comments
 (0)