'"Type expected" error in Powershell Add-Type code block . DllImport, Windows Known Folders

Im trying .ps1

Add-Type -TypeDefinition @'
using System;       // IntPtr
using System.Runtime;       // guid Type
using System.Runtime.InteropServices;       // DllImport

public class Win32 {
    public static class KnownFolderId {
        public static readonly Guid Desktop = new(0xB4BFCC3A, 0xDB2C, 0x424C, 0xB0, 0x29, 0x7F, 0xE9, 0x9A, 0x87, 0xC6, 0x41);
    }

    [DllImport("shell32.dll")] static extern int SHGetKnownFolderPath(
        [MarshalAs(UnmanagedType.LPStruct)] Guid rfid,
        uint dwFlags,
        IntPtr hToken,
        out IntPtr ppszPath
    );
                
    public static string? GetKnownFolderPath() {
        IntPtr ppszPath = default;
        try {
            int hr = SHGetKnownFolderPath(Win32.KnownFolderId.Desktop, 0, IntPtr.Zero, out ppszPath);
            Marshal.ThrowExceptionForHR(hr); // alternatively, check success with hr >= 0
            return Marshal.PtrToStringUni(ppszPath);
        }
        finally {
            Marshal.FreeCoTaskMem(ppszPath);
        }
    }

}
'@
[Win32]::GetKnownFolderPath() | write-host

read-host 'end'

And of course getting this

Type expected
<<..>>\h1c5k4r2.0.cs(5) : public static class KnownFolderId {
<<..>>\h1c5k4r2.0.cs(6) : >>>     public static readonly Guid Desktop = new(0xB4BFCC3A,<<..>>

123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890



Solution 1:[1]

You're using C# language features that the compiler used by Add-Type in Windows PowerShell doesn't support, specifically:

  • new(...), a constructor call without a type name - replace with new Guid(...)

  • default to indicate a type's default value - replace with IntPtr.Zero.

  • string?, a nullable annotation - remove the ?

Therefore, use the following:

Add-Type -TypeDefinition @'
using System;       // IntPtr
using System.Runtime;       // guid Type
using System.Runtime.InteropServices;       // DllImport

public class Win32 {
    public static class KnownFolderId {
        public static readonly Guid Desktop = new Guid(0xB4BFCC3A, 0xDB2C, 0x424C, 0xB0, 0x29, 0x7F, 0xE9, 0x9A, 0x87, 0xC6, 0x41);
    }

    [DllImport("shell32.dll")] static extern int SHGetKnownFolderPath(
        [MarshalAs(UnmanagedType.LPStruct)] Guid rfid,
        uint dwFlags,
        IntPtr hToken,
        out IntPtr ppszPath
    );
                
    public static string GetKnownFolderPath() {
        IntPtr ppszPath = IntPtr.Zero;
        try {
            int hr = SHGetKnownFolderPath(Win32.KnownFolderId.Desktop, 0, IntPtr.Zero, out ppszPath);
            Marshal.ThrowExceptionForHR(hr); // alternatively, check success with hr >= 0
            return Marshal.PtrToStringUni(ppszPath);
        }
        finally {
            Marshal.FreeCoTaskMem(ppszPath);
        }
    }

}
'@

[Win32]::GetKnownFolderPath()

Note:

  • In PowerShell (Core) 7+, Add-Type does support these language features.

  • There, the only change that is needed is to place #nullable enable before the first line of source code, so as to enable nullable annotations.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1