So in my program I'm using COM Auotmation (AutomationFactory in Silverlight 4) to create a FileSystemObject, to which I write a string (theContent). theContent in this case is a small UTF-8 XML file, which I serialized using MemoryStream into the string.
The string is fine, but for some reason whenever I call the FileSystemObject's Write method I get the error "HRESULT 0x800A0005 (CTL_E_ILLEGALFUNCTIONCALL from google)." The strangest part is that if I pass another simple string, like "hello," it works with no problems.
Any ideas?
Alternatively, if there's a way to expose a file/text stream with FileSystemObject that I could serialize to directly, that would be good as well (I can't seem to find anything not in VB).
Thanks in advance!
string theContent = System.Text.Encoding.UTF8.GetString(content, 0, content.Length);
string hello = "hello";
using (dynamic fsoCom = AutomationFactory.CreateObject("Scripting.FileSystemObject"))
{
dynamic file = fsoCom.CreateTextFile("file.xml", true);
file.Write(theContent);
file.Write(hello);
file.Close();
}
I solved the same problem today using ADODB.Stream instead of Scripting.FileSystemObject.
In a Silverlight 4 OOB App (even with elevated trust), you cannot access files in locations outside of 'MyDocuments' and a couple of other user related special folders. You have to use the workaround 'COM+ Automation'. But the Scripting.FileSystemObject, which works great for text files, cannot handle binary files. Fortunately you can also use ADODB.Stream there. And that handles binary files just fine. Here is my code, tested with Word Templates, .dotx files:
public static void WriteBinaryFile(string fileName, byte[] binary)
{
const int adTypeBinary = 1;
const int adSaveCreateOverWrite = 2;
using (dynamic adoCom = AutomationFactory.CreateObject("ADODB.Stream"))
{
adoCom.Type = adTypeBinary;
adoCom.Open();
adoCom.Write(binary);
adoCom.SaveToFile(fileName, adSaveCreateOverWrite);
}
}
A file read can be done like this:
public static byte[] ReadBinaryFile(string fileName)
{
const int adTypeBinary = 1;
using (dynamic adoCom = AutomationFactory.CreateObject("ADODB.Stream"))
{
adoCom.Type = adTypeBinary;
adoCom.Open();
adoCom.LoadFromFile(fileName);
return adoCom.Read();
}
}
Why not just:
File.WriteAllText("file.xml", theContent, Encoding.UTF8);
or even
File.WriteAllBytes("file.xml", content);
Related
I'm using a could service to upload files to an Azure Storage service, so I want to check the file's integrity using MD5 checksum, so first I get the checksum from a function.
public static string GetMD5HashFromFile(Stream stream)
{
using (var md5 = MD5.Create())
{
return BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", string.Empty);
}
}
for the test file I'm using I'm getting: 1dffc245282f4e0a45a9584fe90f12f2 and I got the same result when I use an online tool like this.
Then I upload the file to Azure and get it from my code like this: (In order to avoid include the validations let's assume the file and directories do exist.)
public bool CompareCheckSum(string fileName, string checksum)
{
this.storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("MyConnectionString"));
this.fileClient = this.storageAccount.CreateCloudFileClient();
this.shareReference = this.fileClient.GetShareReference(CloudStorageFileShareSettings.StorageFileShareName);
this.rootDir = this.shareReference.GetRootDirectoryReference();
this.directoryReference = this.rootDir.GetDirectoryReference("MyDirectory");
this.fileReference = this.directoryReference.GetFileReference(fileName);
Stream stream = new MemoryStream();
this.fileReference.DownloadToStream(stream);
string azureFileCheckSum = GetMD5HashFromFile(stream);
return azureFileCheckSum.ToLower() == checksum.ToLower();
}
I also tried to get the checksum using a different process like this:
public bool CompareCheckSum(string fileName, string checksum)
{
this.storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("MyConnectionString"));
this.fileClient = this.storageAccount.CreateCloudFileClient();
this.shareReference = this.fileClient.GetShareReference(CloudStorageFileShareSettings.StorageFileShareName);
this.rootDir = this.shareReference.GetRootDirectoryReference();
this.directoryReference =
this.rootDir.GetDirectoryReference("MyDirectory");
this.fileReference = this.directoryReference.GetFileReference(fileName);
this.fileReference.FetchAttributes();
string azureFileCheckSum = this.fileReference.Metadata["md5B64"];
return azureFileCheckSum.ToLower() == checksum.ToLower();
}
Finally, for the azureFileCheckSum I'm getting: d41d8cd98f00b204e9800998ecf8427e not sure if am I doing something wrong or if something change when I upload the file to the ftp...
Before you call md5.ComputeHash(stream), you need to reset the stream's position to the beginning.
stream.Position = 0;
Of course, this will fail with a NotSupportedException if the stream type doesn't support seeking, but in your case it should work.
I am submitting the ACA forms(tax year:2016) to the IRS, getting the below error
<ns3:FormBCTransmitterSubmissionDtl xmlns="urn:us:gov:treasury:irs:ext:aca:air:ty16" xmlns:ns2="urn:us:gov:treasury:irs:common" xmlns:ns3="urn:us:gov:treasury:irs:msg:form1094-1095BCtransmittermessage">
<ACATransmitterSubmissionDetail>
<TransmitterErrorDetailGrp>
<ns2:ErrorMessageDetail>
<ns2:ErrorMessageCd>MANIFEST-025</ns2:ErrorMessageCd>
<ns2:ErrorMessageTxt>Manifest 'ChecksumAugmentationNum' must match the IRS-calculated 'ChecksumAugmentationNum' value of the transmission</ns2:ErrorMessageTxt>
</ns2:ErrorMessageDetail>
</TransmitterErrorDetailGrp>
</ACATransmitterSubmissionDetail>
Attached is our MTOM format we are using to send it through A2A.
https://www.dropbox.com/home?preview=samplemtom.txt
I am also tried the ChecksumAugmentationNum value set as Lower case also.
Have you successfully transmitted for Tax Year 2015? I have seen another post related to this issue, but have not run into this issue while sending TY2015 (to AATS or Production) or TY2016 records to AATS. My checksum calculation has not changed, and is very simple.
I have two methods I use to create the checksum: GetChecksum(string) and GetMD5Hash(MD5, string). This approach worked for TY2015, and I expect it to work for TY2016. IIRC, I took this approach directly from MSDN.
The string I pass into the GetChecksum method is the contents of the Form Data Attachment. In my process, I output the XML document into the file system for audit purposes, so the attachment is a physical file for me to use and reference. I read the attachment into a string variable using File.ReadAllText(string path) method.
After generating the checksum my process also will check the checksum against the database and return whether or not that checksum exists (meaning it was used by another form). In the case where this is true, then I update the Contact Suffix, regenerate the Form Data and then regenerate the checksum; this is per the IRS rules for transmission.
This is what is currently working for me, and hopefully this helps you.
Application Callers:
This is what I am doing to call the Checksum calculation functions/routines. It should be noted, I am physically writing each Form Data XML file to the File System, then reading from that.
string AttachmentFileContents = "";
AttachmentFileContents = File.ReadAllText(FormDataFilePath);
string checkSumAugmentationNumber = new Checksum().GetChecksum(AttachmentFileContents);
Checksum Methods:
These are the two methods I use for Checksum Calculation.
public string GetChecksum(string stringToEncrpyt)
{
string hash = "";
using(MD5 md5Hash = MD5.Create())
{
hash = GetMD5Hash(md5Hash, stringToEncrpyt);
}
return hash;
}
private string GetMD5Hash(MD5 md5Hash, string input)
{
byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
StringBuilder sb = new StringBuilder();
for (int i = 0; i < data.Length; i++)
{
sb.Append(data[i].ToString("x2"));
}
return sb.ToString();
}
I ran into a problem this week regarding the Windows Shell Property System when applied to TIFF/TIF files. I'm using Microsoft.WindowsAPICodePack 1.1.0.0 to access the property system.
When adding properties, the file gets corrupted because it seems to get stored where the first IFD pointer would be expected. Now I'm not sure it simply inserts itself at the 5th byte, after the file header (0x49 0x49 0x2A 0x00), of if it overwrites any existing data. Additionally, when comparing the hexadecimal of the IDF entries headers, the bytes looks different. Now when I say corrupted, it is only when programmatically opening the file as a byte stream, not knowing if the file has a property system container added to it. It opens fine in Windows Image Preview, but not in the software my clients are using to view TIFF files.
Here's how I'm adding the properties (as an array of key=value strings).
public void SetFileTag(string fileName, string tagName, string tagValue)
{
try
{
using (var shellFile = ShellFile.FromFilePath(fileName))
{
var keywords = shellFile.Properties.System.Keywords.Value;
var keyValue = string.Concat(tagName, "=", tagValue);
var list = keywords == null ? new List<string>() : new List<string>(keywords);
if (list.Contains(keyValue))
{
return;
}
list.Add(keyValue);
using (var writer = shellFile.Properties.GetPropertyWriter())
{
writer.WriteProperty(shellFile.Properties.System.Keywords, list.ToArray(), true);
writer.Close();
}
}
}
finally
{
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
I looked in the code pack for anything available to entirely remove the properties, but I can't find any method to do so, I can only remove the keywords value. Anyone would have an idea on how to perform this? It doesn't have to be .NET code, it can very well be a command-line tool or win32 code.
I'm writing a short to a file, using the following code in Java:
RandomAccessFile file = new RandomAccessFile("C:\\Users\\PC\\Desktop\\myFile.bin", "rw");
file.writeShort(11734);
file.close();
When I read it back in Java, I get the same (11734) number back. However, when I read the number in C# using the following code:
string p = "C:\\Users\\PC\\Desktop\\myFile.bin";
short s = new BinaryReader(File.OpenRead(p)).ReadInt16();
The variable s contains -10707.
How can this happen, and is there a way to retrieve the number I wrote to a file in Java, in C#?
BigEndian/LittleEndian problem. see below
byte[] b = BitConverter.GetBytes((short)11734);
var s = BitConverter.ToInt16(new byte[] {b[1],b[0] }, 0);
s will be -10707
You can use IPAddress.HostToNetworkOrder to convert from one form to another.
var sh1 = IPAddress.HostToNetworkOrder((short)11734); //-10707
var sh2 = IPAddress.HostToNetworkOrder((short)-10707); //11734
You can also crete your own BinaryReader
public class MyBinaryReader : BinaryReader
{
public MyBinaryReader(Stream s) : base(s)
{
}
public override short ReadInt16()
{
return IPAddress.HostToNetworkOrder(base.ReadInt16());
}
}
As others have said, this is an endianness problem.
My MiscUtil library includes EndianBinaryReader and EndianBitConverter which let you use the familiar API but with the flexibility of specifying the endianness:
using System;
using System.IO;
using MiscUtil.Conversion;
using MiscUtil.IO;
static class Test
{
static void Main()
{
using (var stream = File.OpenRead("myfile.bin"))
{
var converter = new BigEndianBitConverter();
var reader = new EndianBinaryReader(converter, stream);
Console.WriteLine(reader.ReadInt16());
}
}
}
Take note that in Java you also have the option to employ a ByteBuffer.allocate(size).order(LITTLE_ENDIAN).asShortBuffer().
your byte order is wrong
11734 = 2DD6
-10707 = D62D
http://en.wikipedia.org/wiki/Endianness
Java always uses network-order (aka big-endian) when it writes out shorts, ints and longs. My guess is that C# reads it little-endian.
I am forced to use an older version of the SharpZipLib and the standard Microsoft libraries to perform this. I have a gziped file whose name is different than the filename inside the archive. I need to parse the gzip file header to return the original filename. Here is documentation on the gzip website:
http://www.gzip.org/zlib/rfc-gzip.html#conventions
And a java example that looks like it might be doing what I want. it looks like it checks for the file header, but doesn't actually read the file name.
(Sorry couldn't post more than 1 hyperlink)
(http://www).java2s.com/Open-Source/Java-Document/6.0-JDK-Modules/j2me/java/util/zip/GZIPInputStream.java.htm
Any help on this problem would be much appreciated. Thanks!
Well if finally figured it out. Its not the safest way or best but i needed a quick and dirty way to do it and this works. So if anyone else needs to know this or want to improve on it, here you go.
using (FileStream stream = File.OpenRead(filePath))
{
int size = 2048;
byte[] data = new byte[2048];
size = stream.Read(data,0,size);
if (data[3] == 8)
{
List<byte> byteList = new List<byte>();
int i = 10;
while (data[i] != 0)
{
byteList.Add(data[i]);
i++;
}
string test = System.Text.ASCIIEncoding.ASCII.GetString(byteList.ToArray());
Console.WriteLine(test);
}
}