Category: C#
ScribeStation Beta Testing Open
Link: http://www.scribestation.com
ScribeStation.com has open beta testing of the new Livescribe acquisition client which can take data off of your Livescribe Pulse pen and convert it to many usable formats. Go to http://www.scribestation.com for more information and become a beta tester today!
ASP .NET Session
Link: http://msdn.microsoft.com/en-us/magazine/cc300437.aspx
I deployed a multi-user web application today and for some reason the session was being SHARED between users. Not sure what is causing this. It was a simple application that only needed the session for some non-confidential data so I just threw them into a cookie for now. I am across this interesting link that has some good information so I figured I would post it:
Microsoft.Ink COM Error
I was working with Ink and deploying my assemblies all over the place. Eventually I deployed to a win2k3 server and it starting throwing:
Creating an instance of the COM component with CLSID {AAC46A37-9229-4FC0-8CCE-4497569BF4D1} from the IClassFactory failed due to the following error: 80040235
To resolve this, I went to:
And downloaded the Microsoft Windows XP Tablet PC Edition 2005 Recognizer Pack. Install that and you will no longer get that error.
Hope that helps, would have saved me 4 hours :-)
SQL 2005 and XML Data Type
I was just working with the new XML datatype for SQL 2005 and started getting this error when inserting the value:
XML parsing: line 1, character 45, unable to switch the encoding
I was simply sending a string to a stored proc thinking that would work (it was a string of valid XML)... I was wrong. I did some research and solved the problem by wrapping up the XML String into a SQL XML datatype.
System.Data.SqlTypes.SqlXml xmlSafe = new System.Data.SqlTypes.SqlXml(new System.Xml.XmlTextReader(xmlAsString, System.Xml.XmlNodeType.Document, null));
Sure, it's simple enough but I haven't used the XML type before.
Exploring the AFD File
Having extracted the AFD file from the pen in a previous post I started poking around the contents of it. I then started looking through the LiveScribe desktop DLLs for methods that would help me in getting data out. My goal in this whole exploration of the AFD is to get stroke data off the pen and I managed to find that in the AFD file. I created a C# project and added the following references to "C:\Program Files\Livescribe\Livescribe Desktop\LS.Desktop.AFDDB.dll". Once you add that reference to the project, you can get the stroke contents of the AFD file like so:
LS.Desktop.AFDDB.LSDocument doc = LS.Desktop.AFDDB.LSDocument.LoadDocument("YOURPATHHERE.AFD");
//Check for strokes
if (doc.HasStrokes(0))
{
Console.WriteLine("Has Strokes!");
//Go through each page
for (int pageno = 0; pageno < doc.pageInstances.Count; pageno++)
{
Console.WriteLine(string.Format("Page No {0}", pageno));
//Go through each stroke
for (int strokeno = 0; strokeno < doc.pageInstances[pageno].NumStrokes; strokeno++)
{
Console.WriteLine(string.Format("\tStroke No {0}", strokeno));
//Go through the points
foreach (Point p in doc.pageInstances[pageno].GetStroke(strokeno).Points)
{
Console.WriteLine(string.Format("\t\t({0}, {1})", p.X, p.Y));
}
}
}
}
else
{
Console.WriteLine("No Strokes!");
}
You can use that object to get other things too. If you have any questions or need help just send me an e-mail or post a comment. I would be glad to assist.
-Anthony
LiveScribe Custom Printing... ALMOST!
To custom print your own forms using the LiveScribe Pen there are a few steps. This tutorial assumes you have installed
the LiveScribe Desktop and have it all working normally. CLOSE THE LIVESCRIBE DESKTOP SOFTWARE BEFORE DOING THIS.
Locate your AFD files. By default they are located at "C:\Program Files\Livescribe\Livescribe Desktop\Printing". You will see AFD files here along with a "Printables.xml" files. Go ahead and copy the "LS_PYON_TestPage.afd" and the "Printables.xml" for backup so that you can restore them later if need be. Now, on to the file changing.
Rename "LS_PYON_TestPage.afd" to "MyTestForm.afd".
Open "Printables.xml" in notepad. Change the first Printable Node
from:
<Notepad id="1" guid="0x66d4de896a2c6c85" filename="LS_PYON_TestPage.afd" numberofpages="1" menutext="T&est Page (1 Page)..." menuorder="5" mustexist="True" />
to:
<Notepad id="1" guid="0x66d4de896a2c6c85" filename="MyTestForm.afd" numberofpages="1" menutext="Wicked Cool Document..." menuorder="5" mustexist="True" />
Now, you can open the LiveScribe Desktop and see your form listed on the menu. That is the first step... the next is actually making that document look like one you want.
Go back to the "C:\Program Files\Livescribe\Livescribe Desktop\Printing" folder, rename "MyTestForm.afd" to "MyTestForm.zip".
Extract the "MyTestForm.zip" files to a directory. Look through the files, you will see a bunch of different things. The AFD (as discovered previously) stores a bunch of information. I am not sure what it all is, or even if stroke data that I was looking for would be in there but, there are some good things in here.
Since we want to make our own custom looking form, navigate to the "\userdata\lsac_data" in the extracted file. There you will see "LS_PYON_TestPage.v1.png", that is the form background image. Change that to whatever you would like using Photoshop, or any other imaging tool. There is also a EPS file in "pages\resources", open and change that as well. Once your modifications have been completed go ahead and copy the changed file into the "MyTestForm.zip" file using a zip utility (Winzip, PKZIP, etc.). Finally, rename the file to "MyTestForm.afd".
I figured that would do the trick but the document is not printing to the printer. It says it is but then it doesn't print. So, I am looking into why that could be. I am thinking it has to do with my EPS editing. I am probably not exporting properly. There might also be some kind of check on the AFD file. I'm still not sure.... Any ideas? I plan to revist this soon. I have to get back to getting stroke data out of the AFD for now...
LiveScribe AFD File
Last I left off I was looking into what an AFD file was. I used Red Gate Softwares .NET Reflector (Originally Lutz Roeder's) and saw a lot of metion to Zip utilities and unpacking... so, I figured I'd change the extension from .AFD to .ZIP. IT WORKED! AFD files are simply ZIP files. I unzipped it and all this
came out. I am going to examine the contents and post my findings.
LiveScribe Pulse Data
Now that we know how to get the pen object I am going forward looking into getting data off of the LiveScribe Pen. Using the previous example (see last posting) I have come up with this:
void pc_OnPenDocked(LS.LDSlim.PulseAccessSDK.Interop.HardwarePen pen)
{
Console.WriteLine(pen.PenID.ToString());
ulong t = 0;
LS.LDSlim.PulseAccessSDK.PenData.GetPenData(pen.PenHandle, "Test Page", ref t, @"C:\livescribedump.txt");
}
First I put livescribedump.txt as the output but after researching further (examining the LiveScribe Desktop using filewatcher, etc.) I believe that this is an AFD file. At this point it looks like AFD is the proprietary to LiveScribe so the next step is looking into how these can be viewed/modified/etc. If you want to see some images and output data from the LiveScribe Desktop software check out:
C:\Documents and Settings\alocurto\My Documents\My Livescribe\Library\2594160249046\0x66d4de896a2c6c85_18619045271\cache\userdata\lsac_data
You will want to replace my name with your account of course. I haven't had time to see if those numbers under the Library directory are random to my machine or actually identify a document.
LiveScribe Docking Client
This week I was tasked with figuring out the LiveScribe pen and what can be done to integrate it with some of our existing data entry systems. Over the next few weeks I plan to post information as I find it out. This might be useful to someone else in the future as well as a good reference for me going forward.
If you have a LiveScribe pen, install the LiveScribe desktop (I haven't tested without doing this). Simply create a C# win form application in visual studio. Add the following references:
LS.LDSlim.PluseAccessSDK
LS.LDSlim.PluseAccessSDK.Interop
Both of those can be found in: "C:\Program Files\Livescribe\Livescribe Desktop" (by default).
The PulseAccessSDK.dll needs to be in the bin for this work. What I did was simply add the PulseAccessSDK.dll file which is also found at "C:\Program Files\Livescribe\Livescribe Desktop" and set that to "Copy Always". This will ensure that it copies to the bin at compile time and my app will find it.
Next, add a using statement at the top of your form.
using LS.LDSlim.PulseAccessSDK;
Now we are ready to create the object needed.
Create a member variable:
PenConnection pc;
On the form load, do the following:
pc = PenConnection.CreateInstance();
pc.OnPenDocked += new PenConnection.PenDocked(pc_OnPenDocked);
pc.InitilizeDeviceListening();
Create the following event handler:
void pc_OnPenDocked(LS.LDSlim.PulseAccessSDK.Interop.HardwarePen pen)
{
Console.WriteLine(pen.PenID.ToString());
}
Run the application. When the pen is docked the penId will be printed to the console. There are some other cool properties on there too, just take a look at the HardwarePen object.
Next I plan to see how I can get stroke data off of the pen.
C# File In Use
One of the issues I run into here and there is determining in a file is in use. I have done this in the past by relying on exceptions to help me determine this. I have never liked that so I looked into other ways of determining this.
I am going to try and leverage the ManagementObjectSearcher I know I can write WMI queries to the system and ask for stuff. I found a page on MSDN that lists stuff I can get information on through the WMI query. Check it out here: http://msdn.microsoft.com/en-us/library/aa386179(VS.85).aspx
After adding a reference to System.Management I wrote the following code:
public ManagementObject GetFileManagementObject(string drive, string extension, string fileName, string wmiPath)
{
ManagementObjectSearcher moSearcher = new ManagementObjectSearcher(string.Format("SELECT * FROM CIM_LogicalFile WHERE (Drive='{0}' AND FileName='{1}' AND Extension='{2}')", drive, fileName, extension));
foreach (ManagementObject mangementObj in moSearcher.Get())
{
if (mangementObj.Properties["Path"].Value.ToString() == wmiPath)
{
return (mangementObj);
}
}
return (null);
}
This will find a file and return the management object of the file. You could tweak the inputs to take a file path and chop it up but I am not looking to add all that code for a simple test. I find it odd that I can't seem to add a clause like "WHERE PATH='C:\myfile.txt'" as it results in a error indicating an invalid query. Looks like you can only query certain properties. I tested this on a large VHD file I had at "C:\Test\xpbasedynamic.vhd". Here was my method call:
ManagementObject mangementObj = GetFileManagementObject("C:", "vhd", "xpbasedynamic", @"\test\");
I then ran the following code:
foreach (PropertyData moPropData in mangementObj.Properties)
{
Console.WriteLine(String.Format("{0}:\t{1}", moPropData.Name, moPropData.Value));
}
This resulted in the following printing to the console:
AccessMask: 18809343
Archive: True
Caption: c:\test\xpbasedynamic.vhd
Compressed: False
CompressionMethod:
CreationClassName: CIM_LogicalFile
CreationDate: 20080819163136.458642-240
CSCreationClassName: Win32_ComputerSystem
CSName: YOGI
Description: c:\test\xpbasedynamic.vhd
Drive: c:
EightDotThreeFileName: c:\test\xpbase~1.vhd
Encrypted: False
EncryptionMethod:
Extension: vhd
FileName: xpbasedynamic
FileSize: 1478863872
FileType: Virtual Machine Hard Drive Image
FSCreationClassName: Win32_FileSystem
FSName: NTFS
Hidden: False
InstallDate: 20080819163136.458642-240
InUseCount:
LastAccessed: 20080819163447.176171-240
LastModified: 20070404113325.000000-240
Manufacturer:
Name: c:\test\xpbasedynamic.vhd
Path: \test\
Readable: True
Status: OK
System: False
Version:
Writeable: True
One would think that you could leverage the "InUseCount" property to determine if the file is "In Use." That is not the case. The "InUseCount" property apparently doesn't report the proper data. I Googled around on that and found that people have run into the same thing.
So my big attempt to not rely on exceptions to determine if a file is in use has failed. However, I was introduced to WMI Queries which will be a great addition to my code knowledge.
02/12/10 05:24:14 pm, 