c# - PowerShell 中内联 C# 中的 ScriptBuilder(2.0 及更高版本)

标签 c# .net powershell namespaces pinvoke

我试图内联的 C# 位于底部,但我的错误发生在第二个 DllImport,因为未加载 StringBuilder。我已经尝试了很多关于加载程序集、在 C# 中添加使用引用等的事情。这是一个例子。但是没有任何效果,我很确定我只是遗漏了一些对 C# 程序员来说非常明显的东西,而对我的大脑来说完全不明显。

$assemblies = ('mscorlib.dll')

$code = @'
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
internal static extern IntPtr LoadLibrary(string lpLibFileName);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
internal static extern int LoadString(IntPtr hInstance, uint wID, StringBuilder lpBuffer, int nBufferMax);

public static class PxTest
{
    // Note
}
'@

Add-Type -memberDefinition $code -referencedAssemblies $assemblies -namespace Px -name Test -errorAction stop

我也试过$assemblies = ('system.text')然后尝试加载未找到的 system.text.dll。这就是将我发送到上面的 dll 的原因,我相信这是找到 StringBuilder 的地方。

最终使用的 C# 代码
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
    internal static extern IntPtr LoadLibrary(string lpLibFileName);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
    internal static extern int LoadString(IntPtr hInstance, uint wID, StringBuilder lpBuffer, int nBufferMax);

    public static bool PinUnpinTaskbar(string filePath, bool pin)
    {
        if (!File.Exists(filePath)) throw new FileNotFoundException(filePath);
        int MAX_PATH = 255;
        var actionIndex = pin ? 5386 : 5387; // 5386 is the DLL index for"Pin to Tas&kbar", ref. http://www.win7dll.info/shell32_dll.html
        StringBuilder szPinToStartLocalized = new StringBuilder(MAX_PATH);
        IntPtr hShell32 = LoadLibrary("Shell32.dll");
        LoadString(hShell32, (uint)actionIndex, szPinToStartLocalized, MAX_PATH);
        string localizedVerb = szPinToStartLocalized.ToString();

        string path = Path.GetDirectoryName(filePath);
        string fileName = Path.GetFileName(filePath);

        // create the shell application object
        dynamic shellApplication = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application"));
        dynamic directory = shellApplication.NameSpace(path);
        dynamic link = directory.ParseName(fileName);

        dynamic verbs = link.Verbs();
        for (int i = 0; i < verbs.Count(); i++)
        {
            dynamic verb = verbs.Item(i);
            if (verb.Name.Equals(localizedVerb))
            {
                verb.DoIt();
                return true;
            }
        }
        return false;
    }

编辑:试图理解编辑。我得到了添加的标签,但用...相同的文本替换了一些正文?我不明白的。这至少是我所看到的。 StringBuilder 是 替换为 StringBuilder 是 等等,嗯?

最佳答案

这是因为StringBuilder不是完全限定的和/或命名空间 System.Text未使用

所以要么将参数更改为

System.Text.StringBuilder lpBuffer

或添加 UsingNamespace Add-Type 的参数小命令
Add-Type -memberDefinition $code -referencedAssemblies $assemblies -namespace Px -UsingNamespace 'System.Text' -name Test -errorAction stop

由于您的环境固定为 PoSh 2.0 和 Win7,我重写了代码以通过 PowerShell 处理动态内容(无论如何在这种情况下更惯用)并通过您提供的 C# 代码获取本地化动词,因此最终看起来像这样为您提供方便的PowerShell功能PinUnpinTaskbar
$assemblies = ('mscorlib.dll')
$code = @'
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
    internal static extern IntPtr LoadLibrary(string lpLibFileName);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
    internal static extern int LoadString(IntPtr hInstance, uint wID, StringBuilder lpBuffer, int nBufferMax);

    public static string GetLocalizedPinToStartVerb(bool pin)
    {
        int MAX_PATH = 255;
        int actionIndex = pin ? 5386 : 5387; // 5386 is the DLL index for"Pin to Tas&kbar", ref. http://www.win7dll.info/shell32_dll.html
        StringBuilder szPinToStartLocalized = new StringBuilder(MAX_PATH);
        IntPtr hShell32 = LoadLibrary("Shell32.dll");
        LoadString(hShell32, (uint)actionIndex, szPinToStartLocalized, MAX_PATH);
        return szPinToStartLocalized.ToString();
    }
'@

Add-Type -MemberDefinition $code `
         -ReferencedAssemblies $assemblies `
         -Namespace Px `
         -UsingNamespace 'System.Text' `
         -Name Helper `
         -ErrorAction stop

function PinUnpinTaskbar([string]$FilePath, [boolean]$Pin) {
    if (Test-Path $FilePath) {
        $localizedVerb = [Px.Helper]::GetLocalizedPinToStartVerb($Pin)

        $path = [IO.Path]::GetDirectoryName($FilePath)
        $fileName = [IO.Path]::GetFileName($FilePath)

        $shellAppType = [Type]::GetTypeFromProgID("Shell.Application")
        $shellAppInst = [Activator]::CreateInstance($shellAppType)
        $directory = $shellAppInst.NameSpace($path)
        $link = $directory.ParseName($fileName)
        $verbs = $link.Verbs()
        for ($i = 0; $i -lt $verbs.Count; ++$i) {
            $verb = $verbs.Item($i)
            Write-Host $verb.Name
            if ($verb.Name.Equals($localizedVerb)) {
                $verb.DoIt()
                return $true
            }
        }
        return $false
    }
    else {
        Write-Error "File '$FilePath' does not exist"
    }
}  

在普通 Win7 机器上运行的脚本

Showing script in action

关于c# - PowerShell 中内联 C# 中的 ScriptBuilder(2.0 及更高版本),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38942498/

相关文章:

c# - Unity Ads 无法在 Android 设备上运行,Advertisement.IsReady() 返回 false

c# - 如何在C#中使用MessagePack?

powershell - 通过 startprocess 执行脚本 block

azure - Powershell - 设置环境变量而无需关闭应用程序

powershell - 使用Powershell分配文件夹权限时遇到问题

c# - 根据亮度和饱和度在颜色名称前添加 pale/vivid/light/dark

c# - 在 F# 中实现 C# 事件处理程序

c# - 与网站上的程序(如 iTunes)互动

c# - STL/CLR 库使用 IComparable 实现 == 运算符并抛出 NullReferenceException

c# - 如何在 Android 中使用 C# 生成的 RSA 公钥?