Generic method throws COM exception on return - c#

I have an application using the office interop libraries (Word and Excel 2007) library version 12.0 and I have a generic method for executing tasks with a timeout in case Office stops responding for some reason but when the method returns its value it throws an exception stating the Com object can't be used when separated from its rcw.
Method:
public static R ExecuteOfficeTimoutAction<R>(Func<R> ToExecute, TimeSpan TimeOut)
{
object returnVal = new OfficeEmptyReturn(); // Empty Class Used With Reflection To Tell If There Was Really A Value Returned
try
{
Exception threadError = null;
System.Threading.Thread timedThread = new System.Threading.Thread(() =>
{
try
{
returnVal = ToExecute();
}
catch (Exception ex)
{
threadError = ex;
}
});
timedThread.Priority = System.Threading.ThreadPriority.Normal;
timedThread.SetApartmentState(System.Threading.ApartmentState.STA);
timedThread.Start();
timedThread.Join(TimeOut);
if (threadError != null)
{
throw threadError;
}
if (timedThread.ThreadState != System.Threading.ThreadState.Stopped)
{
bool abortCalled = false;
bool processKilled = false;
int waitTime = 0;
do
{
if (!abortCalled)
{
timedThread.Abort();
abortCalled = true;
}
if (waitTime < 2500)
{
waitTime += 250;
System.Threading.Thread.Sleep(250);
}
else if (!processKilled)
{
processKilled = true;
foreach (System.Diagnostics.Process process in System.Diagnostics.Process.GetProcesses())
{
if (process.ProcessName.ToLower().Contains("winword.exe") || process.ProcessName.ToLower().Contains("excel.exe"))
{
process.Close();
}
}
}
else
{
throw new TimeoutException("The Timeout Action Could Not Be Terminated");
}
}
while (!(timedThread.ThreadState == System.Threading.ThreadState.Aborted || timedThread.ThreadState == System.Threading.ThreadState.Stopped));
}
}
catch (Exception)
{
throw;
}
return (R)returnVal; // Throws Exception Here
}
Method Where It Throws An Error:
public Document GetDocument(string FilePath)
{
Document newDoc = null;
if (!String.IsNullOrWhiteSpace(FilePath))
{
if (File.Exists(FilePath) && IsWordDoc(new FileInfo(FilePath)))
{
if (IsActive)
{
if (FilePath.Length < 255)
{
newDoc = ExecuteOfficeTimoutAction<Application, Document>((Application app) =>
{
Document tempDoc = app.Documents.Open(FilePath, Type.Missing, true);
return tempDoc;
}, App, new TimeSpan(0, 0, 10));
if (newDoc == null || newDoc is OfficeEmptyReturn)
{
newDoc = null;
}
}
else
{
throw new ArgumentOutOfRangeException("The Word Document's Full Path Must Be Shorter Than 255 Characters To Be Reached");
}
}
else
{
throw new InvalidOperationException("The Word Application Must Be Open To Process Word Data");
}
}
else
{
throw new FileNotFoundException("The Word File Did Not Exist At The Specified Path");
}
}
else
{
throw new ArgumentNullException("The File Path Was Null");
}
return newDoc;
}
The App object being passed in is a static Word.Application object stored in a field within the containing word class so that it is visible to all applicable methods and disposed of appropriately when no longer needed.
I don't see why it would be giving this exception when returning a value, even if it is a com object.
My desired outcome is for the method to return the value generated by the passed Func, throw the exception generated by said delegate or return OfficeEmptyReturn.
Any help or pointers with this would be greatly appreciated.
Side note, I do have fallback error handling for when the office application is terminated outside the application automating it, I would open the task manager and manually terminate word when it froze my code then it would continue but that is not an acceptable outcome.

Related

How to return a File in a different method than the main one?

I want to download a file via Results.File(). It works when executing it in the main method (app.MapGet), however returning it in a different method does do nothing. The line where it should send the file is executed in the Debugger, however it does not return, but jumps back to the main method to execute the last return (The one that never should be executed). This last return does indeed return a result.
I have also used several methods like Result.BadRequest(), however nothing is executed when it is not in the main method.
I saw people using IResult as return method but I am not sure whether this is even right.
My guess is maybe the wrong return type or executing a Task or so.
Whole methods:
app.MapGet("/", (HttpContext context) =>
{
if (context.Request.Query.ContainsKey("amount"))
{
if (context.Request.Query["amount"].Count > 1)
{
return Results.BadRequest(new { Error = "The query parameter 'amount' may only be used once." });
}
if (int.TryParse(context.Request.Query["amount"], out int amount))
{
if (amount <= 0)
{
return Results.BadRequest(new { Error = "The specified amount must be greater or equal to 1." });
}
var list = new List<string>();
for (int i = 0; i < amount; i++)
{
list.Add(Ulid.NewUlid().ToString());
}
CheckIfDownload(context, (list, null));
return Results.Json(new { Ulids = list });
}
else
{
return Results.BadRequest(new { Error = "The specified amount is not a valid number." });
}
}
string ulid = Ulid.NewUlid().ToString();
CheckIfDownload(context, (null, ulid));
return Results.Json(new { Ulid = ulid });
});
static IResult? CheckIfDownload(HttpContext context, (List<string>? list, string? single) ulidListOrSingle)
{
if (context.Request.Query.ContainsKey("download"))
{
if (context.Request.Query["download"].Count > 1)
{
return Results.BadRequest(new { Error = "The query parameter 'download' may only be used once." });
}
if (context.Request.Query["download"] == "" || (bool.TryParse(context.Request.Query["download"], out bool download) && download))
{
if (ulidListOrSingle.list != null)
{
return SendJsonFile(JsonSerializer.Serialize(ulidListOrSingle.list));
}
if (ulidListOrSingle.single != null)
{
return SendJsonFile(JsonSerializer.Serialize(ulidListOrSingle.single));
}
return Results.BadRequest(new { Error = "An unknown error occurred." });
}
}
return null;
}
static IResult SendJsonFile(string data)
{
byte[] buffer = Encoding.UTF8.GetBytes(data);
var stream = new MemoryStream(buffer);
return Results.File(stream, "application/json", $"UlidGenerator_{DateTime.Now:MM-dd-yyyy_HH-mm-ss}.json");
}
when you inline an entire method block (not just a single expression), you must return what you want to be the output of the block. In your case you are not capturing the result of SendJsonFile to return it:
app.MapGet("/download", () =>
{
string data = "json data";
var result = SendJsonFile(data);
return result;
});

Setting Controls in Classes

I'm trying a booking system, I want to put controls on the booking aspect. I want to use If and then cases. I want to control in such a way that if number of booking is 4, then it will throw an exception and stop inserting in the database.
public ApiResult<TimeModelExtended> SaveBooking(Booking booking)
{
AchimotaGCDb repo = new AchimotaGCDb();
var result = new ApiResult<TimeModelExtended>();
try
{
booking.PlayDate = getPlayDate(booking.RefCode);
Int16 nb = getNbBooked(booking.RefCode);
if (nb == 4)
{
Exception ex = new Exception();
result.Successfull = 0;
result.InternalError = ex.Message;
result.Error = "Booking slot is full";
}
else if (nb == 0)
{
booking.BookingStatus = 1;//Booked already
}
else
{
booking.BookingStatus = 0;//Reservation already
}
repo.Insert(booking);
result.Successfull = 1;
result = GetOneteeTime(booking.RefCode);
}
catch (Exception ex)
{
result.Successfull = 0;
result.InternalError = ex.Message;
result.Error = "Error from server";
}
finally
{
repo.Dispose();
}
return result;
}
help to solve that.
If you want to throw an exception, you need to really throw it:
if (nb == 4)
{
throw new Exception("Booking slot is full.");
}
But I don't think throwing an exception is a good idea. Throwing an exception and validation is a different thing.
Here is my suggestion:
if (nb == 4)
{
return result = new ApiResult<TimeModelExtended>()
{
Successfull = 0,
InternalError = "Other messages",
Error = ""Booking slot is full."
};
}
This will return as result message that nothing will continue unless you satisfy that nb != 4

How to check access rights on remote hosts and local and UNC paths?

I write a program, where the user can select local and remote directories. Before performing any operation on a selected path, I want to check if it's valid and if the user has read/write permission(s) granted on it. That's what I have:
private bool checkInput(string dirPath, string depthStr, string filename)
{
...
string reason = null;
try
{
...
else if ((reason = CAN_ACCESS(dirPath)) == null)
{
if (!(new DirectoryInfo(dirPath)).Exists)
reason = string.Format("The directory '{0}' is no directory or does not exist!", dirPath);
...
}
}
catch (Exception ex)
{
reason = ex.Message;
}
if (reason != null)
{
MessageBox.Show(reason, "Wrong input", MessageBoxButton.OK, MessageBoxImage.Error);
return false;
}
return true;
}
public static string CAN_ACCESS(string dirPath)
{
Uri uri = new Uri(dirPath);
//UserFileAccessRights rights = new UserFileAccessRights(dirPath);
string errorMsg = null;
if (uri.IsUnc && !haveAccessPermissionOnHost(uri))
{
string domain = new Uri(dirPath).Host;
domain = dirPath;
ErrorClass res = PinvokeWindowsNetworking.connectToRemote(domain, null, null, true);
if (res == null)
return null;
else
errorMsg = string.Format("(Code {0}): {1}", res.num, res.message);
}
return errorMsg;
}
private static bool haveAccessPermissionOnHost(Uri uri)
{
throw new NotImplementedException();
}
The primary question is, how to simple check in haveAccessPermissionOnHost(Uri uri), if a user has read/write permission(s) on a remote host and unc path granted.
Hint:
If no permissions granted, the well known Windows logon window pops up to force the user to enter some credentials, which is working fine:
ErrorClass res = PinvokeWindowsNetworking.connectToRemote(domain, null, null, true);
I got it from this question (and changed the provided code to return the ErrorClass, null on success).
My secondary question is, if my structure in general is the way to go to check a path, whether it's local or remote, for validity (that's why I provided more code as necessary).
I found myself a workaround, since nobody replied to this question:
public static bool canAccess(DirectoryInfo dirInfo)
{
Uri uri = new Uri(dirInfo.FullName);
// is this a remote path?
if (uri.IsUnc)
{
if (hostOnline(uri.Host))
{
// check if remote path exists
if (!dirInfo.Exists)
{
string domain = dirInfo.FullName;
ErrorClass res = PinvokeWindowsNetworking.connectToRemote(domain, null, null, true);
if (res == null)
{
if (!dirInfo.Exists)
throw new Exception(
string.Format("No access permissions or directory not existing."));
return true;
}
else if (res.num == 53)
throw new Exception("Remote directory not existing.");
else
throw new Exception(
string.Format("(Code {0}): {1}", res.num, res.message));
}
}
else
throw new Exception("Unknown host or not online.");
}
// local directory existing?
return dirInfo.Exists;
}
private static bool hostOnline(string hostname)
{
Ping ping = new Ping();
try
{
PingReply pr = ping.Send(hostname);
return pr.Status == IPStatus.Success;
}
catch (Exception)
{
return false;
}
}

MySQL OdbcCommand commands sometimes hangs?

I am running a loop in C# that reads a file and make updates to the MySQL database with MySQL ODBC 5.1 driver in a Windows 8 64-bit environment.
The operations is simple
Count +1
See if file exists
Load XML file(XDocument)
Fetch data from XDocument
Open ODBCConnection
Run a couple of Stored Procedures against the MySQL database to store data
Close ODBCConnection
The problem is that after a while it will hang on for example a OdbcCommand.ExecuteNonQuery. It is not always the same SP that it will hang on?
This is a real problem, I need to loop 60 000 files but it only last around 1000 at a time.
Edit 1:
The problem seemse to accure here hever time :
public bool addPublisherToGame(int inPublisherId, int inGameId)
{
string sqlStr;
OdbcCommand commandObj;
try
{
sqlStr = "INSERT INTO games_publisher_binder (gameId, publisherId) VALUE(?,?)";
commandObj = new OdbcCommand(sqlStr, mainConnection);
commandObj.Parameters.Add("#gameId", OdbcType.Int).Value = inGameId;
commandObj.Parameters.Add("#publisherId", OdbcType.Int).Value = inPublisherId;
if (Convert.ToInt32(executeNonQuery(commandObj)) > 0)
return true;
else
return false;
}
catch (Exception ex)
{
throw (loggErrorMessage(this.ToString(), "addPublisherToGame", ex, -1, "", ""));
}
finally
{
}
}
protected object executeNonQuery(OdbcCommand inCommandObj)
{
try
{
//FileStream file = new FileStream("d:\\test.txt", FileMode.Append, FileAccess.Write);
//System.IO.StreamWriter stream = new System.IO.StreamWriter(file);
//stream.WriteLine(DateTime.Now.ToString() + " - " + inCommandObj.CommandText);
//stream.Close();
//file.Close();
//mainConnection.Open();
return inCommandObj.ExecuteNonQuery();
}
catch (Exception ex)
{
throw (ex);
}
}
I can see that the in parameters is correct
The open and close of the connection is done in a top method for ever loop (with finally).
Edit 2:
This is the method that will extract the information and save to database :
public Boolean addBoardgameToDatabase(XElement boardgame, GameFactory gameFactory)
{
int incomingGameId = -1;
XElement tmpElement;
string primaryName = string.Empty;
List<string> names = new List<string>();
GameStorage externalGameStorage;
int retry = 3;
try
{
if (boardgame.FirstAttribute != null &&
boardgame.FirstAttribute.Value != null)
{
while (retry > -1)
{
try
{
incomingGameId = int.Parse(boardgame.FirstAttribute.Value);
#region Find primary name
tmpElement = boardgame.Elements("name").Where(c => c.Attribute("primary") != null).FirstOrDefault(a => a.Attribute("primary").Value.Equals("true"));
if (tmpElement != null)
primaryName = tmpElement.Value;
else
return false;
#endregion
externalGameStorage = new GameStorage(incomingGameId,
primaryName,
string.Empty,
getDateTime("1/1/" + boardgame.Element("yearpublished").Value),
getInteger(boardgame.Element("minplayers").Value),
getInteger(boardgame.Element("maxplayers").Value),
boardgame.Element("playingtime").Value,
0, 0, false);
gameFactory.updateGame(externalGameStorage);
gameFactory.updateGameGrade(incomingGameId);
gameFactory.removeDesignersFromGame(externalGameStorage.id);
foreach (XElement designer in boardgame.Elements("boardgamedesigner"))
{
gameFactory.updateDesigner(int.Parse(designer.FirstAttribute.Value), designer.Value);
gameFactory.addDesignerToGame(int.Parse(designer.FirstAttribute.Value), externalGameStorage.id);
}
gameFactory.removePublishersFromGame(externalGameStorage.id);
foreach (XElement publisher in boardgame.Elements("boardgamepublisher"))
{
gameFactory.updatePublisher(int.Parse(publisher.FirstAttribute.Value), publisher.Value, string.Empty);
gameFactory.addPublisherToGame(int.Parse(publisher.FirstAttribute.Value), externalGameStorage.id);
}
foreach (XElement element in boardgame.Elements("name").Where(c => c.Attribute("primary") == null))
names.Add(element.Value);
gameFactory.removeGameNames(incomingGameId);
foreach (string name in names)
if (name != null && name.Length > 0)
gameFactory.addGameName(incomingGameId, name);
return true;
}
catch (Exception)
{
retry--;
if (retry < 0)
return false;
}
}
}
return false;
}
catch (Exception ex)
{
throw (new Exception(this.ToString() + ".addBoardgameToDatabase : " + ex.Message, ex));
}
}
And then we got one step higher, the method that will trigger addBoardgameToDatabase :
private void StartThreadToHandleXmlFile(int gameId)
{
FileInfo fileInfo;
XDocument xmlDoc;
Boolean gameAdded = false;
GameFactory gameFactory = new GameFactory();
try
{
fileInfo = new FileInfo(_directory + "\\" + gameId.ToString() + ".xml");
if (fileInfo.Exists)
{
xmlDoc = XDocument.Load(fileInfo.FullName);
if (addBoardgameToDatabase(xmlDoc.Element("boardgames").Element("boardgame"), gameFactory))
{
gameAdded = true;
fileInfo.Delete();
}
else
return;
}
if (!gameAdded)
{
gameFactory.InactivateGame(gameId);
fileInfo.Delete();
}
}
catch (Exception)
{ throw; }
finally
{
if(gameFactory != null)
gameFactory.CloseConnection();
}
}
And then finally the top level :
public void UpdateGames(string directory)
{
DirectoryInfo dirInfo;
FileInfo fileInfo;
Thread thread;
int gameIdToStartOn = 1;
dirInfo = new DirectoryInfo(directory);
if(dirInfo.Exists)
{
_directory = directory;
fileInfo = dirInfo.GetFiles("*.xml").OrderBy(c=> int.Parse(c.Name.Replace(".xml",""))).FirstOrDefault();
gameIdToStartOn = int.Parse(fileInfo.Name.Replace(".xml", ""));
for (int gameId = gameIdToStartOn; gameId < 500000; gameId++)
{
try
{ StartThreadToHandleXmlFile(gameId); }
catch(Exception){}
}
}
}
Use SQL connection pooling by adding "Pooling=true" to your connectionstring.
Make sure you properly close the connection AND the file.
You can create one large query and execute it only once, I think it is a lot faster then 60.000 loose queries!
Can you show a bit of your code?

Access USB port from C# and send and receive data

How to access a USB port in C#, send a data stream and receive other data?
there's a .net library for that: SharpUSBLib
http://www.icsharpcode.net/OpenSource/SharpUSBLib/default.aspx
There are many libraries that achieve the job. Here is sample code for three platforms from Usb.Net (https://github.com/MelbourneDeveloper/Device.Net)
Windows (WinUSB)
https://github.com/MelbourneDeveloper/Device.Net/blob/411fea4acfbf965fc0160bf728a46b5ded8abc5d/src/Usb.Net/Windows/WindowsUsbDevice.cs#L33
public override Task InitializeAsync()
{
Dispose();
int errorCode;
if (string.IsNullOrEmpty(DeviceId))
{
throw new WindowsException($"{nameof(DeviceDefinition)} must be specified before {nameof(InitializeAsync)} can be called.");
}
_DeviceHandle = APICalls.CreateFile(DeviceId, (APICalls.GenericWrite | APICalls.GenericRead), APICalls.FileShareRead | APICalls.FileShareWrite, IntPtr.Zero, APICalls.OpenExisting, APICalls.FileAttributeNormal | APICalls.FileFlagOverlapped, IntPtr.Zero);
if (_DeviceHandle.IsInvalid)
{
//TODO: is error code useful here?
errorCode = Marshal.GetLastWin32Error();
if (errorCode > 0) throw new Exception($"Device handle no good. Error code: {errorCode}");
}
var isSuccess = WinUsbApiCalls.WinUsb_Initialize(_DeviceHandle, out var defaultInterfaceHandle);
HandleError(isSuccess, "Couldn't initialize device");
var bufferLength = (uint)Marshal.SizeOf(typeof(USB_DEVICE_DESCRIPTOR));
isSuccess = WinUsbApiCalls.WinUsb_GetDescriptor(defaultInterfaceHandle, WinUsbApiCalls.DEFAULT_DESCRIPTOR_TYPE, 0, 0, out _UsbDeviceDescriptor, bufferLength, out var lengthTransferred);
HandleError(isSuccess, "Couldn't get device descriptor");
byte i = 0;
//Get the first (default) interface
var defaultInterface = GetInterface(defaultInterfaceHandle);
_UsbInterfaces.Add(defaultInterface);
while (true)
{
isSuccess = WinUsbApiCalls.WinUsb_GetAssociatedInterface(defaultInterfaceHandle, i, out var interfacePointer);
if (!isSuccess)
{
errorCode = Marshal.GetLastWin32Error();
if (errorCode == APICalls.ERROR_NO_MORE_ITEMS) break;
throw new Exception($"Could not enumerate interfaces for device {DeviceId}. Error code: { errorCode}");
}
var associatedInterface = GetInterface(interfacePointer);
_UsbInterfaces.Add(associatedInterface);
i++;
}
IsInitialized = true;
RaiseConnected();
return Task.CompletedTask;
}
public override async Task<byte[]> ReadAsync()
{
return await Task.Run(() =>
{
var bytes = new byte[ReadBufferSize];
//TODO: Allow for different interfaces and pipes...
var isSuccess = WinUsbApiCalls.WinUsb_ReadPipe(_DefaultUsbInterface.Handle, _DefaultUsbInterface.ReadPipe.WINUSB_PIPE_INFORMATION.PipeId, bytes, ReadBufferSize, out var bytesRead, IntPtr.Zero);
HandleError(isSuccess, "Couldn't read data");
Tracer?.Trace(false, bytes);
return bytes;
});
}
public override async Task WriteAsync(byte[] data)
{
await Task.Run(() =>
{
if (data.Length > WriteBufferSize)
{
throw new Exception($"Data is longer than {WriteBufferSize} bytes which is the device's max buffer size.");
}
//TODO: Allow for different interfaces and pipes...
var isSuccess = WinUsbApiCalls.WinUsb_WritePipe(_DefaultUsbInterface.Handle, _DefaultUsbInterface.WritePipe.WINUSB_PIPE_INFORMATION.PipeId, data, (uint)data.Length, out var bytesWritten, IntPtr.Zero);
HandleError(isSuccess, "Couldn't write data");
Tracer?.Trace(true, data);
});
}
UWP
https://github.com/MelbourneDeveloper/Device.Net/blob/411fea4acfbf965fc0160bf728a46b5ded8abc5d/src/Usb.Net.UWP/UWPUsbDevice.cs#L24
public override async Task InitializeAsync()
{
await GetDevice(DeviceId);
if (_ConnectedDevice != null)
{
var usbInterface = _ConnectedDevice.Configuration.UsbInterfaces.FirstOrDefault();
if (usbInterface == null)
{
_ConnectedDevice.Dispose();
throw new Exception("There was no Usb Interface found for the device.");
}
var interruptPipe = usbInterface.InterruptInPipes.FirstOrDefault();
if (interruptPipe == null)
{
throw new Exception("There was no interrupt pipe found on the interface");
}
interruptPipe.DataReceived += InterruptPipe_DataReceived;
RaiseConnected();
}
else
{
throw new Exception($"Could not connect to device with Device Id {DeviceId}. Check that the package manifest has been configured to allow this device.");
}
}
public override async Task WriteAsync(byte[] bytes)
{
var bufferToSend = bytes.AsBuffer();
var usbInterface = _ConnectedDevice.Configuration.UsbInterfaces.FirstOrDefault();
var outPipe = usbInterface.InterruptOutPipes.FirstOrDefault();
await outPipe.OutputStream.WriteAsync(bufferToSend);
Tracer?.Trace(false, bytes);
}
public override async Task<byte[]> ReadAsync()
{
if (_IsReading)
{
throw new Exception("Reentry");
}
lock (_Chunks)
{
if (_Chunks.Count > 0)
{
var retVal = _Chunks[0];
Tracer?.Trace(false, retVal);
_Chunks.RemoveAt(0);
return retVal;
}
}
_IsReading = true;
_TaskCompletionSource = new TaskCompletionSource<byte[]>();
return await _TaskCompletionSource.Task;
}
Android
https://github.com/MelbourneDeveloper/Device.Net/blob/411fea4acfbf965fc0160bf728a46b5ded8abc5d/src/Usb.Net.Android/AndroidUsbDevice.cs#L199
public async Task InitializeAsync()
{
//TODO: Use a semaphore lock here
if (_IsInitializing)
{
return;
}
_IsInitializing = true;
try
{
//TODO:
//Dispose();
var isPermissionGranted = await RequestPermissionAsync();
if (!isPermissionGranted.HasValue)
{
throw new Exception("User did not respond to permission request");
}
if (!isPermissionGranted.Value)
{
throw new Exception("The user did not give the permission to access the device");
}
var usbInterface = _UsbDevice.GetInterface(0);
//TODO: This selection stuff needs to be moved up higher. The constructor should take these arguments
for (var i = 0; i < usbInterface.EndpointCount; i++)
{
var ep = usbInterface.GetEndpoint(i);
if (_ReadEndpoint == null && ep.Type == UsbAddressing.XferInterrupt && ep.Address == (UsbAddressing)129)
{
_ReadEndpoint = ep;
continue;
}
if (_WriteEndpoint == null && ep.Type == UsbAddressing.XferInterrupt && (ep.Address == (UsbAddressing)1 || ep.Address == (UsbAddressing)2))
{
_WriteEndpoint = ep;
}
}
//TODO: This is a bit of a guess. It only kicks in if the previous code fails. This needs to be reworked for different devices
if (_ReadEndpoint == null)
{
_ReadEndpoint = usbInterface.GetEndpoint(0);
}
if (_WriteEndpoint == null)
{
_WriteEndpoint = usbInterface.GetEndpoint(1);
}
if (_ReadEndpoint.MaxPacketSize != ReadBufferLength)
{
throw new Exception("Wrong packet size for read endpoint");
}
if (_WriteEndpoint.MaxPacketSize != ReadBufferLength)
{
throw new Exception("Wrong packet size for write endpoint");
}
_UsbDeviceConnection = UsbManager.OpenDevice(_UsbDevice);
if (_UsbDeviceConnection == null)
{
throw new Exception("could not open connection");
}
if (!_UsbDeviceConnection.ClaimInterface(usbInterface, true))
{
throw new Exception("could not claim interface");
}
Logger.Log("Hid device initialized. About to tell everyone.", null, LogSection);
IsInitialized = true;
RaiseConnected();
return;
}
catch (Exception ex)
{
Logger.Log("Error initializing Hid Device", ex, LogSection);
}
_IsInitializing = false;
}
public override async Task<byte[]> ReadAsync()
{
try
{
var byteBuffer = ByteBuffer.Allocate(ReadBufferLength);
var request = new UsbRequest();
request.Initialize(_UsbDeviceConnection, _ReadEndpoint);
request.Queue(byteBuffer, ReadBufferLength);
await _UsbDeviceConnection.RequestWaitAsync();
var buffers = new byte[ReadBufferLength];
byteBuffer.Rewind();
for (var i = 0; i < ReadBufferLength; i++)
{
buffers[i] = (byte)byteBuffer.Get();
}
//Marshal.Copy(byteBuffer.GetDirectBufferAddress(), buffers, 0, ReadBufferLength);
Tracer?.Trace(false, buffers);
return buffers;
}
catch (Exception ex)
{
Logger.Log(Helpers.ReadErrorMessage, ex, LogSection);
throw new IOException(Helpers.ReadErrorMessage, ex);
}
}
public override async Task WriteAsync(byte[] data)
{
try
{
var request = new UsbRequest();
request.Initialize(_UsbDeviceConnection, _WriteEndpoint);
var byteBuffer = ByteBuffer.Wrap(data);
Tracer?.Trace(true, data);
request.Queue(byteBuffer, data.Length);
await _UsbDeviceConnection.RequestWaitAsync();
}
catch (Exception ex)
{
Logger.Log(Helpers.WriteErrorMessage, ex, LogSection);
throw new IOException(Helpers.WriteErrorMessage, ex);
}
}
Heres some information, and a library: USB & C#
this site definitely help u...
http://libusbdotnet.sourceforge.net
it contains a class library and some sample codes release on 2010
If you USB device Class is HID you can also try this C# driver.

Categories

Resources