When running a NUnit test from ReSharper to calculate the second answer to AdventOfCode.com day 23, the execution time is around 4 seconds. When running the same test from a console or windows application, the execution time is around 20 seconds. I can't figure out the cause of this difference.
Environment:
Microsoft Visual Studio Professional 2019 (Version 16.8.1)
ReSharper 2020.2.1
Windows 10 Pro (Version 10.0.18363.1198)
Core i7-9750H 2.6 GHz, 16 GB RAM
Project settings:
Release, Any CPU, Do not prefer 32-bit
Console Application
.NET Framework 4.8
NUnit 3.12.0
A LinkedList and a LinkedListNode[] lookup table is allocated, both containing 1 000 000 elements. The following operations are then performed 10 000 000 times: 3 elements are removed and inserted at a different place in the linked list.
The unit test is contained within the console application and is either run using the ReSharper test runner from within Visual Studio (execution time 3.7-4.2 seconds). Or the console application is started, entering the Main() method which jst contains:
static void Main()
{
new AoC_2020_23().D();
}
It doesn't matter if I start the console application from within Visual Studio, from a command prompt or from the Run item in the Windows Start menu. The execution time is around 20-22 seconds every time. The Environment.Is64BitProcess property is true regardless whether running the unit test or the console application.
Including the complete unit test for reference:
[Test]
public void D()
{
Stopwatch timer = Stopwatch.StartNew();
long result = RunB("853192647", 10 * 1000 * 1000);
Console.WriteLine(result);
Assert.AreEqual(664642452305, result);
Console.WriteLine(Environment.Is64BitProcess + " " + timer.Elapsed.TotalSeconds.ToString("0.0"));
}
private long RunB(string input, int turns)
{
int[] labels = input.Select(o => o - '0').ToArray();
LinkedList<int> cups = new LinkedList<int>();
LinkedListNode<int>[] lookup = new LinkedListNode<int>[1000 * 1000 + 1];
foreach(int label in labels)
lookup[label] = cups.AddLast(label);
const int maximumLabel = 1000 * 1000;
for(int cup = cups.Max() + 1; cup <= maximumLabel; cup++)
lookup[cup] = cups.AddLast(cup);
LinkedListNode<int> current = cups.First;
for(int turn = 0; turn < turns; turn++)
{
PerformMovesB(cups, lookup, maximumLabel, ref current);
}
LinkedListNode<int> node = lookup[1].Next ?? cups.First;
long a = node.Value;
long b = (node.Next ?? cups.First).Value;
return a * b;
}
private void PerformMovesB(LinkedList<int> cups, LinkedListNode<int>[] lookup, int maximumLabel, ref LinkedListNode<int> current)
{
int currentLabel = current.Value;
List<int> removed = new List<int>(3);
LinkedListNode<int> node = current.Next ?? cups.First;
for(int i = 0; i < 3; i++)
{
lookup[node.Value] = null;
removed.Add(node.Value);
LinkedListNode<int> next = node.Next ?? cups.First;
cups.Remove(node);
node = next;
}
int search = currentLabel - 1;
if(search < 1)
search = maximumLabel;
while(removed.Contains(search))
if(--search < 1)
search = maximumLabel;
node = lookup[search];
foreach(int label in removed)
lookup[label] = node = cups.AddAfter(node, label);
current = current.Next ?? cups.First;
}
I would suspect anti-virus kicking in. This is my hunch as Resharper might not spawn a new process to run your test in and usually anti-virus scanners will scan processes when they are launched (which is definitely the case when you run the console app).
Try setting up an explicit exclusion for the location that the console application is being launched from.
I am trying to use OpenCV for hand gesture recognition in my Unity ARCore game. However, with the deprecation of TextureReaderAPI, the only way to capture the image from the camera is by using Frame.CameraImage.AcquireCameraImageBytes(). The problem with that is not only that the image is in 640x480 resolution (this cannot be changed AFAIK), but it is also in YUV_420_888 format.
As if that were not enough, OpenCV does not have free C#/Unity packages, so if I do not want to cash out 20$ for a paid package, I need to use available C++ or python versions. How do I move the YUV image to OpenCV, convert it to an RGB (or HSV) color space, and then either do some processing on it or return it back to Unity?
In this example, I will use C++ OpenCV libraries and Visual Studio 2017 and I will try to capture ARCore camera image, move it to OpenCV (as efficiently as possible), convert it to RGB color space, then move it back to Unity C# code and save it in the phone's memory.
Firstly, we have to create a C++ dynamic library project to use with OpenCV. For this, I highly recommend to follow both Pierre Baret's and Ninjaman494's answers on this question: OpenCV + Android + Unity. The process is rather straightforward, and if you will not deviate from their answers too much (i.e. you can safely download a newer than 3.3.1 version of OpenCV, but be careful when compiling for ARM64 instead of ARM, etc.), you should be able to call a C++ function from C#.
In my experience, I had to solve two problems - firstly, if you made the project part of your C# solution instead of creating a new solution, Visual Studio will keep messing with your configuration, like trying to compile a x86 version instead of an ARM version. To save yourself the hassle, create a completely separate solution. The other problem is that some functions failed to link for me, thus throwing a undefined reference linker error (undefined reference to 'cv::error(int, std::string const&, char const*, char const*, int, to be exact). If this happens and the problem is with a function that you do not really need, just recreate the function in your code - for instance if you have problems with cv::error, add this code in the end of your .cpp file:
namespace cv {
__noreturn void error(int a, const String & b, const char * c, const char * d, int e) {
throw std::string(b);
}
}
Sure, this is ugly and dirty way to do things, so if you know how to fix the linker error, please do so and let me know.
Now, you should have a working C++ code that compiles and can be run from a Unity Android application. However, what we want is for OpenCV to not return a number, but to convert an image. So change your code to this:
.h file
extern "C" {
namespace YOUR_OWN_NAMESPACE
{
int ConvertYUV2RGBA(unsigned char *, unsigned char *, int, int);
}
}
.cpp file
extern "C" {
int YOUR_OWN_NAMESPACE::ConvertYUV2RGBA(unsigned char * inputPtr, unsigned char * outputPtr, int width, int height) {
// Create Mat objects for the YUV and RGB images. For YUV, we need a
// height*1.5 x width image, that has one 8-bit channel. We can also tell
// OpenCV to have this Mat object "encapsulate" an existing array,
// which is inputPtr.
// For RGB image, we need a height x width image, that has three 8-bit
// channels. Again, we tell OpenCV to encapsulate the outputPtr array.
// Thanks to specifying existing arrays as data sources, no copying
// or memory allocation has to be done, and the process is highly
// effective.
cv::Mat input_image(height + height / 2, width, CV_8UC1, inputPtr);
cv::Mat output_image(height, width, CV_8UC3, outputPtr);
// If any of the images has not loaded, return 1 to signal an error.
if (input_image.empty() || output_image.empty()) {
return 1;
}
// Convert the image. Now you might have seen people telling you to use
// NV21 or 420sp instead of NV12, and BGR instead of RGB. I do not
// understand why, but this was the correct conversion for me.
// If you have any problems with the color in the output image,
// they are probably caused by incorrect conversion. In that case,
// I can only recommend you the trial and error method.
cv::cvtColor(input_image, output_image, cv::COLOR_YUV2RGB_NV12);
// Now that the result is safely saved in outputPtr, we can return 0.
return 0;
}
}
Now, rebuild the solution (Ctrl + Shift + B) and copy the libProjectName.so file to Unity's Plugins/Android folder, as in the linked answer.
The next thing is to save the image from ARCore, move it to C++ code, and get it back. Let us add this inside the class in our C# script:
[DllImport("YOUR_OWN_NAMESPACE")]
public static extern int ConvertYUV2RGBA(IntPtr input, IntPtr output, int width, int height);
You will be prompted by Visual Studio to add System.Runtime.InteropServices using clause - do so.
This allows us to use the C++ function in our C# code. Now, let's add this function to our C# component:
public Texture2D CameraToTexture()
{
// Create the object for the result - this has to be done before the
// using {} clause.
Texture2D result;
// Use using to make sure that C# disposes of the CameraImageBytes afterwards
using (CameraImageBytes camBytes = Frame.CameraImage.AcquireCameraImageBytes())
{
// If acquiring failed, return null
if (!camBytes.IsAvailable)
{
Debug.LogWarning("camBytes not available");
return null;
}
// To save a YUV_420_888 image, you need 1.5*pixelCount bytes.
// I will explain later, why.
byte[] YUVimage = new byte[(int)(camBytes.Width * camBytes.Height * 1.5f)];
// As CameraImageBytes keep the Y, U and V data in three separate
// arrays, we need to put them in a single array. This is done using
// native pointers, which are considered unsafe in C#.
unsafe
{
for (int i = 0; i < camBytes.Width * camBytes.Height; i++)
{
YUVimage[i] = *((byte*)camBytes.Y.ToPointer() + (i * sizeof(byte)));
}
for (int i = 0; i < camBytes.Width * camBytes.Height / 4; i++)
{
YUVimage[(camBytes.Width * camBytes.Height) + 2 * i] = *((byte*)camBytes.U.ToPointer() + (i * camBytes.UVPixelStride * sizeof(byte)));
YUVimage[(camBytes.Width * camBytes.Height) + 2 * i + 1] = *((byte*)camBytes.V.ToPointer() + (i * camBytes.UVPixelStride * sizeof(byte)));
}
}
// Create the output byte array. RGB is three channels, therefore
// we need 3 times the pixel count
byte[] RGBimage = new byte[camBytes.Width * camBytes.Height * 3];
// GCHandles help us "pin" the arrays in the memory, so that we can
// pass them to the C++ code.
GCHandle YUVhandle = GCHandle.Alloc(YUVimage, GCHandleType.Pinned);
GCHandle RGBhandle = GCHandle.Alloc(RGBimage, GCHandleType.Pinned);
// Call the C++ function that we created.
int k = ConvertYUV2RGBA(YUVhandle.AddrOfPinnedObject(), RGBhandle.AddrOfPinnedObject(), camBytes.Width, camBytes.Height);
// If OpenCV conversion failed, return null
if (k != 0)
{
Debug.LogWarning("Color conversion - k != 0");
return null;
}
// Create a new texture object
result = new Texture2D(camBytes.Width, camBytes.Height, TextureFormat.RGB24, false);
// Load the RGB array to the texture, send it to GPU
result.LoadRawTextureData(RGBimage);
result.Apply();
// Save the texture as an PNG file. End the using {} clause to
// dispose of the CameraImageBytes.
File.WriteAllBytes(Application.persistentDataPath + "/tex.png", result.EncodeToPNG());
}
// Return the texture.
return result;
}
To be able to run unsafe code, you also need to allow it in Unity. Go to Player Settings (Edit > Project Settings > Player Settings and check the Allow unsafe code checkbox.)
Now, you can call the CameraToTexture() function, let's say, every 5 seconds from Update(), and the camera image should be saved as /Android/data/YOUR_APPLICATION_PACKAGE/files/tex.png. The image will probably be landscape oriented, even if you held the phone in portrait mode, but this is not that hard to fix anymore. Also, you might notice a freeze everytime the image is saved - I recommend calling this function in a separate thread because of this. Also, the most demanding operation here is saving the image as an PNG file, so if you need it for any other reason, you should be fine (still use the separate thread, though).
If you want to undestand the YUV_420_888 format, why you need a 1.5*pixelCount array, and why we modified the arrays the way we did, read https://wiki.videolan.org/YUV/#NV12. Other websites seem to have incorrect information about how this format works.
Also, feel free to comment me with any issues you might have, and I will try to help with them, as well as any feedback for both the code and answer.
APPENDIX 1: According to https://docs.unity3d.com/ScriptReference/Texture2D.LoadRawTextureData.html, you should use GetRawTextureData instead of LoadRawTextureData, to prevent copying. To do this, just pin the array returned by GetRawTextureData instead of the RGBimage array (which you can remove). Also, do not forget to call result.Apply(); afterwards.
APPENDIX 2: Do not forget to call Free() on both GCHandles when you are done using them.
I figured out how to get the full resolution CPU image in Arcore 1.8.
I can now get the full camera resolution with cameraimagebytes.
put this in your class variables:
private ARCoreSession.OnChooseCameraConfigurationDelegate m_OnChoseCameraConfiguration = null;
put this in Start()
m_OnChoseCameraConfiguration = _ChooseCameraConfiguration; ARSessionManager.RegisterChooseCameraConfigurationCallback(m_OnChoseCameraConfiguration); ARSessionManager.enabled = false; ARSessionManager.enabled = true;
Add this callback to the class:
private int _ChooseCameraConfiguration(List<CameraConfig> supportedConfigurations) { return supportedConfigurations.Count - 1; }
Once you add those, you should have cameraimagebytes returning the full resolution of the camera.
For everyone who want to try this with OpencvForUnity:
public Mat getCameraImage()
{
// Use using to make sure that C# disposes of the CameraImageBytes afterwards
using (CameraImageBytes camBytes = Frame.CameraImage.AcquireCameraImageBytes())
{
// If acquiring failed, return null
if (!camBytes.IsAvailable)
{
Debug.LogWarning("camBytes not available");
return null;
}
// To save a YUV_420_888 image, you need 1.5*pixelCount bytes.
// I will explain later, why.
byte[] YUVimage = new byte[(int)(camBytes.Width * camBytes.Height * 1.5f)];
// As CameraImageBytes keep the Y, U and V data in three separate
// arrays, we need to put them in a single array. This is done using
// native pointers, which are considered unsafe in C#.
unsafe
{
for (int i = 0; i < camBytes.Width * camBytes.Height; i++)
{
YUVimage[i] = *((byte*)camBytes.Y.ToPointer() + (i * sizeof(byte)));
}
for (int i = 0; i < camBytes.Width * camBytes.Height / 4; i++)
{
YUVimage[(camBytes.Width * camBytes.Height) + 2 * i] = *((byte*)camBytes.U.ToPointer() + (i * camBytes.UVPixelStride * sizeof(byte)));
YUVimage[(camBytes.Width * camBytes.Height) + 2 * i + 1] = *((byte*)camBytes.V.ToPointer() + (i * camBytes.UVPixelStride * sizeof(byte)));
}
}
// Create the output byte array. RGB is three channels, therefore
// we need 3 times the pixel count
byte[] RGBimage = new byte[camBytes.Width * camBytes.Height * 3];
// GCHandles help us "pin" the arrays in the memory, so that we can
// pass them to the C++ code.
GCHandle pinnedArray = GCHandle.Alloc(YUVimage, GCHandleType.Pinned);
IntPtr pointer = pinnedArray.AddrOfPinnedObject();
Mat input = new Mat(camBytes.Height + camBytes.Height / 2, camBytes.Width, CvType.CV_8UC1);
Mat output = new Mat(camBytes.Height, camBytes.Width, CvType.CV_8UC3);
Utils.copyToMat(pointer, input);
Imgproc.cvtColor(input, output, Imgproc.COLOR_YUV2RGB_NV12);
pinnedArray.Free();
return output;
}
}
Here is an implementation of this which just uses the free plugin OpenCV Plus Unity. Very simple to set up and great documentation if you are familiar with OpenCV.
This implementation rotates the image properly using OpenCV, stores them into memory and upon exiting the app, saves them to file. I have tried to strip all Unity aspects from the code so that the function GetCameraImage() can be run on a separate thread.
I can confirm it works on Andoird (GS7), I presume it will work pretty universally.
using System;
using System.Collections.Generic;
using GoogleARCore;
using UnityEngine;
using OpenCvSharp;
using System.Runtime.InteropServices;
public class CamImage : MonoBehaviour
{
public static List<Mat> AllData = new List<Mat>();
public static void GetCameraImage()
{
// Use using to make sure that C# disposes of the CameraImageBytes afterwards
using (CameraImageBytes camBytes = Frame.CameraImage.AcquireCameraImageBytes())
{
// If acquiring failed, return null
if (!camBytes.IsAvailable)
{
return;
}
// To save a YUV_420_888 image, you need 1.5*pixelCount bytes.
// I will explain later, why.
byte[] YUVimage = new byte[(int)(camBytes.Width * camBytes.Height * 1.5f)];
// As CameraImageBytes keep the Y, U and V data in three separate
// arrays, we need to put them in a single array. This is done using
// native pointers, which are considered unsafe in C#.
unsafe
{
for (int i = 0; i < camBytes.Width * camBytes.Height; i++)
{
YUVimage[i] = *((byte*)camBytes.Y.ToPointer() + (i * sizeof(byte)));
}
for (int i = 0; i < camBytes.Width * camBytes.Height / 4; i++)
{
YUVimage[(camBytes.Width * camBytes.Height) + 2 * i] = *((byte*)camBytes.U.ToPointer() + (i * camBytes.UVPixelStride * sizeof(byte)));
YUVimage[(camBytes.Width * camBytes.Height) + 2 * i + 1] = *((byte*)camBytes.V.ToPointer() + (i * camBytes.UVPixelStride * sizeof(byte)));
}
}
// GCHandles help us "pin" the arrays in the memory, so that we can
// pass them to the C++ code.
GCHandle pinnedArray = GCHandle.Alloc(YUVimage, GCHandleType.Pinned);
IntPtr pointerYUV = pinnedArray.AddrOfPinnedObject();
Mat input = new Mat(camBytes.Height + camBytes.Height / 2, camBytes.Width, MatType.CV_8UC1, pointerYUV);
Mat output = new Mat(camBytes.Height, camBytes.Width, MatType.CV_8UC3);
Cv2.CvtColor(input, output, ColorConversionCodes.YUV2BGR_NV12);// YUV2RGB_NV12);
// FLIP AND TRANPOSE TO VERTICAL
Cv2.Transpose(output, output);
Cv2.Flip(output, output, FlipMode.Y);
AllData.Add(output);
pinnedArray.Free();
}
}
}
I then call ExportImages() when exiting the program to save to file.
private void ExportImages()
{
/// Write Camera intrinsics to text file
var path = Application.persistentDataPath;
StreamWriter sr = new StreamWriter(path + #"/intrinsics.txt");
sr.WriteLine(CameraIntrinsicsOutput.text);
Debug.Log(CameraIntrinsicsOutput.text);
sr.Close();
// Loop through Mat List, Add to Texture and Save.
for (var i = 0; i < CamImage.AllData.Count; i++)
{
Mat imOut = CamImage.AllData[i];
Texture2D result = Unity.MatToTexture(imOut);
result.Apply();
byte[] im = result.EncodeToJPG(100);
string fileName = "/IMG" + i + ".jpg";
File.WriteAllBytes(path + fileName, im);
string messge = "Succesfully Saved Image To " + path + "\n";
Debug.Log(messge);
Destroy(result);
}
}
Seems you already fix this.
But for anyone who want to combine AR with hand gesture recognition and tracking, try Manomotion: https://www.manomotion.com/
free SDk and work prefect in 12/2020.
Use the SDK Community Edition and Download ARFoundation version
I am having some trouble with this error in Visual Studio:
An unhandled exception of type 'System.IO.IOException' occurred in mscorlib.dll
Additional information: The process cannot access the file 'C:\Users\aheij\Desktop\KinectOutput\swipe.txt' because it is being used by another process.
What I Have tried:
I have tried using these codes obtained from other solved StackOverflow questions similar to mine to try to solve the problem - but even that didn't seem to work?
Ive tried checking if the file is in use, but with no success.
I also run Visual Studio as administrator.
The file is not read-only.
The folder is not open, and the file is not being used in any other program when executing the code - at least not that I can see/know of.
The code:
So, to add some context to my code: I am writing some quick gesture detection code to the Kinect c# BodyBasics SDK v2 code freely available. This is a helper method that I added, that gets called in when a person is in view. If that person is executing the gesture, the method writes the frame time and gesture name to a text file.
Half the time, when the code does work, the gesture recognition works well. However, the other half of the time, the code breaks/stops because the writing to file bit causes the error.
Below is my code to see if the person is standing in the neutral position - its a bit waffly, so apologies about that. I have commented 'ERROR' where the error is (unsurprisingly):
private void Neutral_stance(VisualStyleElement.Tab.Body body, IReadOnlyDictionary<JointType, Joint> joints, IDictionary<JointType, Point> jointPoints, BodyFrame bf)
{
CameraSpacePoint left_hand = joints[JointType.HandLeft].Position;
CameraSpacePoint left_elbow = joints[JointType.ElbowLeft].Position;
CameraSpacePoint left_shoulder = joints[JointType.ShoulderLeft].Position;
CameraSpacePoint left_hip = joints[JointType.HipLeft].Position;
CameraSpacePoint right_hand = joints[JointType.HandRight].Position;
CameraSpacePoint right_elbow = joints[JointType.ElbowRight].Position;
CameraSpacePoint right_shoulder = joints[JointType.ShoulderRight].Position;
CameraSpacePoint right_hip = joints[JointType.HipRight].Position;
double vertical_error = 0.15;
double shoulderhand_xrange_l = Math.Abs(left_hand.X - left_shoulder.X);
double shoulderhand_xrange_r = Math.Abs(right_hand.X - right_shoulder.X);
if (bf != null)
{
TimeSpan frametime = bf.RelativeTime;
string path_p = #"C:\Users\aheij\Desktop\KinectOutput\Punch.txt"; //write to punch file
string path_s = #"C:\Users\aheij\Desktop\KinectOutput\swipe.txt"; //write to swipe file
if (left_hand.Y < left_elbow.Y)
{
if (right_hand.Y < right_elbow.Y)
{
if (shoulderhand_xrange_l < vertical_error)
{
if (shoulderhand_xrange_r < vertical_error)
{
Gesture_being_done.Text = " Neutral";
File.AppendAllText(path_p, frametime.ToString() + " Neutral" + Environment.NewLine); //ERROR
File.AppendAllText(path_s, frametime.ToString() + " Neutral" + Environment.NewLine); //ERROR
}
}
}
}
else
{
Gesture_being_done.Text = " Unknown";
File.AppendAllText(path_p, frametime.ToString() + " Unknown" + Environment.NewLine); //ERROR
File.AppendAllText(path_s, frametime.ToString() + " Unknown" + Environment.NewLine); //ERROR
}
}
}
Any solutions/ideas/suggestions to point me on the right track would be appreciated. I think that it would be good to use the 'using streamwriter' method as opposed to the method I am using here - but I am not sure how? Any help would be appreciated.
Additonal Info: Using Visual Studio 2015; Using windows 10.
Sidenote: I read somewhere that the Windows Search tool in Windows 10 can interfere and cause problems like this so I need to disable it?
As suggested to me I used the Filestream method & ensured the file was closed after use. But, even this still caused the same error.
Thus, I also got rid of having two file-writing actions in rapid succession of each other. I dont know if this is technically right or even true, but based off of this post here: link, my error could be coming up because I am trying to execute the second 'write to text file' line whilst the previous 'write to text file' line is still executing/writing to that same folder & location - hence the clash? Please someone, correct me if I am wrong.
Either way, this seems to have worked.
See below for my edited/corrected method:
private void Neutral_stance(Body body, IReadOnlyDictionary<JointType, Joint> joints, IDictionary<JointType, Point> jointPoints, BodyFrame bf)
{
//cameraspace point joint stuff here again (see original post for this bit leading up to the if statements.)
if (bf != null)
{
TimeSpan frametime = bf.RelativeTime;
string path_s = #"C:\Users\aheij\Desktop\KinectOutput\swipe.txt";
if (left_hand.Y < left_elbow.Y)
{
if (right_hand.Y < right_elbow.Y)
{
if (shoulderhand_xrange_l < vertical_error)
{
if (shoulderhand_xrange_r < vertical_error)
{
Gesture_being_done.Text = " Neutral";
FileStream fs_s = new FileStream(path_s, FileMode.Append); //swipe
byte[] bdatas = Encoding.Default.GetBytes(frametime.ToString() + " Neutral" + Environment.NewLine);
fs_s.Write(bdatas, 0, bdatas.Length);
fs_s.Close();
}
}
}
}
else
{
Gesture_being_done.Text = " Unknown";
FileStream fs_s = new FileStream(path_s, FileMode.Append);
byte[] bdatas = Encoding.Default.GetBytes(frametime.ToString() + " Unknown" + Environment.NewLine);
fs_s.Write(bdatas, 0, bdatas.Length);
fs_s.Close();
}
}
}
Do let me know if there is any way I can make this more elegant or anything else I should be aware of w.r.t this answer.
The code is based off of the code found here: FileStream Tutorial website
I have an application that is using an smart card reader for allowing the users to access parts of the system. On one location i have no issues. But another, which have an different type of card manufacturer has a lot of issues. It keeps getting an id of zero back. Then looking into the eventlog i saw this:
And this is the code:
card.Connect(reader, SHARE.Shared, PROTOCOL.T0orT1);
var apduGetID = new APDUCommand(0xFF, 0xCA, 0, 0, null, 4);
var apduRespGetID = card.Transmit(apduGetID);
long cardId = BitConverter.ToUInt32(apduRespGetID.Data.Reverse().ToArray(), 0);
the second problem is that then trying to debug the code, it works perfect, only then remove the breakpoint can i see the issue but not where. Can some one please help me?
P.S. i found this thread, but it does not work: https://superuser.com/questions/715688/smart-card-errors
Update: Here are the Transmit class
public override APDUResponse Transmit(APDUCommand ApduCmd)
{
var RecvLength = (uint)(ApduCmd.Le + APDUResponse.SW_LENGTH);
byte[] ApduBuffer;
var ApduResponse = new byte[ApduCmd.Le + APDUResponse.SW_LENGTH];
var ioRequest = new SCard_IO_Request
{
m_dwProtocol = m_nProtocol,
m_cbPciLength = 8
};
// Build the command APDU
if (ApduCmd.Data == null)
{
ApduBuffer = new byte[APDUCommand.APDU_MIN_LENGTH + ((ApduCmd.Le != 0) ? 1 : 0)];
if (ApduCmd.Le != 0)
{
ApduBuffer[4] = ApduCmd.Le;
}
}
else
{
ApduBuffer = new byte[APDUCommand.APDU_MIN_LENGTH + 1 + ApduCmd.Data.Length];
for (var nI = 0; nI < ApduCmd.Data.Length; nI++)
{
ApduBuffer[APDUCommand.APDU_MIN_LENGTH + 1 + nI] = ApduCmd.Data[nI];
}
ApduBuffer[APDUCommand.APDU_MIN_LENGTH] = (byte)ApduCmd.Data.Length;
}
ApduBuffer[0] = ApduCmd.Class;
ApduBuffer[1] = ApduCmd.Ins;
ApduBuffer[2] = ApduCmd.P1;
ApduBuffer[3] = ApduCmd.P2;
m_nLastError = SCardTransmit(m_hCard, ref ioRequest, ApduBuffer, (uint)ApduBuffer.Length, IntPtr.Zero, ApduResponse, out RecvLength);
if (m_nLastError != 0)
{
var msg = "SCardTransmit error: " + m_nLastError;
throw new SmartCardException(msg, m_nLastError);
}
var apduData = new byte[RecvLength];
for (var nI = 0; nI < RecvLength; nI++)
{
apduData[nI] = ApduResponse[nI];
}
return new APDUResponse(apduData);
}
Update 2: I have also tried with to put some Thread.Sleep()
Please check that on the second machine you have all the up-to-date drivers of the smart card. Also, sometimes it helps to replace the driver which is provided by the manufacturer with "Microsoft WUDF driver" - https://msdn.microsoft.com/en-us/library/windows/hardware/dn653571(v=vs.85).aspx
Please note, that you have two type of devices detected by the OS when you plug it in - the smart card enumerator device (smart card reader) and the smart card (sometimes called the smart card container) itself. One smart card reader can contain several smart cards.
Example of the smart card which driver was forcefully replaced with Microsoft WUDF to make the client application (iBank2) work:
The four smart card drivers have been forcefully replaced with basic Microsoft driver to make the application work.
Well if the other system does not take your smart card,just check the BIOS settings for smartcard.There is an option to disable/enable them in some systems.
I need to keep track of another program's memory, constantly looking for a sequence of bytes to appear in there, and when they do, i need to remember their location so i later know where to write to.
I used the following post to learn how to look for byte[] in another process's memory:
C#: Search a byte[] array in another process's memory
My program is very simple: It launches process (using Process.Start), and then repeatedly runs function from the linked thread's one of the answers:
private static int GetMemoryAddressOfString(byte[] searchedBytes)
{
IntPtr hProcess = OpenProcess(ProcessAccessFlags.VMOperation | ProcessAccessFlags.VMRead | ProcessAccessFlags.VMWrite, false, Program.ArtemisProcess.Id);
if (hProcess == IntPtr.Zero)
throw new Win32Exception(Marshal.GetLastWin32Error());
int addr = 0;
int speed = 1024 * 64;
for (int j = 0x00400000; j < 0x11000000; j += speed)
{
byte[] bigMem = new byte[speed + searchedBytes.Length];
IntPtr unmanagedPointer = Marshal.AllocHGlobal(4);
ReadProcessMemory(hProcess, (IntPtr)j, bigMem, new UIntPtr((uint)(speed + searchedBytes.Length)), unmanagedPointer);
int result = Marshal.ReadInt32(unmanagedPointer);
Marshal.DestroyStructure(unmanagedPointer, typeof(int));
for (int k = 0; k < bigMem.Length - searchedBytes.Length; k++)
{
bool found = true;
for (int l = 0; l < searchedBytes.Length; l++)
{
if (bigMem[k + l] != searchedBytes[l])
{
found = false;
break;
}
}
if (found)
{
addr = k + j;
break;
}
}
if (addr != 0)
break;
}
return addr;
}
where ArtemisProcess is the Process i ran with .Start()
Most of the times, it works fine. As soon as i do the action in the watched process that puts the searched sequence of bytes to the memory, the next search finds it. However, sometimes, it wont.
I was wondering if i'm right and used Cheat Engine to be sure that the searched data IS there.
Then i added the part where i create an unmanaged pointer to know how many bytes there were read - and thats when i found out that exactly the place in the memory where the searched bytes appear (that Cheat Engine correctly identifies) returns 0! It wont let me read memory there. This "lockout" happens for about a minute or two, and only then it allows me to read the memory (just out of sudden, the next attempt to read the memory at that location is a success and the sequence of bytes is found all right).
Now, i read on the msdn that "he function fails if the requested read operation crosses into an area of the process that is inaccessible" but how do i know which part of the process memory is accessible and which isnt?
Why is Cheat Engine able to read that memory, and my program isnt?
Why does it suddenly allow me to read the process memory again?
I am at a loss here...