mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-08 04:07:40 +02:00
Update Control Panel
The Control Panel now also includes third party panel items.
This commit is contained in:
@@ -51,9 +51,9 @@ namespace Wox.Plugin.SystemPlugins.ControlPanel
|
|||||||
|
|
||||||
foreach (ControlPanelItem item in controlPanelItems)
|
foreach (ControlPanelItem item in controlPanelItems)
|
||||||
{
|
{
|
||||||
if (!File.Exists(iconFolder + item.ApplicationName + fileType))
|
if (!File.Exists(iconFolder + item.LocalizedString + fileType))
|
||||||
{
|
{
|
||||||
item.Icon.ToBitmap().Save(iconFolder + item.ApplicationName + fileType);
|
item.Icon.ToBitmap().Save(iconFolder + item.LocalizedString + fileType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,7 +75,7 @@ namespace Wox.Plugin.SystemPlugins.ControlPanel
|
|||||||
Title = item.LocalizedString,
|
Title = item.LocalizedString,
|
||||||
SubTitle = item.InfoTip,
|
SubTitle = item.InfoTip,
|
||||||
Score = item.Score,
|
Score = item.Score,
|
||||||
IcoPath = "Images\\ControlPanelIcons\\" + item.ApplicationName + fileType,
|
IcoPath = "Images\\ControlPanelIcons\\" + item.LocalizedString + fileType,
|
||||||
Action = e =>
|
Action = e =>
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -8,18 +8,16 @@ namespace Wox.Plugin.SystemPlugins.ControlPanel
|
|||||||
{
|
{
|
||||||
public string LocalizedString { get; private set; }
|
public string LocalizedString { get; private set; }
|
||||||
public string InfoTip { get; private set; }
|
public string InfoTip { get; private set; }
|
||||||
public string ApplicationName { get; private set; }
|
|
||||||
public ProcessStartInfo ExecutablePath { get; private set; }
|
public ProcessStartInfo ExecutablePath { get; private set; }
|
||||||
public Icon Icon { get; private set; }
|
public Icon Icon { get; private set; }
|
||||||
public int Score { get; set; }
|
public int Score { get; set; }
|
||||||
|
|
||||||
public ControlPanelItem(string newLocalizedString, string newInfoTip, string newApplicationName, ProcessStartInfo newExecutablePath, Icon newLargeIcon)
|
public ControlPanelItem(string newLocalizedString, string newInfoTip, ProcessStartInfo newExecutablePath, Icon newIcon)
|
||||||
{
|
{
|
||||||
LocalizedString = newLocalizedString;
|
LocalizedString = newLocalizedString;
|
||||||
InfoTip = newInfoTip;
|
InfoTip = newInfoTip;
|
||||||
ApplicationName = newApplicationName;
|
|
||||||
ExecutablePath = newExecutablePath;
|
ExecutablePath = newExecutablePath;
|
||||||
Icon = (Icon)newLargeIcon.Clone();
|
Icon = newIcon;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,172 +45,238 @@ namespace Wox.Plugin.SystemPlugins.ControlPanel
|
|||||||
|
|
||||||
static Queue<IntPtr> iconQueue;
|
static Queue<IntPtr> iconQueue;
|
||||||
|
|
||||||
public static List<ControlPanelItem> Create(int iconSize)
|
|
||||||
{
|
|
||||||
List<ControlPanelItem> controlPanelItems = new List<ControlPanelItem>();
|
|
||||||
string applicationName;
|
|
||||||
string[] localizedString;
|
|
||||||
string[] infoTip = new string[1];
|
|
||||||
List<string> iconString;
|
|
||||||
IntPtr dataFilePointer;
|
|
||||||
uint stringTableIndex;
|
|
||||||
IntPtr iconIndex;
|
|
||||||
StringBuilder resource;
|
|
||||||
ProcessStartInfo executablePath;
|
|
||||||
IntPtr iconPtr = IntPtr.Zero;
|
|
||||||
Icon myIcon;
|
|
||||||
|
|
||||||
RegistryKey nameSpace = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ControlPanel\\NameSpace");
|
static RegistryKey nameSpace = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ControlPanel\\NameSpace");
|
||||||
RegistryKey clsid = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Classes\\CLSID");
|
static RegistryKey clsid = Registry.ClassesRoot.OpenSubKey("CLSID");
|
||||||
|
|
||||||
|
public static List<ControlPanelItem> Create(uint iconSize)
|
||||||
|
{
|
||||||
|
int size = (int)iconSize;
|
||||||
RegistryKey currentKey;
|
RegistryKey currentKey;
|
||||||
|
ProcessStartInfo executablePath;
|
||||||
|
List<ControlPanelItem> controlPanelItems = new List<ControlPanelItem>();
|
||||||
|
string localizedString;
|
||||||
|
string infoTip;
|
||||||
|
Icon myIcon;
|
||||||
|
|
||||||
foreach (string key in nameSpace.GetSubKeyNames())
|
foreach (string key in nameSpace.GetSubKeyNames())
|
||||||
{
|
{
|
||||||
//todo:throw exceptions in my computer, need to check this,Silently Fail for now.
|
currentKey = clsid.OpenSubKey(key);
|
||||||
try
|
if (currentKey != null)
|
||||||
{
|
{
|
||||||
currentKey = clsid.OpenSubKey(key);
|
executablePath = getExecutablePath(currentKey);
|
||||||
if (currentKey != null)
|
|
||||||
{
|
|
||||||
if (currentKey.GetValue("System.ApplicationName") != null &&
|
|
||||||
currentKey.GetValue("LocalizedString") != null)
|
|
||||||
{
|
|
||||||
applicationName = currentKey.GetValue("System.ApplicationName").ToString();
|
|
||||||
//Debug.WriteLine(key.ToString() + " (" + applicationName + ")");
|
|
||||||
localizedString = currentKey.GetValue("LocalizedString")
|
|
||||||
.ToString()
|
|
||||||
.Split(new char[] {','}, 2);
|
|
||||||
if (localizedString[0][0] == '@')
|
|
||||||
{
|
|
||||||
localizedString[0] = localizedString[0].Substring(1);
|
|
||||||
}
|
|
||||||
localizedString[0] = Environment.ExpandEnvironmentVariables(localizedString[0]);
|
|
||||||
if (localizedString.Length > 1)
|
|
||||||
{
|
|
||||||
dataFilePointer = LoadLibraryEx(localizedString[0], IntPtr.Zero,
|
|
||||||
LOAD_LIBRARY_AS_DATAFILE);
|
|
||||||
|
|
||||||
stringTableIndex = sanitizeUint(localizedString[1]);
|
if (executablePath == null)
|
||||||
|
continue; //Cannot have item without executable path
|
||||||
|
|
||||||
resource = new StringBuilder(255);
|
localizedString = getLocalizedString(currentKey);
|
||||||
LoadString(dataFilePointer, stringTableIndex, resource, resource.Capacity + 1);
|
|
||||||
|
|
||||||
localizedString[0] = resource.ToString();
|
if (string.IsNullOrEmpty(localizedString))
|
||||||
|
continue; //Cannot have item without Title
|
||||||
|
|
||||||
if (currentKey.GetValue("InfoTip") != null)
|
infoTip = getInfoTip(currentKey);
|
||||||
{
|
|
||||||
infoTip = currentKey.GetValue("InfoTip").ToString().Split(new char[] {','}, 2);
|
|
||||||
if (infoTip[0][0] == '@')
|
|
||||||
{
|
|
||||||
infoTip[0] = infoTip[0].Substring(1);
|
|
||||||
}
|
|
||||||
infoTip[0] = Environment.ExpandEnvironmentVariables(infoTip[0]);
|
|
||||||
|
|
||||||
dataFilePointer = LoadLibraryEx(infoTip[0], IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE);
|
myIcon = getIcon(currentKey, size);
|
||||||
|
|
||||||
stringTableIndex = sanitizeUint(infoTip[1]);
|
controlPanelItems.Add(new ControlPanelItem(localizedString, infoTip, executablePath, myIcon));
|
||||||
|
|
||||||
resource = new StringBuilder(255);
|
|
||||||
LoadString(dataFilePointer, stringTableIndex, resource, resource.Capacity + 1);
|
|
||||||
|
|
||||||
infoTip[0] = resource.ToString();
|
|
||||||
}
|
|
||||||
else if (currentKey.GetValue(null) != null)
|
|
||||||
{
|
|
||||||
infoTip[0] = currentKey.GetValue(null).ToString();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
infoTip[0] = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
FreeLibrary(dataFilePointer);
|
|
||||||
//We are finished with extracting strings. Prepare to load icon file.
|
|
||||||
dataFilePointer = IntPtr.Zero;
|
|
||||||
myIcon = null;
|
|
||||||
iconPtr = IntPtr.Zero;
|
|
||||||
|
|
||||||
if (currentKey.OpenSubKey("DefaultIcon") != null)
|
|
||||||
{
|
|
||||||
if (currentKey.OpenSubKey("DefaultIcon").GetValue(null) != null)
|
|
||||||
{
|
|
||||||
iconString =
|
|
||||||
new List<string>(
|
|
||||||
currentKey.OpenSubKey("DefaultIcon")
|
|
||||||
.GetValue(null)
|
|
||||||
.ToString()
|
|
||||||
.Split(new char[] {','}, 2));
|
|
||||||
if (iconString[0][0] == '@')
|
|
||||||
{
|
|
||||||
iconString[0] = iconString[0].Substring(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
dataFilePointer = LoadLibraryEx(iconString[0], IntPtr.Zero,
|
|
||||||
LOAD_LIBRARY_AS_DATAFILE);
|
|
||||||
|
|
||||||
if (iconString.Count < 2)
|
|
||||||
{
|
|
||||||
iconString.Add("0");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
iconIndex = (IntPtr) sanitizeUint(iconString[1]);
|
|
||||||
|
|
||||||
if (iconIndex == IntPtr.Zero)
|
|
||||||
{
|
|
||||||
iconQueue = new Queue<IntPtr>();
|
|
||||||
EnumResourceNamesWithID(dataFilePointer, GROUP_ICON,
|
|
||||||
new EnumResNameDelegate(EnumRes), IntPtr.Zero);
|
|
||||||
//Iterate through resources.
|
|
||||||
|
|
||||||
while (iconPtr == IntPtr.Zero && iconQueue.Count > 0)
|
|
||||||
{
|
|
||||||
iconPtr = LoadImage(dataFilePointer, iconQueue.Dequeue(), 1, iconSize,
|
|
||||||
iconSize, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
iconPtr = LoadImage(dataFilePointer, iconIndex, 1, iconSize, iconSize, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
myIcon = Icon.FromHandle(iconPtr);
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
//Silently fail for now.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
executablePath = new ProcessStartInfo();
|
|
||||||
executablePath.FileName = Environment.ExpandEnvironmentVariables(CONTROL);
|
|
||||||
executablePath.Arguments = "-name " + applicationName;
|
|
||||||
controlPanelItems.Add(new ControlPanelItem(localizedString[0], infoTip[0],
|
|
||||||
applicationName, executablePath, myIcon));
|
|
||||||
FreeLibrary(dataFilePointer);
|
|
||||||
if (iconPtr != IntPtr.Zero)
|
|
||||||
{
|
|
||||||
DestroyIcon(myIcon.Handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Debug.Write(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return controlPanelItems;
|
return controlPanelItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static ProcessStartInfo getExecutablePath(RegistryKey currentKey)
|
||||||
|
{
|
||||||
|
ProcessStartInfo executablePath = new ProcessStartInfo();
|
||||||
|
string applicationName;
|
||||||
|
|
||||||
|
if (currentKey.GetValue("System.ApplicationName") != null)
|
||||||
|
{
|
||||||
|
//CPL Files (usually native MS items)
|
||||||
|
applicationName = currentKey.GetValue("System.ApplicationName").ToString();
|
||||||
|
executablePath.FileName = Environment.ExpandEnvironmentVariables(CONTROL);
|
||||||
|
executablePath.Arguments = "-name " + applicationName;
|
||||||
|
}
|
||||||
|
else if (currentKey.OpenSubKey("Shell\\Open\\Command") != null && currentKey.OpenSubKey("Shell\\Open\\Command").GetValue(null) != null)
|
||||||
|
{
|
||||||
|
//Other files (usually third party items)
|
||||||
|
executablePath.FileName = Environment.ExpandEnvironmentVariables(currentKey.OpenSubKey("Shell\\Open\\Command").GetValue(null).ToString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return executablePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string getLocalizedString(RegistryKey currentKey)
|
||||||
|
{
|
||||||
|
IntPtr dataFilePointer;
|
||||||
|
string[] localizedStringRaw;
|
||||||
|
uint stringTableIndex;
|
||||||
|
StringBuilder resource;
|
||||||
|
string localizedString;
|
||||||
|
|
||||||
|
if (currentKey.GetValue("LocalizedString") != null)
|
||||||
|
{
|
||||||
|
localizedStringRaw = currentKey.GetValue("LocalizedString").ToString().Split(new char[] { ',' }, 2);
|
||||||
|
|
||||||
|
if (localizedStringRaw.Length > 1)
|
||||||
|
{
|
||||||
|
if (localizedStringRaw[0][0] == '@')
|
||||||
|
{
|
||||||
|
localizedStringRaw[0] = localizedStringRaw[0].Substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
localizedStringRaw[0] = Environment.ExpandEnvironmentVariables(localizedStringRaw[0]);
|
||||||
|
|
||||||
|
dataFilePointer = LoadLibraryEx(localizedStringRaw[0], IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE); //Load file with strings
|
||||||
|
|
||||||
|
stringTableIndex = sanitizeUint(localizedStringRaw[1]);
|
||||||
|
|
||||||
|
resource = new StringBuilder(255);
|
||||||
|
LoadString(dataFilePointer, stringTableIndex, resource, resource.Capacity + 1); //Extract needed string
|
||||||
|
FreeLibrary(dataFilePointer);
|
||||||
|
|
||||||
|
localizedString = resource.ToString();
|
||||||
|
|
||||||
|
/*This shouldn't be necessary, but some apps (e.g. Bootcamp)
|
||||||
|
* don't follow Microsoft's standard. Have to make a choice whether
|
||||||
|
* empty string == failure, or use default name. I'm using default name */
|
||||||
|
|
||||||
|
if (String.IsNullOrEmpty(localizedString))
|
||||||
|
{
|
||||||
|
if (currentKey.GetValue(null) != null)
|
||||||
|
{
|
||||||
|
localizedString = currentKey.GetValue(null).ToString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null; //Cannot have item without title.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
localizedString = localizedStringRaw[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (currentKey.GetValue(null) != null)
|
||||||
|
{
|
||||||
|
localizedString = currentKey.GetValue(null).ToString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null; //Cannot have item without title.
|
||||||
|
}
|
||||||
|
return localizedString;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string getInfoTip(RegistryKey currentKey)
|
||||||
|
{
|
||||||
|
IntPtr dataFilePointer;
|
||||||
|
string[] infoTipRaw;
|
||||||
|
uint stringTableIndex;
|
||||||
|
StringBuilder resource;
|
||||||
|
string infoTip = "";
|
||||||
|
|
||||||
|
if (currentKey.GetValue("InfoTip") != null)
|
||||||
|
{
|
||||||
|
infoTipRaw = currentKey.GetValue("InfoTip").ToString().Split(new char[] { ',' }, 2);
|
||||||
|
|
||||||
|
if (infoTipRaw.Length == 2)
|
||||||
|
{
|
||||||
|
if (infoTipRaw[0][0] == '@')
|
||||||
|
{
|
||||||
|
infoTipRaw[0] = infoTipRaw[0].Substring(1);
|
||||||
|
}
|
||||||
|
infoTipRaw[0] = Environment.ExpandEnvironmentVariables(infoTipRaw[0]);
|
||||||
|
|
||||||
|
dataFilePointer = LoadLibraryEx(infoTipRaw[0], IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE); //Load file with strings
|
||||||
|
|
||||||
|
stringTableIndex = sanitizeUint(infoTipRaw[1]);
|
||||||
|
|
||||||
|
resource = new StringBuilder(255);
|
||||||
|
LoadString(dataFilePointer, stringTableIndex, resource, resource.Capacity + 1); //Extract needed string
|
||||||
|
FreeLibrary(dataFilePointer);
|
||||||
|
|
||||||
|
infoTip = resource.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
infoTip = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return infoTip;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Icon getIcon(RegistryKey currentKey, int iconSize)
|
||||||
|
{
|
||||||
|
IntPtr iconPtr = IntPtr.Zero;
|
||||||
|
List<string> iconString;
|
||||||
|
IntPtr dataFilePointer;
|
||||||
|
IntPtr iconIndex;
|
||||||
|
Icon myIcon = null;
|
||||||
|
|
||||||
|
if (currentKey.OpenSubKey("DefaultIcon") != null)
|
||||||
|
{
|
||||||
|
if (currentKey.OpenSubKey("DefaultIcon").GetValue(null) != null)
|
||||||
|
{
|
||||||
|
iconString = new List<string>(currentKey.OpenSubKey("DefaultIcon").GetValue(null).ToString().Split(new char[] { ',' }, 2));
|
||||||
|
if (iconString[0][0] == '@')
|
||||||
|
{
|
||||||
|
iconString[0] = iconString[0].Substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
dataFilePointer = LoadLibraryEx(iconString[0], IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE);
|
||||||
|
|
||||||
|
if (iconString.Count < 2)
|
||||||
|
{
|
||||||
|
iconString.Add("0");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
iconIndex = (IntPtr)sanitizeUint(iconString[1]);
|
||||||
|
|
||||||
|
if (iconIndex == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
iconQueue = new Queue<IntPtr>();
|
||||||
|
EnumResourceNamesWithID(dataFilePointer, GROUP_ICON, new EnumResNameDelegate(EnumRes), IntPtr.Zero); //Iterate through resources.
|
||||||
|
|
||||||
|
while (iconPtr == IntPtr.Zero && iconQueue.Count > 0)
|
||||||
|
{
|
||||||
|
iconPtr = LoadImage(dataFilePointer, iconQueue.Dequeue(), 1, iconSize, iconSize, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iconPtr = LoadImage(dataFilePointer, iconIndex, 1, iconSize, iconSize, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
FreeLibrary(dataFilePointer);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
myIcon = Icon.FromHandle(iconPtr);
|
||||||
|
myIcon = (Icon)myIcon.Clone(); //Remove pointer dependancy.
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
//Silently fail for now..
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iconPtr != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
DestroyIcon(iconPtr);
|
||||||
|
}
|
||||||
|
return myIcon;
|
||||||
|
}
|
||||||
|
|
||||||
private static uint sanitizeUint(string args) //Remove all chars before and after first set of digits.
|
private static uint sanitizeUint(string args) //Remove all chars before and after first set of digits.
|
||||||
{
|
{
|
||||||
int x = 0;
|
int x = 0;
|
||||||
@@ -241,12 +307,14 @@ namespace Wox.Plugin.SystemPlugins.ControlPanel
|
|||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static uint GET_RESOURCE_ID(IntPtr value)
|
private static uint GET_RESOURCE_ID(IntPtr value)
|
||||||
{
|
{
|
||||||
if (IS_INTRESOURCE(value) == true)
|
if (IS_INTRESOURCE(value) == true)
|
||||||
return (uint)value;
|
return (uint)value;
|
||||||
throw new System.NotSupportedException("value is not an ID!");
|
throw new System.NotSupportedException("value is not an ID!");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GET_RESOURCE_NAME(IntPtr value)
|
private static string GET_RESOURCE_NAME(IntPtr value)
|
||||||
{
|
{
|
||||||
if (IS_INTRESOURCE(value) == true)
|
if (IS_INTRESOURCE(value) == true)
|
||||||
|
|||||||
4
Wox.sln
4
Wox.sln
@@ -1,8 +1,6 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 2013
|
# Visual Studio 2012
|
||||||
VisualStudioVersion = 12.0.30110.0
|
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.Test", "Wox.Test\Wox.Test.csproj", "{FF742965-9A80-41A5-B042-D6C7D3A21708}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.Test", "Wox.Test\Wox.Test.csproj", "{FF742965-9A80-41A5-B042-D6C7D3A21708}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.Plugin", "Wox.Plugin\Wox.Plugin.csproj", "{8451ECDD-2EA4-4966-BB0A-7BBC40138E80}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.Plugin", "Wox.Plugin\Wox.Plugin.csproj", "{8451ECDD-2EA4-4966-BB0A-7BBC40138E80}"
|
||||||
|
|||||||
Reference in New Issue
Block a user