Home > Back-end >  "Type expected" error in Powershell Add-Type code block . DllImport, Windows Known Folders
"Type expected" error in Powershell Add-Type code block . DllImport, Windows Known Folders

Time:05-06

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

CodePudding user response:

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.

  • Related