能否在.NET框架的DLL内使用PowerShell实例?

huangapple go评论67阅读模式
英文:

Is it possible to use a powershell instance inside a .net framework dll?

问题

以下是代码的中文翻译部分:

// 这是用于将文件夹固定到快速访问菜单的代码
private void PinFolderToQuickAccess(string path)
{
    try
    {
        using (var runspace = RunspaceFactory.CreateRunspace())
        {
            runspace.Open();

            var ps = PowerShell.Create();
            var shellApplication =
                ps.AddCommand("New-Object").AddParameter("ComObject", "shell.application").Invoke();

            dynamic nameSpace = shellApplication.FirstOrDefault()?.Methods["NameSpace"].Invoke(path);
            nameSpace?.Self.InvokeVerb("pintohome");
        }
    }
    catch (Exception e)
    {
        Console.Error.WriteLine("错误: {0}", e);
    }
}

// 这是用于从快速访问菜单中取消固定文件夹的代码
private void UnpinFolderFromQuickAccess(string path)
{
    try
    {
        using (var runspace = RunspaceFactory.CreateRunspace())
        {
            runspace.Open();
            var ps = PowerShell.Create();
            var removeScript =
                $"((New-Object -ComObject shell.application).Namespace(\"shell:::{{679f85cb-0220-4080-b29b-5540cc05aab6}}\").Items() | Where-Object {{ $_.Path -EQ \"{path}\" }}).InvokeVerb(\"unpinfromhome\")";

            ps.AddScript(removeScript);
            ps.Invoke();
        }
    }
    catch (Exception e)
    {
        Console.Error.WriteLine("错误: {0}", e);
    }
}

// 这是一个示例测试方法,用于从快速访问菜单中移除文件夹
[TestMethod]
public void RemoveFromQuickAccess_WithAddFirst()
{
    QuickAccessHandler handler = new QuickAccessHandler();

    string testPath = @"C:\Users\hp\Downloads\Compressed";

    handler.RemoveFromQuickAccess(testPath);
}

请注意,这些代码是用于在 .NET Framework DLL 中将文件夹固定到或从快速访问菜单中移除的示例。您也提到了尝试使用 PowerShell 实例的方法,但遇到了一些问题。如果您有更多关于此问题的问题或需要进一步帮助,请随时提出。

英文:

As the topic says, i'm trying to intergrate these code from Programatically Pin\UnPin the folder from quick access menu in windows 10 into a .net framework dll.

This is my code and it will throw error "Common Language Runtime detected an invalid program."

private void PinFolderToQuickAccess(string path)
{
    try
    {
        using (var runspace = RunspaceFactory.CreateRunspace())
        {
            runspace.Open();

            var ps = PowerShell.Create();
            var shellApplication =
                ps.AddCommand("New-Object").AddParameter("ComObject", "shell.application").Invoke();

            dynamic nameSpace = shellApplication.FirstOrDefault()?.Methods["NameSpace"].Invoke(path);
            nameSpace?.Self.InvokeVerb("pintohome");
        }
    }
    catch (Exception e)
    {
        Console.Error.WriteLine("Err: {0}", e);
    }
}

private void UnpinFolderFromQuickAccess(string path)
{
    try
    {
        using (var runspace = RunspaceFactory.CreateRunspace())
        {
            runspace.Open();
            var ps = PowerShell.Create();
            var removeScript =
                $"((New-Object -ComObject shell.application).Namespace(\"shell:::{{679f85cb-0220-4080-b29b-5540cc05aab6}}\").Items() | Where-Object {{ $_.Path -EQ \"{path}\" }}).InvokeVerb(\"unpinfromhome\")";

            ps.AddScript(removeScript);
            ps.Invoke();
        }
    }
    catch (Exception e)
    {
        Console.Error.WriteLine("Err: {0}", e);
    }
}

[TestMethod]
public void RemoveFromQuickAccess_WithAddFirst()
{
    QuickAccessHandler handler = new QuickAccessHandler();

    string testPath = @"C:\Users\hp\Downloads\Compressed";

    handler.RemoveFromQuickAccess(testPath);
}

I have tried another solution from here Is it possible programmatically add folders to the Windows 10 Quick Access panel in the explorer window?

but this time it will stuck at InvokeVerb("pintohome")

private void PinFolderToQuickAccess(string path)
{
    try
    {
        Type shellAppType = Type.GetTypeFromProgID("Shell.Application");
        Object shell = Activator.CreateInstance(shellAppType);
        Shell32.Folder2 f = (Shell32.Folder2)shellAppType.InvokeMember("NameSpace", System.Reflection.BindingFlags.InvokeMethod, null, shell, new object[] { path });
        f.Self.InvokeVerb("pintohome");
    }
    catch (Exception e)
    {
        Console.Error.WriteLine("Err: {0}", e);
    }
}

private void UnpinFolderFromQuickAccess(string path)
{
    try
    {
        Type shellAppType = Type.GetTypeFromProgID("Shell.Application");
        Object shell = Activator.CreateInstance(shellAppType);
        Shell32.Folder2 f2 = (Shell32.Folder2)shellAppType.InvokeMember("NameSpace", System.Reflection.BindingFlags.InvokeMethod, null, shell, new object[] { "shell:::{679f85cb-0220-4080-b29b-5540cc05aab6}" });
        foreach (FolderItem fi in f2.Items())
        {

            if (fi.Path == path)
            {
                ((FolderItem)fi).InvokeVerb("unpinfromhome");
            }
        }
    }
    catch (Exception e)
    {
        Console.Error.WriteLine("Err: {0}", e);
    }
}

Is it possible to use a powershell instance inside a .net framework dll? Or how should it be?

答案1

得分: 0

总结一下,这样做完全没问题。

在我的情况下,问题有两个影响。

首先,我直接使用了System.Management.Automation,这是不推荐的。如果你正在使用 .net 框架,请改用Microsoft.PowerShell.5.ReferenceAssemblies

关于此问题的更多细节,你应该查看这个答案 如何自动化 PowerShell 或 PowerShell Core 在同一台机器上运行

其次,为了将所有引用嵌入到 .exe 文件中,我使用了Costura.Fody来实现,但这导致了一些意外问题,比如难以运行我的与 PowerShell 实例相关的代码。不确定原因,但只需将其移除,一切都正常。

英文:

In conclusion, it's totally ok to do it.

In my case, the problem has two effects.

First, i used System.Management.Automation directly, which is not recommended. If you're using .net framework, use Microsoft.PowerShell.5.ReferenceAssemblies instead.

For more details about it, you should check this answer How to automate either PowerShell or PowerShell Core for same machine.

Second, to embed all reference into .exe file, i use Costura.Fody to do it which leads to some unexpected problem, like hard to run my code about powershell instance. Not sure why, but just remove it, then everything goes well.

huangapple
  • 本文由 发表于 2023年5月24日 23:58:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/76325416.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定