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.
Related
I have one VB6 ActiveX DLL that exposes a class INewReport. I added some new methods to this class and I was able to rebuild it and keep binary compatibility.
I have a second DLL that exposes a class clsNewReport, which implements the first class using:
Implements RSInterfaces.INewReport
Since I added new methods to INewReport, I had to also add those new methods to clsNewReport.
However, when I try to compile the second DLL, I get the binary-compatibility error "...class implemented an interface in the version-compatible component, but not in the current project".
I'm not sure what is happening here. Since I'm only adding to the class, why can't I maintain binary compatibility with the second DLL? Is there any way around this?
I think this is a correct explanation of what is happening, and some potential workarounds.
I made up a test case which reproduced the problem in the description and then dumped the IDL using OLEView from the old & new DLL which contained the interface.
Here is a diff of the old (left) and new IDL from INewReport:
Important differences:
The UUID of interface _INewReport has changed
A typedef called INewReport___v0 has been added which refers to the original UUID of the interface
(I assume that this is also what is happening to the code referred to in the question.)
So now in the client project the bincomp DLL refers to the original interface UUID; but that UUID only matches against a different name (INewReport___v0 instead of INewReport) than it did originally. I think this is the reason VB6 thinks there is a bincomp mismatch.
How to fix this problem? I've not been able to do anything in VB6 that would allow you to use the updated interface DLL with the client code without having to break bincomp of the client code.
A (bad) option could be to just change the client DLL to use project compatibility... but that may or may not be acceptable in your circumstances. It could cause whatever uses the client DLL to break unless all the consumers were also recompiled. (And this could potentially cause a cascade of broken bincomp).
A better but more complex option would be to define the interface in IDL itself, use the MIDL compiler to generate a typelib (TLB file), and reference that directly. Then you would have full control over the interface naming, etc. You could use the IDL generated from OLEView as a starting point for doing this.
This second option assumes that the interface class is really truly an interface only and has no functional code in it.
Here's how I setup a case to reproduce this:
Step 1. Original interface definition - class called INewReport set to binary compatible:
Sub ProcA()
End Sub
Sub ProcB()
End Sub
Step 2. Create a test client DLL which implements INewReport, also set to binary compatible:
Implements INewReport
Sub INewReport_ProcA()
End Sub
Sub INewReport_ProcB()
End Sub
Step 3: Add ProcC to INewReport and recompile (which also registers the newly built DLL):
(above code, plus:)
Sub ProcC()
End Sub
Step 4: Try to run or compile the test client DLL - instantly get the OP's error. No need to change any references or anything at all.
I was able to recreate your problem, using something similar to DaveInCaz's code. I tried a number of things to fix it, probably repeating things you've already tried. I came up with a possible hypothesis as to why this is happening. It doesn't fix the problem, but it may throw some additional light on it.
Quoting from This doc page:
To ensure compatibility, Visual Basic places certain restrictions on changes you make to default interfaces. Visual Basic allows you to add new classes, and to enhance the default interface of any existing class by adding properties and methods. Removing classes, properties, or methods, or changing the arguments of existing properties or methods, will cause Visual Basic to issue incompatibility warnings.
Another quote:
The ActiveX rule you must follow to ensure compatibility with multiple interfaces is simple: once an interface is in use, it can never be changed. The interface ID of a standard interface is fixed by the type library that defines the interface.
So, here's a hypothesis. The first quote mentions the default interface, which suggests that it may not be possible to alter custom interfaces in any way. That's suggested by the second quote as well. You're able to alter the interface class, because you are essentially altering its default interface. However, when you attempt to alter the implementing class in kind, to reflect the changes in your interface, your implementation reference is pointing to the older version of the interface, which no longer exists. Of course, the error message doesn't hint at this at all, because it appears to be based on the idea that you didn't attempt to implement the interface.
I haven't been able to prove this, but looking at DaveInCaz's answer, the fact that the UUID has changed seems to bear this idea out.
We have developed project using vb.net for our internal purposes and then we obfuscated it. It is throwing error as mentioned below.
“Public member ‘Var1’ on type ‘e’ not found.”
Code:
Public Sub get_constants_from_DbList(ByRef frm As Object, ByRef sDbname As String)
For Each Row As DataRow In CommonObj.DSCommonProc.Tables("dblist").Rows
If StrComp(Row("DbName").ToString, sDbname, CompareMethod.Text) = 0 Then
prg_id = Row("PrgId").ToString
frm.Var1= Row("ChangesDbName").ToString
frm.Var2 = Row("LoadTableName").ToString
frm.Var3 = Row("ServerName").ToString
Exit Sub
End If
Next
End Sub
A form (named FrmMain) is passed to the parameter ‘frm’ from the calling procedure to this sub-routine. Var1, etc are public variables in that form.
Obfuscation tools we tried are –
SmartAssembly 6
PreEmptive Dotfuscator and Analytics CE (which has come with Visual studio 2012)
Without obfuscation exe is working fine.
Error is thrown while assigning variable ‘Var1’ in the sub-routine. If the code line is modified as below then obfuscated exe will work fine.
FrmMain.Var1= Row("ChangesDbName").ToString
We thought obfuscation is missing late binding & tried similar type of code in a small sample project. But that didn’t have any error. We have attached this small code. But due to its magnitude we can’t upload original project.
How can we trace the error?
You can find the source code of my sample application here
Don't use obfuscation with reflection/late binding/dynamic. It will only get you into troubles like this.
The obfuscator will obfuscate all private & internal identifiers but it can't know that you are binding to them by name at run-time.
Turn on Option Strict and resolve the errors (i.e. change the type of the argument frm to its real type)
Obfuscators rely on static analysis to determine what is "safe" to obfuscate. When you introduce late binding and reflection into the mix, it becomes very difficult to detect that something isn't safe to rename. Most obfuscators provide the ability to exclude certain elements of your application from obfuscation so that you can work around this problem.
I actually don't know VB.Net very well, but with the way that you're doing late binding appears to be something that an obfuscator can't detect. So, this means you need to exclude that property from being renamed. In Dotfuscator at least, this is should be easy. You should also be able to turn on "Library Mode" which will automatically exclude all public members of every class.
In my VB6 application I make several calls to a COM server my team created from a Ada project (using GNATCOM). There are basically 2 methods available on the COM server. Their prototypes in VB are:
Sub PutParam(Param As Parameter_Type, Value)
Function GetParam(Param As Parameter_Type)
where Parameter_Type is an enumerated type which distinguishes the many parameters I can put to/get from the COM server and 'Value' is a Variant type variable. PutParam() receives a variant and GetParam() returns a variant. (I don't really know why in the VB6 Object Browser there's no reference to the Variant type on the COM server interface...).
The product of this project has been used continuously this way for years without any problems in this interface on computers with Windows XP with SP2. On computers with WinXP SP3 we get the error 0x800706F7 "The stub received bad data" when trying to put parameters with the 'Long' type.
Does anybody have any clue on what could be causing this? The COM server is still being built in a system with SP2. Should make any difference building it on a system with SP3? (like when we build for X64 in X64 systems).
One of the calls that are causing the problem is the following (changed some var names):
Dim StructData As StructData_Type
StructData.FirstLong = 1234567
StructData.SecondLong = 8901234
StructData.Status = True
ComServer.PutParam(StructDataParamType, StructData)
Where the definition of StructData_Type is:
Type StructData_Type
FirstLong As Long
SecondLong As Long
Status As Boolean
End Type
(the following has been added after the question was first posted)
The definition of the primitive calls on the interface of the COM server in IDL are presented below:
// Service to receive data
HRESULT PutParam([in] Parameter_Type Param, [in] VARIANT *Value);
//Service to send requested data
HRESULT GetParam([in] Parameter_Type Param, [out, retval] VARIANT *Value);
The definition of the structure I'm trying to pass is:
struct StructData_Type
{
int FirstLong;
int SecondLong;
VARIANT_BOOL Status;
} StructData_Type;
I found it strange that this definition here is using 'int' as the type of FirstLong and SeconLong and when I check the VB6 object explorer they are typed 'Long'. Btw, when I do extract the IDL from the COM server (using a specific utility) those parameters are defined as Long.
Update:
I have tested the same code with a version of my COM server compiled for Windows 7 (different version of GNAT, same GNATCOM version) and it works! I don't really know what happened here. I'll keep trying to identify the problem on WinXP SP3 but It is good to know that it works on Win7. If you have a similar problem it may be good to try to migrate to Win7.
I'll focus on explaining what the error means, there are too few hints in the question to provide a simple answer.
A "stub" is used in COM when you make calls across an execution boundary. It wasn't stated explicitly in the question but your Ada program is probably an EXE and implements an out-of-process COM server. Crossing the boundary between processes in Windows is difficult due to their strong isolation. This is done in Windows by RPC, Remote Procedure Call, a protocol for making calls across such boundaries, a network being the typical case.
To make an RPC call, the arguments of a function must be serialized into a network packet. COM doesn't know how to do this because it doesn't know enough about the actual arguments to a function, it needs the help of a proxy. A piece of code that does know what the argument types are. On the receiving end is a very similar piece of code that does the exact opposite of what the proxy does. It deserializes the arguments and makes the internal call. This is the stub.
One way this can fail is when the stub receives a network packet and it contains more or less data than required for the function argument values. Clearly it won't know what to do with that packet, there is no sensible way to turn that into a StructData_Type value, and it will fail with "The stub received bad data" error.
So the very first explanation for this error to consider is a DLL Hell problem. A mismatch between the proxy and the stub. If this app has been stable for a long time then this is not a happy explanation.
There's another aspect about your code snippet that is likely to induce this problem. Structures are very troublesome beasts in software, their members are aligned to their natural storage boundary and the alignment rules are subject to interpretation by the respective compilers. This can certainly be the case for the structure you quoted. It needs 10 bytes to store the fields, 4 + 4 + 2 and they align naturally. But the structure is actually 12 bytes long. Two bytes are padded at the end to ensure that the ints still align when the structure is stored in an array. It also makes COM's job very difficult, since COM hides implementation detail and structure alignment is a massive detail. It needs help to copy a structure, the job of the IRecordInfo interface. The stub will also fail when it cannot find an implementation of that interface.
I'll talk a bit about the proxy, stub and IRecordInfo. There are two basic ways a proxy/stub pair are generated. One way is by describing the interfaces in a language called IDL, Interface Description Language, and compile that with MIDL. That compiler is capable of auto-generating the proxy/stub code, since it knows the function argument types. You'll get a DLL that needs to be registered on both the client and the server. Your server might be using that, I don't know.
The second way is what VB6 uses, it takes advantage of a universal proxy that's built into Windows. Called FactoryBuffer, its CLSID is {00000320-0000-0000-C000-000000000046}. It works by using a type library. A type library is a machine readable description of the functions in a COM server, good enough for FactoryBuffer to figure out how to serialize the function arguments. This type library is also the one that provides the info that IRecordInfo needs to figure out how the members of a structure are aligned. I don't know how it is done on the server side, never heard of GNATCOM before.
So a strong explanation for this problem is that you are having a problem with the type library. Especially tricky in VB6 because you cannot directly control the guids that it uses. It likes to generate new ones when you make trivial changes, the only way to avoid it is by selecting the binary compatibility option. Which uses an old copy of the type library and tries to keep the new one as compatible as possible. If you don't have that option turned on then do expect trouble, especially for the guid of the structure. Kaboom if it changed and the other end is still using the old guid.
Just some hints on where to start looking. Do not assume it is a problem caused by SP3, this COM infrastructure hasn't changed for a very long time. But certainly expect this kind of problem due to a new operating system version being installed and having to re-register everything. SysInternals' ProcMon is a good utility to see the programs use the registry to find the proxy, stub and type library. And you'd certainly get help from a COM Spy kind of utility, albeit that they are very hard to find these days.
If it suddenly stopped working happily on XP, the first culprit I'd look for is type mismatches. It is possible that "long" on such systems is now 64-bits, while your Ada COM code (and/or perhaps your C ints) are exepecting 32-bits. With a traditionally-compiled system this would have been checked for you by your compiler, but the extra indirection you have with COM makes that difficult.
The bit you wrote in there about "when we compile for 64-bit systems" makes me particularly leery. 64-bit compiles may change the size of many C types, you know.
This Related Post suggests you need padding in your struct, as marshalling code may expect more data than you actually send (which is a bug, of course). Your struct contains 9 bytes (assuming 4 bytes for each of the ints/longs and one for the boolean). Try to add padding so that your struct contains a multiple of 4 bytes (or, failing that, multiple of 8, as the post isn't clear on the expected size)
I am also suggesting that the problem is due to a padding issue in your structure. I don't know whether you can control this using a #pragma, but it might be worth looking at your documentation.
I think it would be a good idea to try and patch your struct so that the resulting type library struct is a multiple of four (or eight). Your Status member takes up 2 bytes, so maybe you should insert a dummy value of the same type either before or after Status - which should bring it up to 12 bytes (if packing to eight bytes, this would have to be three dummy variables).
If I write the following code:
public void Execute()
{
var stream = new MemoryStream();
...
}
then code analysis will flag this as:
Warning 1 CA2000 : Microsoft.Reliability : In method 'ServiceUser.Execute()', call System.IDisposable.Dispose on object 'stream' before all references to it are out of scope. C:\Dev\VS.NET\DisposeTest\DisposeTest\ServiceUser.cs 14 DisposeTest
However, if I create a factory pattern, I still might be required to dispose of the object, but now FxCop/Code Analysis doesn't complain. Rather, it complains about the factory method, not the code that calls it. (I think I had an example that did complain about the factory method, but the one I post here doesn't, so I struck that out)
Is there a way, for instance using attributes, to move the responsibility of the IDisposable object out of the factory method and onto the caller instead?
Take this code:
public class ServiceUser
{
public void Execute()
{
var stream = StreamFactory.GetStream();
Debug.WriteLine(stream.Length);
}
}
public static class StreamFactory
{
public static Stream GetStream()
{
return new MemoryStream();
}
}
In this case, there are no warnings. I'd like FxCOP/CA to still complain about my original method. It is still my responsibility to handle that object.
Is there any way I can tell FxCOP/CA about this? For instance, I recently ventured into the annotation attributes that ReSharper has provided, in order to tell its analysis engine information it would otherwise not be able to understand.
So I envision something like this:
public static class StreamFactory
{
[return: CallerResponsibility]
public static Stream GetStream()
{
return new MemoryStream();
}
}
Or is this design way off?
There is a difference between FxCop 10 (which ships with the Windows 7 and .NET 4.0 SDK) and Code Analysis 2010 (which ships with Visual Studio Premium and higher). Code Analysis 2010 has a set of additional rules, which includes a highly improved version of the IDisposable rules.
With Code Analysis 2010 under Visual Studio Premium, the Factory isn't being flagged (as the rule now sees the IDisposable variable is returned to the calling method). The Receiving method, however, isn't flagged either, due to one of the corner case exceptions to the rule. There is a list of method names that will cause the rule to trigger. If you rename your GetStream method to CreateStream, suddenly the rule will trigger:
Warning 4 CA2000 : Microsoft.Reliability : In method 'ServiceUser.Execute()',
call System.IDisposable.Dispose on object 'stream' before all references to it are out
of scope. BadProject\Class1.cs 14 BadProject
I was unable to locate the list of method pre-fixes that will work. I've tried a few and Create~, Open~ trigger the rule, many others that you might expect to work, don't, including Build~, Make~, Get~.
Additionally there is a long list of bugs surrounding this rule. The rule was altered in Visual Studio 2010 to trigger fewer false positives, but now it sometimes misses items it should have flagged (and would have flagged in the previous version). There wasn't enough time to fix the rules in the Visual Studio 2010 time frame (check the bug report comments).
With the upcoming Roslyn compilers, Code Analysis will probably see a major upgrade, until then there are only minor updates to be expected. The current build of Visual Studio Dev11 does not trigger where you want it.
So concluding, no your attribute wouldn't help much, as the rule already detects that you're passing the IDisposable as a return value. Thus Code Analysis knows it's not good to dispose it before returning. If you're using the undocumented naming rules, the rule will trigger. Maybe an attribute could extend the naming rules, but I'd rather have Microsoft would actually fix the actual rule.
I created a connect bug requesting the naming guideline to be documented in the rules documentation.
Comment from Microsoft:
Posted by Microsoft on 1/19/2012 at 10:41 AM
Hello,
Thank you for taking the time to investigate this and file the request for the documentation update. However after some discussion with our documentation team, we have decided to not document the naming convention as you requested.
As you indicated on the stackoverflow thread, there have historically been a lot of reliability issues with this rule, and keying off of the names was an internal implementation detail added to try to reduce the number of false positives. However this is not considered prescriptive guidance for how developers should name their methods, it was added after a survey of common coding practices. We believe the long-term fix is to improve the reliability of the rule, not add naming guidance to our public documentation based on internal implementation details that will continue to change as the rule is improved.
Best Regards,
Visual Studio Code Analysis Team
I have written some code in VB that verifies that a particular port in the Windows Firewall is open, and opens one otherwise. The code uses references to three COM DLLs. I wrote a WindowsFirewall class, which Imports the primary namespace defined by the DLLs. Within members of the WindowsFirewall class I construct some of the types defined by the DLLs referenced. The following code isn't the entire class, but demonstrates what I am doing.
Imports NetFwTypeLib
Public Class WindowsFirewall
Public Shared Function IsFirewallEnabled as Boolean
Dim icfMgr As INetFwMgr
icfMgr = CType(System.Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FwMgr")), INetFwMgr)
Dim profile As INetFwProfile
profile = icfMgr.LocalPolicy.CurrentProfile
Dim fIsFirewallEnabled as Boolean
fIsFirewallEnabled = profile.FirewallEnabled
return fIsFirewallEnabled
End Function
End Class
I do not reference COM DLLs very often. I have read that unmanaged code may not be cleaned up by the garbage collector and I would like to know how to make sure that I have not introduced any memory leaks. Please tell me (a) if I have introduced a memory leak, and (b) how I may clean it up.
(My theory is that the icfMgr and profile objects do allocate memory that remains unreleased until after the application closes. I am hopeful that setting their references equal to nothing will mark them for garbage collection, since I can find no other way to dispose of them. Neither one implements IDisposable, and neither contains a Finalize method. I suspect they may not even be relevant here, and that both of those methods of releasing memory only apply to .Net types.)
Not sure what to recommend here. There is most definitely no memory leak here, the garbage collector releases COM reference counts. COM objects are not disposable but you can release them early with Marshal.ReleaseComObject(). The trouble with doing this explicitly is that it is normally very hard to track interface references.
In your code snippet for example, calling ReleaseComObject on the icfMgr won't have any effect. There's a hidden reference through the LocalPolicy member that will keep the interface reference alive. You'd have to call ReleaseComObject on that hidden reference as well.
I would not recommend making this a practice at all. Getting it wrong produces hard to diagnose failure, you're essentially back to the bad old days of explicit memory management. But it is somewhat manageable in your specific example.
You are exactly right: unmanaged code cannot be managed and thus needs to be managed by hand: disposed of. However, this greatly depends on what you are doing, but in many cases, it is sufficient to wrap the object instantiation around a Using-block. This only works if you use an object that implements IDisposable.
However, the way you currently create an instance of a COM object, you will not have the possibility to clean up easily. It depends on the object. When it doesn't need cleaning up (check the destructor of FwMgr), it doesn't need disposing either. However, most COM objects do need disposal.
So, how to add the IDisposable interface to a COM object that doesn't natively support it? It's a bit of work to do so manually, but you should create a wrapper .NET assembly. Luckily, the work has been taken out of our hands and Microsoft has created some tools and guidelines.
Some of this information is covered here too. You may want to also look up WeakReference as an alternative.
Note that COM and .NET do not talk well together, but they do talk. An excellent reference is .NET and COM The Complete Interoperability Guide by Don Box, SAMS Publishing.
EDIT:
In answer to your "memory leak" question: it is impossible to tell whether you introduced a memory leak, and how big it is. It depends on how often you call your COM object. Call it once per running process? Don't worry too much. Call it hundredths of times in an inner loop? Be very careful. Want to know for sure? Lookup the original documentation or source: if it releases handles, memory or other resources when it is destructed, then yes, you introduced a leak.