In VB.Net, which file stream accept Seek end Peek methods? - vb.net

I recently read on Setting position index of filestream that it is possible to use
seek() method of BaseStream class.
But now, using .Net Framework 4.8 or greater these 2 functions seem to have been deleted.
Which stream in .Net 4.8 or greater does implement this 2 functions ?
I search a solution that is distinct from My.MyComputer.SystemFile.Seek() and is not restricted to using old VB 6 FileOpen() method !

The System.IO.FileStream class inherits the System.IO.Stream class. The latter provides the base functionality for all streams while the former provides functionality for streams backed by files. The Seek method is a member of the Stream class and thus every stream, regardless of type, has that method. That's true up to .NET 6 and will continue to be true as long as .NET exists.
The Seek method might throw a NotSupportedException in some cases, in which case the CanSeek property of that stream will be False. If you have a stream and you're not sure whether it can seek or not, test that property before calling Seek to ensure no exception will be thrown. In the case of a FileStream, the documentation (which you should already have read) tells us when to expect that property to be False:
true if the stream supports seeking; false if the stream is closed or if the FileStream was constructed from an operating-system handle such as a pipe or output to the console.
You can read the documentation of other types of streams to see whether they support seeking, e.g. MemoryStream does and NetworkStream doesn't. Basically, seeking requires random access to all the data rather than just sequential access.
There is no BaseStream property on a FileStream. The property you refer to is a member of StreamReader class. That property will return a Stream reference to the stream being read. That could be a FileStream, NetworkStream, MemoryStream or whatever. If you have a StreamReader and you want to seek to a specific position in the underlying stream but you don't know whether it is supported or not then you get the BaseStream, test the CanSeek property and, if it's True, call the Seek method.
With myStreamReader.BaseStream
If .CanSeek Then
'Advance the file pointer 64 bytes.
.Seek(64L, SeekOrigin.Current)
End If
End With
That will work no matter what type of stream backs the reader because CanSeek and Seek are members of Stream and StreamReader.BaseStream is type Stream.

Related

Adding new members and extending methods in an external API interface

I am building an VB.NET application in Visual Studio using SOLIDWORKS API - my application connects to SOLIDWORKS application via COM, and performs some actions in it using various API calls. The API is accessed by adding project references to SOLIDWORKS .dll files. These files must be embedded to the executable of my application for legal reasons.
This question is not specific to that API, but I will try to explain what I want to do. There is a SOLIDWORKS API interface called Body2 that governs manipulation of model objects (bodies) in 3D space. For example, Body2 interface provides a method ApplyTransform that allows moving or rotating a certain body by applying a MathTransform (a transform matrix) to it:
ModelBody.ApplyTransform(rotationMatrix) 'rotates the body
Now, the Body2 objects do not store these transformation matrices - they are applied and forgotten. However, in my application, I need to persistently store that information, so that at some point, I can reverse all transformations, and return the body to it's original position.
Therefore, I want to extend the Body2 interface by adding a new property to it, called "CombinedTransformMatrix", so that every time I call ApplyTransform, I could also update the value of this property, for example:
ModelBody.ApplyTransform(rotationMatrix)
ModelBody.CombinedTransformMatrix.Multiply(rotationMatrix)
ModelBody.ApplyTransform(translationMatrix)
ModelBody.CombinedTransformMatrix.Multiply(translationMatrix)
And when I finally want to return the body to it's original position, I could call:
ModelBody.ApplyTransform(ModelBody.CombinedTransformMatrix.Inverse)
ModelBody.CombinedTransformMatrix = New MathTransform 'reset matrix
Ideally, it would be really nice to also extend the ApplyTransform method, so that it would update the CombinedTransformMatrix automatically, for example:
Overrides Function ApplyTransform(Xform As MathTransform) As Boolean
'Do whatever SOLIDWORKS does in this function
'My additional code:
Me.CombinedTransformMatrix.Multiply(Xform)
End function
(I know I should do an extension rather than an override, but I don't know how)
If this is possible, then I could simplify the code for the body transformations, as the CombinedTransformMatrix would update automatically:
'Rotate and move
ModelBody.ApplyTransform(rotationMatrix)
ModelBody.ApplyTransform(translationMatrix)
'Return to original position
ModelBody.ApplyTransform(ModelBody.CombinedTransformMatrix.Inverse)
ModelBody.CombinedTransformMatrix = New MathTransform 'reset matrix
I would very much prefer this kind of a solution instead of creating some derived class from Body2, or making some kind of a wrapper class that stores CombinedTransformMatrix outside the Body2 object. I want to store that bit inside the object itself. As for derived class, Visual Studio doesn't even allow me to inherit from Body2 - says "'Body2Class' is not allowed when its assembly is configured to embed interop types.". And I must embed these .dll files because otherwise I would have to ship them along the .exe of my application, which is legally prohibited by SOLIDWORKS.
Is what I want possible? Can I add that CombinedTransformMatrix to the Body2 interface without creating a derived class? And is it possible to extend that ApplyTransform method with my additional code without knowing how that method is implemented?
If not, what is the next best solution to achieve what I want? Like I said, I would very much like to avoid wrappers or additional variables outside of Body2, because there will be lots of these Body2 objects, they will persist throughout the application's lifetime, each will have a different transformation, so having to store their transformation information outside themselves would seriously complicate my code.
There is no universal way of doing this. You can maintain the separate dictionary with your COM object (e.g. IBody2 in this case) to be a key and the additional parameters (tags) to be a value. You will need to manually update the dictionary to remove the data when the pointer is destroyed. There are however some specific SW interfaces that do have some ways to associate custom data (similar to tags). For instance, IBody2 has the IBody2::AddPropertyExtension2 which allows associating custom data with the body itself, IEntity has the IEntity::CreateStringAttributeDefinition (note, this is not documented method) etc.
But there is no something like universal System::Windows::Forms::Tag property for Windows Controls or Dependency Property for DependencyObjects exists for COM classes.

How to obtain the initial class file bytes

At some point in my program I need the initial class file bytes (the bytes describing the class before any transformations were applied). The methods I evaluated so far are:
Using the corresponding classloader to get the resource and simply loading the byte array again. This won't work for dynamically generated classes though (ASM, proxies, etc).
Storing a reference to the initial class file bytes in a ClassFileTransformer. While this works it means that I need to proactively store all byte arrays for all classes in case I need some of them later one. No cool.
Pretty much the same as above but using JVMTIs ClassFileLoadHook. The issue is the same as with the ClassFileTransformer though.
I checked what is happening when Instrumentation.retransformClasses is called. In the end this comes down to a native method needing the instanceKlassHandles to get the class file bytes. So nothing I can really access as well (at least I wouldn't know how).
Any other ideas for how I could get the initial class file bytes without storing a reference to the bytes for all classes upfront?

Need to figure out equivalent object in vb.net from real basic

I am trying to figure out what I can use in visual basic .net that would act similar to this
http://docs.xojo.com/index.php/MemoryBlock
Thank you
You can either use an array Byte() or List(Of Byte), or manipulate memory directly with the System.Runtime.InteropServices.Marshal class's .AllocHGlobal method with IntPtr. Note that VB.NET does not allow for pointer arithmetic like C# does. A common workaround is to use Marshal to copy memory from an address into a Byte array, perform the work there, then copy it back to the original address.
But we need more information about your ultimate intent. I want to avoid an "XY Problem".

Migrating Lucene HitCollector (2.x) to Collector (3.x)

In one of our projects, we use an old Lucene version (2.3.2). I'm now looking at current Lucene versions (3.5.0) and trying to re-write the old code. In the old project, we extended TopFieldDocCollector to do some extra filtering in the collect() method. I'm having a bit of trouble understanding the new Collector class however, and I couldn't find a good example.
1) The method setScorer(). How/where do I get a Scorer object from?
2) The method collect(). I guess I need to create my own Collection and store the docIds I'm interested in, correct?
3) When extending TopDocsCollector instead, I'd need to implement a PriorityQueue to use in the constructor, correct? There seems to be no standard implementation for it. But I still need my own Collection to store docIds (or rather, ScoreDocs), and call populateResults after the search is finished?
Overall, it seems like extending Collector is (a lot) easier than extending TopDocsCollector, but maybe I'm missing something.
setScorer() is a hook, the Scorer is passed in by IndexSearcher when it actually does the search. So you basically override this method if you care about scores at all (e.g. saving the passed in Scorer away so you can use it). From its javadocs:
Called before successive calls to {#link #collect(int)}. Implementations
that need the score of the current document (passed-in to
{#link #collect(int)}), should save the passed-in Scorer and call
scorer.score() when needed.
collect() is called for each matching document, passing in the per-segment docid. Note if you need the 'rebased docid' (relative to the entire reader across all of its segments) then you must override setNextReader, saving the docBase, and compute docBase + docid. From Collector javadocs:
NOTE: The doc that is passed to the collect
method is relative to the current reader. If your
collector needs to resolve this to the docID space of the
Multi*Reader, you must re-base it by recording the
docBase from the most recent setNextReader call.
TopDocsCollector is a base class for TopFieldCollector (sort by field) and TopScoreDocCollector (sort by score). If you are writing a custom collector that sorts by score, then its probably easier to just extend TopScoreDocCollector.
Also: the simplest Collector example is TotalHitCountCollector!

The requested clipboard operation failed

I've using vb.net 2003 and some of the times this error arises. Can anyone know on how this error arises and how to fix it?
Error: The requested clipboard operation failed
I googled this question to see what I'd see, and a lot of people have asked this question, and none of them have gotten a solid answer...
So I went to the MSDN documentation and found a note that explains what most people who have asked this question describe... The symptom usually appears when the user switches to another application while the code is running. The note is quoted below, with the link to the documentation following:
All Windows-based applications share
the system Clipboard, so the contents
are subject to change when you switch
to another application.
An object must be serializable for it
to be put on the Clipboard. If you
pass a non-serializable object to a
Clipboard method, the method will fail
without throwing an exception. See
System.Runtime.Serialization for more
information on serialization. If your
target application requires a very
specific data format, the headers
added to the data in the serialization
process may prevent the application
from recognizing your data. To
preserve your data format, add your
data as a Byte array to a MemoryStream
and pass the MemoryStream to the
SetData method.
The Clipboard class can only be used
in threads set to single thread
apartment (STA) mode. To use this
class, ensure that your Main method is
marked with the STAThreadAttribute
attribute.
Special considerations may be
necessary when using the metafile
format with the Clipboard. Due to a
limitation in the current
implementation of the DataObject
class, the metafile format used by the
.NET Framework may not be recognized
by applications that use an older
metafile format. In this case, you
must interoperate with the Win32
Clipboard application programming
interfaces (APIs). For more
information, see article 323530,
"Metafiles on Clipboard Are Not
Visible to All Applications," in the
Microsoft Knowledge Base at
http://support.microsoft.com.
http://msdn.microsoft.com/en-us/library/system.windows.forms.clipboard.aspx
Funnily enough, this makes sense of a strange behavior I noticed in one of my own apps. I have an app that writes to an Excel spreadsheet (actually, to hundreds of them, modifying hundreds of cells each). I don't use the clipboard at all, just the Interop API for excel, yet when it's running, my clipboard clears every time a new spreadsheet is created. In my case, Excel is messing with the clipboard, even there is no discernible reason for it to do so. I'd chalk it up to one of those mysterious Windows phenomena that we mortals will never understand.
At any rate, thanks to your question, I think I understand my issue, so +1 to you for helping me out.
I have that error while trying to:
Clipboard.Clear();
...
Clipboard.SetText(...);
For solving it I replace Clipboard.Clear() with pinvoking some methods from the user32.dll:
[DllImport("user32.dll")]
static extern IntPtr GetOpenClipboardWindow();
[DllImport("user32.dll")]
private static extern bool OpenClipboard(IntPtr hWndNewOwner);
[DllImport("user32.dll")]
static extern bool EmptyClipboard();
[DllImport("user32.dll", SetLastError=true)]
static extern bool CloseClipboard();
...
IntPtr handleWnd = GetOpenClipboardWindow();
OpenClipboard(handleWnd);
EmptyClipboard();
CloseClipboard();
...
Clipboard.SetText(...);
I use C# here, but vb version could be easily created from it.
Is there a chance that UltraVNC is running. I have issues when that application is running in the background on the client PC side. When I close VNC, I can copy to the clipboard successfully. This is not really a satisfying solution but at least I know in my case the source of the problem.