1

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?

Hellagur
  • 93
  • 7
  • The link you had referred to a Win95 utility. See : https://learn.microsoft.com/en-us/powershell/scripting/developer/hosting/adding-and-invoking-commands?force_isolation=true&view=powershell-7.3#addscript – jdweng May 24 '23 at 16:42
  • The error message suggests that you're trying to use the _Windows PowerShell_ (.NET Framework) SDK from a .NET (Core) application, which doesn't work. See [this answer](https://stackoverflow.com/a/58211901/45375) for what PowerShell SDK NuGet package to choose when. – mklement0 May 24 '23 at 18:53
  • @jdweng thanks for the doc, it seems to better to use the second code. – Hellagur May 25 '23 at 14:49
  • 1
    @mklement0 Thanks for your help and i've figured out that's exactly part of the problem! – Hellagur May 25 '23 at 14:51

1 Answers1

0

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.

Hellagur
  • 93
  • 7