やりたいこと
エクスプローラのクイックアクセスのピン留めが時々勝手に外れる。(多分Windows10の不具合)
対策として、プログラムから一発登録できるようにしたい。
要点
後述のソースコードの下記の部分で、指定されたフォルダに対するピン留めを実現している。
var folder = shell.NameSpace(path);
var item = folder.Self;
item.InvokeVerb("pintohome");
ソースコード
コマンドラインオプションで指定したフォルダ(またはフォルダへのショートカット)を入力として、そのフォルダをクイックアクセスにピン止めします。
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
class SampleProgram
{
static void PinToQuickAccess(string[] paths)
{
if ( paths.Length > 0 ) {
Type type = Type.GetTypeFromProgID("Shell.Application");
dynamic shell = Activator.CreateInstance(type);
foreach ( string tmp in paths ) {
string path = Path.GetFullPath(tmp);
if ( File.Exists(path) && path.EndsWith(".lnk",true,null) ) {
// lnk file
path = GetTargetPath(path) ?? "";
}
if ( Directory.Exists(path) ) {
var folder = shell.NameSpace(path);
var item = folder.Self;
item.InvokeVerb("pintohome");
}
}
}
// COMオブジェクト解放 ... これでいいはず
GC.Collect();
GC.WaitForPendingFinalizers();
}
// ※ピン止めされていないものもリストアップされる
static string[] GetEntriesOfQuickAccess()
{
var paths = new List<string>();
{
Type type = Type.GetTypeFromProgID("Shell.Application");
dynamic shell = Activator.CreateInstance(type);
dynamic folder = shell.NameSpace("shell:::{679f85cb-0220-4080-b29b-5540cc05aab6}");
if ( folder != null ) {
foreach (dynamic folderItem in folder.Items()) {
string s = folderItem.Path;
paths.Add(s);
Console.WriteLine(s);
}
}
}
GC.Collect();
GC.WaitForPendingFinalizers();
return paths.ToArray();
}
// .lnkファイルからパスを取得する
static string GetTargetPath(string fullPath)
{
{
Type type = Type.GetTypeFromProgID("WScript.Shell");
dynamic shell = Activator.CreateInstance(type);// IWshRuntimeLibrary.WshShell
dynamic lnk = shell.CreateShortcut(fullPath);// IWshRuntimeLibrary.IWshShortcut
if (string.IsNullOrEmpty(lnk.TargetPath)) {
return null;
}
return lnk.TargetPath;
}
}
[STAThread]
static void Main(string[] args)
{
GetEntriesOfQuickAccess();
PinToQuickAccess(args);
}
}