Coding4Fun硬件骨骼-使用CueCat和.NET

In an ongoing Mardi Gras celebration of the soon-to-happen Coding4Fun Redesign, I got permission from the rockin' awesome Dan Fernandez to published a Coding4Fun article here on Hanselman.com as an exclusive. This article will be republished on the new redesigned site very soon, along with a "Coding with the FingerPrint Reader" article and possible a fabulous super-secret IR/Robot/PowerShell article.

在正在进行的即将到来的Coding4Fun重新设计的狂欢节庆祝活动中,我得到了摇滚歌手Dan Fernandez的许可,在此处以Hanselman.com的身份独家发表了Coding4Fun文章。 这篇文章将很快在重新设计的新网站上重新发布,同时还会刊登“用指纹读取器进行编码”一文,并可能还会刊登一篇神话般的超级秘密IR / Robot / PowerShell文章。

Dig up your CueCat and enjoy.

挖出您的CueCat并享受。

Coding4Fun Hardware Boneyard - Using the CueCat with .NET

Coding4Fun硬件骨骼-使用CueCat和.NET

Summary: In this rogue installment of "Some Assembly Required" column, Scott Hanselman borrows Travis Illig's CueCat BarCode scanner and creates a plugin for Windows Live Writer than lets him blog more easily about books he's reading. We decode the bar code info, change UPCs into ISBNs, call Amazon's Web Service via REST and integrate with Windows Live Writer all in one article. Whew!

简介:在“某些需要组装”一栏中的流氓文章中,Scott Hanselman借用了Travis Illig的CueCat BarCode扫描仪,并为Windows Live Writer创建了一个插件,这比让他更轻松地针对他所阅读的书籍写博客。 我们在一篇文章中对条形码信息进行解码,将UPC更改为ISBN,通过REST调用Amazon的Web服务并与Windows Live Writer集成。 ew!

The CueCat BarCode Scanner

CueCat条形码扫描仪

180px-Cuecat1

Here's what Wikipedia has to say about the CueCat BarCode scanner:

维基百科对CueCat条码扫描器的评价如下:

The :CueCat is a cat-themed handheld barcode reader developed in the late 1990s by the now-defunct DigitalConvergence Corporation, which connected to computers using the PS/2 keyboard port and later USB. The :CueCat enabled users to link to an Internet URL by scanning a barcode appearing in an article, catalog or on some other printed matter. In this way a user could be directed to a web page containing related information. The system that supported this functionality is no longer in operation.

:CueCat是一款猫主题的手持式条形码阅读器,它是由现已不复存在的DigitalConvergence Corporation在1990年代后期开发的,该公司使用PS / 2键盘端口和后来的USB连接到计算机。 :CueCat使用户可以通过扫描文章,目录或其他印刷品上显示的条形码来链接到Internet URL。 通过这种方式,可以将用户定向到包含相关信息的网页。 支持此功能的系统不再运行。

Ah, nothing like the smell of obsolete hardware to get me thinking. You can get CueCats all over, there are millions of them, including on ebay. I asked around and my buddy Travis Illig loaned me his. It's ripe for hacking.

啊,没什么让我思考的陈旧硬件的味道。 您可以到处都有CueCats,其中包括ebay上有数百万个。 我四处询问,我的好友特拉维斯·伊利格(Travis Illig)把他借给了我。 入侵的时机已经成熟。

Decoding the CueCat Output

解码CueCat输出

The CueCat speaks a funky encoded format that it "types" as if it were a keyboard. For all intents, it IS a keyboard as the PS2 version we're using is installed in series with your existing (if you have one) keyboard.

CueCat讲的是一种时髦的编码格式,就像键盘一样,它可以“键入”。 对于所有目的,它都是键盘,因为我们正在使用的PS2版本是与现有(如果有)键盘串联安装的。

For example, my copy of Neil Gaiman's excellent "Stardust" produces this output:

例如,我的尼尔·盖曼(Neil Gaiman)出色的《星尘》(Stardust)副本产生了以下输出:

.C3nZC3nZC3nZE3r0Chr3CNnY.cGf2.ENr7C3n1C3PWD3rYCxzYChnZ.

.C3nZC3nZC3nZE3r0Chr3CNnY.cGf2.ENr7C3n1C3PWD3rYCxzYChnZ。

Which can be broken up into a series of tokens, some are one character and some are two. The periods are delimiters, so we'll toss them for now.

可以分为一系列令牌,其中一些是一个字符,而有些则是两个。 句点是定界符,因此我们现在将它们抛开。

 C3 n Z C3 n Z C3 n Z E3 r 0 Ch r 3 CN n Y EN r 7 C3 n 1 C3 P W D3 r Y Cx z Y Ch n Z

C3 n Z C3 n Z C3 n Z E3 r 0 Ch r 3 CN n Y EN r 7 C3 n 1 C3 PW D3 r Y Cx z Y Ch n Z

The first part is the serial number of CueCat itself, which freaked a log of privacy folks out in the past. The scanned barcode is actually the last part after the third . delimiter:

第一部分是CueCat本身的序列号,它使过去的隐私人士感到震惊。 扫描的条形码实际上是第三部分之后的最后一部分。 分隔符:

EN r 7 C3 n 1 C3 P W D3 r Y Cx z Y Ch n Z

EN r 7 C3 n 1 C3 PW D3 r Y Cx z Y Ch n Z

Each of these tokens is a key to a lookup table. The encoding is pretty lame, and very arbitrary, but it confounded folks for a few hours at least. There's dozens of implementations of this decoding to be found on the Web, although none in .NET, which is where we come in. Here's a resource page that includes several implementations in C, Perl and Python, http://www.beau.lib.la.us/~jmorris/linux/cuecat/ but it hasn't been updated in at least six years. There's also some very old but interesting discussion here http://cexx.org/cuecat.htm.

这些令牌中的每一个都是查找表的关键。 编码非常la脚,而且非常随意,但是它至少使人们困惑了几个小时。 在Web上有数十种这种解码的实现,尽管在.NET中找不到,这就是我们的用武之地。这是一个资源页面,其中包括C,Perl和Python的几种实现, http://www.beau。 lib.la.us/~jmorris/linux/cuecat/,但至少有六年没有更新。 http://cexx.org/cuecat.htm上还有一些非常古老但有趣的讨论。

The lookup table looks like this (a C# example):

查找表如下所示(一个C#示例):

static Decoder()

静态Decoder()

{

{

    decodingTable = new Dictionary<string, int>[3];

encodingTable =新字典< string , int > [3];

    decodingTable[0] = new Dictionary<string, int>();

codingTable [0] =新字典< string , int >();

    decodingTable[1] = new Dictionary<string, int>();

codingTable [1] =新字典< string , int >();

    decodingTable[2] = new Dictionary<string, int>();

codingTable [2] =新字典< string , int >();

    decodingTable[0]["Z"] = 0;

encodingTable [0] [ “ Z” ] = 0;

    decodingTable[0]["Y"] = 1;

encodingTable [0] [ “ Y” ] = 1;

    decodingTable[0]["X"] = 2;

encodingTable [0] [ “ X” ] = 2;

    decodingTable[0]["W"] = 3;

encodingTable [0] [ “ W” ] = 3;

    decodingTable[0]["3"] = 4;

codingTable [0] [ “ 3” ] = 4;

    decodingTable[0]["2"] = 5;

encodingTable [0] [ “ 2” ] = 5;

    decodingTable[0]["1"] = 6;

encodingTable [0] [ “ 1” ] = 6;

    decodingTable[0]["0"] = 7;

encodingTable [0] [ “ 0” ] = 7;

    decodingTable[0]["7"] = 8;

encodingTable [0] [ “ 7” ] = 8;

    decodingTable[0]["6"] = 9;

encodingTable [0] [ “ 6” ] = 9;

    decodingTable[1]["C3"] = 0;

codingTable [1] [ “ C3” ] = 0;

    decodingTable[1]["CN"] = 1;

encodingTable [1] [ “ CN” ] = 1;

    decodingTable[1]["Cx"] = 2;

codingTable [1] [ “ Cx” ] = 2;

    decodingTable[1]["Ch"] = 3;

encodingTable [1] [ “ Ch” ] = 3;

    decodingTable[1]["D3"] = 4;

encodingTable [1] [ “ D3” ] = 4;

    decodingTable[1]["DN"] = 5;

encodingTable [1] [ “ DN” ] = 5;

    decodingTable[1]["Dx"] = 6;

encodingTable [1] [ “ Dx” ] = 6;

    decodingTable[1]["Dh"] = 7;

codingTable [1] [ “ Dh” ] = 7;

    decodingTable[1]["E3"] = 8;

codingTable [1] [ “ E3” ] = 8;

    decodingTable[1]["EN"] = 9;

encodingTable [1] [ “ EN” ] = 9;

    decodingTable[2]["n"] = 0;

encodingTable [2] [ “ n” ] = 0;

    decodingTable[2]["j"] = 1;

encodingTable [2] [ “ j” ] = 1;

    decodingTable[2]["f"] = 2;

encodingTable [2] [ “ f” ] = 2;

    decodingTable[2]["b"] = 3;

encodingTable [2] [ “ b” ] = 3;

    decodingTable[2]["D"] = 4;

encodingTable [2] [ “ D” ] = 4;

    decodingTable[2]["z"] = 5;

encodingTable [2] [ “ z” ] = 5;

    decodingTable[2]["v"] = 6;

encodingTable [2] [ “ v” ] = 6;

    decodingTable[2]["r"] = 7;

encodingTable [2] [ “ r” ] = 7;

    decodingTable[2]["T"] = 8;

encodingTable [2] [ “ T” ] = 8;

    decodingTable[2]["P"] = 9;

encodingTable [2] [ “ P” ] = 9;

}

}

private static Dictionary<string, int>[] decodingTable;

私有静态字典< string , int > []

See how some tokens are two chars and some are one? We'll run through the tokens testing to see if they are in each dictionary and creating the result. For my Gaiman book, we end up with:

看看有些令牌是两个字符,有些是一个字符吗? 我们将对令牌进行测试,以查看它们是否在每个字典中并创建结果。 对于我的盖曼书,我们得出以下结论:

978006093471251300

978006093471251300

Now what do we do with it?

现在我们该怎么办?

UPCs and ISBN

UPC和ISBN

Universal Product Codes or UPCs are different from ISBNs. This page at the Book-Scanning Project gave me the algorithm I needed to convert a UPC code into an ISBN that I could use to talk to Amazon.com. Most books have a bar code with 13 digits starting with "978." Turns out that the first 3 digits of a UPC are the country of origin, but "978" is "Bookland." Apparently the UPC number for a book is called the "Bookland EAN."

通用产品代码或UPC与ISBN不同。 Book-Scanning Project上的此页面为我提供了将UPC代码转换为ISBN所需的算法,我可以使用该ISBN与Amazon.com进行交流。 大多数书籍都有以“ 978”开头的13位数字的条形码。 原来,UPC的前3位数字是原籍国,但是“ 978”是“ Bookland”。 显然,一本书的UPC编号称为“ Bookland EAN”。

Here's the Javascript taken from http://isbn.nu.

这是取自http://isbn.nu的Javascript。

if (indexisbn.indexOf("978") == 0) {
   isbn = isbn.substr(3,9);
   var xsum = 0;
   var add = 0;
   var i = 0;
   for (i = 0; i < 9; i++) {
        add = isbn.substr(i,1);
        xsum += (10 - i) * add;
   }
   xsum %= 11;
   xsum = 11 - xsum;
   if (xsum == 10) { xsum = "X"; }
   if (xsum == 11) { xsum = "0"; }
   isbn += xsum;
}

如果(indexisbn.indexOf(“ 978”)== 0){ isbn = isbn.substr(3,9); var xsum = 0; var add = 0; var i = 0; 对于(i = 0; i <9; i ++){ 加= isbn.substr(i,1); xsum + =(10-i)*加; } xsum%= 11; xsum = 11-xsum; 如果(xsum == 10){xsum =“ X”; } 如果(xsum == 11){xsum =“ 0”; } isbn + = xsum; }

Now, converted into C#

现在,转换为C#

public static string ConvertUPCtoISBN(string code)

公共静态字符串ConvertUPCtoISBN(字符串代码)

{

{

    if (code.StartsWith("978") == false)

如果(code.StartsWith( “ 978” )== false )

    {

{

        throw new ArgumentOutOfRangeException("UPCs that might be books have length 13 and start with 978");

抛出新的ArgumentOutOfRangeException ( “可能是书籍的UPC的长度为13,以978开头” );

    }

}

    code = code.Substring(3,9);

代码= code.Substring(3,9);

    int xsum = 0;

int xsum = 0;

    for (int i = 0; i < 9; i++)

对于( int i = 0; i <9; i ++)

    {

{

        xsum += (10 - i) * int.Parse(code[i].ToString());

xsum + =(10-i)* int .Parse(code [i] .ToString());

    }

}

    xsum %= 11;

xsum%= 11;

    xsum = 11 - xsum;

xsum = 11-xsum;

    String val = xsum.ToString();

字符串val = xsum.ToString();

    switch (xsum)

开关(xsum)

    {

{

        case 10: val = "X"; break;

情况10:val = “ X” ; 休息;

        case 11: val = "0"; break;

情况11:val = “ 0” ; 休息;

    }

}

    code += val;

代码+ = val;

    return code; //Now an ISBN

返回码; //现在是一个ISBN

 }

}

So, my Gaiman UPC of 978006093471251300 turns into an ISBN of 0060934719. This ISBN can be used to talk to Amazon. Note that the source code to this article includes both C# and VB.

因此,我的Gaiman UPC(978006093471251300)变成了一个ISBN(0060934719)。该ISBN可用于与Amazon对话。 请注意,本文的源代码包括C#和VB。

Calling Amazon's REST Web Service

调用亚马逊的REST Web服务

Amazon.com has a rich Web Services platform that includes formal SOAP-based Web Services, but for our project, their HTTP GET-based system will work nicely. I visited the Amazon Web Services Home Page and applied for a free Amazon Web Service Developer Key. You'll need to do the same if you want to get the code to work. Amazon has some create documentation on their site that makes this really easy.

Amazon.com有一个丰富的Web服务平台,其中包括基于SOAP的正式Web服务,但对于我们的项目,其基于HTTP GET的系统将很好地运行。 我访问了Amazon Web Services主页,并申请了免费的Amazon Web Service开发人员密钥。 如果要使代码正常工作,则需要执行相同的操作。 亚马逊在他们的网站上有一些创建文档,这使这变得非常容易。

I'll make an HTTP GET call to Amazon like this (broken up for readability):

我将这样向Amazon进行HTTP GET调用(为提高可读性而分解):

http://webservices.amazon.com/onca/xml?
Service=AWSECommerceService&
AWSAccessKeyId=YOURAWSKEYHERE&
Operation=ItemLookup&
ItemId=0060934719&
IdType=ASIN

http://webservices.amazon.com/onca/xml? 服务= AWSECommerceService& AWSAccessKeyId = YOURAWSKEYHERE Operation = ItemLookup& ItemId = 0060934719 IdType = ASIN

This HTTP GET will result in an XML document as seen in this screenshot.

如该屏幕截图所示,此HTTP GET将生成一个XML文档。

Hanselmancuecataws

Ah! Just the kind of information I was looking for.

啊! 正是我想要的那种信息。

A CueCatConsole

CueCatConsole

Before we integrate with Windows Live Writer, let's make a little test console to make sure this all works together. I put the CueCatDecoder into a small reusable assembly and called it from the Console Application. I also pull the Amazon Web Services key from the configuration file. Note that VS.NET 2005 creates a strongly typed accessor for the "AWSAccessKeyId" automatically.

在与Windows Live Writer集成之前,让我们做一个小的测试控制台,以确保它们可以一起使用。 我将CueCatDecoder放入一个小型可重用的程序集中,并从控制台应用程序中对其进行了调用。 我还从配置文件中拉出Amazon Web Services密钥。 请注意,VS.NET 2005会为“ AWSAccessKeyId”自动创建一个强类型的访问器。

I've removed the error handling in this listing for clarity.

为了清楚起见,我已删除了此清单中的错误处理。

CueCatDecoder.Product product = null;

CueCatDecoder。 产品product = null ;

product = CueCatDecoder.Decoder.Decode(input);

产品= CueCatDecoder。 解码器。解码(输入);

Console.WriteLine("Type: {0}.", product.Type.ToString());

Console .WriteLine( “ Type:{0}。” ,product.Type.ToString());

string amazonType = "ASIN";

字符串amazonType = “ ASIN” ;

string amazonUrl = String.Format("http://webservices.amazon.com/onca/xml
      ?Service=AWSECommerceService&AWSAccessKeyId={0}
      &Operation=ItemLookup&ItemId={1}
      &IdType={2}
      &SearchIndex=",

串amazonUrl =字符串.Format(“http://webservices.amazon.com/onca/xml
?Service = AWSECommerceService&AWSAccessKeyId = {0}
&Operation = ItemLookup&ItemId = {1}
&IdType = {2}
&SearchIndex =“ ,

            Properties.Settings.Default.AWSAccessKeyId,

属性。 设置.Default.AWSAccessKeyId,

            product.ID,

product.ID,

            amazonType);

amazonType);

System.Net.WebClient web = new WebClient();

System.Net。 WebClient web =新的WebClient ();

string amazonData = web.DownloadString(amazonUrl);

字符串amazonData = web.DownloadString(amazonUrl);

XmlDocument xmlDocument = new XmlDocument();

XmlDocument xmlDocument =新的XmlDocument ();

XmlNamespaceManager xnm = new XmlNamespaceManager(xmlDocument.NameTable);

XmlNamespaceManager xnm =新的XmlNamespaceManager (xmlDocument.NameTable);

xnm.AddNamespace("def", "http://webservices.amazon.com/AWSECommerceService/2005-10-05");

xnm.AddNamespace( “ def” , “ http://webservices.amazon.com/AWSECommerceService/2005-10-05” );

xmlDocument.Load(new System.IO.StringReader(amazonData));

XMLDocument.load方法(新System.IO StringReader(amazonData)。);

XmlNode itemNode = xmlDocument.SelectSingleNode("/def:ItemLookupResponse/def:Items/def:Item", xnm);

XmlNode itemNode = xmlDocument.SelectSingleNode( “ / def:ItemLookupResponse / def:Items / def:Item” ,xnm);

Console.WriteLine(String.Format("FOUND a {0} called {1} by {2}",

Console .WriteLine( String .Format( “发现{0}被{2}称为{1}的{0}” ,

        itemNode.SelectSingleNode("//def:ProductGroup", xnm).InnerText,

itemNode.SelectSingleNode( “ // def: ProductGroup ” ,xnm).InnerText,

        itemNode.SelectSingleNode("//def:Title", xnm).InnerText,

itemNode.SelectSingleNode( “ // def:Title” ,xnm).InnerText,

        itemNode.SelectSingleNode("//def:Author", xnm).InnerText));

itemNode.SelectSingleNode( “ // def:Author” ,xnm).InnerText));

Notice that since the Amazon XML includes a default namespace, we have to let SelectSingleNode know about that namespace by registering a namespace prefix - in this case "def:" - that we use later in our XPath. There are many ways to query XML within the .NET Base Class Library that are faster, but for a small application like this the XmlDocument is a reasonable choice when performance doesn't matter.

请注意,由于Amazon XML包括默认名称空间,因此我们必须通过注册名称空间前缀(在本例中为“ def:”)让SelectSingleNode知道该名称空间,我们稍后将在XPath中使用该名称空间。 .NET基本类库中有许多查询XML的方法,这些方法更快,但是对于像这样的小型应用程序,当性能不重要时,XmlDocument是一个合理的选择。

Here's the output from my CueCatConsole:

这是我的CueCatConsole的输出:

Coding4Fun: CueCatDecoder by Scott Hanselman @ http://www.hanselman.comScan item with CueCat now or press Q then Enter to exit.C3nZC3nZC3nZE3r0Chr3CNnY.cGen.ENr7C3T7D3f0C3vYDW.Type: ISBN.FOUND a Book called The Goal: A Process of Ongoing Improvement by Eliyahu M. GoldrattScan item with CueCat now or press Q then Enter to exit.C3nZC3nZC3nZE3r0Chr3CNnY.cGf2.ENr7CNz6C3z6DxvXChzXD3P6.Type: ISBN.FOUND a Book called Programming Sudoku (Technology in Action) by Wei-Meng LeeScan item with CueCat now or press Q then Enter to exit.C3nZC3nZC3nZE3r0Chr3CNnY.cGf2.ENr7C3n1C3PWD3rYCxzYChnZ.Type: ISBN.FOUND a Book called Stardust by Neil GaimanScan item with CueCat now or press Q then Enter to exit

Coding4Fun:Scott Hanselman的CueCatDecoder @ http://www.hanselman.com立即使用CueCat扫描项目,或按Q,然后按Enter键退出。由Eliyahu M.GoldrattScan改进并立即使用CueCat或按Q再按Enter退出。C3nZC3nZC3nZE3r0Chr3CNnY.cGf2.ENr7CNz6C3z6DxvXChzXD3P6.Type:ISBN。 Q,然后按Enter退出。C3nZC3nZC3nZE3r0Chr3CNnY.cGf2.ENr7C3n1C3PWD3rYCxzYChnZ.Type:ISBN.FOUND现在有一本名为CustCat的Neil GaimanScan项目的Stardust书,或按Q然后按Enter退出

Fantastic. It works. Let's integrate it with Windows Live Writer, the new Offline Blogging Editor in BETA (at the time of this writing) from http://www.live.com.

太棒了有用。 让我们将其与Windows Live Writer集成在一起,Windows Live Writer是BETA中新的脱机博客编辑器(在撰写本文时),其网址http://www.live.com

Integrating with Windows Live Writer

与Windows Live Writer集成

Windows Live Writer (download) is a new desktop application that folks with blogs can use to write their blog posts offline. I use DasBlog for my blog at http://www.hanselman.com, and since DasBlog supports the standard MetaWebLog API also supported by Live Writer, I was in business right away.

Windows Live Writer(下载)是一个新的桌面应用程序,拥有博客的人可以用来离线编写其博客文章。 我在http://www.hanselman.com的博客上使用了DasBlog ,由于DasBlog支持Live Writer也支持的标准MetaWebLog API,所以我马上就从事商务活动。

Windows Live Writer also has an SDK that supports "Content Source Plugins" to extend the capabilities of the application and let folks insert new kinds of data. That's exactly what I want to do! I'd like to click "Blog about Book" and have the book title and author appear linked with an image of the book cover. I'd also like have the Amazon.com URL to include my Amazon Associates ID so I could make a few cents if someone clicks my link and buys the book.

Windows Live Writer还具有一个支持“内容源插件”的SDK ,以扩展应用程序的功能并允许人们插入新类型的数据。 那正是我想做的! 我想单击“关于书的博客”,并显示书名和作者与书的封面图片的链接。 我还希望Amazon.com URL包含我的Amazon Associates ID,这样,如果有人单击我的链接并购买该书,我可以赚几美分。

Writing a plugin for Windows Live Writer couldn't be easier. The SDK includes step-by-step instructions. I created a class that derived from WindowsLive.Writer.Api.ContentSource and overrode the CreateContent method, returning my new snippet of HTML in the newContent string variable.

为Windows Live Writer编写插件再简单不过了。 SDK包含分步说明。 我创建了一个从WindowsLive.Writer.Api.ContentSource派生的类,并覆盖了CreateContent方法,在newContent字符串变量中返回了我HTML新代码段。

Here's the gist of the source, again with error handling removed for clarity. VB is included in the download.

这是消息源的要旨,为清晰起见,再次删除了错误处理。 VB包含在下载中。

using System;

使用系统;

using System.Collections.Generic;

使用System.Collections.Generic;

using System.Windows.Forms;

使用System.Windows.Forms;

using WindowsLive.Writer.Api;

使用WindowsLive.Writer.Api;

using CueCatDecoder;

使用CueCatDecoder;

namespace AmazonLiveWriterPlugin

命名空间AmazonLiveWriterPlugin

{

{

    [WriterPlugin("605EEA63-B74B-4e9d-A290-F5E9E8229FC1", "Amazon Links with CueCat",

[ WriterPlugin ( “ 605EEA63-B74B-4e9d-A290-F5E9E8229FC1” , “与CueCat的Amazon链接” ,

        ImagePath = "Images.CueCat.png",

ImagePath = “ Images.CueCat.png” ,

        PublisherUrl = "http://www.hanselman.com",

PublisherUrl = “ http://www.hanselman.com” ,

        Description = "Amazon Links with a CueCat.")]

Description = “带有CueCat的Amazon链接。” )]

    [InsertableContentSource("Amazon Links")]

[ InsertableContentSource ( “ Amazon链接” )]

    public class Plugin : ContentSource

公共类插件: ContentSource

    {

{

        const string AMAZONASSOCIATESID = "amazonassociatesid";

const string AMAZONASSOCIATESID = “ amazonassociatesid” ;

        const string AMAZONWEBSERVICESID = "amazonwebservicesid";

const string AMAZONWEBSERVICESID = “ amazonwebservicesid” ;

        public override System.Windows.Forms.DialogResult CreateContent(System.Windows.Forms.IWin32Window dialogOwner, ref string newContent)

公共重写System.Windows.Forms。 的DialogResult createContent中(System.Windows.Forms的。IWin32Window dialogOwner,REF串newContent)

        {

{

            using(InsertForm form = new InsertForm())

使用( InsertForm form = new InsertForm ())

            {

{

                form.AmazonAssociatesID = this.Options[AMAZONASSOCIATESID];

form.AmazonAssociatesID = this .Options [AMAZONASSOCIATESID];

                form.AmazonWebServicesID = this.Options[AMAZONWEBSERVICESID];

form.AmazonWebServicesID = this .Options [AMAZONWEBSERVICESID];

                DialogResult result = form.ShowDialog();

DialogResult结果= form.ShowDialog();

                if (result == DialogResult.OK)

如果(结果== DialogResult。确定)

                {

{

                    this.Options[AMAZONASSOCIATESID] = form.AmazonAssociatesID;

this .Options [AMAZONASSOCIATESID] = form.AmazonAssociatesID;

                    this.Options[AMAZONWEBSERVICESID] = form.AmazonWebServicesID;

this .Options [AMAZONWEBSERVICESID] = form.AmazonWebServicesID;

                    Product p = Decoder.Decode(form.CueCatData);

产品p = Decoder .Decode(form.CueCatData);

                    AmazonBook book = AmazonBookPopulator.CreateAmazonProduct(p, form.AmazonWebServicesID);

AmazonBook book = AmazonBookPopulator .CreateAmazonProduct(p,form.AmazonWebServicesID);

                    string associatesId = form.AmazonAssociatesID.Trim();

字符串associatesId = form.AmazonAssociatesID.Trim();

                    string builtAmazonUrl = "<a href=\"http://www.amazon.com/exec/obidos/redirect?link_code=as2&path=ASIN/{0}&tag={1}&camp=1789&creative=9325\">{2} by {3}</a><a href=\"http://www.amazon.com/exec/obidos/redirect?link_code=as2&path=ASIN/{0}&tag={1}&camp=1789&creative=9325\"><img border=\"0\" src=\"http://images.amazon.com/images/P/{0}.01._AA_SCMZZZZZZZ_.jpg\"></a><img src=\"http://www.assoc-amazon.com/e/ir?t={1}&l=as2&o=1&a={0}\" width=\"1\" height=\"1\" border=\"0\" alt=\"\" style=\"border:none !important; margin:0px !important;\" />";

内置的字符串AmazonUrl = “ <a href=\"http://www.amazon.com/exec/obidos/redirect?link_code=as2&path=ASIN/{0}&tag={1}&camp=1789&creative=9325\"> {2 }由{3} </a> <a href = \“ http://www.amazon.com/exec/obidos/redirect?link_code=as2&path=ASIN/{0}&tag={1}&camp=1789&creative=9325 \“> <img border = \” 0 \“ src = \” http://images.amazon.com/images/P/ {0} .01._AA_SCMZZZZZZZZZ_.jpg \“> </a> <img src = \“ http://www.assoc-amazon.com/e/ir?t= {1}&l = as2&o = 1&a = {0} \” width = \“ 1 \” height = \“ 1 \” border = \“ 0 \” alt = \“ \” style = \“ border:none!important; margin:0px!important; \“ />” ;

                    newContent = string.Format(builtAmazonUrl, book.ID, associatesId, book.Title, book.Author);

newContent =字符串.Format(builtAmazonUrl,book.ID,associatesId,book.Title,book.Author);

                }

}

                return result;

返回结果;

            }

}

        }

}

    }

}

}

}

Notice the crazy Amazon.com URL. Most folks with blogs become Amazon Associates to make a little money to pay for hosting (you won't get rich doing this, believe me). The Amazon Associates site includes link builders that create these complex snippets of HTML. I selected the large image, basic HTML option, then inserted String.Format tokens like {0} in the appropriate places.

注意疯狂的Amazon.com URL。 大多数拥有博客的人都成为了Amazon Associates,可以赚一点钱来支付托管费用(相信我,您这样做不会致富)。 Amazon Associates网站包括创建这些HTML复杂片段的链接构建器。 我选择了大图像,基本HTML选项,然后在适当的位置插入了String.Format标记,例如{0}。

Installation is simple, just copy Coding4Fun.AmazonLiveWriterPlugin.dll and Coding4Fun.CueCatDecoder.dll to C:\Program Files\Windows Live Writer\Plugins and they will be automatically detected.

安装很简单,只需将Coding4Fun.AmazonLiveWriterPlugin.dll和Coding4Fun.CueCatDecoder.dll复制到C:\ Program Files \ Windows Live Writer \ Plugins,它们就会被自动检测到。

Our plugin appears automatically in the Windows Live Writer sidebar. Notice the text and the icon was picked up from the Plugin class attributes. My Amazon Web Services ID and Associates ID are both stored internally by an Options bag managed by Windows Live Writer, making management of preferences very easy for the plugin developer. Once the CueCat data is scanned, we decode it and make the HTTP GET Web Services call using our external CueCat assembly created earlier.

我们的插件会自动显示在Windows Live Writer侧栏中。 注意,文本和图标是从Plugin类属性中拾取的。 我的Amazon Web Services ID和Associates ID都由Windows Live Writer管理的“选项”包在内部存储,这使插件开发人员非常容易管理首选项。 扫描完CueCat数据后,我们将对其解码并使用之前创建的外部CueCat程序集进行HTTP GET Web服务调用。

Hanselmancuecatplugin

Conclusion

结论

There's things that could be extended, added, and improved on with this project. Here are some ideas to get you started:

这个项目可以扩展,添加和改进某些东西。 这里有一些想法可以帮助您入门:

  • Include support for CDs and other products available on Amazon.

    包括对CD和Amazon上其他产品的支持。
  • Add support for more web-based databases with UPC codes.

    使用UPC代码添加对更多基于Web的数据库的支持。
  • Support different Amazon link styles. 

    支持不同的Amazon链接样式。
  • Create a system to print out product tags for a Garage Sale.

    创建一个系统以打印出车库销售的产品标签。

Have fun and have no fear when faced with the words - Some Assembly Required!

遇到这些单词时要开心,不要害怕-需要一些组装!

File Attachment: Hanselman Coding4Fun CueCat.zip (74 KB)

附件:Hanselman Coding4Fun CueCat.zip(74 KB)

Scott Hanselman is the Chief Architect at the Corillian Corporation, an eFinance enabler. He has thirteen years experience developing software in C, C++, VB, COM, and most recently in VB.NET and C#. Scott is proud to be both a Microsoft RD and Architecture MVP. He is co-author of Professional ASP.NET 2.0 with Bill Evjen, available on BookPool.com and Amazon. His thoughts on the Zen of .NET, Programming and Web Services can be found on his blog at http://www.computerzen.com. He thanks his wife and 9 month old Z for indulging him in these hobbies!

Scott Hanselman是Corillian Corporation(eFinance的推动者)的首席架构师。 他在使用C,C ++,VB,COM以及最近在VB.NET和C#中进行软件开发方面拥有十三年的经验。 斯科特为能成为Microsoft RD和架构MVP而感到自豪。 他与Bill Evjen共同撰写了Professional ASP.NET 2.0,可在BookPool.com和Amazon上找到。 他对.NET,编程和Web服务Zen的想法可以在他的博客http://www.computerzen.com上找到。 感谢他的妻子和9个月大的Z给他的这些爱好!

翻译自: https://www.hanselman.com/blog/coding4fun-hardware-boneyard-using-the-cuecat-with-net

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值