在C#和Windows命令提示符下完全是新手,所以请耐心等待。
这是我第一次写代码来创建一个可执行文件,旨在改变注册表以及Chrome中的首选项。
先来了解一下背景。与我签约的公司的工程师使用的是一个叫Cadkey的旧程序,这个程序用于查看公司自40年代以来一直在制造的东西的文件。
你们中的许多人可能都知道,出于安全考虑,Chrome不再允许在浏览器中查看applet和其他类型的文件,但该公司的大多数工程师更愿意使用Chrome而不是IE。
因此,我的任务是为他们提供通过“应用程序链接”打开文件的能力,有些人还将其称为“自定义url协议”,比如下面的例子:
<a href="cadkey://<some domain>/<some drive>/<some directory>/<some file name>.prt">some file</a>
这允许工程师在浏览器中单击文件名,然后在程序Cadkey中打开该文件。
为此,我必须在用户的注册表中注册注册表项,并更改Chrome的首选项文件,这样他们就不会被提醒此文件即将使用Windows命令提示符的小窗口所困扰。我对后者没有意见,但我的老板希望这个过程尽可能顺利。
说了这么多,我可以用下面的代码来完成这个任务:
using System;
using System.IO;
using Microsoft.Win32;
using Newtonsoft.Json.Linq;
namespace CadkeyRegAndPrefs
{
class Program
{
static void Main()
{
try
{
RegistryKey hkCurUsr = Registry.CurrentUser.OpenSubKey("Software\\Classes", true);
// Create a subkey named cadkey under HKEY_CURRENT_USER.
RegistryKey cadkey = hkCurUsr.CreateSubKey("cadkey", true);
cadkey.SetValue("", "URL:cadkey Protocol");
cadkey.SetValue("URL Protocol", "");
// Create data for the defltIcn subkey.
RegistryKey cadkeyDefltIcn = cadkey.CreateSubKey("DefaultIcon", true);
cadkeyDefltIcn.SetValue("", "");
cadkeyDefltIcn.SetValue("C:\\CK19\\Ckwin.exe", "-1");
// Create data for the cadkeyShell subkey.
RegistryKey cadkeyShell = cadkey.CreateSubKey("shell", true);
RegistryKey cadkeyShellOpen = cadkeyShell.CreateSubKey("open", true);
// Create data for the cadkeyCommand subkey.
RegistryKey cadkeyCommand = cadkeyShellOpen.CreateSubKey("command", true);
cadkeyCommand.SetValue("", "");
cadkeyCommand.SetValue("", "cmd /V:ON /C \"SET r=%1 & start C:\\CK19\\Ckwin.exe !r:cadkey:=!\"");
// Retrieve path of the current user
string path = System.Environment.ExpandEnvironmentVariables("%userprofile%");
string pathToPrefs = path + "\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Preferences";
// Have to create a JObject of the json file
JObject jsonObj = JObject.Parse(File.ReadAllText(pathToPrefs));
// Determine if the user has a protocol handler set and append cadkey set to false, otherwise, create node and set cadkey to false
var isExlcudedSchemes = jsonObj.SelectToken("protocol_handler.excluded_schemes");
if (isExlcudedSchemes != null)
{
jsonObj["protocol_handler"]["excluded_schemes"]["cadkey"] = false;
} else {
jsonObj.Add(new JProperty("protocol_handler", new JObject(
new JProperty("excluded_schemes", new JObject(
new JProperty("cadkey", new JObject()))))));
jsonObj["protocol_handler"]["excluded_schemes"]["cadkey"] = false;
}
// set the variable output and write the json content to the preferences file for Chrome
string output = Newtonsoft.Json.JsonConvert.SerializeObject(jsonObj, Newtonsoft.Json.Formatting.Indented);
File.WriteAllText(pathToPrefs, output);
// Let the end user know that the operation was successful
Console.WriteLine("Cadkey registration installed successfully");
Console.WriteLine("\nPress any key to exit");
Console.ReadKey();
}
catch (Exception e)
{
Console.WriteLine("{0} Exception caught.", e.ToString());
}
}
}
}
工程师有一个小的引导模式,它给他们提供了下载可执行文件的说明,然后双击可执行文件来安装注册表项并更改Chrome首选项。
那么问题出在哪里呢?该代码将密钥注册到用户的注册表中,并更改Chrome首选项文件,并在最后通知用户成功。
问题是有些文件的名称中有一个空格,这使得Cadkey提示用户找不到该文件。主要是因为"%20“出现在空格的位置。我猜Cadkey是在urlencoding不是设计的一部分的时候制作的。
我尝试通过命令提示符修改url,就像我从传递到命令提示符的参数中删除字符串"cadkey:“所做的那样:
cmd /V:ON /C \"SET r=%1 & start C:\\CK19\\Ckwin.exe !r:cadkey:=! & !r:%20= !\"
我试过了:
cmd /V:ON /C \"SET r=%1 & start C:\\CK19\\Ckwin.exe !r:cadkey:=! | !r:%20= !\"
我试过了:
cmd /V:ON /C \"SET r=%1 & start C:\\CK19\\Ckwin.exe !r:cadkey:=! & !r:%%20= !\"
我已经尝试使用另一个变量
cmd /V:ON /C \"SET r=%1 & !r:cadkey:=! & SET s=r start C:\\CK19\\Ckwin.exe !s:%20= !\"
当命令成功替换字符串"cadkey:“时,我还没有同时替换这两个字符串。我已经尝试了太多的东西,但我在这方面是一个新手,任何帮助都将不胜感激。
提前感谢
发布于 2019-11-26 20:48:13
在昨晚与我的老板合作后,我们终于找到了答案,如下所示:
变化
cadkeyCommand.SetValue("", "cmd /V:ON /C \"SET r=%1 & start C:\\CK19\\Ckwin.exe !r:cadkey:=!\"");
至:
cadkeyCommand.SetValue("", "cmd /V:ON /C \"SET r=%1 & SET s=!r:cadkey:= ! & SET t=!s:%%20= ! & start C:\\CK19\\Ckwin.exe !t!\"");
结果是字符串" cadkey :“和字符串"%20”都被删除,字符串"%20“被空格替换,这导致将以下内容传递给cadkey,其中您会看到变量"t”
https://stackoverflow.com/questions/59007788
复制相似问题