C# execute method on other thread - c#

i have a method that read some files and get hashes SHA1Managed and then compare it with other hashes from a list, how can i do this method on other thread?
public bool CheckFile(string file, string filehash)
{
if (File.Exists(file))
{
using (FileStream stream = File.OpenRead(file))
{
SHA1Managed sha = new SHA1Managed();
byte[] checksum = sha.ComputeHash(stream);
string sendCheckSum = BitConverter.ToString(checksum)
.Replace("-", string.Empty);
return sendCheckSum.ToLower() == filehash;
}
}
else return false;
}

If you just want to run it in a background thread you'd actually need to move the task creation up one level since your function returns a result. Depending on how the calling code works something like this might work for you.
var backgroundTask = Task.Factory.StartNew(() =>
{
var result = CheckFile("file", "filehash");
//do something with the result
});

Try by this codes:
public async Task<bool> CheckFile(string file, string filehash)
{
await Task.Run<bool>(()=> {
if (File.Exists(file))
{
using (FileStream stream = File.OpenRead(file))
{
SHA1Managed sha = new SHA1Managed();
byte[] checksum = sha.ComputeHash(stream);
string sendCheckSum = BitConverter.ToString(checksum)
.Replace("-", string.Empty);
return sendCheckSum.ToLower() == filehash;
}
}
else return false;
});
}

Related

Task.Run still freezing UI

So, i'm trying to convert a large byte array into it's base64 encoded variant. But no matter what i try, it seems to freeze up my UI every time it runs.
This is what i've got currently:
private async void TxtOutput_DragDrop(object sender, DragEventArgs e)
{
string outputText = String.Empty;
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
string[] path = (string[])e.Data.GetData(DataFormats.FileDrop);
byte[] fileBytes = File.ReadAllBytes(path[0]);
txtOutput.Text = await Task.Run(() => {return Convert.ToBase64String(fileBytes);});
_ = fileBytes;
_ = path;
}
}
So, the line that freezes everything up is:
txtOutput.Text = await Task.Run(() => {return Convert.ToBase64String(fileBytes);});
File.ReadAllBytes(path[0])
Could be a bottle neck you can use async operation for read files
Here is an example how to read file async
public async Task ProcessReadAsync()
{
string filePath = #"temp2.txt";
if (File.Exists(filePath) == false)
{
Debug.WriteLine("file not found: " + filePath);
}
else
{
try
{
string text = await ReadTextAsync(filePath);
Debug.WriteLine(text);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
}
private async Task<string> ReadTextAsync(string filePath)
{
using (FileStream sourceStream = new FileStream(filePath,
FileMode.Open, FileAccess.Read, FileShare.Read,
bufferSize: 4096, useAsync: true))
{
StringBuilder sb = new StringBuilder();
byte[] buffer = new byte[0x1000];
int numRead;
while ((numRead = await sourceStream.ReadAsync(buffer, 0, buffer.Length)) != 0)
{
string text = Encoding.Unicode.GetString(buffer, 0, numRead);
sb.Append(text);
}
return sb.ToString();
}
}
Right, so it turns out that my problem was using a textbox for writing the string to instead of a richtextbox. This fixed my problem. Thanks for your answers.

How to hash file (MD5, SHA..v.v..) in UWP

I'm coding an Universal App, how can I hash a file with md5 or SHA algorithm ?
I searched, found this: system.security.cryptography, but it's not available in my project.
I'm using Visual Studio 2015.
In UWP, it is Windows.Security.Cryptography namespace and Windows.Security.Cryptography.Core namespace.
In the CryptographicBuffer class there is sample showing how to use this class.
Here is my demo about getting MD5 hash:
private string strAlgNameUsed;
public string GetMD5Hash(String strMsg)
{
string strAlgName = HashAlgorithmNames.Md5;
IBuffer buffUtf8Msg = CryptographicBuffer.ConvertStringToBinary(strMsg, BinaryStringEncoding.Utf8);
HashAlgorithmProvider objAlgProv = HashAlgorithmProvider.OpenAlgorithm(strAlgName);
strAlgNameUsed = objAlgProv.AlgorithmName;
IBuffer buffHash = objAlgProv.HashData(buffUtf8Msg);
if (buffHash.Length != objAlgProv.HashLength)
{
throw new Exception("There was an error creating the hash");
}
string hex = CryptographicBuffer.EncodeToHexString(buffHash);
return hex;
}
I'm going to throw this in, just because it is UWP... and if you use storageFolder.GetFileAsync to get to the file, the method will have to return an Async Task or a void. Forgive me if this isn't perfect, I'm more familiar with asp.net. But this does return a valid MD5 Hash on a file that was created in the LocalState folder:
private async Task<string> GetMD5Hash()
{
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
var storageFolder = localFolder; // await KnownFolders.GetFolderForUserAsync(null, KnownFolderId.PicturesLibrary);
var file = await storageFolder.GetFileAsync("signature.png");
byte[] computedHash = new MD5CryptoServiceProvider().ComputeHash(File.ReadAllBytes(file.Path));
var sBuilder = new StringBuilder();
foreach (byte b in computedHash)
{
sBuilder.Append(b.ToString("x2").ToLower());
}
string result = sBuilder.ToString();
return result;
}

How to get SHA1 and MD5 checksum from HttpPostedFileBase file.InputStream

I want to get the checksum of uploaded file in MVC.
Currently I am doing this
public ActionResult Index(HttpPostedFileBase file, string path)
{
if (file != null)
{
string checksumMd5 = HashGenerator.GetChecksum(file.InputStream, HashGenerator.MD5);;
string checksumSha1 = HashGenerator.GetChecksum(file.InputStream, HashGenerator.SHA1);
//other logic follows....
}
but when I do following in Console app and read file from File path then,
string path = #"C:\Users\anandv4\Desktop\Manifest-5977-681-673.txt";
var md5hash = HashGenerator.GetChecksum(path, HashGenerator.MD5);
var sha1 = HashGenerator.GetChecksum(path, HashGenerator.SHA1);
the values of both are different.
Code for generating hash :
public static string GetChecksum(string fileName, HashAlgorithm algorithm)
{
using (var stream = new BufferedStream(File.OpenRead(fileName), 1000000))
{
return BitConverter.ToString(algorithm.ComputeHash(stream)).Replace("-", string.Empty);
}
}
public static string GetChecksum(Stream stream, HashAlgorithm algorithm)
{
using (stream)
{
return BitConverter.ToString(algorithm.ComputeHash(stream)).Replace("-", string.Empty);
}
}
Can anyone explain me what is the difference between the two. Utlimately both the methods resolve to Stream in GetChecksum method
If you are hashing a stream, you need to set the current position of the stream to 0 before computing the hash.
file.InputStream.Seek(0, SeekOrigin.Begin);
For me, this is a great place for an extension method, eg.:
//compute hash using extension method:
string checksumMd5 = file.InputStream.GetMD5hash();
Which is supported by the class:
using System;
using System.IO;
public static class Extension_Methods
{
public static string GetMD5hash(this Stream stream)
{
stream.Seek(0, SeekOrigin.Begin);
using (var md5Instance = System.Security.Cryptography.MD5.Create())
{
var hashResult = md5Instance.ComputeHash(stream);
stream.Seek(0, SeekOrigin.Begin);
return BitConverter.ToString(hashResult).Replace("-", "").ToLowerInvariant();
}
}
}

Unity3D WWW Error C#

I am working in Unity trying to figure out the WWW class and access API from online-go.com
I get an error in the Debug.Log though. Additionally, the Debug on Line 58 just returns a blank string. I don't think I am fully understanding how to use WWW since this is the first time I am using it.
Necessary data rewind wasn't possible
UnityEngine.Debug:Log(Object)
<LoadWWW>c__Iterator0:MoveNext() (at Assets/OGS.cs:60)
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using System.IO;
using System.Net;
using System.Text;
//using System.Net.httpclient;
public class OGS : MonoBehaviour {
string generateAPIClient = "http://beta.online-go.com/developer";
string APIKey = "0c63a59dd17ec69a48af5d9dc8b4e956";
string requestUserToken = "oauth2/access_token";
string clientID = "";
string clientSecret = "";
string baseURL = "http://online-go.com/";
string url = "";
string username;
string password;
string POST;
List<Settings> settings;
// Use this for initialization
void Start () {
Debug.Log("Opened");
settings = new List<Settings>();
Load("Settings");
clientID = AssignSetting("clientID");
clientSecret = AssignSetting("clientSecret");
username = AssignSetting("username");
password = AssignSetting("password");
POST = string.Format( "client_id={0}&client_secret={1}&grant_type=password&username={2}&password={3}",
clientID, clientSecret, username, password);
url = baseURL + requestUserToken;
StartCoroutine("LoadWWW");
}
//Assign settings loaded to settings variables
string AssignSetting (string item) {
int position = -1;
for(int i=0;i<settings.Count;i++) {
if(settings[i].name == item){return settings[i].value;}
}
return string.Empty;
}
IEnumerator LoadWWW() {
byte[] byteArray = GetBytes(POST);
Dictionary<string,string> headers = new Dictionary<string,string>();
headers.Add("Content-Type", "application/x-www-form-urlencoded");
WWW text = new WWW(url, byteArray, headers);
yield return text;
byteArray = text.bytes;
string POSTResponse = GetString(byteArray);
Debug.Log(POSTResponse);
Debug.Log(text.responseHeaders);
Debug.Log(text.error);
}
static byte[] GetBytes(string str)
{
byte[] bytes = new byte[str.Length * sizeof(char)];
System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
return bytes;
}
static string GetString(byte[] bytes)
{
char[] chars = new char[bytes.Length / sizeof(char)];
System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
return new string(chars);
}
private bool Load(string fileName)
{
// Handle any problems that might arise when reading the text
try
{
string line;
// Create a new StreamReader, tell it which file to read and what encoding the file
// was saved as
StreamReader theReader = new StreamReader(Application.dataPath + "/Resources/" + fileName + ".txt");
// Immediately clean up the reader after this block of code is done.
// You generally use the "using" statement for potentially memory-intensive objects
// instead of relying on garbage collection.
// (Do not confuse this with the using directive for namespace at the
// beginning of a class!)
using (theReader)
{
// While there's lines left in the text file, do this:
do
{
line = theReader.ReadLine();
if (line != null)
{
// Do whatever you need to do with the text line, it's a string now
// In this example, I split it into arguments based on comma
// deliniators, then send that array to DoStuff()
string[] entries = line.Split(':');
if (entries.Length > 0){
Settings newSetting = new Settings(entries[0], entries[1]);
settings.Add(newSetting);
}
}
}
while (line != null);
// Done reading, close the reader and return true to broadcast success
theReader.Close();
return true;
}
}
// If anything broke in the try block, we throw an exception with information
// on what didn't work
catch (Exception e)
{
Console.WriteLine("{0}\n", e.Message);
return false;
}
}
}
necessary data rewind wasn't possible mainly occurs when redirection is involved during the WWW call.
To fix this, make sure that the URL's you call are not redirecting you to another page in the process. Also it would be a good idea to have some error handling before you use the value.
// wait for the result
yield return text;
// Handle the error if there is any
if (!string.IsNullOrEmpty(text.error)) {
Debug.Log(text.error);
}
// Now do with POSTResponse whatever you want if there were no errors.

Size for ApplicationDataCompositeValue

I'm porting my published app in Windows Phone, to Win 8. While trying to write to the IsolatedStorage equivalent, ApplicationDataContainer, I get an exception. The exception says
Error : The size of the state manager setting has exceeded the limit
I'm not sure if this is the correct way of using the ApplicationDataContainer.
public void WriteToIsolatedStorage()
{
try
{
ApplicationDataContainer localSettings = ApplicationData.Current.LocalSettings;
ApplicationDataCompositeValue composite = new ApplicationDataCompositeValue();
if (localSettings.Containers.ContainsKey("LoveCycleSetting"))
{
localSettings.DeleteContainer("LoveCycleSetting");
}
composite["GetWeekStart"] = m_bWeekStart;
composite["iHistCount"] = m_iHistCount;
composite["dtHistory"] = this.DateTimeToString(m_dtHistory);
composite["avgCycleTime"] = m_iAvgCycleTime;
}
}
The exception occurs at the second last line. m_dtHistory is a string array of size 400. So does the ApplicationDataCompositeValue have a fixed size? Or do I have to write the m_dtHistory array into a file? Cuz in WindowsPhone I could directly write the array into the IsolatedStorageSettings.
It would be really helpful if someone could guide me on this or give links.
Alfah
Yes, ironically settings storage is easier on the phone than WinRT. You can just serialize to a file instead. Here is what I did (partially copied from the code already in SuspensionManager.cs), which works for both value and reference types.
internal static async Task<bool> SaveSetting(string Key, Object value)
{
var ms = new MemoryStream();
DataContractSerializer serializer = new DataContractSerializer(value.GetType());
serializer.WriteObject(ms, value);
await ms.FlushAsync();
// Uncomment this to preview the contents being written
/*char[] buffer = new char[ms.Length];
ms.Seek(0, SeekOrigin.Begin);
var sr = new StreamReader(ms);
sr.Read(buffer, 0, (int)ms.Length);*/
ms.Seek(0, SeekOrigin.Begin);
StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync(Key, CreationCollisionOption.ReplaceExisting);
using (Stream fileStream = await file.OpenStreamForWriteAsync())
{
await ms.CopyToAsync(fileStream);
await fileStream.FlushAsync();
}
return true;
}
// Necessary to pass back both the result and status from an async function since you can't pass by ref
internal class ReadResults
{
public bool Success { get; set; }
public Object Result { get; set; }
}
internal async static Task<ReadResults> ReadSetting<type>(string Key, Type t)
{
var rr = new ReadResults();
try
{
var ms = new MemoryStream();
DataContractSerializer serializer = new DataContractSerializer(t);
StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync(Key);
using (IInputStream inStream = await file.OpenSequentialReadAsync())
{
rr.Result = (type)serializer.ReadObject(inStream.AsStreamForRead());
}
rr.Success = true;
}
catch (FileNotFoundException)
{
rr.Success = false;
}
return rr;
}
The name of each setting can be 255 characters in length at most. Each setting can be up to 8K bytes in size and each composite setting can be up to 64K bytes in size.
https://msdn.microsoft.com/library/windows/apps/windows.storage.applicationdata.localsettings.aspx
I read somewhere but lost the reference that the size is 64KB
public static void StoreConfig(string content)
{
IEnumerable<string> strs = Split(content, 2000);
int i = 1;
foreach(var s in strs)
{
AppLocalSettings.Values["test" + (i++)] = s;
}
AppLocalSettings.Values["test_count"] = i-1 +"";
}
public static string ReadConfig()
{
string s = "";
int count = Convert.ToInt32(AppLocalSettings.Values["test_count"]);
for(int i = 1; i<=count; i++)
{
s += Convert.ToString(AppLocalSettings.Values["test" + (i)]);
}
return s;
}

Categories